package yi.iu.processor.color;

/**
 * <p>
 * Based on the code from John Burkardt.  More information see
 * http://www.psc.edu/~burkardt/src/colors/colors.html
 *
 * <p>
 * CIELab is a utility class converting the color instances between RGB color
 * space and CIEL*a*b space.  Other converting utilities include:
 * CIELAB, CIELUV, CIExyY, CIEXYZ, CMY, CMYK, HLS, HSV, PhotoYCC, RGB, Y'CbCr, Y'IQ and Y'UV.
 * </p>
 *
 * <p>
 * The most useful methods in this class:
 * </p>
 *
 * <pre>
 * rgb2lab(double[], double[]);
 * rgb2lab(int);
 * rgb2lab(int[]);
 * </pre>
 *
 * <p>Title: CIELab</p>
 * <p>Description: Conversion between RGB color space and CIELab color space</p>
 */

public class CIELab implements java.io.Serializable
{
    public double L, a, b;

    public CIELab() {
    }

    public CIELab(double l, double a, double b) {
      this.L = l; this.a = a; this.b = b;
    }

    public double getL() {
      return L;
    }
    public void setL(double l) {
      this.L = l;
    }
    public double getA() {
      return a;
    }
    public void setA(double a) {
      this.a = a;
    }
    public double getB() {
      return b;
    }
    public void setB(double b) {
      this.b = b;
    }
    /**
     * <p>
     * Corrects out-of-range CIE L*a*b* color coordinates.
     * The CIE L*a*b* color system describes a color based on three
     * qualities: L* is CIE lightness, a* and b* contain chromatic
     * information.  A given color will be represented by three
     * numbers, (L*,a*,b*).  The ranges are
     * </p>
     *
     *         0 <= L* <= 100,
     *      -500 <= a* <= 500,
     *      -200 <= b* <= 200.
     *
     * <p>
     * Input/output, real LSTAR, ASTAR, BSTAR, the CIE L*a*b* color coordinates
     * to be checked.
     * </p>
     *
     * @param lab the three components of a CIE L*a*b* color
     */
    static void labCheck(double[] lab)
    {
        if (lab[0]<0) lab[0]=0;
        else if (lab[0]>100) lab[0]=100;

        if (lab[1]<-500) lab[1]=500;
        else if (lab[1]>500) lab[1]=500;

        if (lab[2]<-200) lab[2]=200;
        else if (lab[2]>200) lab[2]=200;
    }

    final static double RAD2DEG= 180/Math.PI;

    /**
     * Returns certain properties of a CIE L*a*b* color.  Specifically, return
     * Hue, Chroma, Luminance of a CIE L*a*b* color.
     *
     * @param lab Input, real LSTAR, ASTAR, BSTAR, the CIE L*a*b* coordinates
     *            of the color.
     * @param hcl Output, real CHROMA, HUE, LUMINANCE, the chroma, hue, and
     *            relative luminance.  HUE is returned as an angle, in degrees.
     */
    static void labProp(double[] lab, double[] hcl) {
        double lstar= lab[0], astar=lab[1], bstar=lab[2];

        hcl[1]= Math.sqrt(astar*astar + bstar*bstar);
        //chroma = sqrt ( astar**2 + bstar**2 )
        hcl[0]= Math.atan2 ( bstar, astar ) * RAD2DEG;

        if ( lstar<=0.0 ) hcl[2]= 0.0;
        else if ( lstar <= 903.3 * 0.008856 ) hcl[2] = lstar / 903.3;
        else if ( lstar <= 100.0 ) hcl[2] = Math.pow( ((lstar+16.0) / 116.0 ) , 3 );
        else hcl[2] = 1.0;
    }


    //***********************************************************************
    //
    //! LAB_TO_XYZ converts CIE L*a*b* to CIE XYZ color coordinates.
    //
    //
    //  Definition:
    //
    //    The CIE L*a*b* color system describes a color based on three
    //    qualities: L* is CIE lightness, a* and b* contain chromatic
    //    information.  A given color will be represented by three
    //    numbers, (L*,a*,b*).  The ranges are 0 <= L* <= 100, -500 <= a* <= 500,
    //    -200 <= b* <= 200.
    //
    //    The CIE XYZ color system describes a color in terms of its components
    //    of X, Y and Z primaries.  In ordinary circumstances, all three of
    //    these components must be nonnegative.
    //
    //  Reference:
    //
    //    Edward Giorgianni and Thomas Madden,
    //    Digital Color Management, Encoding Solutions,
    //    Addison Wesley, 1998.
    //
    //  Modified:
    //
    //    09 September 1998
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, real LSTAR, ASTAR, BSTAR, the CIE L*a*b* color coordinates.
    //
    //    Output, real XCAP, YCAP, ZCAP, the CIE XYZ color coordinates.
    //
    //    Input, real XCAPN, YCAPN, ZCAPN, the CIE XYZ color coordinates of white.
    public static void lab2xyz(double[] lab, double[] xyz, double[] capn)
    {
        double lstar= lab[0], astar=lab[1], bstar=lab[2];
        double xcapn= capn[0],ycapn= capn[1],zcapn= capn[2];
        double fx,fy,fz;
        double xcap, ycap, zcap;

        if ( lstar <= 0.0 ) ycap = 0.0;
        else if ( lstar <= 8.0 )  ycap = lstar * ycapn / 903.3;
        else if ( lstar <= 100.0 )  ycap = ycapn * Math.pow( ( ( lstar + 16.0 ) / 116.0 ) , 3);
        else ycap = ycapn;

        if ( ycap <= 0.00856 * ycapn ) fy = 7.787 * ycap / ycapn + 16.0 / 116.0;
        else  fy = Math.pow ( ycap / ycapn , 1.0/3);

        fx = fy + ( astar / 500.0 );

        if ( fx*fx*fx <= 0.008856 )  xcap = xcapn * ( fx - 16.0 / 116.0 ) / 7.787;
        else  xcap = xcapn * fx*fx*fx;

        fz = fy - ( bstar / 200.0 );

        if ( fz*fz*fz <= 0.008856 ) zcap = zcapn * ( fz - 16.0 / 116.0 ) / 7.787;
        else  zcap = zcapn * fz*fz*fz;

        xyz[0]=xcap; xyz[1]=ycap; xyz[2]=zcap;
    }

    //
    //***********************************************************************
    //
    //! XYZ_TO_LAB converts CIE XYZ to CIE L*a*b* color coordinates.
    //
    //
    //  Definition:
    //
    //    The CIE XYZ color system describes a color in terms of its components
    //    of X, Y and Z primaries.  In ordinary circumstances, all three of
    //    these components must be nonnegative.
    //
    //    The CIE L*a*b* color system describes a color based on three
    //    qualities: L* is CIE lightness, a* and b* contain chromatic
    //    information.  A given color will be represented by three
    //    numbers, (L*,a*,b*).  The ranges are 0 <= L* <= 100, -500 <= a* <= 500,
    //    -200 <= b* <= 200.
    //
    //  Modified:
    //
    //    11 September 1998
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, real XCAP, YCAP, ZCAP, the CIE XYZ color coordinates.
    //
    //    Input, real XCAPN, YCAPN, ZCAPN, the CIE XYZ color coordinates of white.
    //
    //    Output, real LSTAR, ASTAR, BSTAR, the CIE L*a*b* color coordinates.
    //
    public static void xyz2lab(double[] xyz, double[] lab, double[] capn)
    {
        double xcap= xyz[0], ycap=xyz[1], zcap=xyz[2];
        double xcapn= capn[0],ycapn= capn[1],zcapn= capn[2];
        double fx,fy,fz;
        double astar, bstar, lstar;

        if ( xcapn==0 || ycapn==0 || zcapn== 0.0 ) {
            System.err.println("ERROR: XCAPN, YCAPN and ZCAPN cannot be zero.");
            return;
        }

        //
        //  Compute the CIE lightness.
        //

        if ( ycap == 0.0 ) lstar = 0.0;
        else if ( ycap <= 0.008856 * ycapn ) lstar = 903.3 * ycap / ycapn;
        else if ( ycap <= ycapn )
            lstar = 116.0 * Math.pow(  ycap / ycapn , 1.0/3 ) - 16.0;
        else lstar = 100.0;

        if ( xcap <= 0.008856 * xcapn ) fx = 7.787 * xcap / xcapn + 16.0 / 116.0;
        else fx = Math.pow( ( xcap / xcapn ), 1.0/3);

        if ( ycap <= 0.008856 * ycapn ) fy = 7.787 * ycap / ycapn + 16.0 / 116.0;
        else  fy = Math.pow ( ( ycap / ycapn ), 1.0/3);

        if ( zcap <= 0.008856 * zcapn ) fz = 7.787 * zcap / zcapn + 16.0 / 116.0;
        else fz = Math.pow ( ( zcap / zcapn ), 1.0/3);

        astar = 500.0 * ( fx - fy );
        bstar = 200.0 * ( fy - fz );
        lab[0]= lstar; lab[1]= astar; lab[2]=bstar;
    }

