imageIO打开.HDR文件

时间:2015-07-14 16:47:00

标签: java javax.imageio hdr

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

问题在于我需要尽可能少地保持信息丢失:32bpc是完美的,16是好的,而不是16韩元的工作。

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

  1. 找一个允许我打开.HDR文件的插件。我一直在寻找它,但没有运气;
  2. 找到一种方法将.HDR文件转换为我可以找到插件的格式。 Tiff也许?试过这个,但仍然没有运气;
  3. 将动态范围从32bpc降低到16bpc,然后将其转换为png。这很棘手,因为一旦我获得了一个png文件,但是在不杀死图像的情况下切割范围并不容易..
  4. 你建议我做什么?你知道如何让这3个选项之一有效吗?或者你有更好的主意吗?

1 个答案:

答案 0 :(得分:1)

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

这是第一个版本,所以边缘可能有点粗糙,但应该适用于标准(默认设置)Radiance RGBE .HDR文件。你现在必须从源代码下载和构建项目,但我希望很快就能发布。

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

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

还可以使用HDRImageReadParamImageReader传递给NullToneMapper实例。这甚至更快,但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(...));