14

I'm trying to do some image processing in Android. I need to get a chunk of pixel information of a bitmap. So I tried to use one of the Bitmap class method getPixels(). However, it seems like I'm not using it correctly or I misunderstood of the sole purpose of the method's behaviour.

For example, I'm doing the following in order to get pixel information of a 10 by 10 region of a bitmap from an arbitrary location(bitmap coordinate) x, y.

Bitmap bitmap = BitmapFactory.decodeFile(filePath);
int[] pixels = new int[100];
bitmap.getPixels(pixels, 0, bitmap.getWidth(), x, y, 10, 10);

And I'm getting ArrayIndexOutOfBoundsException. I've been Googling around to see what I'm doing wrong, but I'm clueless. Most of the examples or questions regarding the use of getPixels() are usually for the case of extracting pixel information of the entire image. Hence the size of the int array is usually bitmap.getWidth()*bitmap.getHeight(), x and y values are 0, 0, and the width, height is bitmap's width and height.

Is Bitmap's getPixels() not designed for the purpose of my use(getting a chunk of pixel information of a sub-region of the bitmap)? Or am I using it incorrectly? Is there an alternative way to do this, perhaps using a different class?

I would appreciate it if anyone has something to say about this. Thanks.

YoonSoo Lee
  • 167
  • 1
  • 2
  • 6

3 Answers3

12

getPixels() returns the complete int[] array of the source bitmap, so has to be initialized with the same length as the source bitmap's height x width.

Using like so, bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, 10, 10); does actually grab the desired pixels from the bitmap, and fills the rest of the array with 0. So with a 10 x 10 subset of a bitmap of 100 x 10, starting at 0,0 the first 100 values would be the desired int value, the rest would be 0.

You could always try using Bitmap.createBitmap() to create your subset bitmap, then use getPixels() on your new Bitmap to grab the complete array.

the.Doc
  • 867
  • 9
  • 17
  • 1
    Although I'm quite surprised by the fact that getPixels() always returns the array size of the entire source bitmap, thank you for your helpful advice. – YoonSoo Lee Nov 19 '12 at 04:33
  • 2
    is using getPixels better than getPixel , in terms of speed? – android developer May 26 '14 at 20:40
  • 3
    I'm from the year 2017 and now I'm not sure that it does return the whole bitmap. I tried setting the size of the pixels array to the stride*heignt value (the parameters passed to getPixels) and it worked. I got this value by testing using a loop of ever-decreasing pixels array size – FrinkTheBrave Jul 11 '17 at 22:45
8

Most guys want to use getPixels() getting a specific region pixels, but actually it returned a full size of the origin bitmap. Valid region is placed left corner and others are translucent colors. I suggest you use Android Studio debug mode to see the visual pixels by creating a bitmap.

And the following is my version of getPixels() to get specific region pixels:

public class BitmapHelper {

public static int[] getBitmapPixels(Bitmap bitmap, int x, int y, int width, int height) {
    int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
    bitmap.getPixels(pixels, 0, bitmap.getWidth(), x, y,
            width, height);
    final int[] subsetPixels = new int[width * height];
    for (int row = 0; row < height; row++) {
        System.arraycopy(pixels, (row * bitmap.getWidth()),
                subsetPixels, row * width, width);
    }
    return subsetPixels;
}
}
ieatbyte
  • 133
  • 2
  • 6
  • Wanted to emphasize that the requested region from `getPixels()` is placed in the left corner of the resulting array **no matter** the (x,y). So requesting a square starting at (1,1) will be at (0,0) in the resulting array. – Luciano Jan 14 '20 at 23:31
0

I suspect the issue was that you specified the 'stride' to be bitmap.getWidth().

This means that the space reserved in each row of your pixel array will be that width and not just 10. In that case you should have allocated the pixels array to be [bitmap.getWidth() * 10] big, not just [10 * 10].

Alternatively and probably what you wanted to do in the first place, was just to specify a stride of just that 10:

bitmap.getPixels(pixels, 0, 10, x, y, 10, 10);
colidyre
  • 4,170
  • 12
  • 37
  • 53