简体   繁体   中英

Android: How to get pixels of a single channel 16bit PNG Bitmap

I have a png file created with python PIL that contains an height map (positive values).

The format is : single channel (grey level) at 16bit, thus 16 bit per pixel.

I read the file on android with BitmapFactory.decodeStream(<...data input stream...>);

I correctly get the size of the image through getWidth() and getHeight() .

However when I loop though the pixels calling the getPixel(i,j) I obtain negative values, something like: -16776192 -16250872 -16250872 -16250872 -16250872 -16249848 ....

Instead I expect a positive value between 0 and 65535.

I discover that the value -16250872 in binary is 1111111111111111111111111111111111111111000010000000100000001000

This shows that the information relies on the first 16 least significant bits.

I tryed with getPixel(i,j)&0xffff and I obtain a plausible values, however I'm not sure about the endianess: should I to flip the 2 extracted bytes?

Is there a way to do it in more elegant and portable way this conversion ?

NOTE: the file is not a color (RGBA) PNG but a grey level PNG image with a single 16 bit value for each pixel.

I found a solution by myself using the consideration made in this post: Android: loading an alpha mask bitmap

Basically, If you load directly a 16 bit greylevel PNG from bitmap factory the pixel format will be not correct. You need to use a RGBA 32 bit color format setting the pixel format to ARGB_8888. Then you have to get all the pixels with getPixel(i,j) and mask the integer value with 0xffff. In this way you will obtain the expected 16bit values.

This is a part of the code that I've used:

BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig= Bitmap.Config.ARGB_8888;
Bitmap bmp=BitmapFactory.decodeStream(entity.getContent(),null,opt);
int W=bmp.getWidth();
int H=bmp.getHeight();
int px;
for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++)
    {
          px= bmp.getPixel(j, i)&0x0000ffff;//in px you will find a value between 0 and 65535
          ...
    }

I assume your trying to get the RGB for a pixel in an image. If that is correct then you will find the following helpful.

Returns the Color at the specified location. Throws an exception if x or y are out of bounds (negative or >= to the width or height respectively).

That is the quote for the Bitmap.getPixel();

What you need to do to print this off so that it is human readable. I have programed with android, but not done this with android. I used the following function for one my programs.

public static int[] getRGBValue(BufferedImage bi, int x, int y) {
    int argb = bi.getRGB(x, y);
    int rgb[] = new int[] {
            (argb >> 16) & 0xff, // red
            (argb >>  8) & 0xff, // green
            (argb      ) & 0xff, // blue
    };
    return rgb;
}

public static String getStringOfRGB(int[] value) {
    return "Color: (" + value[0] + ", " + value[1] + ", " + value[2] + ")";
}

I don't kow what you trying to do exactly, so the code above won't answer your question... but should assist you in finding your answer on however you want to use the data of the pixel.

Hope this helps! :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM