Skip to main content

Convert ColorSpace issue with JAI

3 replies [Last post]
rdander
Offline
Joined: 2005-11-16
Points: 0

I am trying to convert the colorspace of a 16-bit tiff image using JAI. I have a source ICC profile for the image, and output ICC profile which is a LAB profile. The goal is to convert the image data from the RGB input profile space to the LAB profile space. The below code runs, but the LAB image data is incorrect. When I select a pixel, and pull the data out, I find the L to be fairly accurate, however the "a" and "b" are off by 32K.

For example, If I look at the pixel data for a single point, the value is R=18377, G=14840, and B=12692. This is 16-bit data, so it is on a scale of 0 - 65535. I then run the conversion using the below code, and I get a LAB value of L=16973, A=35309, and B=36745. The LAB value I expect to get for this pixel point should be L=16945, A=2575, and B=3962. I got this expected LAB value by using the same input profile, output profile, and test image on a C++ profile engine, and am confident these expected values are correct.

The L seems to be fairly accurate accross all pixels. The "a" and "b" however seem to be off by around 32K, or half the range of a 16-bit value.

Is there anything obvious in the below method that I am doing wrong? I am farily new to JAI, but have done many imaging algorithms in c++ code.

Thanks in advance for any suggestions or ideas.

My Method for ColorSpace conversion:

public PlanarImage convertColorSpace(PlanarImage piInputImage, String strInputICCProfile, String strOutputICCProfile)
{

ICC_ColorSpace iccInput = null;

try
{
iccInput = new ICC_ColorSpace(ICC_Profile.getInstance(strInputICCProfile));
}
catch(IOException ex)
{
return null;
}

ColorModel cmInput = RasterFactory.createComponentColorModel(piInputImage.getSampleModel().getDataType(), iccInput,
false, false, Transparency.OPAQUE);

ImageLayout ilInput = new ImageLayout();
ilInput.setColorModel(cmInput);
RenderingHints rhInput = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, ilInput);

ParameterBlock pbInput = new ParameterBlock();
pbInput.addSource(piInputImage);
pbInput.add(piInputImage.getSampleModel().getDataType());

PlanarImage piInputWithProfile = JAI.create("format", pbInput, rhInput);

//Now Convert to output color spaces.
ICC_ColorSpace iccOutput = null;

try
{
iccOutput = new ICC_ColorSpace(ICC_Profile.getInstance(strOutputICCProfile));
}
catch(IOException ex)
{
return null;
}

ColorModel cmOutput = RasterFactory.createComponentColorModel(piInputWithProfile.getSampleModel().getDataType(), iccOutput,
false, false, Transparency.OPAQUE);

ImageLayout ilOutput = new ImageLayout();
ilOutput.setSampleModel(cmOutput.createCompatibleSampleModel(piInputWithProfile.getWidth(), piInputWithProfile.getHeight()));
RenderingHints rhOutput = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, ilOutput);

ParameterBlock pbOutput = new ParameterBlock();
pbOutput.addSource(piInputWithProfile);
pbOutput.add(cmOutput);

return JAI.create("ColorConvert", pbOutput, rhOutput);

}

My Unit Test to convert the image:

public void testConvertColorSpace() throws Exception
{
String strInputProfile = "./TestData/profile.icc";
String strOutputProfile = "./TestData/Generic Lab Profile.icm";
PlanarImage planarImage = JAI.create("fileload", "./TestData/TestTiff.tif");

assertEquals(3456, planarImage.getData().getWidth());
assertEquals(2304, planarImage.getData().getHeight());

int[] iRGB = new int[3];
planarImage.getData().getPixel(1275, 852, iRGB);
assertEquals(18377, iRGB[0]);
assertEquals(14840, iRGB[1]);
assertEquals(12692, iRGB[2]);

ImageProcessing imageProcessing = new ImageProcessing();

PlanarImage piLab = imageProcessing.convertColorSpace(planarImage, strInputProfile, strOutputProfile);

JAI.create("filestore",piLab, "./MyLab.tif", "TIFF");

}

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Jerry Evans

>
>
>For example, If I look at the pixel data for a single point, the value is R=18377, G=14840, and B=12692. This is 16-bit data, so it is on a scale of 0 - 65535. I then run the conversion using the below code, and I get a LAB value of L=16973, A=35309, and B=36745. The LAB value I expect to get for this pixel point should be L=16945, A=2575, and B=3962. I got this expected LAB value by using the same input profile, output profile, and test image on a C++ profile engine, and am confident these expected values are correct.
>
>The L seems to be fairly accurate accross all pixels. The "a" and "b" however seem to be off by around 32K, or half the range of a 16-bit value.
>

The ICC_ColorSpace class in Java SE assumes that Lab spaces are encoded
as follows
for 16-bit unsigned sample values:

L: 0.0 - 100.0 => 0x0000 - 0xFFFF
a: -128.0 - +127.0 => 0x0000 - 0xFFFF
b: -128.0 - +127.0 => 0x0000 - 0xFFFF

Does your Lab profile follow this convention?

It's suspicious that the values are off by about 32K. This could be a
bug in the
Java SE color conversion code. You might try subclassing ICC_ColorSpace and
overriding the getMinValue and getMaxValue methods to see if you can work
around the problem.

Jerry

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
For additional commands, e-mail: interest-help@jai.dev.java.net

rdander
Offline
Joined: 2005-11-16
Points: 0

Thanks for the reply Jerry. Yes, the Lab profile follows the convention

L: 0.0 - 100.0 => 0x0000 - 0xFFFF
a: -128.0 - +127.0 => 0x0000 - 0xFFFF
b: -128.0 - +127.0 => 0x0000 - 0xFFFF

I also was suspecting there might be a bug in the color conversion due to the a and b values being 32K off. I wanted to have others look at the code though, to make sure I'm doing the color conversion correctly before I try to write code to work around a potential bug.

rdander
Offline
Joined: 2005-11-16
Points: 0

I checked the getMinValue and getMaxValue methods in the ICC_ColorSpace class, and they are returning the correct ranges for the L A B components.