Skip to main content

help with single-pixel color transform (RGB->CMYK)

2 replies [Last post]
Anonymous

Hi everyone,

I'm new to Java, but before I took on this project I used LCMS for my
color management applications and I'm finding the differences quite
overwhelming... I hope you don't mind if I ask a few questions!

I'm trying to grab a pixel value from a specific point in an sRGB
BufferedImage, and then convert that to a CMYK value based on
specified input & output Profiles. I've searched through all sorts of
documentation and code samples online with moderate success, but I'm
stuck here. The input profile is RGB, the output profile is CMYK.

The results I'm getting are crazy, sometimes it comes up with
ultra-tiny values for the CMYK (like 0.0023 etc), and other very
strange results... I don't understand the output.

For example, the results I'm getting right now are:

Pixel RGB Values = 221,221,221 (light gray)
C: 0.0025787747, M: 0.0038147555, Y: 0.0070038913, K: 0.0

Below is the code I'm currently working on. I've added my questions
and comments in the code itself... If anyone can help, I'd really
appreciate it! Thank you!!!!!

-- Tyler

</p>
<p>               int w = 1;<br />
               int h = 1;<br />
               int row = 10;<br />
               int column = 20;<br />
               int RGBpixel[] = new int[1];  // PixelGrabber expects an array...<br />
               float SinglePixel[] = new float[3];</p>
<p>               int RGBSource[] = new int[12];<br />
               int CMYKdest[] = new int[12];</p>
<p>               // Absolute paths to ICC profiles<br />
               String strInputProfile = Workspace.prefix +<br />
File.separator +"AdobeRGB1998.icc";<br />
               String strOutputProfile = Workspace.prefix +<br />
File.separator  +"USWebCoatedSWOP.icc";</p>
<p>              ICC_Profile InputProfile = null;<br />
              ICC_Profile OutputProfile = null;</p>
<p>              try {<br />
                 InputProfile = ICC_Profile.getInstance(strInputProfile);<br />
              } catch (IOException e) {<br />
                  System.err.println("Can't open the profile for some reason");<br />
                  return;<br />
              }</p>
<p>               try {<br />
                 OutputProfile = ICC_Profile.getInstance(strOutputProfile);<br />
              } catch (IOException e) {<br />
                  System.err.println("Can't open the profile for some reason");<br />
                  return;<br />
              }</p>
<p>              // Is this how I set the rendering intent for the color transform?<br />
              int input_renderingIntent = InputProfile.icPerceptual;<br />
              int output_renderingIntent = OutputProfile.icPerceptual;</p>
<p>              ColorSpace colorspaceInput = new ICC_ColorSpace(InputProfile);<br />
              ColorSpace colorspaceOutput = new ICC_ColorSpace(OutputProfile);</p>
<p>              /* The PixelGrabber code seems to be working...<br />
                 This returns an int value for the pixel.<br />
                 image is my BufferedImage */<br />
              PixelGrabber pgSource = new PixelGrabber(image, column,<br />
row, w, h, RGBpixel, 0, w);<br />
              try {<br />
                  pgSource.grabPixels();<br />
              } catch (InterruptedException e) {<br />
                  System.err.println("interrupted waiting for pixels!");<br />
                  return;<br />
              }<br />
              if ((pgSource.getStatus() & ImageObserver.ABORT) != 0) {<br />
                  System.err.println("image fetch aborted or errored");<br />
                  return;<br />
              }</p>
<p>              // The RGB values this returns are correct.<br />
              int alpha = (RGBpixel[0] >> 24) & 0xff;<br />
              int red   = (RGBpixel[0] >> 16) & 0xff;<br />
              int green = (RGBpixel[0] >>  8) & 0xff;<br />
              int blue  = (RGBpixel[0]      ) & 0xff;</p>
<p>              // Everything seems to be working up until this point.<br />
              // Should I include the alpha channel in here?</p>
<p>              SinglePixel[0] = red;<br />
              SinglePixel[1] = green;<br />
              SinglePixel[2] = blue;</p>
<p>              float[] xyzValues = colorspaceInput.toCIEXYZ(SinglePixel);<br />
              float[] opValues = colorspaceOutput.fromCIEXYZ(xyzValues);</p>
<p>              System.err.println("C: "+opValues[0]);<br />
              System.err.println("M: "+opValues[1]);<br />
              System.err.println("Y: "+opValues[2]);<br />
              System.err.println("K: "+opValues[3]);</p>
<p>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
alex2d
Offline
Joined: 2006-03-31

Hello Tyler,

It seems that your problem is that you are using non-normalized colors in your transformations. You should replace your code with following one:

...
SinglePixel[0] = red/255.0;
SinglePixel[1] = green/255.0;
SinglePixel[2] = blue/255.0;

float[] xyzValues = colorspaceInput.toCIEXYZ(SinglePixel);
float[] opValues = colorspaceOutput.fromCIEXYZ(xyzValues);
...

