无法使用ImageIO.read(文件文件)读取JPEG图像

我在使用ImageIO.read(File file)读取这一个JPEG文件时遇到了问题 – 它会通过消息“Unsupported Image Type”引发exception。

我试过其他的JPEG图像,他们似乎工作正常。

唯一的区别,我已经能够发现的是,这个文件似乎包括一个缩略图 – 是已知会导致ImageIO.read()的问题?

麻烦的形象

编辑:

添加结果图像:

奇怪的颜色

您的图像“Color Model”是CMYK, JPEGImageReader (读取文件的内部类)只读取RGB Color Model。

如果你坚持阅读CMYK图像,那么你将需要转换它们,试试这个代码。

UPDATE

将CMYK图像读入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); 

更新 – 2015年3月 – 添加模拟图像

原始图像被从OP的保pipe箱中删除。 所以我添加了新的图像(不是原件),模拟了与他们发生的问题。

第一个图像是一个正常的RGB图像的样子。

图像RGB

第二个图像是如何在CMYK颜色模型中看到相同的图像。

您实际上看不到它在networking上的外观,因为它将由主机转换为RGB。 要查看它的外观,请使用RGB图像并通过RGB到CMYK转换器运行。

第三个图像是读取CMYK图像时的样子,然后使用Java ImageIO写入。

图像CMYK通过Java RGB读取

与OP发生的问题是,他们有像图像2,当你尝试读取它引发exception。

旧post,但供将来参考:

受这个问题和这里find的链接的启发,我已经为支持CMYK颜色模型的ImageIO写了一个JPEGImageReader插件(包含原始颜色模型,或者在读取时隐式转换为RGB)。 阅读器也可以使用embedded在JPEGstream中的ICCconfiguration文件进行适当的颜色转换,与此处提到的其他解决scheme相反。

这是普通的Java,不需要JAI。 源代码和二进制发行版可以在github.com/haraldk/TwelveMonkeys上免费获得,并且包含BSD样式的许可证。

一旦你安装了它,它可以让你阅读使用ImageIO.read(...) CMYK JPEG像这样:

 File cmykJPEGFile = new File(/*path*/); BufferedImage image = ImageIO.read(cmykJPEGFile); 

即:在大多数情况下,没有必要修改你的代码。

我对晚会有点晚了。 但可能仍然值得我发表我的答案,因为没有任何答案真正解决了这个问题。

解决scheme需要Sanselan(或现在称为Apache Commons Imaging),它需要合理的CMYK颜色configuration文件(.icc文件)。 你可以从Adobe或eci.org获得更新的版本。

