主要2個(gè)方法:
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)
加粗了2個(gè)方法中比較關(guān)鍵的參數(shù)
新建一個(gè)bitmap冒窍,長寬均為400:
Bitmap bitmap = Bitmap.createBitmap(400, 400, Bitmap.Config.ARGB_8888);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
其中createBitmap()最后一個(gè)參數(shù)Config.ARGB_8888递沪,表示色彩的存儲(chǔ)方式,還有4444,565等超燃,
8888效果最好区拳,但相比其他更占空間拘领。
接下來往bitmap中添加紅黃藍(lán)綠4種顏色意乓,看效果:
上面的圖片就是由400乘以400個(gè)像素點(diǎn)組成,像素點(diǎn)的排列方式约素,就跟小學(xué)作文本一樣届良,可以看做一個(gè)二維的坐標(biāo)系,每個(gè)像素點(diǎn)相當(dāng)于作文本的一個(gè)小格子圣猎,當(dāng)顏色去填充像素點(diǎn)士葫,如同寫作文,從第一行開始送悔,從左往右慢显,第一行到頭了,換第二行欠啤,再從左往右...
上面的圖怎么畫的:
需要用到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);//藍(lán)色
}
}
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);//綠色
}
}
比如上圖右下的綠色塊应狱,開始填充的第一個(gè)坐標(biāo)點(diǎn)在二維坐標(biāo)系中就是(200,200),最后一個(gè)坐標(biāo)點(diǎn)在右下點(diǎn)(400,400)祠丝,所以寬高的for循環(huán)都從200開始疾呻,400結(jié)束。
直接把bitmap放入imageview写半,就會(huì)顯示圖1岸蜗。
imageView.setImageBitmap(bitmap);
到此已經(jīng)可以用setPixel方法往bitmap中添加顏色
接下來用bitmap的width*height,從而得到一個(gè)int[]數(shù)組叠蝇,這個(gè)數(shù)組就是用來裝整個(gè)bitmap的像素點(diǎn)璃岳。
int[] pixels = new int[width * height];
//pixels.length = 160000
現(xiàn)在pixels[]數(shù)組有長度,但是并沒有給數(shù)組賦值蟆肆,所以數(shù)組中每個(gè)單位值都為0矾睦,可以AS打斷點(diǎn)看到,按住alt炎功,單擊pixels:
這時(shí)候就要用到getPixels方法
bitmap.getPixels(pixels,0,width,0,0,width,height);
當(dāng)代碼走過getPixels方法后再斷點(diǎn):
已經(jīng)有值了枚冗,在上面說過,像素點(diǎn)的排列方式如同寫作文蛇损,一行一行哆姻,從左往右业栅,可以想象到圖一中第一行的前200個(gè)像素點(diǎn)為紅色申眼,后200個(gè)為黃色,那么在pixels[]數(shù)組中 0~ 199為紅色,200~399 為黃色袜匿?查閱數(shù)組:
確實(shí)如此。顏色解釋:
這個(gè)時(shí)候應(yīng)該能理解到getPixels的作用:
將一個(gè)bitmap所有像素點(diǎn)組成的二維圖形(作文本)稚疹,通過一定的約束條件居灯,轉(zhuǎn)化為int[] 類型的一維數(shù)組
通過一定的約束條件,條件就是getPixels的參數(shù)内狗,getPixels方法中前3個(gè)參數(shù)相比后4個(gè)參數(shù)更難理解怪嫌,所以先把getPixels方法中后4個(gè)參數(shù)搞明白
getPixels(int[] pixels , int offset , int stride , int x , int y ,int width , int height)
先遍歷數(shù)組,把每一個(gè)數(shù)全部賦值柳沙,相當(dāng)于給了bitmap給了默認(rèn)的顏色岩灭!
for (int i = 0; i < pixels.length; i++) {
//設(shè)置默認(rèn)值
pixels[i] = Color.BLACK;
}
若現(xiàn)在截取圖1中左上的紅色塊區(qū)域,代碼:
bitmap.getPixels(pixels,0,width, 0, 0, width/2, height/2)
若現(xiàn)在截取圖1中右上的黃色塊區(qū)域赂鲤,代碼:
bitmap.getPixels(pixels,0,width, width/2, 0, width/2, height/2)
若現(xiàn)在截取圖1中左下的藍(lán)色塊區(qū)域噪径,代碼:
bitmap.getPixels(pixels,0,width, 0, height/2, width/2, height/2)
若現(xiàn)在截取圖1中右下的綠色塊區(qū)域,代碼:
bitmap.getPixels(pixels,0,width, width/2, height/2, width/2, height/2)
從上面四個(gè)操作應(yīng)該能理解getPixels方法后4個(gè)參數(shù):x和y表示需要截取圖像左上角的點(diǎn)坐標(biāo)数初,width和height分別表示需要截取的寬高找爱。
接下來說明 offset ,它可以決定截取圖的擺放位置妙真,offset = 像素點(diǎn)以上的矩形區(qū)域加上像素點(diǎn)所在行的下標(biāo)缴允。
- getPixels方法后4個(gè)參數(shù)在原圖上的操作,而offset和stride都表示截取圖(新圖)的操作.
舉個(gè)例子:現(xiàn)在要把上圖截取的綠色塊居中
bitmap.getPixels(pixels, width*100+100, width, 200, 200, width/2, height/2);
- offset這里我設(shè)置的為 :width * 100+100 珍德,width * 100(寬*高)等于上圖紅色塊的像素總數(shù)练般,+100就為白色所在行的像素?cái)?shù),如同最開始所說bitmap的排列如同小學(xué)作文本锈候,offset就是要算出你前面已經(jīng)用過的所有格子薄料。
如果不+100的樣子:
bitmap.getPixels(pixels, width*100, width, 200, 200, width/2, height/2);
相信這2個(gè)例子也能幫你理解offset了。
接下來就輪到stride參數(shù)了:讀取多少個(gè)像素才能換行
場景:現(xiàn)在有一圖片(w:400泵琳,h:2)摄职,需要把這800個(gè)像素全部放入一維數(shù)組pixels中讓新圖(w:800,h:1)使用获列。
//我們先把其他參數(shù)固定:
bitmap.getPixels(pixels, 0, stride, 0, 0,400, 2);
getPixels方法后四個(gè)參數(shù)固定為x:0谷市,y:0,width:400击孩,height:2 就相當(dāng)于截取整個(gè)原圖迫悠,offset也等于0,表示新bitmap從(0,0)開始填充
當(dāng)stride=800時(shí):規(guī)定了在原圖上讀取800個(gè)像素才能換行巩梢,而原圖一行只有400创泄,剩下400沒有艺玲,又不能換行,只能用0填充(android規(guī)定的)鞠抑, 加入到一維數(shù)組中:
一維數(shù)組:0~800前400為有色,后400值為0饭聚,新圖用來畫第一行的時(shí)候,一半有色搁拙,一半無色
當(dāng)stride=400時(shí):規(guī)定了在原圖上讀取400個(gè)像素才能換行秒梳,原圖一行就為400,讀取完400換行感混,不會(huì)出現(xiàn)為空的情況端幼,加入到一維數(shù)組中:
一維數(shù)組組:0~800都為有色的像素點(diǎn),新圖用來畫第一行時(shí)都為有色礼烈。
還是拿綠色塊弧满,舉2個(gè)例子:
- 第一種當(dāng)stride=800
bitmap.getPixels(pixels, 0, 800, 200, 200, width / 2, height / 2);
因?yàn)榫G色塊長寬為200,所以當(dāng)stride=800時(shí)此熬,數(shù)組中0 ~ 800就出現(xiàn) 0 ~ 199為綠色庭呜,200~799為黑色(設(shè)置過默認(rèn)為黑色),把這個(gè)數(shù)組用到上圖400*400的bitmap中時(shí),就會(huì)出現(xiàn)第一行取數(shù)組 0~399 ,其中 0~199 為綠色犀忱, 200~399 為黑色募谎,第二行取數(shù)組400~799,全部為黑色阴汇。
- 同理第二種當(dāng)stride=400
bitmap.getPixels(pixels, 0, 400, 200, 200, width / 2, height / 2);
看完上述解釋数冬,理解stride也不難。
現(xiàn)在把createBitmap(int[] colors , int offset , int stride , int width , int height , Config config)方法拉出來搀庶,這個(gè)方法里面的參數(shù)理解就簡單了拐纱,前3個(gè)參數(shù)和getPixels方法一樣,后3個(gè)就沒啥說的哥倔。
建議如果有截取秸架,拼接圖片這種需求,先想好createBitmap方法的參數(shù)咆蒿,也就是新圖的設(shè)置东抹,比如現(xiàn)在要得到一個(gè)長寬都為400的圖,那么createBitmap參數(shù)中offset 就為0沃测,stride 為寬度400缭黔,width 和 height 都為400;再返回去看getPixels方法的參數(shù)設(shè)置蒂破,這樣思路更加清晰馏谨。
舉個(gè)例子:取圖一這個(gè)四色圖4份,拼成一個(gè)大圖
//數(shù)組放大4倍
int[] pixels = new int[width * height * 4];
//只改變了offset參數(shù)
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表示在數(shù)組中讀取了width*2個(gè)像素 才能換一行
Bitmap bitmap2 = Bitmap.createBitmap(pixels, 0, width*2, width*2, height * 2, Bitmap.Config.ARGB_8888);
代碼中的參數(shù)羅列的很清晰了钠糊。除此之外一些限制:
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()
只要你思路是對(duì)的壹哺,符合正常人操作抄伍,就不會(huì)報(bào)錯(cuò)。
對(duì)于生活理想管宵,應(yīng)該像宗教徒對(duì)待宗教一樣充滿虔誠與熱情截珍!