How to Read Jpeg Image Using Imageio.Read(File File)

Unable to read JPEG image using ImageIO.read(File file)

Your image "Color Model" is CMYK, JPEGImageReader (the inner class that reads your file) reads only RGB Color Model.

If you insist on reading CMYK images, then you will need to convert them, try this code.

UPDATE

Read a CMYK image into RGB BufferedImage.

    File f = new File("/path/imagefile.jpg");

//Find a suitable ImageReader
Iterator readers = ImageIO.getImageReadersByFormatName("JPEG");
ImageReader reader = null;
while(readers.hasNext()) {
reader = (ImageReader)readers.next();
if(reader.canReadRaster()) {
break;
}
}

//Stream the image file (the original CMYK image)
ImageInputStream input = ImageIO.createImageInputStream(f);
reader.setInput(input);

//Read the image raster
Raster raster = reader.readRaster(0, null);

//Create a new RGB image
BufferedImage bi = new BufferedImage(raster.getWidth(), raster.getHeight(),
BufferedImage.TYPE_4BYTE_ABGR);

//Fill the new image with the old raster
bi.getRaster().setRect(raster);

UPDATE - March 2015 - Adding simulation images

Original images were removed from OP's dropbox. So I'm adding new images (not the originals) that simulates the problem that was happening with them.

First image is how a normal RGB image looks like.

Image RGB

Second image is how the same image will look like in CMYK color model.

You cannot actually see how it looks on the web because it will be converted to RGB by the host. To see exactly how it looks, take the RGB image and run it through an RGB to CMYK converter.

Third image is how the CMYK image will look like when read then written using Java ImageIO.

Image CMYK read through Java RGB

The problem that was happening with OP is they had something like image 2 which throws an exception when you try to read it.

ImageIO.read is sporadically reading an image file

From extra information in the comments, we have discovered that the application is running in a Glassfish server, and that there are two ImageIO plugins installed, both capable of reading DICOM images. The problem is not really related to reading, but sometimes writing the decoded image to JPEG fails.

The service providers for mentioned plugins are org.dcm4cheri.imageio.plugins.DcmImageReaderSpi and
org.dcm4che2.imageioimpl.plugins.dcm.DicomImageReaderSpi, but only the latter (DicomImageReaderSpi) seems to work. This is because it produces an 8 bits per sample BufferedImage, which is what the JPEGImageWriter is able to write (the DcmImageReaderSpi creates a 16 bit per sample image, which can't be written as a JFIF JPEG and thus unsupported by the JPEGImageWriter).

Because of the (by default) unspecified (read: unpredictable) order of ImageIO plugins, the result is that sometimes you get the 8 bps version and sometimes the 16 bit version of the image, and the end result is that sometimes the conversion won't work.


Now, the good news is that we can set an explicit order of ImageIO plugins, or we can unregister plugins at runtime, to get a stable predictable result. What is the better of these options, depends on wether there are other code on your server that depends on the undesired plugin or not. If you don't need it, unregister it.

The code below shows both of the above options:

// Get the global registry
IIORegistry registry = IIORegistry.getDefaultInstance();

// Lookup the known providers
ImageReaderSpi goodProvider = lookupProviderByName(registry, "org.dcm4che2.imageioimpl.plugins.dcm.DicomImageReaderSpi");
ImageReaderSpi badProvider = lookupProviderByName(registry, "org.dcm4cheri.imageio.plugins.DcmImageReaderSpi");

if (goodProvider != null && badProvider != null) {
// If both are found, EITHER
// order the good provider BEFORE the bad one
registry.setOrdering(ImageReaderSpi.class, goodProvider, badProvider);

// OR
// un-register the bad provider
registry.deregisterServiceProvider(badProvider);
}

// New and improved (shorter) version. :-)
private static <T> T lookupProviderByName(final ServiceRegistry registry, final String providerClassName) {
try {
return (T) registry.getServiceProviderByClass(Class.forName(providerClassName));
}
catch (ClassNotFoundException ignore) {
return null;
}
}

You should also make sure you run this code only once, for a container-based application, a good time is at application context start-up.

With the above solution, ImageIO.read(...) will always use the good plugin, and ImageIO.write(...) will work as expected.

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

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.

How to Read JPEG image into BufferedImage object using Java

This is apparently a know bug, I saw several suggestions (this is one) that suggest using Toolkit#createImage instead, which apparently ignores the color model.

I tested this and it seems to work fine.

public class TestImageIO01 {

public static void main(String[] args) {
try {
Image in = Toolkit.getDefaultToolkit().createImage("C:\\hold\\test\\13652375852388.jpg");

JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(in)), "Yeah", JOptionPane.INFORMATION_MESSAGE);

BufferedImage out = new BufferedImage(in.getWidth(null), in.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = out.createGraphics();
g2d.drawImage(in, 0, 0, null);
g2d.dispose();

ImageIO.write(out, "jpg", new File("C:\\hold\\test\\Test01.jpg"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

nb- I used the JOptionPane to verify the incoming image. When using ImageIO it comes in with the red tinge, with Toolkit it looks fine.

Updated

And an explantation

Why does reading and writing a JPEG with Java ImageIO reduce the file size?

That code isn't just copying (reading and saving) files. It's decoding the images, and then re-encoding them at the default JPEG compression rate (which, judging by the JPEGImageWriteParam documentation, is 0.75).

If you want to change the compression level, check out this question.

If you're trying to copy the files exactly, don't use ImageIO at all.

Problem using ImageIO.read

Ok since I switched laptops, I looked at my old laptop and found this JAR jai-imageio.jar in the jre/ext/lib (I know bad idea). I moved it to my project/lib and it worked!
I guess this jai-imageio.jar contains additional image readers.

How do you open local project images with ImageIO.read()?

after this interesting discussion , we found that the image file was corrupted and that is why it was not reading (parsing) it to BufferedImage properly



Related Topics



Leave a reply



Submit