And don't forget to convert normalized result into non-normalized one.

Best Regards,
Alexey

Chris Campbell

Hi Tyler,

First, if you do need to go the manual route, it's best to stay away
from PixelGrabber. The BufferedImage and related newer APIs are your
friend.

Second, have you tried ColorConvertOp?
http://java.sun.com/javase/6/docs/api/java/awt/image/ColorConvertOp.html

You should be able to collapse all of your code below into:
ColorConvertOp op = new ColorConvertOp(srcCS, dstCS, null);
BufferedImage res = op.filter(src, null);

Thanks,
Chris

On Jan 28, 2007, at 4:32 AM, Tyler Kivari wrote:
> Hi everyone,
>
> I'm new to Java, but before I took on this project I used LCMS for my
> color management applications and I'm finding the differences quite
> overwhelming... I hope you don't mind if I ask a few questions!
>
> I'm trying to grab a pixel value from a specific point in an sRGB
> BufferedImage, and then convert that to a CMYK value based on
> specified input & output Profiles. I've searched through all sorts of
> documentation and code samples online with moderate success, but I'm
> stuck here. The input profile is RGB, the output profile is CMYK.
>
> The results I'm getting are crazy, sometimes it comes up with
> ultra-tiny values for the CMYK (like 0.0023 etc), and other very
> strange results... I don't understand the output.
>
> For example, the results I'm getting right now are:
>
> Pixel RGB Values = 221,221,221 (light gray)
> C: 0.0025787747, M: 0.0038147555, Y: 0.0070038913, K: 0.0
>
> Below is the code I'm currently working on. I've added my questions
> and comments in the code itself... If anyone can help, I'd really
> appreciate it! Thank you!!!!!
>
>
> -- Tyler
>
>
> [code]
>
> int w = 1;
> int h = 1;
> int row = 10;
> int column = 20;
> int RGBpixel[] = new int[1]; // PixelGrabber expects
> an array...
> float SinglePixel[] = new float[3];
>
> int RGBSource[] = new int[12];
> int CMYKdest[] = new int[12];
>
>
> // Absolute paths to ICC profiles
> String strInputProfile = Workspace.prefix +
> File.separator +"AdobeRGB1998.icc";
> String strOutputProfile = Workspace.prefix +
> File.separator +"USWebCoatedSWOP.icc";
>
> ICC_Profile InputProfile = null;
> ICC_Profile OutputProfile = null;
>
> try {
> InputProfile = ICC_Profile.getInstance
> (strInputProfile);
> } catch (IOException e) {
> System.err.println("Can't open the profile for
> some reason");
> return;
> }
>
> try {
> OutputProfile = ICC_Profile.getInstance
> (strOutputProfile);
> } catch (IOException e) {
> System.err.println("Can't open the profile for
> some reason");
> return;
> }
>
> // Is this how I set the rendering intent for the
> color transform?
> int input_renderingIntent = InputProfile.icPerceptual;
> int output_renderingIntent = OutputProfile.icPerceptual;
>
> ColorSpace colorspaceInput = new ICC_ColorSpace
> (InputProfile);
> ColorSpace colorspaceOutput = new ICC_ColorSpace
> (OutputProfile);
>
>
> /* The PixelGrabber code seems to be working...
> This returns an int value for the pixel.
> image is my BufferedImage */
> PixelGrabber pgSource = new PixelGrabber(image, column,
> row, w, h, RGBpixel, 0, w);
> try {
> pgSource.grabPixels();
> } catch (InterruptedException e) {
> System.err.println("interrupted waiting for
> pixels!");
> return;
> }
> if ((pgSource.getStatus() & ImageObserver.ABORT) != 0) {
> System.err.println("image fetch aborted or errored");
> return;
> }
>
> // The RGB values this returns are correct.
> int alpha = (RGBpixel[0] >> 24) & 0xff;
> int red = (RGBpixel[0] >> 16) & 0xff;
> int green = (RGBpixel[0] >> 8) & 0xff;
> int blue = (RGBpixel[0] ) & 0xff;
>
> // Everything seems to be working up until this point.
> // Should I include the alpha channel in here?
>
> SinglePixel[0] = red;
> SinglePixel[1] = green;
> SinglePixel[2] = blue;
>
> float[] xyzValues = colorspaceInput.toCIEXYZ
> (SinglePixel);
> float[] opValues = colorspaceOutput.fromCIEXYZ
> (xyzValues);
>
> System.err.println("C: "+opValues[0]);
> System.err.println("M: "+opValues[1]);
> System.err.println("Y: "+opValues[2]);
> System.err.println("K: "+opValues[3]);
>
> [/code]
>
> ======================================================================
> =====
> To unsubscribe, send email to listserv@java.sun.com and include in
> the body
> of the message "signoff JAVA2D-INTEREST". For general help, send
> email to
> listserv@java.sun.com and include in the body of the message "help".

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".