    //
    //***********************************************************************
    //
    //  XYZ_TO_RGB709 converts CIE XYZ to RGB709 color coordinates.
    //
    //
    //  Definition:
    //
    //    The CIE XYZ color system describes a color in terms of its components
    //    of X, Y and Z primaries.  In ordinary circumstances, all three of
    //    these components must be nonnegative.
    //
    //  Modified:
    //
    //    06 September 1998
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, real XCAP, YCAP, ZCAP, the CIE XYZ color coordinates.
    //
    //    Output, real R, G, B, the RGB 709 color coordinates.
    //
    public static void xyz2rgb(double[] xyz, double[]rgb)
    {
        double xcap= xyz[0], ycap=xyz[1], zcap=xyz[2];
        rgb[0] =  3.240479 * xcap - 1.53715  * ycap - 0.498535 * zcap;
        rgb[1] = -0.969256 * xcap + 1.875991 * ycap + 0.041556 * zcap;
        rgb[2] =  0.055648 * xcap - 0.204043 * ycap + 1.057311 * zcap;
    }


    //
    //***********************************************************************
    //
    //! RGB709_TO_XYZ converts RGB709 to CIE XYZ color coordinates.
    //
    //
    //  Definition:
    //
    //    The CIE XYZ color system describes a color in terms of its components
    //    of X, Y and Z primaries.  In ordinary circumstances, all three of
    //    these components must be nonnegative.
    //
    //  Modified:
    //
    //    06 September 1998
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, real R, G, B, the RGB 709 color coordinates to be converted.
    //
    //    Output, real XCAP, YCAP, ZCAP, the corresponding CIE XYZ color coordinates.
    //
    public static void rgb2xyz(double[] rgb, double[] xyz)
    {
        double r= rgb[0], g=rgb[1], b=rgb[2];

        xyz[0] = 0.412453 * r + 0.35758  * g + 0.180423 * b;
        xyz[1] = 0.212671 * r + 0.71516  * g + 0.072169 * b;
        xyz[2] = 0.019334 * r + 0.119193 * g + 0.950227 * b;
    }


    //
    //***********************************************************************
    //
    //  NAME_TO_XYZ converts a color or illuminant name to CIE xyz chromaticities.
    //
    //
    //  Definition:
    //
    //    In the CIE color system, the exact chromaticities of several
    //    standard illuminants were defined.  These were generally chosen to
    //    correspond to common lighting situations.
    //
    //  Modified:
    //
    //    27 January 1999
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, character*(*) NAME, the name of a color.  Before considering
    //    the name, the routine removes all blanks and underscores, and
    //    capitalizes the name.  Legal names include:
    //
    //      'A', the CIE illuminant A, light from a tungsten lamp, at 500 watts;
    //      'B', the CIE illuminant B, direct sunlight, at 500 watts;
    //      'C', the CIE illuminant C, average sunlight, at 500 watts;
    //        This is used as the reference white for NTSC color encoding.
    //      'D50' or 'D5000', the CIE illuminant used in graphics printing,
    //        bright tunsten illumination;
    //      'D55' or 'D5500', a CIE illuminant that approximates a cloudy bright day;
    //      'D65' or 'D6500', the CIE illuminant that approximates daylight;
    //        This is used as the reference white for SMPTE, PAL/EBU, and HDTV
    //        color encoding.
    //      'E', the CIE illuminant E, normalized reference source.
    //
    //    Output, real X, Y, Z, the corresponding CIE xyz chromaticities,
    //    or (0,0,0) if the name is not recognized.
    //
    static void name2xyz(String name, double[] xyz)
    {
        double x,y,z;

        if ( name.compareTo( "A" )==0 ) {
            x = 0.448;
            y = 0.407;
            z = 0.145;
        }
        else if ( name.compareTo( "B" )==0 ) {
            x = 0.349;
            y = 0.352;
            z = 0.299;
        }
        else if ( name.compareTo( "C" )==0 ) {
            x = 0.3101;
            y = 0.3162;
            z = 0.3737;
        }
        else if ( name.compareTo( "D50" )==0 || name.compareTo( "D5000" )==0 ) {
            x =  96.42 / ( 96.42 + 100.00 + 82.49 );
            y = 100.00 / ( 96.42 + 100.00 + 82.49 );
            z =  82.49 / ( 95.42 + 100.00 + 82.49 );
        }
        else if ( name.compareTo( "D55" )==0 || name.compareTo( "D5500" )==0 ) {
            x = 0.3324;
            y = 0.3474;
            z = 0.3202;
        }
        else if ( name.compareTo( "D65" )==0 || name.compareTo( "D6500" )==0 ) {
            x =  95.05 / ( 95.05 + 100.00 + 108.91 );
            y = 100.00 / ( 95.05 + 100.00 + 108.91 );
            z = 108.91 / ( 95.05 + 100.00 + 108.91 );
        }
        else if ( name.compareTo( "E" )==0 ) {
            x = 100.0 / 300.0;
            y = 100.0 / 300.0;
            z = 100.0 / 300.0;
        }
        else {
            x = 0.0;
            y = 0.0;
            z = 0.0;
        }
        xyz[0]=x;xyz[1]=y;xyz[2]=z;
    }

