I was trying to save images as a JPEG using ImageIO and I wondered why the colours were corrupted all the time.
I used this method:
private void saveImage(Image img) {
File outFile = new File("cap" + getTimestamp() + ".jpg");
try {
PixelFormat pf = img.getPixelReader().getPixelFormat();
System.out.println("Pixel Format is "+pf.getType().name());
BufferedImage bimg = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
System.out.println("Trying to convert into a BufferedImage of Type="+bimg.getType());
BufferedImage swingImg = SwingFXUtils.fromFXImage(img, bimg);
if (swingImg != bimg) {
System.out.println("not same image");
System.out.println("Converted into a BufferedImage of Type="+swingImg.getType());
}
if (swingImg != null) {
ImageIO.write(swingImg, "jpeg", outFile);
} else {
System.err.println("Failed to convert image???");
}
} catch (IOException ex) {
System.err.println(ex);
}
}
I read the source image from JPEG data, which does not support transparency. Then I tried to write it to a file with the above method and found that it printed the following:
Pixel Format is BYTE_RGB
Trying to convert into a BufferedImage of Type=1
Converted into a BufferedImage of Type=3
This tells me that it knew the source image had no alpha channel (BYTE_RGB), that I tried to write it into a BufferedImage that did not have an alpha channel (Type 1 is TYPE_INT_RGB), but instead it was written into a new image of Type 3 (TYPE_INT_ARGB_PRE).
That caused ImageIO to produce bad output because of an existing ImageIO issue where JPEG images are written in a strange way if the source data contains an alpha channel, confusing most JPEG readers into thinking the colour model is CMYK or something like that.
SwingFXUtils.fromFXImage should never have added the alpha channel in the first place, since the source image clearly didn't have one.
I used this method:
private void saveImage(Image img) {
File outFile = new File("cap" + getTimestamp() + ".jpg");
try {
PixelFormat pf = img.getPixelReader().getPixelFormat();
System.out.println("Pixel Format is "+pf.getType().name());
BufferedImage bimg = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
System.out.println("Trying to convert into a BufferedImage of Type="+bimg.getType());
BufferedImage swingImg = SwingFXUtils.fromFXImage(img, bimg);
if (swingImg != bimg) {
System.out.println("not same image");
System.out.println("Converted into a BufferedImage of Type="+swingImg.getType());
}
if (swingImg != null) {
ImageIO.write(swingImg, "jpeg", outFile);
} else {
System.err.println("Failed to convert image???");
}
} catch (IOException ex) {
System.err.println(ex);
}
}
I read the source image from JPEG data, which does not support transparency. Then I tried to write it to a file with the above method and found that it printed the following:
Pixel Format is BYTE_RGB
Trying to convert into a BufferedImage of Type=1
Converted into a BufferedImage of Type=3
This tells me that it knew the source image had no alpha channel (BYTE_RGB), that I tried to write it into a BufferedImage that did not have an alpha channel (Type 1 is TYPE_INT_RGB), but instead it was written into a new image of Type 3 (TYPE_INT_ARGB_PRE).
That caused ImageIO to produce bad output because of an existing ImageIO issue where JPEG images are written in a strange way if the source data contains an alpha channel, confusing most JPEG readers into thinking the colour model is CMYK or something like that.
SwingFXUtils.fromFXImage should never have added the alpha channel in the first place, since the source image clearly didn't have one.
- relates to
-
JDK-8094355 Unit tests for SwingFXUtils.fromFXImage
- Resolved