基本的问题是,开箱即用的Java只能读取RGB中的JPEG文件。 如果您有CMYK文件,则需要区分常规CMYK,Adobe CMYK(具有反转值,即255表示没有墨水,0表示最大墨水)和Adobe CYYK(具有反转颜色的某些变体)。

 public class JpegReader { public static final int COLOR_TYPE_RGB = 1; public static final int COLOR_TYPE_CMYK = 2; public static final int COLOR_TYPE_YCCK = 3; private int colorType = COLOR_TYPE_RGB; private boolean hasAdobeMarker = false; public BufferedImage readImage(File file) throws IOException, ImageReadException { colorType = COLOR_TYPE_RGB; hasAdobeMarker = false; ImageInputStream stream = ImageIO.createImageInputStream(file); Iterator<ImageReader> iter = ImageIO.getImageReaders(stream); while (iter.hasNext()) { ImageReader reader = iter.next(); reader.setInput(stream); BufferedImage image; ICC_Profile profile = null; try { image = reader.read(0); } catch (IIOException e) { colorType = COLOR_TYPE_CMYK; checkAdobeMarker(file); profile = Sanselan.getICCProfile(file); WritableRaster raster = (WritableRaster) reader.readRaster(0, null); if (colorType == COLOR_TYPE_YCCK) convertYcckToCmyk(raster); if (hasAdobeMarker) convertInvertedColors(raster); image = convertCmykToRgb(raster, profile); } return image; } return null; } public void checkAdobeMarker(File file) throws IOException, ImageReadException { JpegImageParser parser = new JpegImageParser(); ByteSource byteSource = new ByteSourceFile(file); @SuppressWarnings("rawtypes") ArrayList segments = parser.readSegments(byteSource, new int[] { 0xffee }, true); if (segments != null && segments.size() >= 1) { UnknownSegment app14Segment = (UnknownSegment) segments.get(0); byte[] data = app14Segment.bytes; if (data.length >= 12 && data[0] == 'A' && data[1] == 'd' && data[2] == 'o' && data[3] == 'b' && data[4] == 'e') { hasAdobeMarker = true; int transform = app14Segment.bytes[11] & 0xff; if (transform == 2) colorType = COLOR_TYPE_YCCK; } } } public static void convertYcckToCmyk(WritableRaster raster) { int height = raster.getHeight(); int width = raster.getWidth(); int stride = width * 4; int[] pixelRow = new int[stride]; for (int h = 0; h < height; h++) { raster.getPixels(0, h, width, 1, pixelRow); for (int x = 0; x < stride; x += 4) { int y = pixelRow[x]; int cb = pixelRow[x + 1]; int cr = pixelRow[x + 2]; int c = (int) (y + 1.402 * cr - 178.956); int m = (int) (y - 0.34414 * cb - 0.71414 * cr + 135.95984); y = (int) (y + 1.772 * cb - 226.316); if (c < 0) c = 0; else if (c > 255) c = 255; if (m < 0) m = 0; else if (m > 255) m = 255; if (y < 0) y = 0; else if (y > 255) y = 255; pixelRow[x] = 255 - c; pixelRow[x + 1] = 255 - m; pixelRow[x + 2] = 255 - y; } raster.setPixels(0, h, width, 1, pixelRow); } } public static void convertInvertedColors(WritableRaster raster) { int height = raster.getHeight(); int width = raster.getWidth(); int stride = width * 4; int[] pixelRow = new int[stride]; for (int h = 0; h < height; h++) { raster.getPixels(0, h, width, 1, pixelRow); for (int x = 0; x < stride; x++) pixelRow[x] = 255 - pixelRow[x]; raster.setPixels(0, h, width, 1, pixelRow); } } public static BufferedImage convertCmykToRgb(Raster cmykRaster, ICC_Profile cmykProfile) throws IOException { if (cmykProfile == null) cmykProfile = ICC_Profile.getInstance(JpegReader.class.getResourceAsStream("/ISOcoated_v2_300_eci.icc")); ICC_ColorSpace cmykCS = new ICC_ColorSpace(cmykProfile); BufferedImage rgbImage = new BufferedImage(cmykRaster.getWidth(), cmykRaster.getHeight(), BufferedImage.TYPE_INT_RGB); WritableRaster rgbRaster = rgbImage.getRaster(); ColorSpace rgbCS = rgbImage.getColorModel().getColorSpace(); ColorConvertOp cmykToRgb = new ColorConvertOp(cmykCS, rgbCS, null); cmykToRgb.filter(cmykRaster, rgbRaster); return rgbImage; } } 

代码首先尝试使用常规方法读取文件,该方法适用于RGB文件。 如果失败,它会读取颜色模型(configuration文件,Adobe标记,Adobe变体)的详细信息。 然后它读取原始像素数据(光栅),并进行所有必要的转换(YCCK到CMYK,反转颜色,CMYK到RGB)。

我对我的解决scheme不太满意。 虽然颜色大多是好的,但是黑色区域稍微太亮,特别是黑色不完全黑色。 如果有人知道我能改善什么,我会很高兴听到。

ImageIO.read() – >

 File filePath = new File("C:\\Users\\chang\\Desktop\\05036877.jpg"); com.sun.image.codec.jpeg.JPEGImageDecoder jpegDecoder = JPEGCodec.createJPEGDecoder (new FileInputStream(filePath)); BufferedImage image = jpegDecoder.decodeAsBufferedImage(); 

我发现https://stackoverflow.com/questions/22409 …在这里,这一个做了一个伟大的颜色转换

并结合起来得到这个:

 private BufferedImage convertCMYK2RGB(BufferedImage image) throws IOException{ log.info("Converting a CYMK image to RGB"); //Create a new RGB image BufferedImage rgbImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR); // then do a funky color convert ColorConvertOp op = new ColorConvertOp(null); op.filter(image, rgbImage); return rgbImage; }