[ 
https://issues.apache.org/jira/browse/IMAGING-201?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17209933#comment-17209933
 ] 

Gary Lucas commented on IMAGING-201:
------------------------------------

In investigated this further and I have a solution based on the existing 
Commons Imaging API.  Because the example file includes an ICC color profile, 
the TIFF reading functions must use that to interpret the colors. I haven't 
studied color profiles in any depth, so there may be more efficient ways of 
handling this, but here's my solution.

The key is to read the ICC color profile from the file and then use it to 
create a custom photometric interpreter that can be used to convert the CMYK 
data from the file to RGB values used by the Java API.   In the example below, 
I use the high-level Imaging class for simplicity and clarity.  There are 
lower-level TIFF classes and methods that would give you more control and 
flexibility, but they are a bit too complicated for this example.

The sample file provided by the Praful Vaishnav is rather large, 3976-by-5965 
pixels.  Fortunately, it was still available on dropbox.  Running it through 
the TIFF reader requires 19 seconds.  16 seconds of that is used by the Java 
ICC_Profile.toRGB() method.  Anyway, I've attached a copy of my results (size 
reduced, of course) and the example code is given below.
{code:java}
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import javax.imageio.ImageIO;
import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.common.ImageBuilder;
import org.apache.commons.imaging.formats.tiff.constants.TiffConstants;
import 
org.apache.commons.imaging.formats.tiff.photometricinterpreters.PhotometricInterpreter;

public class ExampleIccProfile {

    public static void main(String[] args) throws ImageReadException, 
IOException {

        // For this demo, we have a TIFF file known to have an ICC Profile
        // Use the high-level Imaging class to read it.
        File file = new File(args[0]);
        ICC_Profile profile = Imaging.getICCProfile(file);

        // Create a custom instance of PhotometricInterpreter that
        // uses the ICC Profile.  Most of the constructor arguments for
        // the PhotometricInterpreter are legacy elements that aren't
        // actually used.  But we populate them here for demonstration.
        int[] bitsPerPixel = new int[]{8, 8, 8, 8};
        PhotometricInterpreterICC pi
          = new PhotometricInterpreterICC(
            bitsPerPixel.length,
            bitsPerPixel,
            -1, // predictor, not used,
            0, // image width,
            0, // image height, not used,
            profile);

        // Commons Imaging uses a Java Map to pass in special processing
        // options.  Add the custom PhotometricInterpreter
        HashMap params = new HashMap();
        params.put(TiffConstants.PARAM_KEY_CUSTOM_PHOTOMETRIC_INTERPRETER, pi);
        BufferedImage bImage = Imaging.getBufferedImage(file, params);
        ImageIO.write(bImage, "JPEG", new File("test.jpg"));
    }

    // Here's the implementation of the custom Photometric Interpreter
    private static class PhotometricInterpreterICC extends 
PhotometricInterpreter {
        private final ICC_ColorSpace iccColorSpace;
        public PhotometricInterpreterICC(
          final int samplesPerPixel,
          final int[] bitsPerSample,
          final int predictor,
          final int width,
          final int height,
          final ICC_Profile iccProfile) {
            super(samplesPerPixel, bitsPerSample, predictor, width, height);
            iccColorSpace = new ICC_ColorSpace(iccProfile);
        }

        @Override
        public void interpretPixel(
          ImageBuilder imageBuilder,
          int[] samples,
          int x, int y) throws ImageReadException, IOException {
            float[] s = new float[samplesPerPixel];
            s[0] = ((samples[0] & 0xff)) / 255.0f;
            s[1] = ((samples[1] & 0xff)) / 255.0f;
            s[2] = ((samples[2] & 0xff)) / 255.0f;
            s[3] = ((samples[3] & 0xff)) / 255.0f;

            float[] f = iccColorSpace.toRGB(s);
            int r = (int) (f[0] * 255 + 0.5);
            int g = (int) (f[1] * 255 + 0.5);
            int b = (int) (f[2] * 255 + 0.5);
            int argb = ((((0xff00 | r) << 8) | g) << 8) | b;
            imageBuilder.setRGB(x, y, argb);
        }
    }
}
{code}
  !Imaging201_CustomPhotometricInterpreter.jpg!

 

> Significant change in color of output image of tiff file
> --------------------------------------------------------
>
>                 Key: IMAGING-201
>                 URL: https://issues.apache.org/jira/browse/IMAGING-201
>             Project: Commons Imaging
>          Issue Type: Bug
>          Components: Format: TIFF
>    Affects Versions: 1.0-alpha1
>            Reporter: Praful Vaishnav
>            Priority: Major
>         Attachments: Imaging201_CustomPhotometricInterpreter.jpg, 
> SS_result.png, SS_source.png
>
>
> Hii.. I am reading tiff image file and using this library to convert it to 
> PNG format. Resultant png file has significant change in color wrt its 
> original tiff file. Below is the code :
> {code:java}
> File file = new File("C:\\original.tiff");
> BufferedImage bi = Imaging.getBufferedImage(file);
> File dstFile = new File("C:\\result.png");
> Imaging.writeImage(bi, dstFile, ImageFormats.PNG, null);
> {code}
> Reason could be :
> original image is 32 bit depth and result image is 24 bit depth. Is there any 
> issue with 32 bit depth image file.
> Link for source tiff file - 
> https://www.dropbox.com/s/kgqgdcygelkor8b/original.tiff?dl=0
> Attachements:
> SS_source.png - Screenshot of original tiff file
> SS_result.png - Screenshot of result png file



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to