一、问题代码
BufferedImage bi = ImageIO.read(inputStream);
二、异常信息
javax.imageio.IIOException: Unsupported Image Type
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1068)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1039)
at javax.imageio.ImageIO.read(ImageIO.java:1448)
at javax.imageio.ImageIO.read(ImageIO.java:1352)
三、分析问题原因
Adobe Photoshop (PS)或其他软件处理过的图片保存为jpg格式时,默认是CMYK或者(YCCK)模式。
四、了解色彩空间
RGB色彩
自然界中绝大部分的可见光谱可以用红、绿和蓝三色光按不同比例和强度的混合来表示。RGB分别代表着3种颜色:R代表红色,G代表绿色、B代表蓝色。RGB模型也称为加色模型,通常用于光照、视频和屏幕图像编辑。RGB色彩模式使用RGB模型为图像中每一个像素的RGB分量分配一个0~255范围内的强度值。
CMYK色彩
CMYK色彩模式以打印油墨在纸张上的光线吸收特性为基础,图像中每个像素都是由靛青(C)、品红(M)、黄(Y)和黑(K)色按照不同的比例合成。每个像素的每种印刷油墨会被分配一个百分比值,最亮(高光)的颜色分配较低的印刷油墨颜色百分比值,较暗(暗调)的颜色分配较高的百分比值。
YCCK 色彩
在没有Adobe标记的IJG中,有4个通道,它被假定为CMYK,但在oracle中它是YCCA.此外,IJG的实现并未考虑子采样,而对于4通道子采样,它在oracle规范中是YCCK,依此类推. Oracle 官网解释 If an Adobe
APP14
marker segment is present, the colorspace is determined by consulting thetransform
flag. Thetransform
flag takes one of three values:
- 2 - The image is encoded as YCCK (implicitly converted from CMYK on encoding).
- 1 - The image is encoded as YCbCr (implicitly converted from RGB on encoding).
- 0 - Unknown. 3-channel images are assumed to be RGB, 4-channel images are assumed to be CMYK.
通俗一点我们可以认为CMYK 和 YCCK 是一样的,都是用于打印的色彩
五、解决方案
方案一、Apache Imaging 工具库(推荐)
1. Maven 依赖
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-imaging -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-imaging</artifactId>
<version>1.0-alpha2</version>
</dependency>
2. 简单使用
import org.apache.commons.imaging.ImageInfo;
final ImageInfo imageInfo = Imaging.getImageInfo(file);
System.out.println(imageInfo);
3. 输出信息
Format Details: Jpeg/DCM
Bits Per Pixel: 32
Comments: 0
Format: JPEG
Format Name: JPEG (Joint Photographic Experts Group) Format
Compression Algorithm: JPEG
Height: 2436
MimeType: image/jpeg
Number Of Images: 1
Physical Height Dpi: 300
Physical Height Inch: 8.12
Physical Width Dpi: 300
Physical Width Inch: 3.75
Width: 1125
Is Progressive: false
Is Transparent: false
Color Type: YCCK
Uses Palette: false
4. 获取格式和尺寸
final ImageInfo imageInfo = Imaging.getImageInfo(file);
System.out.println("格式:" + imageInfo.getFormat().getName());
System.out.println("尺寸:" + imageInfo.getWidth() + " x " + imageInfo.getHeight());
System.out.println("色彩空间:" + imageInfo.getColorType());
5. 输出格式和尺寸信息
格式:JPEG
尺寸:1125 x 2436
色彩空间:YCCK
6. 官网其他例子
https://commons.apache.org/proper/commons-imaging/sampleusage.html
方案二、使用jdk的原生方法获取尺寸
Java代码
final JPEGImageDecoder jpegDecoder = JPEGCodec.createJPEGDecoder(new FileInputStream(file));
final BufferedImage bufferedImage = jpegDecoder.decodeAsBufferedImage();
System.out.println("尺寸:" + bufferedImage.getWidth() + " x " + bufferedImage.getHeight());
注意:这里返回的 BufferedImage 不能直接使用,因为色彩失真了。 注意:createJPEGDecoder 的输入流之前不要使用 ImageIO.read 操作,不然会报
输出结果
尺寸:1125 x 2436
参考资料
https://stackoverflow.com/questions/7177655/java-imageio-iioexception-unsupported-image-type https://blog.csdn.net/WuZuoDingFeng/article/details/77946489 https://qa.1r1g.com/sf/ask/3555861011/ https://commons.apache.org/proper/commons-imaging/sampleusage.html https://stackoverflow.com/questions/6829428/pure-java-alternative-to-jai-imageio-for-detecting-cmyk-images
注意:本文归作者所有,未经作者允许,不得转载