imageIO 打开 .HDR 文件
imageIO to open .HDR file
我需要打开一个 .hdr 文件并对其进行处理,但 imageIO 不支持该格式。
问题是我需要尽可能少地丢失信息:32bpc 是完美的,16 是好的,少了 16 就不行了。
我想到了 3 种可能的解决方案:
- 找到一个允许我打开 .HDR 文件的插件。我一直在寻找它,但没有运气;
- 想办法将 .HDR 文件转换为我可以找到插件的格式。也许是蒂夫?也试过了,但还是不行;
- 将动态范围从 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
传递给带有 NullToneMapper
的 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(...));
我需要打开一个 .hdr 文件并对其进行处理,但 imageIO 不支持该格式。
问题是我需要尽可能少地丢失信息:32bpc 是完美的,16 是好的,少了 16 就不行了。
我想到了 3 种可能的解决方案:
- 找到一个允许我打开 .HDR 文件的插件。我一直在寻找它,但没有运气;
- 想办法将 .HDR 文件转换为我可以找到插件的格式。也许是蒂夫?也试过了,但还是不行;
- 将动态范围从 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
传递给带有 NullToneMapper
的 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(...));