Desert Ice
Desert Ice

Reputation: 4600

Android Bitmap Manipulation

Can you tell me what's wrong with this piece of code?

//bmp is a bitmap of already present image
int width=bmp.getWidth();
int height=bmp.getHeight();
int rgbval[]=new int[width*height];
bmp.getPixels(rgbval, 0, width, 0, 0, width, height);
rgbval=actual(rgbval);
Bitmap bmp2=bmp.copy(Bitmap.Config.ARGB_8888,true);
bmp2.setPixels(rgbval, 0, width, 0, 0, width, height);

actual is a function I have created to manipulate the rgb values of a bmp. By using debug functions of eclipse I have checked that it is working correctly , but when I try to recover rgb values of bmp2 , I don't get the manipulated values.

Upvotes: 1

Views: 4641

Answers (2)

Desert Ice
Desert Ice

Reputation: 4600

I think the problem is due to some android bug. I have manipulated the pixels of the bitmap and i needed the pixel values to exactly the same , but when i used setPixels to set the complete pixels of the bitmap it did not work. I found the solution by using

index=0;
for (int j = 0; j < height; j++)
   for (int i = 0; i < width; i++)
   {
    destBitmap.setPixel(i, j, pixelvalues[index]);

   }

So if i set the pixel one by one instead of all at a time somehow it works!

Upvotes: 1

aleph_null
aleph_null

Reputation: 5786

First of all, see this answer: Android Bitmap setPixel doens't work correctly? (set value, then read a different value)

So, it seems that if your original image does not have an alpha channel (i.e., hasAlpha() returns false), it will automatically convert the rgb values to a premultiplied format. Is that what you're experiencing? Is bmp.hasAlpha() false?

I just tested your code with the default android icon as the bitmap, with which hasAlpha() returns true. The alpha channels in the input and output color arrays are identical. However, the red channels are off by one or two for 15 out of 2304 pixels. I didn't check the blue or green channels. I assume this is internal rounding error? I'm posting the rather verbose and used-only-for-testing code I used just in case anyone has anything else to add.

Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon);

int width=bmp.getWidth();
int height=bmp.getHeight();
int rgbval[]=new int[width*height];
bmp.getPixels(rgbval, 0, width, 0, 0, width, height);
int rgbval2[] = actual(rgbval);

Bitmap bmp2=bmp.copy(Bitmap.Config.ARGB_8888,true);
bmp2.setPixels(rgbval2, 0, width, 0, 0, width, height);

int rgb2[] = new int[width*height];
bmp2.getPixels(rgb2, 0, width, 0, 0, width, height);

int alpha1[] = new int[width*height];
int alpha2[] = new int[width*height];
int red1[] = new int[width*height];
int red2[] = new int[width*height];

for(int i=0; i<alpha2.length; ++i) {
    alpha1[i] = Color.alpha(rgbval2[i]);
    alpha2[i] = Color.alpha(rgb2[i]);
    red1[i] = Color.red(rgbval2[i]);
    red2[i] = Color.red(rgb2[i]);

    if(red1[i]!=red2[i]) {
        int a1 = alpha1[i];
        int a2 = alpha2[i];
        int r1 = red1[i];
        int r2 = red2[i];


        Log.e("E", String.format("a1: %d, a2: %d, r1: %d, r2: %d", a1, a2, r1, r2));
    }
}


private int[] actual(int rgb[]) {
    int rgb2[] = new int[rgb.length];

    for(int i=0; i<rgb.length; ++i) {
        rgb2[i] = Color.argb(Color.alpha(rgb[i]), Color.red(rgb[i])/2,  
                      Color.green(rgb[i])/2, Color.blue(rgb[i])/2);
    }

    return rgb2;
}

and here is the LogCat output

a1: 64, a2: 64, r1: 30, r2: 32
a1: 64, a2: 64, r1: 30, r2: 32
a1: 142, a2: 142, r1: 58, r2: 57
a1: 142, a2: 142, r1: 58, r2: 57
a1: 216, a2: 216, r1: 56, r2: 55
a1: 216, a2: 216, r1: 56, r2: 55
a1: 57, a2: 57, r1: 6, r2: 4
a1: 59, a2: 59, r1: 6, r2: 4
a1: 231, a2: 231, r1: 90, r2: 91
a1: 216, a2: 216, r1: 95, r2: 94
a1: 216, a2: 216, r1: 95, r2: 94
a1: 217, a2: 217, r1: 57, r2: 58
a1: 216, a2: 216, r1: 88, r2: 89
a1: 199, a2: 199, r1: 66, r2: 67
a1: 199, a2: 199, r1: 39, r2: 38

Upvotes: 2

Related Questions