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.
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.
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
How Apply CSS on a <H:Inputtext>
Unobtrusive Way to Combine and Compress JavaScript/CSS for Java/Spring/Maven Applications
Add Custom CSS to HTML Code with Jsoup
How to Clear the (Css) Visited History of an Android Webview
How to Implement "CSS Versioning" (To Solve Cache Issues) Using Jsf 2 H:Outputstylesheet
Different War Files, Shared Resources
Selenium Webdriver - Getcssvalue() Method
How to Use CSS for Vaadin Components
Javafx CSS Error ( Property Stylesheets Does Not Exist )
Dynamically Add CSS Stylesheets in Javafx
"Loadstylesheetunprivileged" Error When Trying to Use CSS Stylesheet with Javafx
Javafx - How to Create a Thin Menubar
How to Set -Fx-Max-Width to Use_Pref_Size in Javafx CSS
Find Out If Class Name Contains Certain Text
Javafx - What Is This Weird Container That Holds Context Menu
How to Get the Selected Index of a Radiogroup in Android
Is It Really Impossible to Protect Android Apps from Reverse Engineering