blob: 7345c1dac69efcb0ef2bd55fa78509be9c7f29a1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2008 IBM Corporation 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:
* Junji MAEDA - initial API and implementation
*******************************************************************************/
package org.eclipse.actf.visualization.engines.lowvision.color;
/*
* L*a*b* color space
*/
public class ColorLAB {
private static final double THIRD = 1.0 / 3.0;
private float L;
private float a;
private float b;
// ColorXYZ [0.0, 1.0]
public ColorLAB(ColorXYZ _xyz) {
float x = _xyz.getX();
float y = _xyz.getY();
float z = _xyz.getZ();
// L*
if (y > 0.008856f) {
L = (float) (116.0 * Math.pow((double) y, THIRD) - 16.0);
} else {
L = 903.3f * y;
}
// a*,b*
double xThird = Math.pow((double) x, THIRD);
double yThird = Math.pow((double) y, THIRD);
double zThird = Math.pow((double) z, THIRD);
a = (float) (500.0 * (xThird - yThird));
b = (float) (200.0 * (yThird - zThird));
}
public ColorLAB(float _l, float _a, float _b) throws ColorException {
setL(_l);
setA(_a);
setB(_b);
}
public float getL() {
return (L);
}
public void setL(float _l) throws ColorException {
if (_l < 0.0f || 100.0f < _l) {
throw new ColorException("L is out of range: " + _l);
}
L = _l;
}
public float getA() {
return (a);
}
public void setA(float _a) {
a = _a;
}
public float getB() {
return (b);
}
public void setB(float _b) {
b = _b;
}
public ColorXYZ toXYZ() throws ColorException {
float y = 0.0f;
double y3 = 0.0;
if (L > 8.0f) {
y3 = (double) ((L + 16.0f) / 116.0f);
y = (float) (Math.pow(y3, 3.0));
} else {
y = L / 903.3f;
y3 = Math.pow((double) y, THIRD);
}
float x = (float) (Math.pow(((double) a / 500.0 + y3), 3.0));
float z = (float) (Math.pow((y3 - (double) b / 200.0), 3.0));
return (new ColorXYZ(x, y, z, false));
}
public float chroma() {
return ((float) (Math.sqrt(a * a + b * b)));
}
public double hueAngle() {
return (Math.atan2(b, a));
}
// color-difference
public static float deltaE(ColorLAB _c1, ColorLAB _c2) {
double dL = _c1.L - _c2.L;
double dA = _c1.a - _c2.a;
double dB = _c1.b - _c2.b;
return ((float) (Math.sqrt(dL * dL + dA * dA + dB * dB)));
}
//brightness difference (ABS)
public static float deltaL(ColorLAB _c1, ColorLAB _c2) {
return (Math.abs(_c1.L - _c2.L));
}
//hue difference
public static float deltaH(ColorLAB _c1, ColorLAB _c2) {
float dC = _c1.chroma() - _c2.chroma();
float dA = _c1.a - _c2.a;
float dB = _c1.b - _c2.b;
return ((float) (Math.sqrt(dA * dA + dB * dB - dC * dC)));
}
public static double deltaHueAngle(ColorLAB _c1, ColorLAB _c2) {
double ha1 = _c1.hueAngle();
double ha2 = _c2.hueAngle();
/*
* in usual case, achromatic color -> return NaN
* this method returns 0 (means not need to consider the difference)
*/
if (Double.isNaN(ha1)) {
// return( Double.NaN );
return (0.0);
}
if (Double.isNaN(ha2)) {
// return( Double.NaN );
return (0.0);
}
double diff = Math.abs(ha1 - ha2);
if (diff <= Math.PI) {
return (diff);
} else if (diff <= 2 * Math.PI) {
return (2 * Math.PI - diff);
} else {
return (diff - 2 * Math.PI);
}
}
public static double deltaHueAngleInDegree(ColorLAB _c1, ColorLAB _c2) {
return (deltaHueAngle(_c1, _c2) * 180.0 / Math.PI);
}
}