使用Java添加Tiff图像颜色配置文件(sRGB或Adobe 1998)

使用Java添加Tiff图像颜色配置文件(sRGB或Adobe 1998),java,color-profile,twelvemonkeys,Java,Color Profile,Twelvemonkeys,我在网上到处搜索,找不到一个解决方案来解决如何用Java将sRGB或Abobe(1998)颜色配置文件添加到Tiff图像中的问题。JPG和PNG有一些例子,但它们不适用于TIFF。我一直在尝试使用Commons Imaging和java.awt来实现这一点,但没有任何运气。可能吗 谢谢 更新: 我在使用TwelveMonkeys imageio tiff库和以下代码方面取得了一些进展: File file = new File("/Users/user/Desktop/demo/sandal.t

我在网上到处搜索,找不到一个解决方案来解决如何用Java将sRGB或Abobe(1998)颜色配置文件添加到Tiff图像中的问题。JPG和PNG有一些例子,但它们不适用于TIFF。我一直在尝试使用Commons Imaging和java.awt来实现这一点,但没有任何运气。可能吗

谢谢

更新:

我在使用TwelveMonkeys imageio tiff库和以下代码方面取得了一些进展:

File file = new File("/Users/user/Desktop/demo/sandal.tif");
BufferedImage image = ImageIO.read(file);

ICC_Profile ip = ICC_Profile.getInstance("/Users/user/Documents/icc/AdobeRGB1998.icc");
ICC_ColorSpace ics = new ICC_ColorSpace( ip );
ColorConvertOp cco = new ColorConvertOp( ics, null );
BufferedImage result = cco.filter(image, null);

ImageIO.write(result, "TIFF", new File("/Users/user/Desktop/demo/sandal2.tif"));

应用颜色配置文件,但tiff被展平,alpha被删除。如何保存alpha通道?

如评论中所述,您的代码应该已经运行,除非您的AdobeRGB1998 ICC配置文件有特殊之处

下面的代码适用于我,将图像从sRGB转换为AdobeRGB1998配置文件。生成的TIFF文件具有正确的ICC配置文件,并且包含完整的alpha通道(
258/BitsPerSample:[8,8,8,8],277/SamplesPerPixels:434675/ICCProfile:[…]
)。我能看到的唯一小问题是压缩从LZW更改为无压缩,DPI从300更改为72(+XMP元数据丢失)

如您所见,这里唯一的真正区别是如何获得ICC配置文件/颜色空间

如果您想保留元数据和/或控制压缩,这也是可能的。下面的代码基本相同(但保留了LZW压缩和300dpi),不幸的是它有点冗长:

try (ImageInputStream input = ImageIO.createImageInputStream(new File("C:\\Downloads\\sandal.tif"))) {
    ImageReader reader = ImageIO.getImageReaders(input).next();
    reader.setInput(input);
    IIOImage imageAndMeta = reader.readAll(0, reader.getDefaultReadParam());
    reader.dispose();

    ICC_ColorSpace ics = (ICC_ColorSpace) ColorSpaces.getColorSpace(ColorSpaces.CS_ADOBE_RGB_1998);
    ColorConvertOp cco = new ColorConvertOp(ics, null);
    BufferedImage result = cco.filter((BufferedImage) imageAndMeta.getRenderedImage(), null);

    imageAndMeta.setRenderedImage(result);

    File tempFile = File.createTempFile("test-", ".tif");
    System.err.println("tempFile: " + tempFile);

    ImageWriter tiffWriter = ImageIO.getImageWritersByFormatName("TIFF").next();
    try (ImageOutputStream stream = ImageIO.createImageOutputStream(tempFile)) {
        tiffWriter.setOutput(stream);

        ImageWriteParam writeParam = tiffWriter.getDefaultWriteParam();

        // If you want a specific compression, uncommment these lines
        // The default setting is to copy from metadata
//        writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        // Allowed compression type values are: 
        // "None", "CCITT RLE", "CCITT T.4", "CCITT T.6","LZW", "JPEG", "ZLib", "PackBits" and "Deflate"
//        writeParam.setCompressionType("PackBits");

        tiffWriter.write(null, imageAndMeta, writeParam);
    }

    tiffWriter.dispose();
}
(出于某种原因,XMP元数据仍然从输出中剥离,我认为这是一个bug)


写入程序目前不支持平铺,但将来可能会由
writeParam
控制平铺(使用标准API)。您的原始图像没有平铺,因此我想这不太重要。

如评论中所述,您的代码应该已经运行,除非您的AdobeRGB1998 ICC配置文件有什么特别之处

下面的代码适用于我,将图像从sRGB转换为AdobeRGB1998配置文件。生成的TIFF文件具有正确的ICC配置文件,并且包含完整的alpha通道(
258/BitsPerSample:[8,8,8,8],277/SamplesPerPixels:434675/ICCProfile:[…]
)。我能看到的唯一小问题是压缩从LZW更改为无压缩,DPI从300更改为72(+XMP元数据丢失)

如您所见,这里唯一的真正区别是如何获得ICC配置文件/颜色空间

如果您想保留元数据和/或控制压缩,这也是可能的。下面的代码基本相同(但保留了LZW压缩和300dpi),不幸的是它有点冗长:

try (ImageInputStream input = ImageIO.createImageInputStream(new File("C:\\Downloads\\sandal.tif"))) {
    ImageReader reader = ImageIO.getImageReaders(input).next();
    reader.setInput(input);
    IIOImage imageAndMeta = reader.readAll(0, reader.getDefaultReadParam());
    reader.dispose();

    ICC_ColorSpace ics = (ICC_ColorSpace) ColorSpaces.getColorSpace(ColorSpaces.CS_ADOBE_RGB_1998);
    ColorConvertOp cco = new ColorConvertOp(ics, null);
    BufferedImage result = cco.filter((BufferedImage) imageAndMeta.getRenderedImage(), null);

    imageAndMeta.setRenderedImage(result);

    File tempFile = File.createTempFile("test-", ".tif");
    System.err.println("tempFile: " + tempFile);

    ImageWriter tiffWriter = ImageIO.getImageWritersByFormatName("TIFF").next();
    try (ImageOutputStream stream = ImageIO.createImageOutputStream(tempFile)) {
        tiffWriter.setOutput(stream);

        ImageWriteParam writeParam = tiffWriter.getDefaultWriteParam();

        // If you want a specific compression, uncommment these lines
        // The default setting is to copy from metadata
//        writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        // Allowed compression type values are: 
        // "None", "CCITT RLE", "CCITT T.4", "CCITT T.6","LZW", "JPEG", "ZLib", "PackBits" and "Deflate"
//        writeParam.setCompressionType("PackBits");

        tiffWriter.write(null, imageAndMeta, writeParam);
    }

    tiffWriter.dispose();
}
(出于某种原因,XMP元数据仍然从输出中剥离,我认为这是一个bug)


写入程序目前不支持平铺,但将来可能会由
writeParam
控制平铺(使用标准API)。您的原始图像没有平铺,因此我想这不太重要。

可能是我尝试过的图像的副本,但它不起作用。可能是因为它不完整或不适用于TIFF。@jonD02目前,TwelveMonkeys
TIFFImageWriter
将编写正在使用的ICC配置文件,除非该配置文件是sRGB配置文件(如
ColorSpace.isCS_sRGB()
)。这假设默认TIFF颜色空间为sRGB,这可能不是正确的假设。但它应该适用于AdobeRGB1998。您可以从示例代码链接
sanda.tif
文件吗?如果是这样的话,我将尝试重现这个问题并提出一个解决方案。PS:只是尝试了你的代码(稍作修改,因为我显然没有你的文件),我得到了一个很好的TIFF文件,保留了alpha并嵌入了ICC配置文件。在Windows上使用bot Java 1.8,在macOS上使用Java 1.7,最新的TwelveMonkeys由master构建。已在ColorSync实用程序中验证。@haraldK感谢您的回复!我很喜欢你的图书馆。我不确定如何使用TiffImageWriter,你能提供一个演示吗?这里有一个指向该文件的链接:可能是我尝试过的文件的副本,但它不起作用。可能是因为它不完整或不适用于TIFF。@jonD02目前,TwelveMonkeys
TIFFImageWriter
将编写正在使用的ICC配置文件,除非该配置文件是sRGB配置文件(如
ColorSpace.isCS_sRGB()
)。这假设默认TIFF颜色空间为sRGB,这可能不是正确的假设。但它应该适用于AdobeRGB1998。您可以从示例代码链接
sanda.tif
文件吗?如果是这样的话,我将尝试重现这个问题并提出一个解决方案。PS:只是尝试了你的代码(稍作修改,因为我显然没有你的文件),我得到了一个很好的TIFF文件,保留了alpha并嵌入了ICC配置文件。在Windows上使用bot Java 1.8,在macOS上使用Java 1.7,最新的TwelveMonkeys由master构建。已在ColorSync实用程序中验证。@haraldK感谢您的回复!我很喜欢你的图书馆。我不确定如何使用TiffImageWriter,你能提供一个演示吗?这里有一个文件链接:谢谢!这适用于颜色配置文件,但它会给我的应用程序的另一部分带来问题。TIF随后用于创建PNG,使用以下代码:'File File=new File(TIFFILE);BuffereImage image=ImageIO.read(文件);BuffereImage resizeImagePng=resizeImage(image,buffereImage.TYPE_INT_ARGB,image.getWidth()/4,image.getHeight()/4);write(resizeImagePng,“PNG”,新文件(pngFile));私有静态BuffereImage resizeImage(BuffereImage originalImage,int type,int IMG_WIDTH,int IMG_HEIGHT){BuffereImage resizedImage=new BuffereImage(IMG_WIDTH,IMG_HEIGHT,type);Graphics2D g=resizedImage.createGraphics();g.drawImage(originalImage,0,0,IMG_WIDTH,IMG_HEIGHT,null);g.dispose();return resizedImage;使用带有颜色配置文件的tif生成的png文件:这不会