【问题标题】:imageIO to open .HDR fileimageIO 打开 .HDR 文件
【发布时间】:2015-07-14 16:47:00
【问题描述】:

我需要打开一个 .hdr 文件并对其进行处理,但 imageIO 不支持该格式。

问题是我需要尽可能地减少信息丢失:32bpc 是完美的,16 很好,少了 16 就不行了。

我想出了 3 种可能的解决方案:

  1. 找到一个允许我打开 .HDR 文件的插件。我一直在寻找它,但没有运气;
  2. 想办法将 .HDR 文件转换为我可以找到插件的格式。蒂夫也许?也试过了,但还是不行;
  3. 将动态范围从 32bpc 降低到 16bpc,然后将其转换为 png。这很棘手,因为一旦我有一个 png 文件,我就赢了,但要在不杀死图像的情况下削减范围并不是那么容易..

你会推荐我做什么?您知道使这三个选项中的一个起作用的方法吗?还是你有更好的主意?

【问题讨论】:

  • 如果您可以将 .HDR 图像转换为 RGB 16 或 32 位/样本 TIFF,则有多个插件可以读取它,例如 TwelveMonkeys 之一。 .HDR 格式是否有规范?如果是这样,有人可能会为它创建一个 ImageIO 插件。 ;-)
  • 不幸的是,问题在于将 .HDR 图像准确地转换为 16/32 bpc RGB 文件。如果我有一个 16 位的 .PNG 就没有问题了。我只需要将 .HDR 转换为其他内容,但我不知道该怎么做:(

标签: java javax.imageio hdr


【解决方案1】:

You can now read .HDR using ImageIO。 :-)

这是第一个版本,所以边缘可能有点粗糙,但应该适用于标准(默认设置)Radiance RGBE .HDR 文件。

返回的图像将是带有DataBufferFloat 支持的自定义BufferedImage(即,样本将采用3 个样本,32 位float 交错RGB 格式)。

默认情况下,应用一个简单的全局色调映射,所有 RGB 值都将被归一化到范围 [0...1](这允许任何人只使用 ImageIO.read(hdrFile) 并且图像看起来会有些合理,在一个非常合理的时间)。

也可以使用NullToneMapperHDRImageReadParam 传递给ImageReader 实例。这甚至更快,但float 值将未标准化,并且可能超过最大值。这允许您在转换为更可显示的内容之前对图像数据进行自定义、更复杂的色调映射。

类似:

// Create input stream
ImageInputStream input = ImageIO.createImageInputStream(hdrFile);

try {
    // Get the reader
    Iterator<ImageReader> readers = ImageIO.getImageReaders(input);

    if (!readers.hasNext()) {
        throw new IllegalArgumentException("No reader for: " + hdrFile);
    }

    ImageReader reader = readers.next();

    try {
        reader.setInput(input);

        // Disable default tone mapping
        HDRImageReadParam param = (HDRImageReadParam) reader.getDefaultReadParam();
        param.setToneMapper(new NullToneMapper());

        // Read the image, using settings from param
        BufferedImage image = reader.read(0, param);
    }
    finally {
        // Dispose reader in finally block to avoid memory leaks
        reader.dispose();
    }
}
finally {
    // Close stream in finally block to avoid resource leaks
    input.close();
}

// Get float data
float[] rgb = ((DataBufferFloat) image.getRaster().getDataBuffer()).getData();

// TODO: Custom tone mapping on float RGB data

// Convert the image to something easily displayable
BufferedImage converted = new ColorConvertOp(null).filter(image, new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB));

// Optionally write as JPEG or other format
ImageIO.write(converted, "JPEG", new File(...));

【讨论】:

  • 我只是随机注意到您的帖子(没有来自 stackoverflow 的通知).. 看起来真的很棒!您可能为我节省了数周的随机内部浏览以寻找解决方案:) 非常感谢!附:是否有要添加到路径的 Jar 插件,还是我必须复制您的 github 项目页面上的类?
  • @pedro 通知的奇怪之处。我认为你应该有一个,但我想 SO 也可能有错误...... ;-) 无论如何,是的,当我有时间发布 3.2 时,很快就会有 JAR(以及主页上的下载链接)。在那之前,您必须从 git 中签出,然后手动构建。请参阅主页上的"Building" 部分。
  • @pedro PS:如果您在阅读 HDR 文件时遇到任何问题,请告诉我。我只有非常有限的一组示例文件可供测试。
  • 它确实给了我通知,但它没有向我发送应有的电子邮件。无论如何,再次感谢您的帮助!现在我面临着另一个让我发疯的问题(一个本应支持和读取高动态范围文件但不起作用的 c++ 函数)。一旦我解决它,我将专注于您的 hdr 阅读器实现! :)
猜你喜欢
  • 1970-01-01
  • 2011-12-04
  • 1970-01-01
  • 2018-09-17
  • 1970-01-01
  • 2014-01-12
  • 2021-06-09
  • 1970-01-01
  • 2014-08-06
相关资源
最近更新 更多