學習Graphics中遇到位圖(Bitmap)中getPixels()方法,對該方法的用法大致理解,但對其中的stride參數卻不明白具體的用法以及用意,現記述過程以下:html
getPixels()方法的用處爲獲取位圖(Bitmap)中的像素值(顏色值),存入類型爲int的pixels數組中,至於從RGB轉換爲int數值的算法是什麼,暫時不知,存疑!! java
Android英文SDK中有關getPixels()方法的介紹以下:
android
算法
public void getPixels (int[] pixels, int offset, int stride, int x, int y, int width, int height)api
Since: API Level 1數組
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.app
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 |
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()
ide
public void getPixels (int[] pixels, int offset, int stride, int x, int y, int width, int height) 學習
把位圖的數據拷貝到pixels[]中。每個都由一個表示顏色值的int值來表示。幅度參數(stride)代表調用者容許的像素數組行間距。對一般的填充結果,只要傳遞寬度值給幅度參數。ui
參數
pixels 接收位圖顏色值的數組
offset 寫入到pixels[]中的第一個像素索引值
stride pixels[]中的行間距個數值(必須大於等於位圖寬度)。能夠爲負數
x 從位圖中讀取的第一個像素的x座標值。
y 從位圖中讀取的第一個像素的y座標值
width 從每一行中讀取的像素寬度
height 讀取的行數
異常
IllegalArgumentExcepiton 若是x,y,width,height越界或stride的絕對值小於位圖寬度時將被拋出。
ArrayIndexOutOfBoundsException 若是像素數組過小而沒法接收指定書目的像素值時將被拋出。
看完後仍然對Stride解釋中的"行間距"不太明白,去查了下Stride在英語中的原義,Stride在柯林斯中的英英釋義以下:
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.
Stride can be different from the image width.
Most of the images are 4 byte aligned.
For ex. a 24 bit (RGB) image with width of 50 pixels. The total bytes required will be 150 (3(RGB)*50). As image will be 4 byte aligned, in this case the byte required will become 154.
So you will see stride as 154, width 50 and image alignment as 4 byte.
上面內容表示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圖像(圖上黃色部分)修改程序部分代碼爲:
[java] view plaincopyprint?
int[] pixels = new int[w*h];
mBitmap2.getPixels(pixels, 0, w, 50, 0, w/2, h/2);
mBitmap3 = Bitmap.createBitmap(pixels, 0, w, w, h, Bitmap.Config.ARGB_8888);
mBitmap4 = Bitmap.createBitmap(pixels, 0, w, w, h, Bitmap.Config.ARGB_4444);
String txt = String.valueOf(pixels[10]);
Log.i("myBitmapDecode", "w = " + w + "; h = " + h);
Log.i("myBitmapDecode", "pixels[0] = " + pixels[0] + "; pixels[1] = " + pixels[1] + "; pixels[10] = " + pixels[10]);
Log.i("myBitmapDecode", "pixels[w] = " + pixels[w] + "; pixels[h] = " + pixels[h] + "; pixels[w*h-1] = " + pixels[w*h-1]);
運行結果:
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作爲初始值,顏色不太好,請見諒),修改後代碼以下:
[java] view plaincopyprint?
int[] pixels = new int[w*h];
for(int i=0; i<w*h; i++){
pixels[i] = -2578654;
}
mBitmap2.getPixels(pixels, 0, w, 50, 0, w/2, h/2);
mBitmap3 = Bitmap.createBitmap(pixels, 0, w, w, h, Bitmap.Config.ARGB_8888);
mBitmap4 = Bitmap.createBitmap(pixels, 0, w, w, h, Bitmap.Config.ARGB_4444);
String txt = String.valueOf(pixels[10]);
Log.i("myBitmapDecode", "w = " + w + "; h = " + h);
Log.i("myBitmapDecode", "pixels[0] = " + pixels[0] + "; pixels[1] = " + pixels[1] + "; pixels[10] = " + pixels[10]);
Log.i("myBitmapDecode", "pixels[w] = " + pixels[w] + "; pixels[h] = " + pixels[h] + "; pixels[w*h-1] = " + pixels[w*h-1]);
運行結果:
I/myBitmapDecode( 727): w = 100; h = 100
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 ,本例代碼以下:
[java] view plaincopyprint?
int[] pixels = new int[w*h];
for(int i=0; i<w*h; i++){
pixels[i] = -2578654;
}
mBitmap2.getPixels(pixels, 50, w, 50, 0, w/2, h/2;
mBitmap3 = Bitmap.createBitmap(pixels, 0, w, w, h, Bitmap.Config.ARGB_8888);
mBitmap4 = Bitmap.createBitmap(pixels, 0, w, w, h, Bitmap.Config.ARGB_4444);
String txt = String.valueOf(pixels[10]);
Log.i("myBitmapDecode", "w = " + w + "; h = " + h);
Log.i("myBitmapDecode", "pixels[0] = " + pixels[0] + "; pixels[1] = " + pixels[1] + "; pixels[10] = " + pixels[10]);
Log.i("myBitmapDecode", "pixels[w] = " + pixels[w] + "; pixels[h] = " + pixels[h] + "; pixels[w*h-1] = " + pixels[w*h-1]);
運行結果:
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),具體詳見下面附註
[java] view plaincopyprint?
int[] pixels = new int[w*h];
for(int i=0; i<w*h; i++){
pixels[i] = -65536; // Color.RED : -65536 (0xffff0000)
}
mBitmap2.getPixels(pixels, 50, w, 50, 0, w/2, h/2);
mBitmap3 = Bitmap.createBitmap(pixels, 0, w, w, h, Bitmap.Config.ARGB_8888);
Log.i("myBitmapDecode", "w = " + w + "; h = " + h);
Log.i("myBitmapDecode", "pixels[0] = " + pixels[0] + "; pixels[1] = " + pixels[1] + "; pixels[10] = " + pixels[10] + "; pixels[50] = " + pixels[50]);
Log.i("myBitmapDecode", "pixels[w] = " + pixels[w] + "; pixels[h] = " + pixels[h] + "; pixels[w*h-1] = " + pixels[w*h-1]);
for(int i=0; i<w*h; i++){
pixels[i] = -256; // Color.YELLOW : -256 (0xffffff00)
}
mBitmap2.getPixels(pixels, 50*100 + 50, w, 50, 50, w/2, h/2);
mBitmap4 = Bitmap.createBitmap(pixels, 0, w, w, h, Bitmap.Config.ARGB_4444);
Log.i("myBitmapDecode", "w = " + w + "; h = " + h);
Log.i("myBitmapDecode", "pixels[0] = " + pixels[0] + "; pixels[1] = " + pixels[1] + "; pixels[10] = " + pixels[10] + "; pixels[50] = " + pixels[50]);
Log.i("myBitmapDecode", "pixels[w] = " + pixels[w] + "; pixels[h] = " + pixels[h] + "; pixels[w*h-1] = " + pixels[w*h-1]);
運行結果:
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[]繪製到畫布上就能夠看到兩張圖片已經拼接起來了.
示例以下:
[java] view plaincopyprint?
int w = mBitmap2.getWidth();
int h = mBitmap2.getHeight();
int[] pixels = new int[2*w*h];
for(int i=0; i<2*w*h; i++){
pixels[i] = -2578654;
}
mBitmap2.getPixels(pixels, 0, 2*w, 0, 0, w, h);
mBitmap2.getPixels(pixels, w, 2*w, 0, 0, w, h);
mBitmap3 = Bitmap.createBitmap(pixels, 0, 2*w, 2*w, h, Bitmap.Config.ARGB_8888);
String txt = String.valueOf(pixels[10]);
Log.i("myBitmapDecode", "w = " + w + "; h = " + h);
Log.i("myBitmapDecode", "pixels[0] = " + pixels[0] + "; pixels[1] = " + pixels[1] + "; pixels[10] = " + pixels[10]);
Log.i("myBitmapDecode", "pixels[w] = " + pixels[w] + "; pixels[h] = " + pixels[h] + "; pixels[w*h-1] = " + pixels[w*h-1]);
Log.i("myBitmapDecode", "pixels[2*w-1] = " + pixels[2*w-1] + "; pixels[2*w] = " + pixels[2*w] + "; pixels[2*w*h-1] = " + pixels[2*w*h-1]);
運行結果:
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顏色對應值):
Since: API Level 1
Constant Value: -16777216 (0xff000000)
Since: API Level 1
Constant Value: -16776961 (0xff0000ff)
Since: API Level 1
Constant Value: -16711681 (0xff00ffff)
Since: API Level 1
Constant Value: -12303292 (0xff444444)
Since: API Level 1
Constant Value: -7829368 (0xff888888)
Since: API Level 1
Constant Value: -16711936 (0xff00ff00)
Since: API Level 1
Constant Value: -3355444 (0xffcccccc)
Since: API Level 1
Constant Value: -65281 (0xffff00ff)
Since: API Level 1
Constant Value: -65536 (0xffff0000)
Since: API Level 1
Constant Value: 0 (0x00000000)
Since: API Level 1
Constant Value: -1 (0xffffffff)
Since: API Level 1
Constant Value: -256 (0xffffff00)
引用參考:
1, int, int, int, int, int, int)]Android英文文檔getPixels()方法介紹
3 StackOverflow中關於getPixels()問答.
4 Using the LockBits method to access image data
5 本文引用參考