    //
    //***********************************************************************
    //
    //  XYY_TO_XYZ converts CIE xyY to CIE XYZ color coordinates.
    //
    //
    //  Definition:
    //
    //    The CIE xyY system defines a color in terms of its normalized
    //    chromaticities (x,y), plus the value of Y, which allows the
    //    normalizing factor to be determined.
    //
    //    The CIE XYZ color system describes a color in terms of its components
    //    of X, Y and Z primaries.  In ordinary circumstances, all three of
    //    these components must be nonnegative.
    //
    //  Modified:
    //
    //    09 September 1998
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, real x, y, the CIE xy chromaticities.
    //
    //    Output, real XCAP, the CIE X color coordinate.
    //
    //    Input, real YCAP, the CIE Y color coordinate.
    //
    //    Output, real ZCAP, the CIE Z color coordinate.
    //
    static void xyy2xyz(double x, double y, double[] xyz)
    {
        double ycap= xyz[1];
        double xcap, zcap;
        if ( ycap == 0.0 ) {
            xcap = 0.0;
            zcap = 0.0;
        }
        else {
            xcap = x * ycap / y;
            if (xcap<0) xcap= 0.0;

            double z = 1.0 - x - y;
            zcap = z * ycap / y;
            if (zcap<0) zcap=0;
        }
        xyz[0]=xcap; xyz[2]=zcap;
    }

    /**
     * Convert a RGB color to Lab Colr.
     * @param rgb pass in the r,g,b components of a RGB color.
     * @param lab return the l,a,b components of the lab color.
     */
    public static void rgb2lab(double[] rgb, double[] lab) {
        double r=rgb[0],g=rgb[1],b=rgb[2];
        double x=0.412453 * r + 0.35758  * g + 0.180423 * b;
        double y=0.212671 * r + 0.71516  * g + 0.072169 * b;
        double z=0.019334 * r + 0.119193 * g + 0.950227 * b;

        double fy=f(y);
        double l=116*fy-16;
        double a=500*(f(x/0.950456)-fy);
        double bs=200*(fy-f(z/1.088754));
        lab[0]=l;lab[1]=a;lab[2]=bs;
    }

    public static void rgb2lab(int rgb, double[] lab) {
      int[] rgbs = ColorUtil.RGB2IntArray(rgb);
      double[] double_rgbs = new double[] {rgbs[0]/255.0, rgbs[1]/255.0, rgbs[2]/255.0};
      rgb2lab(double_rgbs, lab);
    }

    public final static int ADJUST_L=0;
    public final static int ADJUST_A=500;
    public final static int ADJUST_B=200;

