ketorin
ketorin

Reputation: 1044

Why Java ImageIO flattens JPEG colors

When I read certain JPG files, colors are flattened. Here is a simple example that reads a jpg and just writes the same image to another file.

import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;

public class JPegReadTest {
    public static void main(String[] args) {
        if (args.length == 2) {
            try {
                BufferedImage src = ImageIO.read(new File(args[0]));
                ImageIO.write(src, "jpg", new File(args[1]));
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            System.err.println("Usage: java JPegReadTest src dest");
        }
    }
}

If you try this with for example http://www.flickr.com/photos/visualpanic/233508614/sizes/l/ , the colors of the destination image differ from the source file. Why is that? How to fix it?

Also tried saving the image as png, but the colors are bland in it too (so assuming color info is not read properly).

Upvotes: 10

Views: 7360

Answers (5)

Jimmy
Jimmy

Reputation: 26

Here is a link with source code that expands on the ImageIO interface - you can change the quality and compression parameters when writing an image.... http://www.universalwebservices.net/web-programming-resources/java/adjust-jpeg-image-compression-quality-when-saving-images-in-java

Upvotes: 0

erjiang
erjiang

Reputation: 45667

It could be several reasons.

  1. JPEG color data is often stored as YCrCb instead of RGB, although conversions should be mostly unnoticeable.
  2. JPEG often has an embedded color profile, but many applications do not understand this and simply ignore it (in which case, your output file might be missing the color profile).
  3. Gamma value could be reset or missing after Java mangles it.

I didn't actually try your example... could you please post both before and after files? Without actually being able to examine the result file, it's hard to tell if this extra data is there or not.

Edit: Yeah, it's clear that your original and converted images have different color profiles. Java stripped out the original's color profile and used generic sRGB instead. They look the same to us on Windows with Firefox and assorted programs because these programs don't use the color profile when renderer. However, on your Mac, Mac actually supports these color profiles (cue debate over Macs for graphics, etc.) and so they render differently. I don't have a Mac handy, but I suspect that if you open the files in Photoshop on any platform, you'll see the difference.

Upvotes: 10

hobbs
hobbs

Reputation: 239930

Perhaps your source image has an assigned color profile with a gamut wider than sRGB (like Adobe RGB), and your load/save cycle isn't preserving the colorspace information? With no color profile, your viewer will assume sRGB, and the compressed gamut will make everything look "blah". If you have exiftool,

exiftool -ProfileDescription filename.jpg

is a quick way to verify the color profiles on your source and output images.

Upvotes: 2

Joachim Sauer
Joachim Sauer

Reputation: 308041

JPEG is a lossy format.

That means that if you open a file and save it again you will lose some information unless you take very specific steps not to lose any (in which case the possible manipulations are very restricted).

Additionally ImageIO.write() probably uses some default quality settings for saving JPEG files, which might be lower than the original, which would lead to an additional loss of quality.

Try saving to a PNG file and you'll see that it will look the same as the source.

Upvotes: 0

Nick
Nick

Reputation: 1340

jpeg is a lossy format. When read in, java stores it as a raw format much like an BMP. Then it's being written out again causing data loss. Also, there isnt much control over the quality like when using something like GIMP.

Maybe look into using other APIs like Image Magick to give you more control over quality.

Upvotes: 0

Related Questions