Image Manipulation - getPixel on a PNG resource error - bug?

606 views
Skip to first unread message

Gavin Aiken

unread,
Mar 15, 2009, 10:26:12 PM3/15/09
to android-d...@googlegroups.com
Hi all!

I am trying to perform a transformation on an image, specifically a PNG although any lossless format supported by Android would suit me, when running my test suite I keep getting errors that the new pixel values I'm creating are slightly wrong.

To narrow the problem I ran my tests with a single pixel PNG image and got some bizarre results. I started by opening the file with gimp and using the pippet to grab the argb value (Not very scientific I know) the pixel has the following properties;

Red:         250
Green:      114
Blue:        142
Hex:         0xFA728E
Binary:     0b11111010 01110010 10001110

To me this suggests the file is stored in 32 bit depth and not the RGB_565 later reported, do images in res/raw get reduced to 16 bit when packaged with an application?

In my test case I check that the values agree in the preconditions

   @SmallTest
       public void testPreconditions() {
         super.testPreconditions();
         assertEquals(String.format("Get Pixel doesn't map to test data %n%s%n%s%n",MiffedTest.getBitPattern(b.getPixel(0,0)), MiffedTest.getBitPattern(0xfffa728e)),b.getPixel(0,0), 0xfffa728e);
       }

I eventually get the following report;

    Failure in testPreconditions:
    junit.framework.AssertionFailedError: Get Pixel doesn't map to test data
    11111111 11110111 01110001 10001100
    11111111 11111010 01110010 10001110
    expected:<-560756> but was:<-363890>

I decode the single pixel PNG using the following command;

        b = BitmapFactory.decodeResource(getContext().getResources(),R.raw.test);

The config for b is RGB_565 , this worries me, I was using the format in the hope that it was lossless but 16 bit colour is not a great sign, I feel like the crux of this issue lies in the conversion from RGB_565 -> ARGB_8888 which much take place in the getPixel method.

Does anyone know why these values are out? They're such minor amounts but the issues grow the more work I do to an image.
How is the conversion from the RGB_565 format to the 32 bit integer returned by getPixel done? Some low end bits seem to be set so it's not the method I'm used to.
Is there any other way to get at the raw pixel data if the methods are inaccurate?
Is there any way for me to store or convert a PNG in ARGB_8888 on the platform? I just need to be able to get the exact 32 bit value of any pixel from the image.

Any information would be greatly appreciated.

Kind regards,

Gav





Romain Guy

unread,
Mar 15, 2009, 10:56:46 PM3/15/09
to android-d...@googlegroups.com
Going from 565 to ARGB 8888 is not what you want. Whenever an image
with no alpha channel is decoded, Android (currently) converts it to
565 because this is how it will be rendered on screen. Doing the
conversion at drawing time would be a waste of CPU.

What you need is to decode the image directly in ARGB 8888. When you
call one of the BitmapFactory.decode*() methods, you can specify a set
of BitmapFactory.Options. Simply pass a set of options in which
inDither == false. This will tell BitmapFactory to not attempt to
dither the original 24 bits image to 16 bits.
--
Romain Guy
Android framework engineer
roma...@android.com

Note: please don't send private questions to me, as I don't have time
to provide private support. All such questions should be posted on
public forums, where I and others can see and answer them
Reply all
Reply to author
Forward
0 new messages