/*******************************************************************************
* Copyright (c) 2016 Weasis Team and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nicolas Roduit - initial API and implementation
*******************************************************************************/
package org.weasis.core.api.image.util;
import java.awt.color.ColorSpace;
public class CIELab extends ColorSpace {
private static final long serialVersionUID = -8341937056180131312L;
private static final ColorSpace CIEXYZ = ColorSpace.getInstance(ColorSpace.CS_CIEXYZ);
private static final double N = 4.0 / 29.0;
private CIELab() {
super(ColorSpace.TYPE_Lab, 3);
}
private static class Holder {
static final CIELab INSTANCE = new CIELab();
}
public static CIELab getInstance() {
return Holder.INSTANCE;
}
@Override
public float[] fromCIEXYZ(float[] colorvalue) {
double l = f(colorvalue[1]);
double L = 116.0 * l - 16.0;
double a = 500.0 * (f(colorvalue[0]) - l);
double b = 200.0 * (l - f(colorvalue[2]));
return new float[] { (float) L, (float) a, (float) b };
}
@Override
public float[] fromRGB(float[] rgbvalue) {
float[] xyz = CIEXYZ.fromRGB(rgbvalue);
return fromCIEXYZ(xyz);
}
@Override
public float getMaxValue(int component) {
return 128f;
}
@Override
public float getMinValue(int component) {
return (component == 0) ? 0f : -128f;
}
@Override
public String getName(int idx) {
return String.valueOf("Lab".charAt(idx)); //$NON-NLS-1$
}
@Override
public float[] toCIEXYZ(float[] colorvalue) {
double i = (colorvalue[0] + 16.0) * (1.0 / 116.0);
double x = fInv(i + colorvalue[1] * (1.0 / 500.0));
double y = fInv(i);
double z = fInv(i - colorvalue[2] * (1.0 / 200.0));
return new float[] { (float) x, (float) y, (float) z };
}
@Override
public float[] toRGB(float[] colorvalue) {
float[] xyz = toCIEXYZ(colorvalue);
return CIEXYZ.toRGB(xyz);
}
private static double f(double x) {
if (x > 216.0 / 24389.0) {
return Math.cbrt(x);
} else {
return (841.0 / 108.0) * x + N;
}
}
private static double fInv(double x) {
if (x > 6.0 / 29.0) {
return x * x * x;
} else {
return (108.0 / 841.0) * (x - N);
}
}
/**
* This method converts integer DICOM encoded L*a*b* values to CIE L*a*b* regular float encoded values.
*
* @param lab
* @return float array of 3 components L* on 0..1 and a*,b* on -128...127
*/
public static float[] convertToFloatLab(int[] lab) {
if (lab == null || lab.length != 3) {
return null;
}
float[] ret = new float[3];
ret[0] = lab[0] / 655.35f;
ret[1] = lab[1] / 257.0f - 128;
ret[2] = lab[2] / 257.0f - 128;
return ret;
}
public static int[] convertToDicomLab(float[] lab) {
if (lab == null || lab.length != 3) {
return null;
}
int[] ret = new int[3];
ret[0] = (int) (lab[0] * 655.35f);
ret[1] = (int) ((lab[1] + 128f) * 257.0f);
ret[2] = (int) ((lab[2] + 128f) * 257.0f);
return ret;
}
}