Traneptora / jxlatte

Java JPEG XL decoder
MIT License
44 stars 5 forks source link

Can not write BufferedImage with ImageIO #13

Closed Ali-RS closed 1 year ago

Ali-RS commented 1 year ago

I can not write the BufferedImage returned by XLImage.asBufferedImage() using ImageIO.write()

       try {
            JXLDecoder decoder = new JXLDecoder("samples/bench.jxl");
            JXLImage decode = decoder.decode();
            BufferedImage image = decode.asBufferedImage();

            File file = new File("bench.png");
            System.out.println("Output=" + file.getAbsolutePath());
            try {
                boolean write = ImageIO.write(image, "png", file);
                if (!write) {
                    System.err.println("Could not write image.");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

Calling ImageIO.write(image, "png", file); returns false. No exception is thrown.

Traneptora commented 1 year ago

That's because it's in linear light unless you transform it. You have to call decode.transform(ColorFlags.PRI_SRGB, ColorFlags.WP_D65, ColorFlags.TF_SRGB, JXLOptions.PEAK_DETECT_AUTO) before ImageIO will accept it. Alternatively, you could just draw it onto another BufferedImage.

Ali-RS commented 1 year ago

You have to call decode.transform(ColorFlags.PRI_SRGB, ColorFlags.WP_D65, ColorFlags.TF_SRGB, JXLOptions.PEAK_DETECT_AUTO)

I added this before calling asBufferedImage but still not exporting. Calling ImageIO.write(image, "png", file); still returns false.

        try {
            JXLDecoder decoder = new JXLDecoder("samples/bench.jxl");
            JXLImage jxlImage = decoder.decode();
            jxlImage = jxlImage.transform(ColorFlags.PRI_SRGB, ColorFlags.WP_D65, ColorFlags.TF_SRGB, JXLOptions.PEAK_DETECT_AUTO);
            BufferedImage image = jxlImage.asBufferedImage();

            File file = new File("bench.png");
            System.out.println("Output=" + file.getAbsolutePath());
            try {
                boolean write = ImageIO.write(image, "png", file);
                if (!write) {
                    System.err.println("Could not write image.");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
Traneptora commented 1 year ago

The PNG writer also doesn't support float output, so you'll need a BufferedImage that isn't TYPE_FLOAT.

Traneptora commented 1 year ago

In either case, ImageIO doesn't write the sRGB chunk so you're better off using PNGWriter, which jxlatte provides.