2011年4月8日金曜日

C# RGB ⇔ CIEXYZ ⇔ CIELAB 相互変換

RGB⇔CIEXYZ⇔CIELABの相互変換できる構造体を作成した

  1. //RGBからL*a*b*へ  
  2. CIELAB Lab = new CIELAB(Color.Blue);  
  3. //L*a*b*からRGBへ  
  4. Color col = Lab.ToColor();  
  5. //RGBからCIEXYZへ  
  6. CIEXYZ xyz = new CIEXYZ(Color.Blue);  
  7. //CIEXYZからRGBへ  
  8. Color col = xyz.ToColor();  
  9. //L*a*b*からXYZへ  
  10. CIEXYZ xyz = new CIEXYZ(Lab);  
  11. //XYZからL*a*b*へ  
  12. CIELAB Lab = new CIELAB(xyz);  
こんなかんじで。





  1. //     
  2. // CIELAB構造体     
  3. // Hiroaki,Komori      
  4. //     
  5. using System;  
  6. using System.Drawing;  
  7.    
  8. struct CIELAB  
  9. {  
  10.   private const double Xn = 0.950456;  
  11.   private const double Yn = 1.0;  
  12.   private const double Zn = 1.088754;  
  13.    
  14.   private double l;  
  15.   private double a;  
  16.   private double b;  
  17.    
  18.   public double L  
  19.   {  
  20.     get { return l; }  
  21.     set { l = value; }  
  22.   }  
  23.    
  24.   public double A  
  25.   {  
  26.     get { return a; }  
  27.     set { a = value; }  
  28.   }  
  29.    
  30.   public double B  
  31.   {  
  32.     get { return b; }  
  33.     set { b = value; }  
  34.   }  
  35.    
  36.    
  37.   public CIELAB(Double _L, Double _A, Double _B)  
  38.   {  
  39.     l = _L;  
  40.     a = _A;  
  41.     b = _B;  
  42.   }  
  43.    
  44.   public CIELAB(Color rgb)  
  45.   {  
  46.     CIELAB _lab = CIELAB.Parse(rgb);  
  47.     l = _lab.L;  
  48.     a = _lab.A;  
  49.     b = _lab.B;  
  50.   }  
  51.    
  52.   public CIELAB(CIEXYZ xyz)  
  53.   {  
  54.     CIELAB _lab = CIELAB.Parse(xyz);  
  55.     l = _lab.L;  
  56.     a = _lab.A;  
  57.     b = _lab.B;  
  58.   }  
  59.    
  60.   ///<summary>  
  61.   /// Colorへ変換  
  62.   ///</summary>  
  63.   ///<param name="" hsv""="">///<returns></returns>  
  64.   public Color ToColor()  
  65.   {  
  66.     return ToCIEXyz().ToColor();  
  67.   }  
  68.    
  69.   ///<summary>  
  70.   /// CIEXyzへ変換  
  71.   ///</summary>  
  72.   ///<param name="" hsv""="">///<returns></returns>  
  73.   public CIEXYZ ToCIEXyz()  
  74.   {  
  75.     double _delta = 6.0 / 29.0;  
  76.     double _fy = (l + 16.0) / 116.0;  
  77.     double _fx = _fy + a / 500.0;  
  78.     double _fz = _fy - b / 200.0;  
  79.    
  80.     double _x, _y, _z;  
  81.    
  82.     if (_fx > _delta)  
  83.     {  
  84.       _x = Xn * Math.Pow(_fx, 3);  
  85.     }  
  86.     else  
  87.     {  
  88.       _x = (_fx - 16.0 / 116.0) * 3 * Math.Pow(_delta, 2);  
  89.     }  
  90.    
  91.     if (_fy > _delta)  
  92.     {  
  93.       _y = Yn * Math.Pow(_fy, 3);  
  94.     }  
  95.     else  
  96.     {  
  97.       _y = (_fy - 16.0 / 116.0) * 3 * Math.Pow(_delta, 2);  
  98.     }  
  99.    
  100.     if (_fz > _delta)  
  101.     {  
  102.       _z = Zn * Math.Pow(_fz, 3);  
  103.     }  
  104.     else  
  105.     {  
  106.       _z = (_fz - 16.0 / 116.0) * 3 * Math.Pow(_delta, 2);  
  107.     }  
  108.    
  109.     return new CIEXYZ(_x, _y, _z);  
  110.   }  
  111.    
  112.   ///<summary>  
  113.   /// CIEXYZからCIELabへ変換  
  114.   ///</summary>  
  115.   public static CIELAB Parse(CIEXYZ xyz)  
  116.   {  
  117.     double _l = 116.0 * Fxyz(xyz.Y / Yn) - 16;  
  118.     double _a = 500.0 * (Fxyz(xyz.X / Xn) - Fxyz(xyz.Y / Yn));  
  119.     double _b = 200.0 * (Fxyz(xyz.Y / Yn) - Fxyz(xyz.Z / Zn));  
  120.    
  121.     CIELAB _result = new CIELAB(_l, _a, _b);  
  122.    
  123.     return _result;  
  124.   }  
  125.    
  126.   ///<summary>  
  127.   /// XYZ to L*a*b* transformation function.  
  128.   ///</summary>  
  129.   private static double Fxyz(double t)  
  130.   {  
  131.     double _result;  
  132.     if (t > 0.008856)  
  133.     {  
  134.       _result = Math.Pow(t, (1.0 / 3.0));  
  135.     }  
  136.     else  
  137.     {  
  138.       _result = 7.787 * t + 16.0 / 116.0;  
  139.     }  
  140.    
  141.     return _result;  
  142.   }  
  143.    
  144.   ///<summary>  
  145.   /// CIEXYZからColorへ変換  
  146.   ///</summary>  
  147.   ///<param name="" col""="">  ///<returns></returns>  
  148.   public static CIELAB Parse(Color col)  
  149.   {  
  150.     CIEXYZ _xyz = CIEXYZ.Parse(col);  
  151.     return CIELAB.Parse(_xyz);  
  152.   }  
  153.    
  154.   ///<summary>  
  155.   ///文字列に変換  
  156.   ///</summary>  
  157.   ///<returns></returns>  
  158.   public override string ToString()  
  159.   {  
  160.     string _result = string.Format("CIELab [L*={0}, a*={1}, b*={2}", l.ToString("F"), a.ToString("F"), b.ToString("F"));  
  161.     return _result;  
  162.   }  
  163. }  
  164.    
  165. //     
  166. // CIEXYZ構造体     
  167. // Hiroaki,Komori      
  168. //     
  169. struct CIEXYZ  
  170. {  
  171.     private double x;  
  172.     private double y;  
  173.     private double z;  
  174.   
  175.     public double X  
  176.     {  
  177.         get { return x; }  
  178.         set { x = value; }  
  179.     }  
  180.   
  181.     public double Y  
  182.     {  
  183.         get { return y; }  
  184.         set { y = value; }  
  185.     }  
  186.   
  187.     public double Z  
  188.     {  
  189.         get { return z; }  
  190.         set { z = value; }  
  191.     }  
  192.   
  193.   
  194.     public CIEXYZ(Double _X, Double _Y, Double _Z)  
  195.     {  
  196.         x = _X;  
  197.         y = _Y;  
  198.         z = _Z;  
  199.     }  
  200.   
  201.     public CIEXYZ(Color rgb)  
  202.     {  
  203.         CIEXYZ _xyz = Parse(rgb);  
  204.   
  205.         x = _xyz.X;  
  206.         y = _xyz.Y;  
  207.         z = _xyz.Z;  
  208.     }  
  209.   
  210.     ///<summary>  
  211.     /// CIELabからCIEXyzへ変換  
  212.     ///</summary>  
  213.     ///<param name="" lab""="">    public CIEXYZ(CIELAB Lab)  
  214.     {  
  215.         CIEXYZ _xyz = Lab.ToCIEXyz();  
  216.         x = _xyz.X;  
  217.         y = _xyz.Y;  
  218.         z = _xyz.Z;  
  219.     }  
  220.   
  221.     ///<summary>  
  222.     /// ColorからXYZへ変換  
  223.     ///</summary>  
  224.     ///<param name="" col""="">    ///<returns></returns>  
  225.     public static CIEXYZ Parse(Color col)  
  226.     {  
  227.         double _RLinear = col.R / 255d;  
  228.         double _GLinear = col.G / 255d;  
  229.         double _BLinear = col.B / 255d;  
  230.   
  231.         double _r, _g, _b, _x, _y, _z;  
  232.   
  233.         if (_RLinear > 0.04045)  
  234.         {  
  235.             _r = Math.Pow((_RLinear + 0.055) / (1 + 0.055), 2.2);  
  236.         }  
  237.         else  
  238.         {  
  239.             _r = (_RLinear / 12.92);  
  240.         }  
  241.   
  242.         if (_GLinear > 0.04045)  
  243.         {  
  244.             _g = Math.Pow((_GLinear + 0.055) / (1 + 0.055), 2.2);  
  245.         }  
  246.         else  
  247.         {  
  248.             _g = (_GLinear / 12.92);  
  249.         }  
  250.   
  251.         if (_BLinear > 0.04045)  
  252.         {  
  253.             _b = Math.Pow((_BLinear + 0.055) / (1 + 0.055), 2.2);  
  254.         }  
  255.         else  
  256.         {  
  257.             _b = (_BLinear / 12.92);  
  258.         }  
  259.   
  260.         _x = _r * 0.4124 + _g * 0.3576 + _b * 0.1805;  
  261.         _y = _r * 0.2126 + _g * 0.7152 + _b * 0.0722;  
  262.         _z = _r * 0.0193 + _g * 0.1192 + _b * 0.9505;  
  263.         CIEXYZ _result = new CIEXYZ(_x, _y, _z);  
  264.   
  265.         return _result;  
  266.     }  
  267.   
  268.     ///<summary>  
  269.     /// Colorへ変換  
  270.     ///</summary>  
  271.     ///<param name="" xyz""="">    ///<returns></returns>  
  272.     public Color ToColor()  
  273.     {  
  274.         double _r = 3.240479 * x - 1.53715 * y - 0.498535 * z;  
  275.         double _g = -0.969256 * x + 1.875991 * y + 0.041556 * z;  
  276.         double _b = 0.055648 * x - 0.204043 * y + 1.057311 * z;  
  277.   
  278.         Color _result = Color.FromArgb(FromLinear(_r), FromLinear(_g), FromLinear(_b));  
  279.         return _result;  
  280.     }  
  281.   
  282.     private static int FromLinear(double v)  
  283.     {  
  284.         int _result;  
  285.   
  286.         if (v <= 0.0031308)  
  287.         {  
  288.             _result = (int)(Clamp(v * 12.92) * 255.0 + 0.5);  
  289.         }  
  290.         else  
  291.         {  
  292.             _result = (int)(Clamp(1.055 * Math.Pow(v, (1.0 / 2.4)) - 0.055) * 255.0 + 0.5);  
  293.         }  
  294.   
  295.         return _result;  
  296.     }  
  297.   
  298.     private static double Clamp(double v)  
  299.     {  
  300.         double _result = v;  
  301.   
  302.         if (v < 0.0)  
  303.         {  
  304.             _result = 0.0;  
  305.         }  
  306.         else if (v > 1.0)  
  307.         {  
  308.             _result = 1.0;  
  309.         }  
  310.   
  311.         return _result;  
  312.     }  
  313.   
  314.     public CIELAB ToCIELab()  
  315.     {  
  316.         CIELAB _result = new CIELAB(new CIEXYZ(x, y, z));  
  317.         return _result;  
  318.     }  
  319.   
  320.     ///<summary>  
  321.     ///文字列に変換  
  322.     ///</summary>  
  323.     ///<returns></returns>  
  324.     public override string ToString()  
  325.     {  
  326.         string _result = string.Format("CIEXyz [X={0}, Y={1}, Z={2}", x.ToString("F"), y.ToString("F"), z.ToString("F"));  
  327.         return _result;  
  328.     }  
  329. }  

0 件のコメント:

コメントを投稿