从全景HDR创建简单的2D图像预览

发布于 2025-02-02 23:46:18 字数 2454 浏览 5 评论 0 原文

是否有一些非常简单且基本的代码用于制作HDR图像的预览(例如获得2D BufferedImage 输出或其他内容)?

我正在使用 this hdr image。

我尝试了 this (它使用 twelvemonkeys ),但根本没有成功(它只是卡住/冷冻在 imageReader reader = readers.next();

我编辑了一些以适合我的需求这是测试它被打破/卡住/冷冻的位置...并且它总是在测试1之后发生,这是测试2,从未达到测试,否 IllegalArgumentException 被抛出 - 如果我删除如果()部分,则永远无法达到测试3(我正在使用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;
}

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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夜无邪 2025-02-09 23:46:18

好吧,如果您不介意偶尔在这里和那里偶尔出现某些颜色的极端亚卤蛋白发生过度饱和(我无法解决问题 - 如果有人知道如何,请随时更新我的​​代码),您可以尝试(它正在使用) javahdr ) +我还添加了一些亮度和对比度对于预览,因此,如果您不喜欢,则可以从代码中删除该部分:

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;
}

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;
}
够运 2025-02-09 23:46:18

我可以编译和运行您发布的代码(显然更改路径),而我的两台MacOS机器上没有问题,对所有LTS Java版本进行了测试(8、11和17)。此外,我运行与此类似的代码作为我项目的CI/CD管道的一部分,该项目也在Windows和Linux上测试。我认为您的IDE或计算机上的Java中的设置有问题。我无法复制您描述的“冻结” - 函数...

这是运行程序的输出(我还打印了生成的 bufferedimage 用于验证):

=====>>> TEST 1
=====>>> TEST 2
=====>>> TEST 3
image = BufferedImage@5a42bbf4: type = 1 DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=0 IntegerInterleavedRaster: width = 1024 height = 512 #Bands = 3 xOff = 0 yOff = 0 dataOffset[0] 0

使用代码AS-IS运行(使用 nulltonemapper 且无后处理),由于值不正常,该图像看起来像这样:

“在此处输入image

使用默认/内置的音调映射器或简单地运行使用 imageio.read(hdrfile)读取图像,如注释中所建议的,图像看起来像这样:

=“ nofollow noreferrer”> “在此处输入映像 param.settonemapper(new defaulttonemapper(0.75f)),我得到这样的结果:

”在此处输入图像描述”

I can compile and run the code you posted (changing the path obviously) without problems on my two macOS machines, testing on all the LTS Java versions (8, 11 and 17). In addition, I run code similar to this as part of the CI/CD pipeline of my project that tests on Windows and Linux as well. I think there is something wrong with the setup in your IDE or Java on your computer. I am not able to reproduce the "freeze"-situation you describe...

Here is the output of running the program (I also printed the resulting BufferedImage for verification):

=====>>> TEST 1
=====>>> TEST 2
=====>>> TEST 3
image = BufferedImage@5a42bbf4: type = 1 DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=0 IntegerInterleavedRaster: width = 1024 height = 512 #Bands = 3 xOff = 0 yOff = 0 dataOffset[0] 0

Running with the code as-is (with the NullToneMapper and no post-processing), the image looks like this, due to unnormalized values:

enter image description here

Running with the default/built-in tone mapper, or simply reading the image with ImageIO.read(hdrFile) as suggested in the comments, the image will look like this:

enter image description here

Finally, playing a bit with the code using a custom global tone mapper; param.setToneMapper(new DefaultToneMapper(0.75f)), I get a result like this:

enter image description here

神经大条 2025-02-09 23:46:18

在与@Haraldk进行了长时间的讨论和他的代码添加之后,我发布了此问题的最终正确代码,实际上是@qraqatit 代码用@haraldk添加校正错误的色调映射进行了一些更新,这里是:

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);
    float colorToneCorrection = 0.75f;
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            float r = hdr.getPixelValue(x, y, 0);
            int red = (int) ((r / (colorToneCorrection + r)) * 255);
            float g = hdr.getPixelValue(x, y, 1);
            int green = (int) ((g / (colorToneCorrection + g)) * 255);
            float b = hdr.getPixelValue(x, y, 2);
            int blue = (int) (int) ((b / (colorToneCorrection + b)) * 255);
            bi.setRGB(x, y, rgbToInteger(red, green, blue));
        }
    }

    //MAKE THE RESULTING IMAGE A BIT BRIGHTER
    float brightness = 1.35f;
    float contrast = 0f;
    RescaleOp rescaleOp = new RescaleOp(brightness, contrast, null);
    rescaleOp.filter(bi, bi);

    return bi;
}

After a long discussion with @HaraldK and his code addition, I am posting the final correct code for this problem, that is in fact mix of @qraqatit code updated a bit with the @HaraldK addition that corrects wrong color tone mapping, here it is:

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);
    float colorToneCorrection = 0.75f;
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            float r = hdr.getPixelValue(x, y, 0);
            int red = (int) ((r / (colorToneCorrection + r)) * 255);
            float g = hdr.getPixelValue(x, y, 1);
            int green = (int) ((g / (colorToneCorrection + g)) * 255);
            float b = hdr.getPixelValue(x, y, 2);
            int blue = (int) (int) ((b / (colorToneCorrection + b)) * 255);
            bi.setRGB(x, y, rgbToInteger(red, green, blue));
        }
    }

    //MAKE THE RESULTING IMAGE A BIT BRIGHTER
    float brightness = 1.35f;
    float contrast = 0f;
    RescaleOp rescaleOp = new RescaleOp(brightness, contrast, null);
    rescaleOp.filter(bi, bi);

    return bi;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文