【问题标题】:How to display HDR picture in Android?如何在 Android 中显示 HDR 图片?
【发布时间】:2019-04-01 15:25:04
【问题描述】:

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

我正在使用 android 的 Bitmap 来显示图片,因为它们有一个构造函数允许使用 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) 方法,因为颜色必须是 int:

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

.
我也尝试过使用 Color (which has a HDR compatible method)、Paint 和 Canvas,但没有 Bitmap 方法接受它们来设置一个像素。

感谢您的帮助!

【问题讨论】:

  • 如果你在做图像编辑,无论如何你都不应该使用 setPixel。获取图像的字节并直接编辑图像。重复调用 setPixel 效率极低。
  • @GabeSechan 感谢您的回答,但这对我没有帮助。我的主要问题是在 Android 中显示每像素 8 字节的图片(如果可能的话,使用位图)。您知道在 Android 上显示 HDR 内容(如 .hdr 文件或字节流)的任何方式吗?
  • Android 上的整个架构都是 ARGB,支持更小的格式(565、灰度等)。你将不得不缩小规模。我敢打赌,您找到的构造函数正在做的事情。但是,如果它让你感觉好些,那它无论如何都会在某个时候发生——硬件不会支持屏幕上每个通道的 16 位输出。
  • 那么我很难理解为什么我的 Galaxy Note 8 上的 Android 支持 HDR10 视频(每个组件 10 位)但不支持 HDR 图片。不幸的是,android文档对此真的不清楚......
  • 完全不同的子系统。 Video 使用 OpenGL 直接写入视频缓冲区。没有真正的可比性。只要您通过自定义视图或 SurfaceView 完成所有操作,您就可以直接使用 openGL,但我不确定它是否值得付出努力。无论哪种方式,您都不太可能使用 Bitmap 对象。

标签: java android colors bitmap hdr


【解决方案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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    • 2015-01-29
    • 1970-01-01
    相关资源
    最近更新 更多