Bitmap類getPixels和createBitmap方法詳解

這玩意的做用吧,第一能幫你更深層理解bitmap,其次bitmap的拼接,截取等效果也能掌握。

主要2個方法:android

getPixels(int[] pixels , int offset , int stride , int x , int y ,int width , int height)數組

createBitmap(int[] colors , int offset , int stride , int width , int height , Config config)bash

加粗了2個方法中比較關鍵的參數 新建一個bitmap,長寬均爲400:ide

Bitmap bitmap = Bitmap.createBitmap(400, 400, Bitmap.Config.ARGB_8888);
int width = bitmap.getWidth();
int height = bitmap.getHeight();

其中createBitmap()最後一個參數Config.ARGB_8888,表示色彩的存儲方式,還有4444,565等,
8888效果最好,但相比其餘更佔空間。
複製代碼

接下來往bitmap中添加紅黃藍綠4種顏色,看效果:spa

圖1(400*400).png
上面的圖片就是由400乘以400個像素點組成,像素點的排列方式,就跟小學做文本同樣,能夠看作一個 二維的座標系,每一個像素點至關於做文本的一個小格子,當顏色去填充像素點,如同寫做文,從第一行開始,從左往右,第一行到頭了,換第二行,再從左往右... 上面的圖怎麼畫的: 須要用到bitmap.setPixel()方法,上代碼,一看就明白。

for (int i = 0; i < width / 2; i++) {
    for (int j = 0; j < height / 2; j++) {//左上塊
        bitmap.setPixel(i, j, Color.RED);//紅色
    }
    for (int j = height / 2; j < height; j++) {//左下塊
         bitmap.setPixel(i, j, Color.BLUE);//藍色
    }
}

for (int i = width / 2; i < width; i++) {
    for (int j = 0; j < height / 2; j++) {//右上塊
        bitmap.setPixel(i, j, Color.YELLOW);//黃色
    }
    for (int j = height / 2; j < height; j++) { //右下塊
        bitmap.setPixel(i, j, Color.GREEN);//綠色
     }
}
複製代碼

好比上圖右下的綠色塊,開始填充的第一個座標點在二維座標系中就是(200,200),最後一個座標點在右下點(400,400),因此寬高的for循環都從200開始,400結束。3d

直接把bitmap放入imageview,就會顯示圖1code

imageView.setImageBitmap(bitmap);
複製代碼

到此已經能夠用setPixel方法往bitmap中添加顏色

接下來用bitmap的width*height,從而獲得一個int[]數組,這個數組就是用來裝整個bitmap的像素點。cdn

int[] pixels = new int[width * height];
//pixels.length = 160000
複製代碼

如今pixels[]數組有長度,可是並無給數組賦值,因此數組中每一個單位值都爲0,能夠AS打斷點看到,按住alt,單擊pixels:blog

pixels[] 爲0的狀況.png
這時候就要用到getPixels方法

bitmap.getPixels(pixels,0,width,0,0,width,height);
複製代碼

當代碼走過getPixels方法後再斷點:圖片

pixels[] 有值.png

已經有值了,在上面說過,像素點的排列方式如同寫做文,一行一行,從左往右,能夠想象到圖一中第一行的前200個像素點爲紅色,後200個爲黃色,那麼在pixels[]數組中 0~ 199爲紅色,200~399 爲黃色?查閱數組:(一個顏色值爲-65536,另外一個爲-256)

pixels[] 有值200變色.png
確實如此。顏色解釋:
red.png

yellow.png
這個時候應該能理解到getPixels的做用:

將一個bitmap全部像素點組成的***二維圖形***(做文本),經過必定的約束條件,轉化爲int[] 類型的***一維數組***

經過必定的約束條件,條件就是getPixels的參數,getPixels方法中前3個參數相比後4個參數更難理解,因此先把getPixels方法中後4個參數搞明白

getPixels(int[] pixels , int offset , int stride , int x , int y ,int width , int height)

先遍歷數組,把每個數所有賦值,至關於給了bitmap給了默認的顏色!

for (int i = 0; i < pixels.length; i++) {
    //設置默認值
    pixels[i] = Color.BLACK;
}
複製代碼

若如今截取圖1中左上的紅色塊區域,代碼:

bitmap.getPixels(pixels,0,width,    0, 0, width/2, height/2)
複製代碼

紅色.jpg
若如今截取 圖1中右上的 黃色塊區域,代碼:

bitmap.getPixels(pixels,0,width,      width/2, 0, width/2, height/2)
複製代碼

黃色.jpg

若如今截取圖1中左下的藍色塊區域,代碼:

bitmap.getPixels(pixels,0,width,     0, height/2, width/2, height/2)
複製代碼

藍色.jpg

若如今截取圖1中右下的綠色塊區域,代碼:

bitmap.getPixels(pixels,0,width,     width/2, height/2, width/2, height/2)
複製代碼

