如何在Android中显示HDR图片?

时间:2019-04-01 15:25:05

标签: java android colors bitmap hdr

我正在做一个Android应用来解压缩,解码和显示HDR图片。
这些HDR图片每个分量(A,R,G,B)使用2个字节,因此一个像素由8个字节的值表示,该值只能与long类型匹配。

我正在使用Android的位图来显示图片,因为它们具有允许通过使用Bitmap.Config.RGBA_F16进行HDR的构造函数:

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

不幸的是,我找不到任何方法来填充位图的像素。我使用推荐的公式,但是不能在Bitmap的setPixel(x,y,color)方法中使用它,因为color必须是int:

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


我也尝试过使用颜色(which has a HDR compatible method),绘画和画布,但是没有位图方法接受它们仅设置一个像素。

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

如果你需要打开一个 HDR 文件,比如 16 位 png,然后显示它,你可以使用 ImageDecoder.setTargetColorSpace 来创建格式为 Bitmap.Config.RGBA_F16 的位图,如下所示:

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

如果您需要显示存储在内存中的 HDR 图像,您可以使用 Bitmap.copyPixelsFromBuffer,因为此方法允许设置位图的像素,而无需像 Bitmap.setPixel 那样转换色彩空间。在这种情况下,您需要将每个像素的 Half 值表示的 4 个通道打包成 long,然后将这些 long 值写入 Buffer,最后将像素从缓冲区复制到位图。

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);