我在使用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