MicroHat11
MicroHat11

Reputation: 227

RGB to CIEXYZ in Java

I'm trying to convert RGB colors to CIEXYZ and eventually would like to convert them to CIELAB however I'm experiencing problems with the java.awt.color.ColorSpace.CS_CIEXYZ Color Space.

Using a calculator online I get different values than the ones provided from the Color Space

Code:

import java.awt.color.ColorSpace;
import java.util.Arrays;

public class CIEXYZ {

    private final static float[] RGB = new float[] {255.0f, 255.0f, 255.0f};
    private final static ColorSpace CIEXYZ = ColorSpace.getInstance(ColorSpace.CS_CIEXYZ);

    public static void main(String[] args) {
        System.out.println("RGB: " + Arrays.toString(RGB));
        System.out.println("CIEXYZ: " + Arrays.toString(CIEXYZ.fromRGB(RGB)));
    }
}

Output:

RGB: [255.0, 255.0, 255.0]

CIEXYZ: [0.95254517, 0.98773193, 0.81500244]

Calculator online:

http://www.easyrgb.com/index.php?X=CALC

XYZ = 95.050 100.000 108.900

Is there something I am overlooking or doing wrong?

Upvotes: 4

Views: 2090

Answers (1)

Kel Solaar
Kel Solaar

Reputation: 4080

What you see is the result of the Java class chromatically adapting to CIE Standard Illuminant D50.

Using Colour, here is for example a conversion to tristimulus values while keeping the sRGB colourspace illuminant (CIE Standard Illuminant D65):

import colour

sRGB = np.array([255., 255., 255.])
sRGB /= 255.

# Default conversion from *sRGB* colourspace 
# to *CIE XYZ* tristimulus values.
# It should return *CIE Standard Illuminant D65* 
# tristimulus values using the above array.
print(colour.sRGB_to_XYZ(sRGB))

[ 0.95042854 1. 1.08890037]

and now the same conversion but chromatically adapting to CIE Standard Illuminant D50:

# Conversion to *CIE XYZ tristimulus* values but chromatically adapting 
# to *CIE Standard Illuminant D50*.
D50 = colour.ILLUMINANTS['cie_2_1931']['D50']

print(colour.sRGB_to_XYZ(sRGB, D50))

[ 0.96421199 1. 0.82518828]

Usually illuminants are normalised to their Luminance which is why Y is equal to 1 in our computations, I didn't investigated why the Java class doesn't return the normalised value but a quick check shows that its computation are almost spot on:

D50 = colour.ILLUMINANTS['cie_2_1931']['D50']

print(colour.sRGB_to_XYZ(sRGB, D50) * 0.98773193)

Colour : [ 0.95238297 0.98773193 0.81506482]

Java : [ 0.95254517 0.98773193 0.81500244]

Upvotes: 2

Related Questions