    /**
     * <p>
     * Convert the rgb color represented as 0xffrrggbb to lab color
     * represented as 0xllaaabbb.
     * </p>
     *
     * <p>
     * The standard l,a, and b are in the ranges:
     * </p>
     *
     * <pre>
     * l:[0..100] could be represented by 7 bits
     * a:[-500..+500] could be represented by 10 bits
     * b:[-200..+200] could be represented by 9 bits
     * </pre>
     *
     * <p>
     * In the returned value, they will be adjusted to [0,100], [0,1000], [0,400]
     * </p>
     *
     * @param rgb rgb color in format of 0xffrrggbb
     * @return lab color in format of 0xllaaabbb
     */
    public static int rgb2lab(int rgb)
    {
        double[] d_rgb= {((rgb>>16)&0xff)/255.0,((rgb>>8)&0xff)/255.0,(rgb&0xff)/255.0};
        double[] lab= new double[3];
        rgb2lab(d_rgb,lab);

        int l= (int)Math.round(lab[0])+ADJUST_L;
        int a= (int)Math.round(lab[1])+ADJUST_A; //[0..1000]
        int b= (int)Math.round(lab[2])+ADJUST_B; //[0..400]
        return (l<<24)| (a<<12) |b;
    }

    /**
     * Return the l component of a lab color.  Remember the components of an
     * integer lab is adjusted?  They will be adjusted back here.
     * @param lab the lab color packed in an integer.
     * @return the l component.
     */
    public static int getL(int lab) {
      int l=((lab>>24)&0xff) - CIELab.ADJUST_L;
      if (l>100) System.err.println("L="+l);
      return ((lab>>24)&0xff) - CIELab.ADJUST_L;
    }

    /**
     * Return the a component of a lab color.  Remember the components of an
     * integer lab is adjusted?  They will be adjusted back here.
     * @param lab the lab color packed in an integer.
     * @return the a component.
     */
    public static int getA(int lab) {
      int a=((lab>>12)&0xfff)-CIELab.ADJUST_A;
      if (a>500) System.err.println("A="+a);
      return ((lab>>12)&0xfff)-CIELab.ADJUST_A;
    }

    /**
     * Return the b component of a lab color.  Remember the components of an
     * integer lab is adjusted?  They will be adjusted back here.
     * @param lab the lab color packed in an integer.
     * @return the b component.
     */
    public static int getB(int lab) {
      int b=((lab)&0xfff) - CIELab.ADJUST_B;
      if (b>200) System.err.println("B="+b);
      return ((lab)&0xfff) - CIELab.ADJUST_B;
    }

    /**
     * <p>
     * Convert an image in rgb color to an image in lab color.  The color
     * components of every lab color are adjusted so that the color can be
     * stored in a integer.
     * </p>
     *
     * <p>
     * The standard l,a, and b are in the ranges:
     * </p>
     *
     * <pre>
     * l:[0..100] could be represented by 7 bits
     * a:[-500..+500] could be represented by 10 bits
     * b:[-200..+200] could be represented by 9 bits
     * </pre>
     *
     * <p>
     * In the returned value, they will be adjusted to [0,100], [0,1000], [0,400]
     * </p>
     * @param image rgb color image in format of 0xffrrggbb
     * @return lab color image in format of 0xllaaabbb
     */
    public static int[] rgb2lab(int[] image) {
        int[] lab_image= new int[image.length];
        for (int i=0;i<image.length;i++) {
            lab_image[i]= rgb2lab(image[i]);
        }
        return lab_image;
    }

    /**
     * Convert an array of rgb colors (eg. an  image) to lab colors
     * @param rgbs
     * @param labs
     */
    public static void rgb2lab(int[] image, double[][] labs) {
      for (int i=0;i<image.length;i++) {
          rgb2lab(image[i], labs[i]);
      }
    }

    static double f(double q) {
        if (q>0.008856) return Math.pow(q,1.0/3);
        else return 7.787*q+16/116.0;
    }

    /**
     * Convert a lab color to a rgb color.
     *
     * @param lab three components of a CIELab color
     * @return RGB color in 0xffrrggbb format
     */
    public static int lab2rgb(double[] lab) {
        double[] xyz=new double[3];
        double[] xyzcapn= {0.950456,1,1.088754};
        double[] rgb2= new double[3];
        lab2xyz(lab, xyz, xyzcapn);
        xyz2rgb(xyz, rgb2);
        int r=(int)Math.round(rgb2[0]*255);
        int g=(int)Math.round(rgb2[1]*255);
        int b=(int)Math.round(rgb2[2]*255);
        if (r>255) {
            r=255;
            if (r>256) {
              System.err.println("lab2rgb: r>256:"+r);
            }
        }
        if (r<0) {
            System.err.println("lab2rgb: r<0:"+r); r=0;
        }
        if (g>255) {
            g=255;
            if (g>256) System.err.println("lab2rgb: g>256:"+g);
        }
        if (g<0) {
            System.err.println("lab2rgb: g<0:"+g); g=0;
        }
        if (b>255) {
            b=255;
            if (b>256) System.err.println("lab2rgb: b>256:"+b);
        }
        if (b<0) {
            System.err.println("lab2rgb: b<0:"+b); b=0;
        }
        return 0xff000000|(r<<16)|(g<<8)|b;
    }

