One of the best features about Java is the amount of low-level complexity it removes, allowing you to focus on developing the application. However, this does sometimes hide some important issues.
We found one of these with the ImageIO class which offers a whole series of methods to save an image as a Tiff, a PNG or a JPEG. All the complexity is hidden and you can save out the image in one line of code (magic). Unfortunately, it also hides an interesting feature…
ImageIO will happily save all kinds of images, including images with transparency (ARGB). And it will save it as a JPEG, even though JPEGs do not really support transparency. The problem comes when you try to view the JPEG. Java understands this hybrid image so it will load back correctly, but very few other tools do.
Because it has 4 bands (RGB are three and then transparency makes the fourth), most JPEG tools assume it must be in the CMYK colorspace and interpret the colors as CMYK. CMYK works completely differently to RGB so the image comes out looking wrong (often with a nasty red tint). Unfortunately, there is no way that a JPEG Decoder can spot this has happened – it is a bug in the way ImageIO works. You can manually fix it by removing any alpha component from your BufferedImage before you save it in ImageIO with the following code
private static BufferedImage convertARGBToRGB(BufferedImage image) {
int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
BufferedImage result = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
int[] pixelsOut = ((DataBufferInt) result.getRaster().getDataBuffer()).getData();
System.arraycopy(pixels, 0, pixelsOut, 0, pixels.length);
return result;
}
In our JDeli image library (which provides a complete JPG Converter), we have actually added a flag to read the JPEG correctly for you if you know the file is broken
try { Map map = new HashMap(); map.put("DECODE_4_COMPONENTS_AS_ARGB","TRUE"); BufferedImage image = JDeli.read(new File(“path/file.jpeg”), map); } catch (IOException e) { // Deal with read error here. }
So while Java makes life much easier most of the time, there are some interesting gotchas out there…
Are you a Java Developer working with Image files?
What is JDeli?
JDeli is a commercial Java Image library that is used to read, write, convert, manipulate and process many different image formats.
Why use JDeli?
To handle many well known formats such as JPEG, PNG, TIFF as well as newer formats like AVIF, HEIC and JPEG XL in java with no calls to any external system or third party library.
What licenses are available?
We have 3 licenses available:
Server for on premises and cloud servers, Distribution for use in a named end user applications, and Custom for more demanding requirements.
How does JDeli compare?
We work hard to make sure JDeli performance is better than or similar to other java image libraries. Check out our benchmarks to see just how well JDeli performs.