學習Graphics中遇到位圖(Bitmap)中getPixels()方法,對該方法的用法大體理解,但對其中的stride參數卻不明白具體的用法以及用意,現記述過程如下:
Android英文SDK中有關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文檔相應內容, getPixels()
public void getPixels (int[] pixels, int offset, int stride, int x, int y, int width, int height)
把位圖的數據拷貝到pixels[]中。每一個都由一個表示顏色值的int值來表示。幅度參數(stride)表明調用者允許的像素數組行間距。對通常的填充結果,只要傳遞寬度值給幅度參數。
參數
pixels 接收位圖顏色值的數組
offset 寫入到pixels[]中的第一個像素索引值
stride pixels[]中的行間距個數值(必須大于等于位圖寬度)。可以為負數
x 從位圖中讀取的第一個像素的x坐標值。
y 從位圖中讀取的第一個像素的y坐標值
width 從每一行中讀取的像素寬度
height 讀取的行數
異常
IllegalArgumentExcepiton 如果x,y,width,height越界或stride的絕對值小于位圖寬度時將被拋出。
ArrayIndexOutOfBoundsException 如果像素數組太小而無法接收指定書目的像素值時將被拋出。
1 If you stride somewhere, you walk there with quick, long steps.
stride意為"大踏步快速前進"
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理解為人行走過程中所邁大步的一段距離,而在此方法中可以理解為每行的像素數,至于用處是什么,還要繼續尋找答案.
然后去StackOverFlow去搜了搜"getPixels() stride"關鍵字,查找到如下信息:
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.
上面內容表示stride參數有兩種用處
第一種:
可以截取圖片中部分區域或者圖片拼接.
截圖:假設讀取像素值的原圖片寬為w,高為h,此時設置參數pixels[w*h], 參數stride為 w ,參數offset為0,參數x ,y為截圖的起點位置,參數width和height為截圖的寬度和高度,則此方法運行后,返回的pixels[]數組中從pixels[0]至pixels[width*height-1]里存儲的是從圖片( x , y )處起讀取的截圖大小為width * height的像素值.
示例:修改Android SDK自帶的AipDemo程序中BitmapDecode示例,更換圖像為自制四角四色圖:

圖像大小為100*100,想截取圖片右上1/4圖像(圖上黃色部分)修改程序部分代碼為:
運行結果:
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]數組設初始值看下情況(通過Log.i()我查到了pixels中存儲的像素值為百萬左右的負整數(-16777216),所以這里胡亂取個數-2578654做為初始值,顏色不太好,請見諒),修改后代碼如下:
運行結果: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
我們可以看到結果了,如果pixels[]中的數值為int默認值(0)的話,圖片相應的部分就為背景色,如果設置為別的初始值而在運行中沒有被修改的話,背景色就是修改值對應的RGB顏色.
原圖位置(offset)
下面設置下getPixels[]方法中offset,使得黃色部分截圖出現在它在原圖中的位置,
offset = x + y*w ,本例代碼如下:
運行結果:
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
當然可以用這個方法進行更復雜的運算,諸如截取素材圖片修改目標圖片(已存儲至pixels數組中)的指定區域!!
背景色設置(pixels[])
背景顏色與pixels[]初始值一致,如紅色RED(-65536 0xffff0000),黃色YELLOW(-256 0xffffff00),具體詳見下面附注
運行結果:
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
圖片拼接:
假設兩張圖片大小都為 w * h ,getPixels()方法中設置參數pixels[2*w*h],參數offset = 0,stride = 2*w讀取第一張圖片,再次運行getPixels()方法,設置參數offset = w,stride = 2*w,讀取第二張圖片,再將pixels[]繪制到畫布上就可以看到兩張圖片已經拼接起來了.
示例如下:
運行結果:
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表示數組pixels[]中存儲的圖片每行的數據,在其中可以附加信息,即
stride = width + padding,如下圖所示

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