    public static int lab2rgb(double l, double a, double b) {
        double[] lab= {l,a,b};
        return lab2rgb(lab);
    }

    public static int lab2rgb(CIELab lab) {
        return lab2rgb(lab.L, lab.a, lab.b);
    }

    public static double distance(double l1, double a1, double b1,
        double l2, double a2, double b2) {
            return Math.sqrt((l1-l2)*(l1-l2)+
                (a1-a2)*(a1-a2)+
                (b1-b2)*(b1-b2));
    }

    public static double distance(int rgb1, int rgb2){
      double[] lab1 = new double[3], lab2 = new double[3];
      rgb2lab(rgb1, lab1);
      rgb2lab(rgb2, lab2);
      double dl = lab1[0]-lab2[0];
      double da = lab1[1]-lab2[1];
      double db = lab1[2]-lab2[2];
      return Math.sqrt(dl * dl + da * da + db * db);
    }

    public static double squaredDistance(double l1, double a1, double b1,
        double l2, double a2, double b2) {
            return ((l1-l2)*(l1-l2)+
                (a1-a2)*(a1-a2)+
                (b1-b2)*(b1-b2));
    }

    public static double edistance(double l1, double a1, double b1,
        double l2, double a2, double b2) {
            if (l1<=35&&l2<=35) return 0;
            return Math.sqrt((l1-l2)*(l1-l2)+
                (a1-a2)*(a1-a2)+
                (b1-b2)*(b1-b2));
    }

    public static void main(String args[]) {
        double[] rgb={0.4,0.4,0};

        double ycapn = 100.0;
        double[] xyzn= new double[3];
        name2xyz ( "D65", xyzn );
        double[] xyzcapn= new double[3];
        xyzcapn[1]=ycapn;
        xyy2xyz ( xyzn[0], xyzn[1], xyzcapn);

        double[] white={1,1,1};
        rgb2xyz(white, xyzcapn);
        //xyzcapn[0]/=100;xyzcapn[1]/=100;xyzcapn[2]/=100;
        double[] xyz= new double[3];
        double[] lab= new double[3];
        double[] lab2= new double[3];
        double[] rgb2= new double[3];
        double max=0,max1=0;
        int index=0;

        double big=0;
        for (int r=0;r<=10;r++) {
            for (int g=0;g<=10;g++) {
                for (int b=0;b<=10;b++) {
                    rgb[0]=r/10.0;rgb[1]=g/10.0;rgb[2]=b/10.0;
                    rgb2xyz(rgb, xyz);
                    xyz2lab(xyz, lab, xyzcapn);
                    rgb2lab(rgb,lab2);
                    lab2xyz(lab, xyz, xyzcapn);
                    xyz2rgb(xyz, rgb2);
                    double d= Math.sqrt(
                        (rgb[0]-rgb2[0])*(rgb[0]-rgb2[0])+
                        (rgb[1]-rgb2[1])*(rgb[1]-rgb2[1])+
                        (rgb[2]-rgb2[2])*(rgb[2]-rgb2[2]));
                    if (d>max) max=d;
                    System.err.println(" "+d+"("+r+","+g+","+b+")");
                    d= Math.sqrt(
                        (lab[0]-lab2[0])*(lab[0]-lab2[0])+
                        (lab[1]-lab2[1])*(lab[1]-lab2[1])+
                        (lab[2]-lab2[2])*(lab[2]-lab2[2]));
                    if (d>max1) {max1=d;index=r*100+g*10+b;}
                    System.err.println(" -"+d);

                    if (r+g+b<3) {
                        if (lab[0]>big) big=lab[0];
                    }

                }
            }
        }
        System.err.println("big="+big);
        System.err.println("max diff="+max);
        System.err.println("max rgb2lab diff="+max1+" at"+index);


    }
}
