1

I searched the web high and low and I can't find a solution for how to add a sRGB or Abobe (1998) color profile to a Tiff Image with Java. There's some examples out there for jpgs and pngs, but they don't apply to tiffs. I have been trying to do it with Commons Imaging and java.awt but not having any luck. Is it possible?

Thanks

Update:

I've made some progress using the TwelveMonkeys imageio-tiff library and the following code:

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"));

The color profile is applied, but the tiff is flattened and the alpha removed. How can the alpha channel be preserved?

jonD02
  • 125
  • 1
  • 11
  • Possible duplicate of [How to set icc color profile in Java and change colorspace](http://stackoverflow.com/questions/380678/how-to-set-icc-color-profile-in-java-and-change-colorspace) – Erwin Bolwidt Oct 01 '16 at 03:24
  • I tried that and it didn't work. Either because it's incomplete or it doesn't work with Tiffs. – jonD02 Oct 01 '16 at 04:05
  • @jonD02 Currently the TwelveMonkeys `TIFFImageWriter` will write the ICC profile in use, unless the profile is the sRGB profile (as in `ColorSpace.isCS_sRGB()`). This assumes that the default TIFF color space is sRGB, which may not be a correct assumption. But it should work for AdobeRGB1998. Can you link the `sandal.tif` file from your sample code? If so, I'll try to reproduce the issue and come up with a solution. – Harald K Oct 03 '16 at 07:46
  • PS: Just tried your code (with some slight modifications, as I don't have your files, obviously), and I get a nice TIFF file with alpha preserved and ICC profile embedded. Using bot Java 1.8 on Windows and Java 1.7 on macOS, latest TwelveMonkeys built from master. Verified in ColorSync Utility. – Harald K Oct 05 '16 at 12:51
  • @haraldK Thank you for the response! I've enjoyed your library. I'm unsure how to use the TiffImageWriter, could you provide a demo? Here's a link to the file: https://drive.google.com/file/d/0B8FrShLAYpOEX25vU2NKM2xfNTA/view?usp=sharing – jonD02 Oct 09 '16 at 23:56

1 Answers1

0

As mentioned in the comments, the code you have should have worked, unless there's something special about your AdobeRGB1998 ICC profile...

The below code works for me, converting the image from sRGB to the AdobeRGB1998 profile. The resulting TIFF file has the correct ICC profile and contains the alpha channel intact (258/BitsPerSample: [8, 8, 8, 8], 277/SamplesPerPixels: 4, 34675/ICCProfile: [...]). The only minor issues I can see, is that the compression is changed from LZW to no compression, and DPI is changed from 300 to 72 (+ XMP metadata is lost).

BufferedImage image = ImageIO.read(new File("C:\\Downloads\\sandal.tif"));

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

File tempFile = File.createTempFile("test-", ".tif");
System.out.println("tempFile: " + tempFile); // Just to know where to look
ImageIO.write(result, "TIFF", tempFile);

As you can see, the only real difference here is how the ICC profile/color space is obtained.

If you want to preserve the meta data and/or control compression, that is possible too. The below code does basically the same (but preserves the LZW compression and 300dpi), unfortunately it's a bit more verbose:

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

(for some reason the XMP metadata is still stripped from the output, I believe that is a bug).

Tiling is currently not supported by the writer, but it may be controlled by the writeParam in the future (using the standard API to do so). Your original image isn't tiled, so I guess that is less of a concern.

Harald K
  • 26,314
  • 7
  • 65
  • 111
  • thanks! That works for the color profile, but it is creating an issue with another part of my app. The TIF is later used to create a PNG, using the following code: – jonD02 Oct 21 '16 at 18:52
  • 'File file = new File(tiffFile); BufferedImage image = ImageIO.read(file); BufferedImage resizeImagePng = resizeImage(image, BufferedImage.TYPE_INT_ARGB, image.getWidth() / 4, image.getHeight() / 4); ImageIO.write(resizeImagePng, "PNG", new File(pngFile)); private static BufferedImage resizeImage(BufferedImage originalImage, int type, int IMG_WIDTH, int IMG_HEIGHT) { BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type); Graphics2D g = resizedImage.createGraphics(); g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null); g.dispose(); return resizedImage; – jonD02 Oct 21 '16 at 18:57
  • The resulting png file using the tif with a color profile: https://drive.google.com/open?id=0B8FrShLAYpOEcDllb3BUYTNfTlE This doesn't happen when I update the Tif the same way in Photoshop: https://drive.google.com/open?id=0B8FrShLAYpOEUjNLQVBCVVJCQjA – jonD02 Oct 21 '16 at 19:05
  • I suggest you ask a new question for this, as aking in comments is only for clearification of the current question/answer. :-) I'll still try to help! – Harald K Oct 22 '16 at 13:27