我在使用ImageIO.read(文件文件)读取这一个JPEG文件时遇到问题 - 它会通过消息“Unsupported Image Type”引发异常。无法使用ImageIO.read(文件文件)读取JPEG图像
我已经尝试过其他JPEG图像,并且它们似乎工作正常。
我已经能够发现的唯一区别是这个文件似乎包括一个缩略图 - 是否已知会导致ImageIO.read()问题?
编辑:
加入所得到的图像:
我在使用ImageIO.read(文件文件)读取这一个JPEG文件时遇到问题 - 它会通过消息“Unsupported Image Type”引发异常。无法使用ImageIO.read(文件文件)读取JPEG图像
我已经尝试过其他JPEG图像,并且它们似乎工作正常。
我已经能够发现的唯一区别是这个文件似乎包括一个缩略图 - 是否已知会导致ImageIO.read()问题?
编辑:
加入所得到的图像:
您的图片 “色彩模式” 为CMYK,JPEGImageReader
(内部类读取文件)只读取RGB颜色模型。
如果你坚持阅读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的投寄箱中删除。因此,我添加了模拟正在发生的问题的新图像(不是原件)。
第一张图像是正常的RGB图像的样子。
2图像是相同的图像将如何看起来像在CMYK色彩模式。
你实际上看不到它在网络上的外观,因为它将被主机转换为RGB。要查看它的外观,请使用RGB图像并通过RGB到CMYK转换器运行。
第三张图片是CMYK图像在读取时如何看起来像使用Java ImageIO写入时的样子。
,将其与OP发生的问题是,他们有这样的事情图像2,当您尝试阅读它会抛出异常。
我发现 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;
}
这是我发现的唯一答案,它解决了JPEG上带有几个问题的绿色色调问题。 – Phil 2016-08-08 19:12:47
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();
从API文档:请注意,com.sun.image.codec.jpeg包中的类不是核心Java API的一部分。它们是Sun JDK和JRE发行版的一部分。虽然其他许可证持有者可能选择分发这些类,但开发人员不能依赖于非Sun实施中的可用性。我们期望等效功能最终将在核心API或标准扩展中可用。 – Omertron 2012-09-17 12:41:17
我晚会有点晚了。但可能仍然值得我发布我的答案,因为没有任何答案真正解决了问题。
该解决方案需要Sanselan(或现在称为Apache Commons Imaging),它需要合理的CMYK颜色配置文件(.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文件。如果失败,它会读取颜色模型的详细信息(配置文件,Adobe标记,Adobe变体)。然后它读取原始像素数据(光栅)并进行所有必要的转换(YCCK到CMYK,反转色彩,CMYK到RGB)。
我对我的解决方案并不满意。虽然颜色大多是好的,但黑色区域稍微太亮,特别是黑色不完全黑色。如果有人知道我可以改进什么,我很乐意听到它。
这是我在此发现的最佳答案,但是您不想在finally块中关闭ImageInputStream吗? – Amalgovinus 2015-11-13 23:34:55
感谢您的代码片段,工作正常。 (ISOcoated_v2_300_eci.icc可以在这里找到:http://www.humburg.de/?page=4) – user2198875 2017-01-05 16:29:04
旧的职位,但以供将来参考:
这个问题,在这里找到的链接的启发,我写了一个ImageIO的插件JPEGImageReader支持CMYK颜色模型(均与原来的颜色模式,或隐式转换为读取RGB)。读者还可以使用嵌入JPEG流中的ICC配置文件进行适当的颜色转换,与此处提到的其他解决方案相反。
这是普通的Java,不需要JAI。源代码和二进制发行版可在github.com/haraldk/TwelveMonkeys免费获得,并且包含BSD样式的许可证。
一旦你安装了它,它可以读取使用ImageIO.read(...)
这样的CMYK JPEG文件:
File cmykJPEGFile = new File(/*path*/);
BufferedImage image = ImageIO.read(cmykJPEGFile);
即:在大多数情况下,它没有必要修改代码。
我解决了这个问题。 只需要添加此依赖关系。我可以通过ImageIO读取CMYK图像。 TwelveMonkeys
ImageIO.read(new URL("http://img3.tianyancha.com/api/9b80a61183787909e719c77fd0f78103.png"))
从异常中查看堆栈跟踪会很有用。 – simonlord 2010-03-09 11:36:44
请恢复图像! – math 2013-11-22 08:26:01