ng2b30
ng2b30

Reputation: 351

get RGB faster in android

The following is my way to get eh RGB color and change the color in temp (Bitmap) when the color in bitmap (another Bitmap) is green. But the performance is quite bad and the time used around 20 secs or more. Is there any ways for me to improve it ? Thank you very much.

 //get the green color of each pixel
    color = new int[bitmap.getWidth()][bitmap.getHeight()];
    for (int x = 0; x < bitmap.getWidth(); x++) {
        for (int y = 0; y < bitmap.getHeight(); y++) {
            color[x][y] = temp.getPixel(x, y);
            if (bitmap.getPixel(x, y) == Color.GREEN) {
                color[x][y] = temp.getPixel(x, y);
                float[] hsv = new float[3];
                Color.RGBToHSV(Color.red(color[x][y]), Color.green(color[x][y]), Color.blue(color[x][y]), hsv);
                hsv[0] = 360;
                color[x][y] = Color.HSVToColor(hsv);
            }
            temp.setPixel(x, y, color[x][y]);
        }
    }

 imageView.setImageBitmap(temp);

Update:

 intArray = new int[bitmap.getWidth()*bitmap.getHeight()];
                    bitmap.getPixels(intArray,0,bitmap.getWidth(),0,0,bitmap.getWidth(),bitmap.getHeight());

    int[] tempArray = new int[bitmap.getWidth()*bitmap.getHeight()];
      temp.getPixels(tempArray,0,temp.getWidth(),0,0,bitmap.getWidth(),bitmap.getHeight());

    //get the color of each pixel
    color = new int[bitmap.getWidth()][bitmap.getHeight()];
    for (int x = 0; x < bitmap.getWidth(); x++) {
        for (int y = 0; y < bitmap.getHeight(); y++) {
            if (intArray[x + y * bitmap.getWidth()] == Color.BLUE) {
                float[] hsv = new float[3];
                Color.RGBToHSV(Color.red(tempArray[x + y * bitmap.getWidth()]), Color.green(tempArray[x + y * bitmap.getWidth()]), Color.blue(tempArray[x + y * bitmap.getWidth()]), hsv);
                hsv[0] = 360;
                tempArray[x + y * bitmap.getWidth()] = Color.HSVToColor(hsv);

            }
        }
    }

    temp.setPixels(tempArray,0,temp.getWidth(),0,0,temp.getWidth(),temp.getHeight());

    imageView.setImageBitmap(temp);

Upvotes: 1

Views: 1059

Answers (2)

Danny_ds
Danny_ds

Reputation: 11406

There are several ways to make this faster. Let's start with the easiest ones:


float[] hsv = new float[3];

Using new allocates memory on the heap, which is slow and not cache friendly (and needs to be freed afterwards (depending on the language this could be automatic)). You could (re)use a local float[3] instead.


    color[x][y] = temp.getPixel(x, y);
    if (bitmap.getPixel(x, y) == Color.GREEN) {
        color[x][y] = temp.getPixel(x, y);

No need to do a second temp.getPixel() (which can be slow) here. The data is already in color[x][y].


    color[x][y] = temp.getPixel(x, y);
    if (bitmap.getPixel(x, y) == Color.GREEN) {
        // ...
    }
    temp.setPixel(x, y, color[x][y]);

No need to set the pixel if it didn't change. So you could move temp.setPixel inside the if block. And actually color[x][y] = temp.getPixel(x, y); could also go inside the if block (or just remove the outer one, because the same is already inside the if block)


color = new int[bitmap.getWidth()][bitmap.getHeight()];

First, you probably want to use unsigned int here, but actually you don't need this third array. You can just use a local unsigned int color variable instead.


for (int x = 0; x < bitmap.getWidth(); x++) {
    for (int y = 0; y < bitmap.getHeight(); y++) {

Depending on the language, you might want to reverse the order of the loops to be more cache friendly (see this). The easiest way to make sure is to do a quick test with both orders.


getPixel() and setPixel() can be slow (again depending on the language). It is better to work on the pixel data directly just like on a two dimensional array. Most languages provide a function to get a pointer or access to the raw pixel data.

Upvotes: 1

Loren Rogers
Loren Rogers

Reputation: 359

I guess what I would do is determine the size of each pixel. Most likely 32 bits ARGB. So you have an array of WxH longs. Loop through that array and if value is whatever G = 255 would be, then replace it. I would also ignore the ALPHA channel

Upvotes: 0

Related Questions