`
asdzheng
  • 浏览: 95125 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

Image读取CMYK和Tif 报错的解决办法

阅读更多
   上一篇说到,Image.read()返回空是null,引入一个包就行。后来要讲读取到的图片缩小,还是会报错。没办法只得先把它先转换成其他格式的图片才能进行缩小,处理办法,为先判断图片的真实格式,用下面类里的getRealFormatName(),如果为Tif格式,先将它转成其他可被ImageIO读取的格式covertTif就可以了。
   后来又碰到一种情况,就是读取的图片有些不是RGB颜色,而是CMYK设置的颜色,此时会报不支持此格式的错误。内容如下:
   javax.imageio.IIOException: Unsupported Image Type 
   at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(Unknown Source) 
   at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(Unknown Source)
   ....
   同样需要将图片的颜色转为RGB再作读取,这里的处理方法是,不用系统自带的ImageIO读取图片,而用下面这个类的readImage(file)方法,这个方法里会对CMYK颜色的图片做特殊处理。
   
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.Sanselan;
import org.apache.sanselan.common.byteSources.ByteSource;
import org.apache.sanselan.common.byteSources.ByteSourceFile;
import org.apache.sanselan.formats.jpeg.JpegImageParser;
import org.apache.sanselan.formats.jpeg.segments.UnknownSegment;

public class ImageTool {

    private static boolean hasAdobeMarker = false;
    private static Log log = LogFactory.getLog(ImageTool.class);
	
	/*
	 *返回图片的真实格式,此方法如果读取的图片为svg格式会返回空值
	 */
    public static String getRealFormatName(Object object) throws Exception {
        ImageInputStream iis = ImageIO.createImageInputStream(object);
        Iterator<ImageReader> iterator = ImageIO.getImageReaders(iis);
        while (iterator.hasNext()) {
            ImageReader reader = (ImageReader) iterator.next();
            return reader.getFormatName();
        }
        return null;
    }
	
	/*
	 *传图片的路径,和要将图片转成的格式
	 */
    public static void convertTif(String fileName, String extension) {
        try {
            File file = new File(fileName);
            if (file.exists() == false) {
                System.out.println("File not exist!!!");
                return;
            }
            BufferedImage image = ImageIO.read(file);
            BufferedImage convertedImage = new BufferedImage(image.getWidth(),
                    image.getHeight(), BufferedImage.TYPE_INT_RGB);
            convertedImage.createGraphics().drawRenderedImage(image, null);
            ImageIO.write(convertedImage, extension, new File(fileName));
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

	/*
	 *传进需要读取的图片,fileName是用来记录CMYK图片的名字
	 */
    public static BufferedImage readImage(File file, String fileName) throws      IOException, ImageReadException {
        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) {
                checkAdobeMarker(file);
                profile = Sanselan.getICCProfile(file);
                WritableRaster raster = (WritableRaster) reader.readRaster(0, null);
                if (hasAdobeMarker) {
                    convertInvertedColors(raster);`
                }
                image = convertCmykToRgb(raster, profile);
                log.info("The CMYK FileName ========" + fileName);
            }
            return image;
        }
        return null;
    }

    private static 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;
            }
        }
    }

    private 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);
        }
    }

    private static BufferedImage convertCmykToRgb(Raster cmykRaster, ICC_Profile cmykProfile) throws IOException {
        if (cmykProfile == null) //读取CMYK的色彩配置文件
        {
            cmykProfile = ICC_Profile.getInstance(ImageTool.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;
    }
}
    


    此类需要引入一个包和ISOcoated_v2_300_eci.icc(CMYK的位图);
   
    注:CMYK转RGB参考自stackoverflow :
http://stackoverflow.com/questions/3123574/how-to-convert-from-cmyk-to-rgb-in-java-correctly?lq=1 codo君的答案;
分享到:
评论
1 楼 yangzg216 2014-01-11  
你好,我用你的方法试了一下,色差太严重了。不知道还有没有更好一点的方法。

相关推荐

Global site tag (gtag.js) - Google Analytics