1

I need to open an .hdr file and work on it, but imageIO doesn't supports that format.

The problem is that I need to keep the information loss as little as possible: 32bpc is perfect, 16 is fine and less the 16 won't work.

There are 3 possible solutions I came up to:

  1. Find a plugin that allow me to open .HDR file. I've been searching for it a lot but without luck;
  2. Find a way to convert the .HDR file to a format I can find a plugin for. Tiff maybe? Tried this too but still no luck;
  3. Reduce the dynamic range from 32bpc to 16bpc and then convert it to png. This is tricky because once I have a png file I win, but it's not that easy to cut the range without killing the image..

What would you recommend me to do? Do you know a way to make one of those 3 options works? Or do you have a better idea?

Harald K
  • 26,314
  • 7
  • 65
  • 111
pedro
  • 417
  • 2
  • 7
  • 25
  • If you can convert the .HDR image to an RGB 16 or 32 bits/sample TIFF, there are multiple plugins that will allow reading that, for example the [TwelveMonkeys](http://haraldk.github.io/TwelveMonkeys/) one. Is there a specification for the .HDR format? If so, someone could potentially create an ImageIO plugin for it. ;-) – Harald K Jul 14 '15 at 18:18
  • Unfortunatly, the problem is exactly converting the .HDR image to a 16/32 bpc RGB file. If I had a 16bit .PNG there would be no problem. I just need to convert the .HDR in something else but I don't know how to do that :( – pedro Jul 14 '15 at 23:24

1 Answers1

1

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

This is a first version, so it might be a little rough around the edges, but should work for standard (default settings) Radiance RGBE .HDR files.

The returned image will be a custom BufferedImage with a DataBufferFloat backing (ie., samples will be in 3 samples, 32-bit float interleaved RGB format).

By default, a simple global tone-mapping is applied, and all RGB values will be normalized to range [0...1] (this allows anyone to just use ImageIO.read(hdrFile) and the image will look somewhat reasonable, in a very reasonable time).

It is also possible to pass an HDRImageReadParam to the ImageReader instance with a NullToneMapper. This is even faster, but the float values will be unnormalized, and might exceed the max value. This allows you to do custom, more sophisticated tone-mapping on the image data, before converting to something more displayable.

Something like:

// 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(...));
Harald K
  • 26,314
  • 7
  • 65
  • 111
  • I just random noticed your post (no notification from stackoverflow).. That looks really great! You probably saved me like weeks of random interner browsing looking for a solution :) Thank you very much! P.s. Is there a Jar plugin to add to the path or do I have to copy the classes that are on your github project's page? – pedro Aug 01 '15 at 14:41
  • @pedro Strange thing with the notification. I think you should have got one, but I guess SO can also have bugs... ;-) Anyway, yes, there will be JARs (and download links on the home page) soon, when I get the time to release 3.2. Until then, you'll have to check out from git, then build manually. See the ["Building"](http://haraldk.github.io/TwelveMonkeys/#building) section from the home page. – Harald K Aug 02 '15 at 16:28
  • @pedro PS: Let me know if you have any issues reading your HDR files. I only have a very limited set of sample files to test on. – Harald K Aug 02 '15 at 16:35
  • It does give me the notification, but it doesn't send me an email as it should. Anyway, thank you again for the help! Right now I'm facing another problem (a c++ function that should natively support and read high dynamic range files but doesn't work) that's driving me crazy. As soon as I'll solve it I'll focus on your hdr reader implementation! :) – pedro Aug 03 '15 at 08:26
  • sorry, this does not work at all for me: it always stuck after `Iterator readers = ImageIO.getImageReaders(input);` - it has no `.next()`, see [this post of mine](https://stackoverflow.com/q/72435424/19018243) – fafa May 30 '22 at 14:15