// Allocate conversion state structures and make look_up tables for // the Yr,Yb,Yg <=> r,g,b conversions. public static int TIFFCIELabToRGBInit(TIFFCIELabToRGB cielab, TIFFDisplay display, double[] refWhite) { cielab.range = TIFFCIELabToRGB.CIELABTORGB_TABLE_RANGE; cielab.display.CopyTo(display); cielab.rstep = (cielab.display.d_YCR - cielab.display.d_Y0R) / cielab.range; cielab.gstep = (cielab.display.d_YCG - cielab.display.d_Y0G) / cielab.range; cielab.bstep = (cielab.display.d_YCB - cielab.display.d_Y0B) / cielab.range; double gammaR = 1.0 / cielab.display.d_gammaR; double gammaG = 1.0 / cielab.display.d_gammaG; double gammaB = 1.0 / cielab.display.d_gammaB; for (int i = 0; i <= cielab.range; i++) { double v = (double)i / cielab.range; cielab.Yr2r[i] = cielab.display.d_Vrwr * ((float)Math.Pow(v, gammaR)); cielab.Yg2g[i] = cielab.display.d_Vrwg * ((float)Math.Pow(v, gammaG)); cielab.Yb2b[i] = cielab.display.d_Vrwb * ((float)Math.Pow(v, gammaB)); } // Init reference white point cielab.X0 = (float)refWhite[0]; cielab.Y0 = (float)refWhite[1]; cielab.Z0 = (float)refWhite[2]; return(0); }
// Allocate conversion state structures and make look_up tables for // the Yr,Yb,Yg <=> r,g,b conversions. public static int TIFFCIELabToRGBInit(TIFFCIELabToRGB cielab, TIFFDisplay display, double[] refWhite) { cielab.range=TIFFCIELabToRGB.CIELABTORGB_TABLE_RANGE; cielab.display.CopyTo(display); cielab.rstep=(cielab.display.d_YCR-cielab.display.d_Y0R)/cielab.range; cielab.gstep=(cielab.display.d_YCG-cielab.display.d_Y0G)/cielab.range; cielab.bstep=(cielab.display.d_YCB-cielab.display.d_Y0B)/cielab.range; double gammaR=1.0/cielab.display.d_gammaR; double gammaG=1.0/cielab.display.d_gammaG; double gammaB=1.0/cielab.display.d_gammaB; for(int i=0; i<=cielab.range; i++) { double v=(double)i/cielab.range; cielab.Yr2r[i]=cielab.display.d_Vrwr*((float)Math.Pow(v, gammaR)); cielab.Yg2g[i]=cielab.display.d_Vrwg*((float)Math.Pow(v, gammaG)); cielab.Yb2b[i]=cielab.display.d_Vrwb*((float)Math.Pow(v, gammaB)); } // Init reference white point cielab.X0=(float)refWhite[0]; cielab.Y0=(float)refWhite[1]; cielab.Z0=(float)refWhite[2]; return 0; }
// Convert color value from the XYZ space to RGB. public static void TIFFXYZToRGB(TIFFCIELabToRGB cielab, float X, float Y, float Z, out uint r, out uint g, out uint b) { int i; float Yr, Yg, Yb; float[,] matrix = cielab.display.d_mat; // Multiply through the matrix to get luminosity values. Yr = matrix[0, 0] * X + matrix[0, 1] * Y + matrix[0, 2] * Z; Yg = matrix[1, 0] * X + matrix[1, 1] * Y + matrix[1, 2] * Z; Yb = matrix[2, 0] * X + matrix[2, 1] * Y + matrix[2, 2] * Z; // Clip input Yr = Math.Max(Yr, cielab.display.d_Y0R); Yg = Math.Max(Yg, cielab.display.d_Y0G); Yb = Math.Max(Yb, cielab.display.d_Y0B); // Avoid overflow in case of wrong input values Yr = Math.Min(Yr, cielab.display.d_YCR); Yg = Math.Min(Yg, cielab.display.d_YCG); Yb = Math.Min(Yb, cielab.display.d_YCB); // Turn luminosity to colour value. i = (int)((Yr - cielab.display.d_Y0R) / cielab.rstep); i = Math.Min(cielab.range, i); r = (uint)Math.Round(cielab.Yr2r[i], MidpointRounding.AwayFromZero); i = (int)((Yg - cielab.display.d_Y0G) / cielab.gstep); i = Math.Min(cielab.range, i); g = (uint)Math.Round(cielab.Yg2g[i], MidpointRounding.AwayFromZero); i = (int)((Yb - cielab.display.d_Y0B) / cielab.bstep); i = Math.Min(cielab.range, i); b = (uint)Math.Round(cielab.Yb2b[i], MidpointRounding.AwayFromZero); // Clip output. r = Math.Min(r, cielab.display.d_Vrwr); g = Math.Min(g, cielab.display.d_Vrwg); b = Math.Min(b, cielab.display.d_Vrwb); }
// Convert color value from the CIE L*a*b* 1976 space to CIE XYZ. public static void TIFFCIELabToXYZ(TIFFCIELabToRGB cielab, uint l, int a, int b, out float X, out float Y, out float Z) { float L = (float)l * 100.0F / 255.0F; float cby, tmp; if (L < 8.856F) { Y = (L * cielab.Y0) / 903.292F; cby = 7.787F * (Y / cielab.Y0) + 16.0F / 116.0F; } else { cby = (L + 16.0F) / 116.0F; Y = cielab.Y0 * cby * cby * cby; } tmp = (float)a / 500.0F + cby; if (tmp < 0.2069F) { X = cielab.X0 * (tmp - 0.13793F) / 7.787F; } else { X = cielab.X0 * tmp * tmp * tmp; } tmp = cby - (float)b / 200.0F; if (tmp < 0.2069F) { Z = cielab.Z0 * (tmp - 0.13793F) / 7.787F; } else { Z = cielab.Z0 * tmp * tmp * tmp; } }
// Convert color value from the CIE L*a*b* 1976 space to CIE XYZ. public static void TIFFCIELabToXYZ(TIFFCIELabToRGB cielab, uint l, int a, int b, out float X, out float Y, out float Z) { float L=(float)l*100.0F/255.0F; float cby, tmp; if(L<8.856F) { Y=(L*cielab.Y0)/903.292F; cby=7.787F*(Y/cielab.Y0)+16.0F/116.0F; } else { cby=(L+16.0F)/116.0F; Y=cielab.Y0*cby*cby*cby; } tmp=(float)a/500.0F+cby; if(tmp<0.2069F) X=cielab.X0*(tmp-0.13793F)/7.787F; else X=cielab.X0*tmp*tmp*tmp; tmp=cby-(float)b/200.0F; if(tmp<0.2069F) Z=cielab.Z0*(tmp-0.13793F)/7.787F; else Z=cielab.Z0*tmp*tmp*tmp; }
// Convert color value from the XYZ space to RGB. public static void TIFFXYZToRGB(TIFFCIELabToRGB cielab, float X, float Y, float Z, out uint r, out uint g, out uint b) { int i; float Yr, Yg, Yb; float[,] matrix=cielab.display.d_mat; // Multiply through the matrix to get luminosity values. Yr=matrix[0, 0]*X+matrix[0, 1]*Y+matrix[0, 2]*Z; Yg=matrix[1, 0]*X+matrix[1, 1]*Y+matrix[1, 2]*Z; Yb=matrix[2, 0]*X+matrix[2, 1]*Y+matrix[2, 2]*Z; // Clip input Yr=Math.Max(Yr, cielab.display.d_Y0R); Yg=Math.Max(Yg, cielab.display.d_Y0G); Yb=Math.Max(Yb, cielab.display.d_Y0B); // Avoid overflow in case of wrong input values Yr=Math.Min(Yr, cielab.display.d_YCR); Yg=Math.Min(Yg, cielab.display.d_YCG); Yb=Math.Min(Yb, cielab.display.d_YCB); // Turn luminosity to colour value. i=(int)((Yr-cielab.display.d_Y0R)/cielab.rstep); i=Math.Min(cielab.range, i); r=(uint)Math.Round(cielab.Yr2r[i], MidpointRounding.AwayFromZero); i=(int)((Yg-cielab.display.d_Y0G)/cielab.gstep); i=Math.Min(cielab.range, i); g=(uint)Math.Round(cielab.Yg2g[i], MidpointRounding.AwayFromZero); i=(int)((Yb-cielab.display.d_Y0B)/cielab.bstep); i=Math.Min(cielab.range, i); b=(uint)Math.Round(cielab.Yb2b[i], MidpointRounding.AwayFromZero); // Clip output. r=Math.Min(r, cielab.display.d_Vrwr); g=Math.Min(g, cielab.display.d_Vrwg); b=Math.Min(b, cielab.display.d_Vrwb); }