imageIO 打开 .HDR 文件

imageIO to open .HDR file

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

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

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

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

你会推荐我做什么?您知道使这 3 个选项之一起作用的方法吗?或者你有更好的主意吗?

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

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

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

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

也可以将 HDRImageReadParam 传递给带有 NullToneMapperImageReader 实例。这甚至更快,但 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(...));