如何在Android中显示HDR图片?

6
我正在制作一款安卓应用程序,用于解压、解码和显示HDR图片。这些HDR图片每个组件(A、R、G、B)使用2个字节,因此一个像素由一个8字节的值表示,只能使用long类型来存储。
我正在使用安卓的Bitmap来显示图片,因为它们提供了一种构造函数,可以使用RGBA_F16来实现HDR功能。
int width = 1;
int height = 1;
Bitmap image = Bitmap.createBitmap(width, height, Bitmap.Config.RGBA_F16);

很不幸,我找不到任何方法来填充位图的像素。我使用了建议的公式,但不能在Bitmap的setPixel(x,y,color)方法中使用,因为颜色必须是int类型:

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

我也尝试了Color(它有一个HDR兼容的方法)、Paint和Canvas,但没有Bitmap方法可以接受它们来设置只有一个像素。

感谢任何帮助!


3
如果你正在进行图像编辑,不应该使用setPixel。获取图像的字节并直接编辑图像。反复调用setPixel非常低效。 - Gabe Sechan
1
@GabeSechan 感谢您的回答,但它并没有帮助我。我的主要问题是在Android上显示每像素8字节的图片(如果可能的话使用Bitmap)。您知道在Android上显示HDR内容(如.hdr文件或bytestream)的任何方法吗? - Nicolas
1
Android的整个架构都是为ARGB而设计的,支持更小的格式(565、灰度等)。你需要进行降采样。我猜你找到的那个构造函数正在这么做。但如果这让你感觉更好一些,无论如何,这种情况迟早会发生——硬件不会支持屏幕每个通道的16位输出。 - Gabe Sechan
1
完全不同的子系统。视频使用OpenGL直接写入视频缓冲区。并不是真正可比较的。你可以通过自定义视图或SurfaceView直接使用openGL,但我不确定这是否值得努力。无论哪种方式,你都不太可能使用Bitmap对象。 - Gabe Sechan
1
@Nicolas,你找到解决方案了吗?我也遇到了同样的问题 - 我只找到了有关在Android上显示HDR视频内容的信息:https://source.android.com/devices/tech/display/hdr - 404pio
显示剩余5条评论
1个回答

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个通道打包成长整型以表示每个像素,然后将这些长整型值写入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);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接