學(xué)習(xí)Graphics中遇到位圖(Bitmap)中g(shù)etPixels()方法,對該方法的用法大體理解,但對其中的stride參數(shù)卻不明白具體的用法以及用意,現(xiàn)記述過程如下:
Android英文SDK中有關(guān)getPixels()方法的介紹如下:
??
public void getPixels (int[] pixels, int offset, int stride, int x, int y, int width, int height)
Returns in pixels[] a copy of the data in the bitmap. Each value is a packed int representing a Color
. The stride parameter allows the caller to allow for gaps in the returned pixels array between rows. For normal packed results, just pass width for the stride value.
Parameters
pixels | The array to receive the bitmap's colors |
---|---|
offset | The first index to write into pixels[] |
stride | The number of entries in pixels[] to skip between rows (must be >= bitmap's width). Can be negative. |
x | The x coordinate of the first pixel to read from the bitmap |
y | The y coordinate of the first pixel to read from the bitmap |
width | The number of pixels to read from each row |
height | The number of rows to read |
Throws
IllegalArgumentException | if x, y, width, height exceed the bounds of the bitmap, or if abs(stride) < width. |
---|---|
ArrayIndexOutOfBoundsException | if the pixels array is too small to receive the specified number of pixels. |
看完英文文檔仍然不甚明白,于是去搜了下中文Android文檔相應(yīng)內(nèi)容, getPixels()
public void getPixels (int[] pixels, int offset, int stride, int x, int y, int width, int height)
把位圖的數(shù)據(jù)拷貝到pixels[]中。每一個都由一個表示顏色值的int值來表示。幅度參數(shù)(stride)表明調(diào)用者允許的像素數(shù)組行間距。對通常的填充結(jié)果,只要傳遞寬度值給幅度參數(shù)。
參數(shù)
pixels 接收位圖顏色值的數(shù)組
offset 寫入到pixels[]中的第一個像素索引值
stride pixels[]中的行間距個數(shù)值(必須大于等于位圖寬度)。可以為負(fù)數(shù)
x 從位圖中讀取的第一個像素的x坐標(biāo)值。
y 從位圖中讀取的第一個像素的y坐標(biāo)值
width 從每一行中讀取的像素寬度
height 讀取的行數(shù)
異常
IllegalArgumentExcepiton 如果x,y,width,height越界或stride的絕對值小于位圖寬度時將被拋出。
ArrayIndexOutOfBoundsException 如果像素數(shù)組太小而無法接收指定書目的像素值時將被拋出。
1 If you stride somewhere, you walk there with quick, long steps.
stride意為"大踏步快速前進(jìn)"
2 A stride is a long step which you take when you are walking or running.
stride在此做名詞,意為"大步"
3 Someone's stride is their way of walking with long steps.
指代某人具體邁大步的方式.
于是可以把stride理解為人行走過程中所邁大步的一段距離,而在此方法中可以理解為每行的像素數(shù),至于用處是什么,還要繼續(xù)尋找答案.
然后去StackOverFlow去搜了搜"getPixels() stride"關(guān)鍵字,查找到如下信息:
1 In most cases the stride is the same as the width. The stride is useful if you are trying to copy/draw a sub-region of a Bitmap. For instance, if you have a 100x100 bitmap and you want to draw the 50x50 top-right corner, you can use a width of 50px and a stride of 100px.(注:stride絕對值要大于等于位圖的寬度)
2 Stride is number of bytes used for storing one image row.
Most of the images are 4 byte aligned.
上面內(nèi)容表示stride參數(shù)有兩種用處
第一種:
可以截取圖片中部分區(qū)域或者圖片拼接.
截圖:假設(shè)讀取像素值的原圖片寬為w,高為h,此時設(shè)置參數(shù)pixels[w*h], 參數(shù)stride為 w ,參數(shù)offset為0,參數(shù)x ,y為截圖的起點(diǎn)位置,參數(shù)width和height為截圖的寬度和高度,則此方法運(yùn)行后,返回的pixels[]數(shù)組中從pixels[0]至pixels[width*height-1]里存儲的是從圖片( x , y )處起讀取的截圖大小為width * height的像素值.
示例:修改Android SDK自帶的AipDemo程序中BitmapDecode示例,更換圖像為自制四角四色圖:

圖像大小為100*100,想截取圖片右上1/4圖像(圖上黃色部分)修改程序部分代碼為:
運(yùn)行結(jié)果:
I/myBitmapDecode( 660): w = 100; h = 100
I/myBitmapDecode( 660): pixels[0]-16777216; pixels[1] = -16777216; pixels[10] = -4352
I/myBitmapDecode( 660): pixels[w]-16777216; pixels[h] = -16777216; pixels[w*h-1] = 0
我們看到右邊兩副ARGB_8888,ARGB_4444圖像隱約只在左上角顯示原圖右上的1/4黃色部分,其余部分為背景色白色,那么問題又來了,此時ARGB_8888,ARGB_4444圖像大小為多少?還是原圖的大小(100*100)嗎,或者是(50*50)了,不然背景色為何是畫布的背景色呢(白色)?那么把 pixels[100*100]數(shù)組設(shè)初始值看下情況(通過Log.i()我查到了pixels中存儲的像素值為百萬左右的負(fù)整數(shù)(-16777216),所以這里胡亂取個數(shù)-2578654做為初始值,顏色不太好,請見諒),修改后代碼如下:
運(yùn)行結(jié)果:I/myBitmapDecode( 727): pixels[0] = -16777216; pixels[1] = -16777216; pixels[10] = -4352
I/myBitmapDecode( 727): pixels[w] = -16777216; pixels[h] = -16777216; pixels[w*h-1] = -2578654
我們可以看到結(jié)果了,如果pixels[]中的數(shù)值為int默認(rèn)值(0)的話,圖片相應(yīng)的部分就為背景色,如果設(shè)置為別的初始值而在運(yùn)行中沒有被修改的話,背景色就是修改值對應(yīng)的RGB顏色.
原圖位置(offset)
下面設(shè)置下getPixels[]方法中offset,使得黃色部分截圖出現(xiàn)在它在原圖中的位置,
offset = x + y*w ,本例代碼如下:
運(yùn)行結(jié)果:
I/myBitmapDecode( 761): w = 100; h = 100
I/myBitmapDecode( 761): pixels[0] = -2578654; pixels[1] = -2578654; pixels[10] = -2578654
I/myBitmapDecode( 761): pixels[w] = -2578654; pixels[h] = -2578654; pixels[w*h-1] = -2578654
當(dāng)然可以用這個方法進(jìn)行更復(fù)雜的運(yùn)算,諸如截取素材圖片修改目標(biāo)圖片(已存儲至pixels數(shù)組中)的指定區(qū)域!!
背景色設(shè)置(pixels[])
背景顏色與pixels[]初始值一致,如紅色RED(-65536 0xffff0000),黃色YELLOW(-256 0xffffff00),具體詳見下面附注
運(yùn)行結(jié)果:
I/myBitmapDecode( 1671): w = 100; h = 100
I/myBitmapDecode( 1671): pixels[0] = -65536; pixels[1] = -65536; pixels[10] = -65536; pixels[50] = -16777216
I/myBitmapDecode( 1671): pixels[w] = -65536; pixels[h] = -65536; pixels[w*h-1] = -65536
I/myBitmapDecode( 1671): w = 100; h = 100
I/myBitmapDecode( 1671): pixels[0] = -256; pixels[1] = -256; pixels[10] = -256; pixels[50] = -256
I/myBitmapDecode( 1671): pixels[w] = -256; pixels[h] = -256; pixels[w*h-1] = -16735513
圖片拼接:
假設(shè)兩張圖片大小都為 w * h ,getPixels()方法中設(shè)置參數(shù)pixels[2*w*h],參數(shù)offset = 0,stride = 2*w讀取第一張圖片,再次運(yùn)行g(shù)etPixels()方法,設(shè)置參數(shù)offset = w,stride = 2*w,讀取第二張圖片,再將pixels[]繪制到畫布上就可以看到兩張圖片已經(jīng)拼接起來了.
示例如下:
運(yùn)行結(jié)果:
I/myBitmapDecode( 989): w = 100; h = 100
I/myBitmapDecode( 989): pixels[0] = -16777216; pixels[1] = -16777216; pixels[10] = -16777216
I/myBitmapDecode( 989): pixels[w] = -16777216; pixels[h] = -16777216; pixels[w*h-1] = -16777216
I/myBitmapDecode( 989): pixels[2*w-1] = -3328; pixels[2*w] = -16777216; pixels[2*w*h-1] = -16735513
第二種:
stride表示數(shù)組pixels[]中存儲的圖片每行的數(shù)據(jù),在其中可以附加信息,即
stride = width + padding,如下圖所示

這樣可以不僅僅存儲圖片的像素信息,也可以儲存相應(yīng)每行的其它附加信息.
最后,stride參數(shù)的意義及用處總結(jié)如下:
1 用來表示pixels[]數(shù)組中每行的像素個數(shù),用于行與行之間區(qū)分,絕對值必須大于參數(shù)width,但不必大于所要讀取圖片的寬度w(在width < w 時成立).(stride負(fù)數(shù)有何作用不知,存疑).另,pixels.length >= stride * height,否則會拋出ArrayIndexOutOfBoundsException異常
2 stride > width時,可以在pixels[]數(shù)組中添加每行的附加信息,可做它用.
附注(Color顏色對應(yīng)值):
1, int, int, int, int, int, int)]Android英文文檔getPixels()方法介紹
3 StackOverflow中關(guān)于getPixels()問答.
4 Using the LockBits method to access image data