Bitmap類getPixels和createBitmap方法詳解

主要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種顏色意乓,看效果:

圖1(400*400).png

上面的圖片就是由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:

pixels[] 為0的情況.png

這時(shí)候就要用到getPixels方法

bitmap.getPixels(pixels,0,width,0,0,width,height);

當(dāng)代碼走過getPixels方法后再斷點(diǎn):

pixels[] 有值.png

已經(jīng)有值了枚冗,在上面說過,像素點(diǎn)的排列方式如同寫作文蛇损,一行一行哆姻,從左往右业栅,可以想象到圖一中第一行的前200個(gè)像素點(diǎn)為紅色申眼,后200個(gè)為黃色,那么在pixels[]數(shù)組中 0~ 199為紅色,200~399 為黃色袜匿?查閱數(shù)組:

pixels[] 有值200變色.png

確實(shí)如此。顏色解釋:
red.png

yellow.png

這個(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)

紅色.jpg

若現(xiàn)在截取圖1中右上的黃色塊區(qū)域赂鲤,代碼:

bitmap.getPixels(pixels,0,width,      width/2, 0, width/2, height/2)
黃色.jpg

若現(xiàn)在截取圖1中左下的藍(lán)色塊區(qū)域噪径,代碼:

bitmap.getPixels(pixels,0,width,     0, height/2, width/2, height/2)
藍(lán)色.jpg

若現(xiàn)在截取圖1中右下的綠色塊區(qū)域,代碼:

bitmap.getPixels(pixels,0,width,     width/2, height/2, width/2, height/2)
綠色.jpg

從上面四個(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);
綠色塊居中.jpg
  • 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);
width*100.jpg

相信這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);
stride=800.jpg

因?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=400.jpg

看完上述解釋数冬,理解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);
拼接4倍圖.jpg

代碼中的參數(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ì)待宗教一樣充滿虔誠與熱情截珍!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市箩朴,隨后出現(xiàn)的幾起案子岗喉,更是在濱河造成了極大的恐慌,老刑警劉巖炸庞,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钱床,死亡現(xiàn)場離奇詭異,居然都是意外死亡埠居,警方通過查閱死者的電腦和手機(jī)查牌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來滥壕,“玉大人纸颜,你說我怎么就攤上這事∫镩伲” “怎么了胁孙?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長称鳞。 經(jīng)常有香客問我涮较,道長,這世上最難降的妖魔是什么胡岔? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任法希,我火速辦了婚禮,結(jié)果婚禮上靶瘸,老公的妹妹穿的比我還像新娘苫亦。我一直安慰自己,他們只是感情好怨咪,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布屋剑。 她就那樣靜靜地躺著,像睡著了一般诗眨。 火紅的嫁衣襯著肌膚如雪唉匾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音巍膘,去河邊找鬼厂财。 笑死,一個(gè)胖子當(dāng)著我的面吹牛峡懈,可吹牛的內(nèi)容都是我干的璃饱。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼肪康,長吁一口氣:“原來是場噩夢啊……” “哼荚恶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起磷支,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤谒撼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后雾狈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體廓潜,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年箍邮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了茉帅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡锭弊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出擂错,到底是詐尸還是另有隱情味滞,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布钮呀,位于F島的核電站剑鞍,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏爽醋。R本人自食惡果不足惜蚁署,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蚂四。 院中可真熱鬧光戈,春花似錦、人聲如沸遂赠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽跷睦。三九已至筷弦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間抑诸,已是汗流浹背烂琴。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工爹殊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人奸绷。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓边灭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親健盒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子绒瘦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容