I'm having problems reading this one JPEG file using ImageIO.read(File file) - it throws an exception with the message "Unsupported Image Type".
我在使用ImageIO.read(文件文件)读取这个JPEG文件时遇到问题 - 它会抛出一条带有“Unsupported Image Type”消息的异常。
I have tried other JPEG images, and they seem to work fine.
我尝试过其他JPEG图像,它们似乎工作正常。
The only differance I've been able to spot is that this file seems to include a thumbnail - is that known to cause problems with ImageIO.read()?
我能够发现的唯一区别是这个文件似乎包含一个缩略图 - 已知会导致ImageIO.read()出现问题吗?
EDIT:
编辑:
Added the resulting image:
添加了生成的图像:
6 个解决方案
#1
35
Your image "Color Model" is CMYK, JPEGImageReader
(the inner class that reads your file) reads only RGB Color Model.
您的图像“颜色模型”是CMYK,JPEGImageReader(读取文件的内部类)只读取RGB颜色模型。
If you insist on reading CMYK images, then you will need to convert them, try this code.
如果您坚持阅读CMYK图像,那么您需要转换它们,尝试此代码。
UPDATE
UPDATE
Read a CMYK image into RGB BufferedImage.
将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);
UPDATE - March 2015 - Adding simulation images
更新 - 2015年3月 - 添加模拟图像
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.
原始图像已从OP的保管箱中删除。所以我正在添加模拟他们正在发生的问题的新图像(不是原始图像)。
First image is how a normal RGB image looks like.
第一张图像是普通RGB图像的样子。
Second image is how the same image will look like in CMYK color model.
第二个图像是CMYK颜色模型中相同图像的外观。
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.
您实际上无法看到它在Web上的外观,因为它将由主机转换为RGB。要准确了解它的外观,请拍摄RGB图像并通过RGB到CMYK转换器运行它。
Third image is how the CMYK image will look like when read then written using Java ImageIO.
第三个图像是CMYK图像在读取然后使用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.
OP发生的问题是它们有类似于图像2的东西,当你试图读取它时会引发异常。
#2
44
Old post, but for future reference:
旧帖子,但供将来参考:
Inspired by this question and links found here, I've written a JPEGImageReader plugin for ImageIO that supports CMYK color models (both with original color model, or implicitly converted to RGB on read). The reader also does proper color conversion, using the ICC profile embedded in the JPEG stream, in contrast to other solutions mentioned here.
受此问题和链接的启发,我为ImageIO编写了一个支持CMYK颜色模型的JPEGImageReader插件(两者都带有原始颜色模型,或者在读取时隐式转换为RGB)。与此处提到的其他解决方案相比,阅读器还使用嵌入在JPEG流中的ICC配置文件进行正确的颜色转换。
It's plain Java and does not require JAI. The source code and binary distributions are freely available at github.com/haraldk/TwelveMonkeys, and is covered by a BSD-style license.
它是普通的Java,不需要JAI。源代码和二进制发行版可在github.com/haraldk/TwelveMonkeys免费获得,并由BSD风格的许可证涵盖。
Once you have it installed, it allows you to read CMYK JPEGs using ImageIO.read(...)
like this:
一旦安装它,它允许您使用ImageIO.read(...)读取CMYK JPEGs,如下所示:
File cmykJPEGFile = new File(/*path*/);
BufferedImage image = ImageIO.read(cmykJPEGFile);
I.e.: In most cases, it's not necessary to modify your code.
即:在大多数情况下,没有必要修改您的代码。
#3
18
I'm a bit late to the party. But it's probably still worth that I post my answer as none of the answers really solves the problem.
我参加聚会有点晚了。但是我发布答案可能还是值得的,因为没有一个答案可以解决问题。
The solution requires Sanselan (or Apache Commons Imaging as it's called now) and it requires a reasonable CMYK color profile (.icc file). You can get the later one from Adobe or from eci.org.
该解决方案需要Sanselan(或现在称为Apache Commons Imaging),它需要合理的CMYK颜色配置文件(.icc文件)。您可以从Adobe或eci.org获取后者。
The basic problem is that Java - out of the box - can only read JPEG files in RGB. If you have a CMYK file, you need to distinguish between regular CMYK, Adobe CMYK (with inverted values, i.e. 255 for no ink and 0 for maximum ink) and Adobe CYYK (some variant with inverted colors as well).
基本问题是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;
}
}
The code first tries to read the file using the regular method, which works for RGB files. If it fails, it reads the details of the color model (profile, Adobe marker, Adobe variant). Then it reads the raw pixel data (raster) and does all the necessary conversion (YCCK to CMYK, inverted colors, CMYK to RGB).
代码首先尝试使用常规方法读取文件,该方法适用于RGB文件。如果失败,则会读取颜色模型的详细信息(配置文件,Adobe标记,Adobe变体)。然后它读取原始像素数据(光栅)并进行所有必要的转换(YCCK到CMYK,反转颜色,CMYK到RGB)。
I'm not quite satisfied with my solution. While the colors are mostly good, dark areas are slightly too bright, in particular black isn't fully black. If anyone knows what I could improve, I'd be glad to hear it.
我对我的解决方案不太满意。虽然颜色大多是好的,但是暗区域略微太亮,特别是黑色不是完全黑色。如果有人知道我可以改进什么,我会很高兴听到它。
#4
6
ImageIO.read()
->
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();
#5
5
I found https://*.com/questions/22409... on here as well, this one does a great colour conversion
我在这里找到了https://*.com/questions/22409 ......这个版本做了很棒的色彩转换
And combined both to get this:
并结合两者来得到这个:
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;
}
#6
0
i fix it by this. only need add this dependency. i can read CMYK image by ImageIO. TwelveMonkeys
我解决这个问题。只需添加此依赖项。我可以通过ImageIO读取CMYK图像。 TwelveMonkeys
ImageIO.read(new URL("http://img3.tianyancha.com/api/9b80a61183787909e719c77fd0f78103.png"))
#1
35
Your image "Color Model" is CMYK, JPEGImageReader
(the inner class that reads your file) reads only RGB Color Model.
您的图像“颜色模型”是CMYK,JPEGImageReader(读取文件的内部类)只读取RGB颜色模型。
If you insist on reading CMYK images, then you will need to convert them, try this code.
如果您坚持阅读CMYK图像,那么您需要转换它们,尝试此代码。
UPDATE
UPDATE
Read a CMYK image into RGB BufferedImage.
将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);
UPDATE - March 2015 - Adding simulation images
更新 - 2015年3月 - 添加模拟图像
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.
原始图像已从OP的保管箱中删除。所以我正在添加模拟他们正在发生的问题的新图像(不是原始图像)。
First image is how a normal RGB image looks like.
第一张图像是普通RGB图像的样子。
Second image is how the same image will look like in CMYK color model.
第二个图像是CMYK颜色模型中相同图像的外观。
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.
您实际上无法看到它在Web上的外观,因为它将由主机转换为RGB。要准确了解它的外观,请拍摄RGB图像并通过RGB到CMYK转换器运行它。
Third image is how the CMYK image will look like when read then written using Java ImageIO.
第三个图像是CMYK图像在读取然后使用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.
OP发生的问题是它们有类似于图像2的东西,当你试图读取它时会引发异常。
#2
44
Old post, but for future reference:
旧帖子,但供将来参考:
Inspired by this question and links found here, I've written a JPEGImageReader plugin for ImageIO that supports CMYK color models (both with original color model, or implicitly converted to RGB on read). The reader also does proper color conversion, using the ICC profile embedded in the JPEG stream, in contrast to other solutions mentioned here.
受此问题和链接的启发,我为ImageIO编写了一个支持CMYK颜色模型的JPEGImageReader插件(两者都带有原始颜色模型,或者在读取时隐式转换为RGB)。与此处提到的其他解决方案相比,阅读器还使用嵌入在JPEG流中的ICC配置文件进行正确的颜色转换。
It's plain Java and does not require JAI. The source code and binary distributions are freely available at github.com/haraldk/TwelveMonkeys, and is covered by a BSD-style license.
它是普通的Java,不需要JAI。源代码和二进制发行版可在github.com/haraldk/TwelveMonkeys免费获得,并由BSD风格的许可证涵盖。
Once you have it installed, it allows you to read CMYK JPEGs using ImageIO.read(...)
like this:
一旦安装它,它允许您使用ImageIO.read(...)读取CMYK JPEGs,如下所示:
File cmykJPEGFile = new File(/*path*/);
BufferedImage image = ImageIO.read(cmykJPEGFile);
I.e.: In most cases, it's not necessary to modify your code.
即:在大多数情况下,没有必要修改您的代码。
#3
18
I'm a bit late to the party. But it's probably still worth that I post my answer as none of the answers really solves the problem.
我参加聚会有点晚了。但是我发布答案可能还是值得的,因为没有一个答案可以解决问题。
The solution requires Sanselan (or Apache Commons Imaging as it's called now) and it requires a reasonable CMYK color profile (.icc file). You can get the later one from Adobe or from eci.org.
该解决方案需要Sanselan(或现在称为Apache Commons Imaging),它需要合理的CMYK颜色配置文件(.icc文件)。您可以从Adobe或eci.org获取后者。
The basic problem is that Java - out of the box - can only read JPEG files in RGB. If you have a CMYK file, you need to distinguish between regular CMYK, Adobe CMYK (with inverted values, i.e. 255 for no ink and 0 for maximum ink) and Adobe CYYK (some variant with inverted colors as well).
基本问题是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;
}
}
The code first tries to read the file using the regular method, which works for RGB files. If it fails, it reads the details of the color model (profile, Adobe marker, Adobe variant). Then it reads the raw pixel data (raster) and does all the necessary conversion (YCCK to CMYK, inverted colors, CMYK to RGB).
代码首先尝试使用常规方法读取文件,该方法适用于RGB文件。如果失败,则会读取颜色模型的详细信息(配置文件,Adobe标记,Adobe变体)。然后它读取原始像素数据(光栅)并进行所有必要的转换(YCCK到CMYK,反转颜色,CMYK到RGB)。
I'm not quite satisfied with my solution. While the colors are mostly good, dark areas are slightly too bright, in particular black isn't fully black. If anyone knows what I could improve, I'd be glad to hear it.
我对我的解决方案不太满意。虽然颜色大多是好的,但是暗区域略微太亮,特别是黑色不是完全黑色。如果有人知道我可以改进什么,我会很高兴听到它。
#4
6
ImageIO.read()
->
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();
#5
5
I found https://*.com/questions/22409... on here as well, this one does a great colour conversion
我在这里找到了https://*.com/questions/22409 ......这个版本做了很棒的色彩转换
And combined both to get this:
并结合两者来得到这个:
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;
}
#6
0
i fix it by this. only need add this dependency. i can read CMYK image by ImageIO. TwelveMonkeys
我解决这个问题。只需添加此依赖项。我可以通过ImageIO读取CMYK图像。 TwelveMonkeys
ImageIO.read(new URL("http://img3.tianyancha.com/api/9b80a61183787909e719c77fd0f78103.png"))