package fr.unistra.pelican.algorithms.conversion; import fr.unistra.pelican.Algorithm; import fr.unistra.pelican.AlgorithmException; import fr.unistra.pelican.ByteImage; import fr.unistra.pelican.Image; /** * This class realizes the transformation of a tristumulus double valued CIE XYZ * image into a CIE LAB image. * * MASK MANAGEMENT (by Regis) : * - input's mask becomes output's mask. * - no modification on color calculation. * * @author Erchan Aptoula, Jonathan Weber * */ public class XYZToLAB extends Algorithm { /** * Input parameter */ public Image input; /** * Output parameter */ public Image output; public boolean scaleToByte=false; /** * Constructor * */ public XYZToLAB() { super.inputs = "input"; super.options="scaleToByte"; super.outputs = "output"; } /* * (non-Javadoc) * * @see fr.unistra.pelican.Algorithm#launch() */ public void launch() throws AlgorithmException { int size = input.size(); if (input.getBDim() != 3) throw new AlgorithmException( "The input must be a tristumulus XYZ image"); output = input.newDoubleImage(); this.output.setMask( this.input.getMask() ); output.setColor(true); for(int i=0;i<size;i=i+3) { double X = input.getPixelDouble(i); double Y = input.getPixelDouble(i+1); double Z = input.getPixelDouble(i+2); double[] lab = convert(X, Y, Z); output.setPixelDouble(i, lab[0]); output.setPixelDouble(i+1, lab[1]); output.setPixelDouble(i+2, lab[2]); } if (scaleToByte) output=scaleToByte(output); } /** * converts a triplet of xyz into cielab * * @param x * @param y * @param z * @return the array of lab values */ public static double[] convert(double x, double y, double z) { // THE white point..D65 double Xn = 0.950456; double Yn = 1.0; double Zn = 1.088754; double Xfrac = x / Xn; double Yfrac = y / Yn; double Zfrac = z / Zn; if (Xfrac > 0.008856) Xfrac = Math.pow(Xfrac, 0.333333); else Xfrac = 7.787 * Xfrac + 16.0 / 116.0; if (Yfrac > 0.008856) Yfrac = Math.pow(Yfrac, 0.333333); else Yfrac = 7.787 * Yfrac + 16.0 / 116.0; if (Zfrac > 0.008856) Zfrac = Math.pow(Zfrac, 0.333333); else Zfrac = 7.787 * Zfrac + 16.0 / 116.0; double[] lab = new double[3]; lab[0] = 116 * Yfrac - 16.0; lab[1] = 500 * (Xfrac - Yfrac); lab[2] = 200 * (Yfrac - Zfrac); return lab; } /** * Scales each band of the resulting lab image according to the value * intervals L in [0,100], a and b in [-128,127] and returns a valid * byteImage..of course only valid for the D65 white point. * * @return resulting ByteImage */ private static Image scaleToByte(Image lab) { ByteImage bimg = new ByteImage(lab, false); int size = bimg.size(); double f = 2.55; // 255.0/100.0 for(int i=0;i<size;i=i+3) { double d = lab.getPixelDouble(i); // L bimg.setPixelByte(i, (int) Math.round(d * f)); // a and b d = lab.getPixelDouble(i+1); bimg.setPixelByte(i+1, (int) Math.round(d + 128)); d = lab.getPixelDouble(i+2); bimg.setPixelByte(i+2, (int) Math.round(d + 128)); } return bimg; } /** * This class realizes the transformation of a tristumulus double valued CIE * XYZ image into a CIE LAB image. * * @param input * Tristumulus double valued CIE XYZ image. * @return A CIE LAB image. */ public static Image exec(Image input) { return (Image) new XYZToLAB().process(input); } public static Image exec(Image input,boolean scaleToByte) { return (Image) new XYZToLAB().process(input,scaleToByte); } }