Java 无法使用ImageIO.read(文件)读取JPEG图像
我在使用ImageIO.read(文件文件)读取这个JPEG文件时遇到问题-它抛出一个异常消息“不支持的图像类型” 我尝试过其他JPEG图像,它们似乎工作正常 我所能发现的唯一不同之处是,该文件似乎包含一个缩略图,这会导致ImageIO.read()出现问题吗 编辑: 添加了生成的图像: 您的图像“颜色模型”是CMYK,Java 无法使用ImageIO.read(文件)读取JPEG图像,java,image,jpeg,javax.imageio,Java,Image,Jpeg,Javax.imageio,我在使用ImageIO.read(文件文件)读取这个JPEG文件时遇到问题-它抛出一个异常消息“不支持的图像类型” 我尝试过其他JPEG图像,它们似乎工作正常 我所能发现的唯一不同之处是,该文件似乎包含一个缩略图,这会导致ImageIO.read()出现问题吗 编辑: 添加了生成的图像: 您的图像“颜色模型”是CMYK,JPEGImageReader(读取文件的内部类)只读取RGB颜色模型 如果您坚持阅读CMYK图像,那么您将需要转换它们,请尝试以下代码 更新 将CMYK图像读入RGB Buf
JPEGImageReader
(读取文件的内部类)只读取RGB颜色模型
如果您坚持阅读CMYK图像,那么您将需要转换它们,请尝试以下代码
更新
将CMYK图像读入RGB BuffereImage
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的dropbox中删除。因此,我正在添加新的图像(而不是原始图像),以模拟正在发生的问题
第一张图像是正常RGB图像的样子
第二张图像是同一张图像在CMYK颜色模型中的外观
您实际上无法看到它在web上的外观,因为它将由主机转换为RGB。要查看它的外观,请获取RGB图像并通过RGB到CMYK转换器运行它
第三个图像是使用Java ImageIO读写CMYK图像时的样子
OP出现的问题是,它们有一个类似于图2的东西,当你试图阅读它时,它会抛出一个异常。我在这里也发现了,这一个做了很好的颜色转换
并将两者结合起来得到:
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;
}
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();
我参加聚会有点晚了。但也许我还是值得发布我的答案,因为没有一个答案能真正解决问题 该解决方案需要Sanselan(或者现在称之为Apache Commons Imaging),并且需要合理的CMYK颜色配置文件(.icc文件)。您可以从Adobe或eci.org获得更高版本 基本的问题是Java——开箱即用——只能读取RGB格式的JPEG文件。如果您有CMYK文件,则需要区分常规CMYK、Adobe CMYK(具有反转值,即255表示无墨水,0表示最大墨水)和Adobe CYYK(一些具有反转颜色的变体)
公共类JPEG阅读器{
公共静态最终整数颜色类型RGB=1;
公共静态最终整数颜色\u类型\u CMYK=2;
公共静态最终整数颜色\u类型\u YCCK=3;
private int colorType=COLOR\u TYPE\u RGB;
私有布尔hasAdobeMarker=false;
公共缓冲区映像读取映像(文件文件)引发IOException,ImageReadException{
颜色类型=颜色类型RGB;
hasAdobeMarker=false;
ImageInputStream=ImageIO.createImageInputStream(文件);
迭代器iter=ImageIO.getImageReaders(流);
while(iter.hasNext()){
ImageReader=iter.next();
reader.setInput(流);
缓冲图像;
ICC_Profile=null;
试一试{
image=reader.read(0);
}捕获(IIOException e){
colorType=颜色\u类型\u CMYK;
选中标记(文件);
profile=Sanselan.getICCProfile(文件);
WritableRaster raster=(WritableRaster)reader.readRaster(0,null);
if(colorType==COLOR\u TYPE\u YCCK)
convertYcckToCmyk(光栅);
if(hasAdobeMarker)
转换颜色(光栅);
图像=转换器CMYKTORGB(光栅、轮廓);
}
返回图像;
}
返回null;
}
public void checkAdobeMarker(文件文件)引发IOException、ImageReadException{
JpegImageParser=新的JpegImageParser();
ByteSource ByteSource=新的ByteSourceFile(文件);
@抑制警告(“原始类型”)
ArrayList segments=parser.readSegments(byteSource,new int[]{0xffee},true);
if(segments!=null&&segments.size()>=1){
UnknownSegment app14Segment=(UnknownSegment)segments.get(0);
字节[]数据=app14Segment.bytes;
如果(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;
如果(转换==2)
颜色类型=颜色类型;
}
}
}
公共静态void convertYcckToCmyk(可写光栅){
int height=graster.getHeight();
int width=graster.getWidth();
int步长=宽度*4;
int[]像素行=新int[步幅];
对于(int h=0;h255)c=255;
如果(m<0)m=0;否则如果(m>255)m=255;
如果(y<0)y=0;否则如果(y>255)y=255;
像素行[x]=255-c;
像素行[x+1]=255-m;
像素行[x+2]=255-y;
}
设置像素(0,h,宽度,1,像素行);
}
}
公共静态void convertdocolors(可写光栅){
int height=graster.getHeight();
int width=graster.getWidth();
int步长=宽度*4;
int[]像素行=新int[步幅];
为了
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;
}
}
File cmykJPEGFile = new File(/*path*/);
BufferedImage image = ImageIO.read(cmykJPEGFile);
ImageIO.read(new URL("http://img3.tianyancha.com/api/9b80a61183787909e719c77fd0f78103.png"))