Bitmap 之 getPixels() 的 stride
學(xué)習(xí)Graphics中遇到位圖(Bitmap)中g(shù)etPixels()方法,對(duì)該方法的用法大體理解,但對(duì)其中的stride參數(shù)卻不明白具體的用法以及用意,現(xiàn)記述過(guò)程如下:
getPixels()方法的用處為獲取位圖(Bitmap)中的像素值(顏色值),存入類(lèi)型為int的pixels數(shù)組中,至于從RGB轉(zhuǎn)換為int數(shù)值的算法是什么,暫時(shí)不知,存疑!!?Android英文SDK中有關(guān)getPixels()方法的介紹如下:
public void getPixels (int[] pixels, int offset, int stride, int x, int y, int width, int height)
Since: API Level 1Returns 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
| The array to receive the bitmap's colors |
| The first index to write into pixels[] |
| The number of entries in pixels[] to skip between rows (must be >= bitmap's width). Can be negative. |
| The x coordinate of the first pixel to read from the bitmap |
| The y coordinate of the first pixel to read from the bitmap |
| The number of pixels to read from each row |
| The number of rows to read |
Throws
| if x, y, width, height exceed the bounds of the bitmap, or if abs(stride) < width. |
| 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[]中。每一個(gè)都由一個(gè)表示顏色值的int值來(lái)表示。幅度參數(shù)(stride)表明調(diào)用者允許的像素?cái)?shù)組行間距。對(duì)通常的填充結(jié)果,只要傳遞寬度值給幅度參數(shù)。
參數(shù)
pixels???????接收位圖顏色值的數(shù)組
offset??????寫(xiě)入到pixels[]中的第一個(gè)像素索引值
stride ? ? ? pixels[]中的行間距個(gè)數(shù)值(必須大于等于位圖寬度)。可以為負(fù)數(shù)
x ? ? ? ? ? ??從位圖中讀取的第一個(gè)像素的x坐標(biāo)值。
???????????????? y ? ? ? ? ? ??從位圖中讀取的第一個(gè)像素的y坐標(biāo)值
???????????????? width ??????從每一行中讀取的像素寬度
???????????????? height? 讀取的行數(shù)???????????????
異常
?????????????????? IllegalArgumentExcepiton??????? ? ? ? ? ?如果x,y,width,height越界或stride的絕對(duì)值小于位圖寬度時(shí)將被拋出。
?????????????????? ArrayIndexOutOfBoundsException??????????如果像素?cái)?shù)組太小而無(wú)法接收指定書(shū)目的像素值時(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理解為人行走過(guò)程中所邁大步的一段距離,而在此方法中可以理解為每行的像素?cái)?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絕對(duì)值要大于等于位圖的寬度)
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.上面內(nèi)容表示stride參數(shù)有兩種用處
第一種:
可以截取圖片中部分區(qū)域或者圖片拼接.
截圖:假設(shè)讀取像素值的原圖片寬為w,高為h,此時(shí)設(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]里存儲(chǔ)的是從圖片( x , y )處起讀取的截圖大小為width * height的像素值.
示例:修改Android SDK自帶的AipDemo程序中BitmapDecode示例,更換圖像為自制四角四色圖:
圖像大小為100*100,想截取圖片右上1/4圖像(圖上黃色部分)修改程序部分代碼為:?
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]);運(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黃色部分,其余部分為背景色白色,那么問(wèn)題又來(lái)了,此時(shí)ARGB_8888,ARGB_4444圖像大小為多少?還是原圖的大小(100*100)嗎,或者是(50*50)了,不然背景色為何是畫(huà)布的背景色呢(白色)?那么把 pixels[100*100]數(shù)組設(shè)初始值看下情況(通過(guò)Log.i()我查到了pixels中存儲(chǔ)的像素值為百萬(wàn)左右的負(fù)整數(shù)(-16777216),所以這里胡亂取個(gè)數(shù)-2578654做為初始值,顏色不太好,請(qǐng)見(jiàn)諒),修改后代碼如下:?
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]);運(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)行中沒(méi)有被修改的話,背景色就是修改值對(duì)應(yīng)的RGB顏色.
原圖位置(offset)
下面設(shè)置下getPixels[]方法中offset,使得黃色部分截圖出現(xiàn)在它在原圖中的位置,
offset = x + y*w ,本例代碼如下:?
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]);運(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)然可以用這個(gè)方法進(jìn)行更復(fù)雜的運(yùn)算,諸如截取素材圖片修改目標(biāo)圖片(已存儲(chǔ)至pixels數(shù)組中)的指定區(qū)域!!
背景色設(shè)置(pixels[])
背景顏色與pixels[]初始值一致,如紅色RED(-65536 0xffff0000),黃色YELLOW(-256 0xffffff00),具體詳見(jiàn)下面附注
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]);運(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[]繪制到畫(huà)布上就可以看到兩張圖片已經(jīng)拼接起來(lái)了.
示例如下:?
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]);運(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[]中存儲(chǔ)的圖片每行的數(shù)據(jù),在其中可以附加信息,即
stride = width + padding,如下圖所示
這樣可以不僅僅存儲(chǔ)圖片的像素信息,也可以?xún)?chǔ)存相應(yīng)每行的其它附加信息.
最后,stride參數(shù)的意義及用處總結(jié)如下:
1 用來(lái)表示pixels[]數(shù)組中每行的像素個(gè)數(shù),用于行與行之間區(qū)分,絕對(duì)值必須大于參數(shù)width,但不必大于所要讀取圖片的寬度w(在width < w 時(shí)成立).(stride負(fù)數(shù)有何作用不知,存疑).另,pixels.length >= stride * height,否則會(huì)拋出ArrayIndexOutOfBoundsException異常
2 stride > width時(shí),可以在pixels[]數(shù)組中添加每行的附加信息,可做它用.
附注(Color顏色對(duì)應(yīng)值):
Constants
public static final int?BLACK
Since:?API Level 1Constant Value:?-16777216 (0xff000000)public static final int?BLUE
Since:?API Level 1Constant Value:?-16776961 (0xff0000ff)public static final int?CYAN
Since:?API Level 1Constant Value:?-16711681 (0xff00ffff)public static final int?DKGRAY
Since:?API Level 1Constant Value:?-12303292 (0xff444444)public static final int?GRAY
Since:?API Level 1Constant Value:?-7829368 (0xff888888)public static final int?GREEN
Since:?API Level 1Constant Value:?-16711936 (0xff00ff00)public static final int?LTGRAY
Since:?API Level 1Constant Value:?-3355444 (0xffcccccc)public static final int?MAGENTA
Since:?API Level 1Constant Value:?-65281 (0xffff00ff)public static final int?RED
Since:?API Level 1Constant Value:?-65536 (0xffff0000)public static final int?TRANSPARENT
Since:?API Level 1Constant Value:?0 (0x00000000)public static final int?WHITE
Since:?API Level 1Constant Value:?-1 (0xffffffff)public static final int?YELLOW
Since:?API Level 1Constant Value:?-256 (0xffffff00)1, int, int, int, int, int, int)]Android英文文檔getPixels()方法介紹
2 Android中文文檔getPixels()方法介紹3 StackOverflow中關(guān)于getPixels()問(wèn)答.
4?Using the LockBits method to access image data
5 本文引用參考總結(jié)
以上是生活随笔為你收集整理的Bitmap 之 getPixels() 的 stride的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 梦到别人醉酒呕吐是怎么回事
- 下一篇: struts2遍历select