綠色.jpg

從上面四個操做應該能理解getPixels方法後4個參數:x和y表示須要截取圖像左上角的點座標,width和height分別表示須要截取的寬高

接下來講明 offset ,它能夠決定截取圖的擺放位置,offset = 像素點以上的矩形區域加上像素點所在行的下標。

  • getPixels方法後4個參數在原圖上的操做,而offset和stride都表示截取圖(新圖)的操做.

舉個例子:如今要把上圖截取的綠色塊居中

bitmap.getPixels(pixels,      width*100+100,      width,  200,  200,  width/2,  height/2);
複製代碼

綠色塊居中.jpg

  • offset這裏我設置的爲 :width * 100+100 ,width * 100(寬*高)等於上圖紅色塊的像素總數,+100就爲白色所在行的像素數,如同最開始所說bitmap的排列如同小學做文本,offset就是要算出你前面已經用過的全部格子。

若是不+100的樣子:

bitmap.getPixels(pixels,      width*100,  width,  200,  200,  width/2,  height/2);
複製代碼

width*100.jpg
相信這2個例子也能幫你理解offset了。

接下來就輪到stride參數了:讀取多少個像素才能換行

場景:如今有一圖片(w:400,h:2),須要把這800個像素所有放入一維數組pixels中讓新圖(w:800,h:1)使用。

//咱們先把其餘參數固定:
 bitmap.getPixels(pixels, 0, stride, 0, 0,400, 2);
複製代碼

getPixels方法後四個參數固定爲x:0,y:0,width:400,height:2 就至關於截取整個原圖,offset也等於0,表示新bitmap從(0,0)開始填充

當stride=800時:規定了在原圖上讀取800個像素才能換行,而原圖一行只有400,剩下400沒有,又不能換行,只能用0填充(android規定的), 加入到一維數組中: 一維數組:0~800前400爲有色,後400值爲0,新圖用來畫第一行的時候,一半有色,一半無色

當stride=400時:規定了在原圖上讀取400個像素才能換行,原圖一行就爲400,讀取完400換行,不會出現爲空的狀況,加入到一維數組中: 一維數組組:0~800都爲有色的像素點,新圖用來畫第一行時都爲有色。

仍是拿綠色塊,舉2個例子:

  • 第一種當stride=800
bitmap.getPixels(pixels, 0,   800,   200, 200, width / 2, height / 2);
複製代碼

stride=800.jpg
由於綠色塊長寬爲200,因此當stride=800時,數組中0 ~ 800就出現 0 ~ 199爲綠色,200~799爲黑色(設置過默認爲黑色),把這個數組用到上圖400*400的bitmap中時,就會出現第一行取數組 0~399 ,其中 0~199 爲綠色, 200~399 爲黑色,第二行取數組400~799,所有爲黑色。

  • 同理第二種當stride=400
bitmap.getPixels(pixels, 0,   400,   200, 200, width / 2, height / 2);
複製代碼

stride=400.jpg
看完上述解釋,理解stride也不難。


如今把createBitmap(int[] colors , int offset , int stride , int width , int height , Config config)方法拉出來,這個方法裏面的參數理解就簡單了,前3個參數和getPixels方法同樣,後3個就沒啥說的。

建議若是有截取,拼接圖片這種需求,先想好createBitmap方法的參數,也就是新圖的設置,好比如今要獲得一個長寬都爲400的圖,那麼createBitmap參數中offset 就爲0,stride 爲寬度400,width 和 height 都爲400;再返回去看getPixels方法的參數設置,這樣思路更加清晰。

舉個例子:取圖一這個四色圖4份,拼成一個大圖

//數組放大4倍
 int[] pixels = new int[width * height * 4];

//只改變了offset參數
 bitmap.getPixels(pixels,  0,                          width * 2, 0, 0, width, height);
 bitmap.getPixels(pixels,  width,                      width * 2, 0, 0, width, height);
 bitmap.getPixels(pixels,  width*2*height,             width * 2, 0, 0, width, height);
 bitmap.getPixels(pixels,  width*2*height+width,       width * 2, 0, 0, width, height);

//新bitmap長寬都是2倍,offset表示從頭開始填入像素,stride表示在數組中讀取了width*2個像素 才能換一行
 Bitmap bitmap2 = Bitmap.createBitmap(pixels, 0, width*2,  width*2, height * 2, Bitmap.Config.ARGB_8888);
複製代碼

拼接4倍圖.jpg
代碼中的參數羅列的很清晰了。除此以外一些限制:

getPixels(int[] pixels , int offset , int stride , int x , int y ,int width , int height)

abs(stride) must be >= width, x + width must be <= bitmap.width()

只要你思路是對的,符合正常人操做,就不會報錯。


對於生活理想,應該像宗教徒對待宗教同樣充滿虔誠與熱情!
相關文章
相關標籤/搜索