Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image saved in JavaFX as jpg is pink toned

I want to save an Image from my ImageView to files with different resolutions. Doing it as .png results as expected. As for .jpg - I get all files pink toned.

should be blue

Where is the trick? Here is the code:

Object[] imagesFromFotoListView = ta.myFotoListView.getItems().toArray();
new File(localDir).mkdirs();
for (int i = 0; i < imagesFromFotoListView.length; i++) {
    new File(localDir + "/" + i).mkdirs(); 
    final ImageView iv = new ImageView((Image) imagesFromFotoListView[i]);
    ImageIO.write(SwingFXUtils.fromFXImage(iv.snapshot(null, null), null), "jpg", new File(localModelFotoDir + "/" + i + "/large.jpg")); // JPG THAT FAILS PINK.
    BufferedImage bi = SwingFXUtils.fromFXImage(iv.snapshot(null, null), null);
    int resolution[] = new int[]{500, 250, 75};
    for (int j = 0; j < resolution.length; j++) {
        BufferedImage resizedBImage;
        if (bi.getWidth() == bi.getHeight()) {
            resizedBImage = resizeBufferedImage(bi, Scalr.Method.ULTRA_QUALITY, Scalr.Mode.AUTOMATIC, resolution[j], resolution[j]);
        } else if (bi.getWidth() > bi.getHeight()) {
            resizedBImage = resizeBufferedImage(bi, Scalr.Method.ULTRA_QUALITY, Scalr.Mode.AUTOMATIC, resolution[j], (int) ((double) resolution[j] * bi.getHeight() / bi.getWidth()));
        } else {
            resizedBImage = resizeBufferedImage(bi, Scalr.Method.ULTRA_QUALITY, Scalr.Mode.AUTOMATIC, (int) ((double) resolution[j] * bi.getWidth() / bi.getHeight()), resolution[j]);
        }
        Image resizedI = (Image) SwingFXUtils.toFXImage(resizedBImage, null);
        ImageIO.write(SwingFXUtils.fromFXImage((Image) SwingFXUtils.toFXImage(resizedBImage, null), null), "png", new File(localModelFotoDir + "/" + i + "/" + resolution[j] + ".png")); // PNG THAT GOES WELL
    }
}
like image 466
Zon Avatar asked Oct 23 '13 17:10

Zon


2 Answers

I found a solution on Oracle forums. As widely discussed, the problem is in alpha-channel that needs to be excluded from the source image, targeted for .jpg save. I also rearranged my code to make it shorter. The workaround is:

// Get buffered image:
BufferedImage image = SwingFXUtils.fromFXImage(myJavaFXImage, null); 

// Remove alpha-channel from buffered image:
BufferedImage imageRGB = new BufferedImage(
    image.getWidth(), 
    image.getHeight(), 
    BufferedImage.OPAQUE); 

Graphics2D graphics = imageRGB.createGraphics();

graphics.drawImage(image, 0, 0, null);

ImageIO.write(imageRGB, "jpg", new File("/mydir/foto.jpg"));

graphics.dispose();

Fixed in Java 8: https://bugs.openjdk.java.net/browse/JDK-8114609

like image 169
Zon Avatar answered Oct 07 '22 10:10

Zon


Update JavaFX 17

I tried this again with JavaFX 17, and unless I used the workaround from the top-rated answer, I was no longer able to get the image saved. In my case it would just output a 0 length file, not even the ugly pink files of when it was broken before.

Update

This issue was fixed for Java 8:

JDK-8114609 Incorrect display of JPEG images


It looks like you are encountering existing bugs in the ImageIO or JavaFX Image processing libraries.

  • RT-14647 Incorrect display of JPEG images

You might wish to try some of the workarounds suggested in the StackOverflow questions below and see if any of them fix the issue for you:

  • Issue using ImageIO.write jpg file: pink background
  • Java 1.5.0_16 corrupted colours when saving jpg image
like image 30
jewelsea Avatar answered Oct 07 '22 11:10

jewelsea