javaimagepreviewhdrtwelvemonkeys

Create simple 2D image preview from panoramic HDR


Is there some really simple and basic code for making preview for HDR images (like getting 2D BufferedImage output or something)?

I am using this HDR image.

I tried this (it uses TwelveMonkeys), but no success at all (it simply stuck/frozen at ImageReader reader = readers.next();)

I edited it a bit to suit my needs like this, testing where it got broken/stuck/frozen...and it always happen after TEST 1, that is TEST 2 is never reached, tho no IllegalArgumentException is thrown - if I remove the if() section, then TEST 3 is never reached (I am using NetBeansIDE v12.4, Win7 x64):

public BufferedImage hdrToBufferedImage(File hdrFile) throws IOException {
    BufferedImage bi = null;

    // Create input stream
    // I WROTE DOWN THE STRING FOR THIS EXAMPLE, normally it is taken from the hdrFile
    // HDR image size is 23.7MB if it matters at all?
    ImageInputStream input = ImageIO.createImageInputStream(new File("Z:/HDR/spiaggia_di_mondello_4k.hdr"));

    try {
        // Get the reader
        Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
        System.err.println("=====>>> TEST 1");

        if (!readers.hasNext()) {
            throw new IllegalArgumentException("No reader for: " + hdrFile);
        }
        System.err.println("=====>>> TEST 2");

        ImageReader reader = readers.next();
        System.err.println("=====>>> TEST 3");

        try {
            reader.setInput(input);

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

            // Read the image, using settings from param
            bi = 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) bi.getRaster().getDataBuffer()).getData();

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

    return converted;
}

Solution

  • Well, if you don't mind occasional extreme halucinogenic oversaturation of some colors here and there (I was unable solving the issue - if anyone knows how to, please, feel free to update my code), you can try this (it is using JavaHDR) + I also added a bit of brightness and contrast to it as all HDR I tested looked too dark for the preview, so if you do not like that you can remove that part from the code:

    public int rgbToInteger(int r, int g, int b) {
        int rgb = r;
        rgb = (rgb << 8) + g;
        rgb = (rgb << 8) + b;
        return rgb;
    }
    
    public BufferedImage hdrToBufferedImage(File hdrFile) throws IOException {
        HDRImage hdr = HDREncoder.readHDR(hdrFile, true);
        int width = hdr.getWidth();
        int height = hdr.getHeight();
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                int r = (int) (hdr.getPixelValue(x, y, 0) * 255);
                int g = (int) (hdr.getPixelValue(x, y, 1) * 255);
                int b = (int) (hdr.getPixelValue(x, y, 2) * 255);
                bi.setRGB(x, y, rgbToInteger(r, g, b));
            }
        }
    
        //***** YOU CAN REMOVE THIS SMALL SECTION IF YOU FEEL THE IMAGE IS TOO BRIGHT FOR YOU
        float brightness = 2f;
        float contrast = 20f;
        RescaleOp rescaleOp = new RescaleOp(brightness, contrast, null);
        rescaleOp.filter(bi, bi);
        //***** 
    
        return bi;
    }