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.
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
}
}
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
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.
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With