using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace CRS
{
    /// <完成sRGB XYZ Lab颜色空间相互转换及相关计算的类>
    ///
    ///
   internal class ColorSpaceTransform
    {
       public static double[] sRGB2XYZ(double [] sRGB)
       {
           double[] XYZ = new double[3];
           double sR, sG, sB;
           sR = sRGB[0];
           sG = sRGB[1];
           sB = sRGB[2];
           sR /= 255;
           sG /= 255;
           sB /= 255;

           if (sR<=0.04045)
           {
               sR = sR / 12.92;
           }
           else
           {
               sR = Math.Pow(((sR + 0.055) / 1.055), 2.4);
           }

           if (sG <= 0.04045)
           {
               sG = sG / 12.92;
           }
           else
           {
               sG = Math.Pow(((sG + 0.055) / 1.055), 2.4);
           }

           if (sB <= 0.04045)
           {
               sB = sB / 12.92;
           }
           else
           {
               sB = Math.Pow(((sB + 0.055) / 1.055), 2.4);
           }

           XYZ[0] = 41.24 * sR + 35.76 * sG + 18.05 * sB;
           XYZ[1] = 21.26 * sR + 71.52 * sG + 7.2 * sB;
           XYZ[2] = 1.93 * sR + 11.92 * sG + 95.05 * sB;

           return XYZ;
       }
       public static int[] XYZ2sRGB(double [] XYZ)
       {
           int[] sRGB = new int[3];
           double X, Y, Z;
           double dr, dg, db;
           X = XYZ[0];
           Y = XYZ[1];
           Z = XYZ[2];

           dr = 0.032406 * X - 0.015371 * Y - 0.0049895 * Z;
           dg = -0.0096891 * X + 0.018757 * Y + 0.00041914 * Z;
           db = 0.00055708 * X - 0.0020401 * Y + 0.01057 * Z;

           if (dr<=0.00313)
           {
               dr = dr * 12.92;
           }
           else
           {
               dr = Math.Exp(Math.Log(dr) / 2.4) * 1.055 - 0.055;
           }

           if (dg <= 0.00313)
           {
               dg = dg * 12.92;
           }
           else
           {
               dg = Math.Exp(Math.Log(dg) / 2.4) * 1.055 - 0.055;
           }

           if (db <= 0.00313)
           {
               db = db * 12.92;
           }
           else
           {
               db = Math.Exp(Math.Log(db) / 2.4) * 1.055 - 0.055;
           }

           dr = dr * 255;
           dg = dg * 255;
           db = db * 255;

           dr = Math.Min(255, dr);
           dg = Math.Min(255, dg);
           db = Math.Min(255, db);

           sRGB[0] = (int)(dr + 0.5);
           sRGB[1] = (int)(dg + 0.5);
           sRGB[2] = (int)(db + 0.5);

           return sRGB;
       }
       public static double[] XYZ2Lab(double[] XYZ,double Xw,double Yw,double Zw)
       {
           double[] Lab = new double[3];
           double X, Y, Z;
           X = XYZ[0];
           Y = XYZ[1];
           Z = XYZ[2];
           double Xn, Yn, Zn;
           Xn = Xw;
           Yn = Yw;
           Zn = Zw;
           double XXn, YYn, ZZn;
           XXn = X / Xn;
           YYn = Y / Yn;
           ZZn = Z / Zn;

           double fx, fy, fz;

           if (XXn > 0.008856)
           {
               fx = Math.Pow(XXn, 0.333333);
           }
           else
           {
               fx = 7.787 * XXn + 0.137931;
           }

           if (YYn > 0.008856)
           {
               fy = Math.Pow(YYn, 0.333333);
           }
           else
           {
               fy = 7.787 * YYn + 0.137931;
           }

           if (ZZn > 0.008856)
           {
               fz = Math.Pow(ZZn, 0.333333);
           }
           else
           {
               fz = 7.787 * ZZn + 0.137931;
           }

           Lab[0] = 116 * fy - 16;
           Lab[1] = 500 * (fx - fy);
           Lab[2] = 200 * (fy - fz);

           return Lab;
       }
       public static double[] Lab2XYZ(double[] Lab)
       {
           double[] XYZ = new double[3];
           double L, a, b;
           double fx, fy, fz;
           double Xn, Yn, Zn;
           Xn = 95.04;
           Yn = 100;
           Zn = 108.89;

           L = Lab[0];
           a = Lab[1];
           b = Lab[2];

           fy = (L + 16) / 116;
           fx = a / 500 + fy;
           fz = fy - b / 200;

           if (fx>0.2069)
           {
               XYZ[0] = Xn * Math.Pow(fx, 3);
           }
           else
           {
               XYZ[0] = Xn * (fx - 0.1379) * 0.1284;
           }

           if ((fy > 0.2069) || (L>8))
           {
               XYZ[1] = Yn * Math.Pow(fy, 3);
           }
           else
           {
               XYZ[1] = Yn * (fy - 0.1379) * 0.1284;
           }

           if (fz > 0.2069)
           {
               XYZ[2] = Zn * Math.Pow(fz, 3);
           }
           else
           {
               XYZ[2] = Zn * (fz - 0.1379) * 0.1284;
           }

           return XYZ;
       }
    }
}
 

此类时我的CRS工程的一部分,用于常用的色度空间的转换计算。在VS08下经过测试,计算结果正确。

我写代码只为了完成功能,很少考虑复杂度,内存开销等问题,请大家谅解!