简体   繁体   中英

How to display HDR picture in Android?

I'm doing an android app to decompress, decode and display HDR pictures.
These HDR pictures use 2 bytes per component (A,R,G,B) so one pixel is represented by a 8 bytes value that can only fit with the long type.

I'm using android's Bitmap to display picture as they have a constructor allowing to do HDR by using Bitmap.Config.RGBA_F16 :

int width = 1;
int height = 1;
Bitmap image = Bitmap.createBitmap(width, height, Bitmap.Config.RGBA_F16);

Unfortunately I can't find any way to fill a pixel of the Bitmap. I use the recommended formula but it cannot be used in the setPixel(x,y,color) method of Bitmap because color has to be a int:

long color = (A & 0xffff) << 48 | (B & 0xffff) << 32 | (G & 0xffff) << 16 | (R & 0xffff);
image.setPixel(0,0,color); //Argument type error

.
I have also tried with Color ( which has a HDR compatible method ), Paint and Canvas but no Bitmap method accepts them to set only one pixel.

Thanks for any help!

If you need to open an HDR file, such as 16-bit png, and then display it, you can use ImageDecoder.setTargetColorSpace to create bitmap with format Bitmap.Config.RGBA_F16 like so:

File file = new File(...);
ImageDecoder.Source source = ImageDecoder.createSource(file);
Drawable drawable = ImageDecoder.decodeDrawable(source, (decoder, info, src) -> {
    decoder.setTargetColorSpace(ColorSpace.Named.EXTENDED_SRGB);
});

If you need to display HDR image that is stored in memory you can use Bitmap.copyPixelsFromBuffer , as this method allows to set pixels of the bitmap without conversion of color space the way Bitmap.setPixel does. In this case you need to pack 4 channels represented byHalf values into long for each pixel, then write these long values into a Buffer and finally copy pixels from the buffer to the bitmap.

LongBuffer buffer = LongBuffer.allocate(width * height);
for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
        // fill pixels values as needed
        float r = (float)y / height;
        float g = (float)y / height;
        float b = (float)y / height;
        float a = 1f;
        long rBits = Half.halfToShortBits(Half.toHalf(r));
        long gBits = Half.halfToShortBits(Half.toHalf(g));
        long bBits = Half.halfToShortBits(Half.toHalf(b));
        long aBits = Half.halfToShortBits(Half.toHalf(a));
        long color = aBits << 48 | bBits << 32 | gBits << 16 | rBits;
        buffer.put(color);
    }
}
buffer.rewind();

bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGBA_F16);
bitmap.copyPixelsFromBuffer(buffer);

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