Grim
Grim

Reputation: 1976

ImageIO throws IIOException for 60x45, 0.5MB - JPEG Image File during Reading

I have a weird JPEG image file that ImageIO.read() fails to load:

ImageIO.read(new URL("http://nocturne.wmw.cc/a.jpg"));

Any ideas?

Exception in thread "main" javax.imageio.IIOException: Unsupported Image Type
    at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:995)
    at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:966)
    at javax.imageio.ImageIO.read(ImageIO.java:1448)
    at javax.imageio.ImageIO.read(ImageIO.java:1400)
    at Main.main(Main.java:23)

imageurl

Upvotes: 4

Views: 4552

Answers (1)

initramfs
initramfs

Reputation: 8405

Okay... Took me a while to find the problem with this... The problem is with the image itself, it has a CMYK colour profile (namely Coated FOGRA27), confusing the JPEG reading library in java.

Opening the image in photoshop yields an image in CMYK color mode (for me at least) which seems to be unsupported by java. Changing the color mode to RGB and saving with a sRGB color profile allowed the ImageIO library to successfully read the image.

The ImageIO library only implements a subset of readable colour profiles and does not handle images without any profiles.

Further reading into the JPEGImageReader source yielded the following code:

switch (colorSpaceCode) {
    case JPEG.JCS_GRAYSCALE:
        list.add(raw);
        list.add(getImageType(JPEG.JCS_RGB));
        break;
    case JPEG.JCS_RGB:
        list.add(raw);
        list.add(getImageType(JPEG.JCS_GRAYSCALE));
        list.add(getImageType(JPEG.JCS_YCC));
        break;
    case JPEG.JCS_RGBA:
        list.add(raw);
        break;
    case JPEG.JCS_YCC:
        if (raw != null) {  // Might be null if PYCC.pf not installed
            list.add(raw);
            list.add(getImageType(JPEG.JCS_RGB));
        }
        break;
    case JPEG.JCS_YCCA:
        if (raw != null) {  // Might be null if PYCC.pf not installed
            list.add(raw);
        }
        break;
    case JPEG.JCS_YCbCr:
        // As there is no YCbCr ColorSpace, we can't support
        // the raw type.

        // due to 4705399, use RGB as default in order to avoid
        // slowing down of drawing operations with result image.
        list.add(getImageType(JPEG.JCS_RGB));

        if (iccCS != null) {
            list.add(new ImageTypeProducer() {
                protected ImageTypeSpecifier produce() {
                    return ImageTypeSpecifier.createInterleaved
                     (iccCS,
                      JPEG.bOffsRGB,  // Assume it's for RGB
                      DataBuffer.TYPE_BYTE,
                      false,
                      false);
                }
            });

        }

        list.add(getImageType(JPEG.JCS_GRAYSCALE));
        list.add(getImageType(JPEG.JCS_YCC));
        break;
    case JPEG.JCS_YCbCrA:  // Default is to convert to RGBA
        // As there is no YCbCr ColorSpace, we can't support
        // the raw type.
        list.add(getImageType(JPEG.JCS_RGBA));
        break;
}

The source of the exception:

Iterator imageTypes = getImageTypes(imageIndex);
if (imageTypes.hasNext() == false) {
    throw new IIOException("Unsupported Image Type");
}

As you can see, when the color profile of the JPEG image is not listed in the switch statement, nothing is added to the 'list' variable which eventually gets passed to the particular iterator in the second segment of code. With an empty list, the Iterator.hasNext() method returns a false, throwing the exception.

Upvotes: 5

Related Questions