Logo Search packages:      
Sourcecode: f-spot version File versions

Cms.cs

//
// A very incomplete wrapper for lcms
//

using System;
using System.IO;
using System.Collections;
using System.Reflection;
using System.Runtime.InteropServices;

#if ENABLE_NUNIT
using NUnit.Framework;
#endif

namespace Cms {
      public enum Format : uint {
            Rgb8  = 262169,
            Rgba8 = 262297,
            Rgba8Planar = 266393,
            Gbr8  = 263193,
            Rgb16 = 262170,
            Rgb16Planar = 266266,
            Rgba16 = 262298,
            Rgba16se = 264436,
            Rgb16se = 264218,
            Lab8 = 655385,
              Lab16 = 655386,
            Xyz16 = 589858,
            Yxy16 = 917530
      }

      public enum IccColorSpace : uint {
            XYZ                        = 0x58595A20,  /* 'XYZ ' */
            Lab                        = 0x4C616220,  /* 'Lab ' */
            Luv                        = 0x4C757620,  /* 'Luv ' */
            YCbCr                      = 0x59436272,  /* 'YCbr' */
            Yxy                        = 0x59787920,  /* 'Yxy ' */
            Rgb                        = 0x52474220,  /* 'RGB ' */
            Gray                       = 0x47524159,  /* 'GRAY' */
            Hsv                        = 0x48535620,  /* 'HSV ' */
            Hls                        = 0x484C5320,  /* 'HLS ' */
            Cmyk                       = 0x434D594B,  /* 'CMYK' */
            Cmy                        = 0x434D5920,  /* 'CMY ' */
            Color2                     = 0x32434C52,  /* '2CLR' */
            Color3                     = 0x33434C52,  /* '3CLR' */
            Color4                     = 0x34434C52,  /* '4CLR' */
            Color5                     = 0x35434C52,  /* '5CLR' */
            Color6                     = 0x36434C52,  /* '6CLR' */
            Color7                     = 0x37434C52,  /* '7CLR' */
            Color8                     = 0x38434C52,  /* '8CLR' */
            Color9                     = 0x39434C52,  /* '9CLR' */
            Color10                    = 0x41434C52,  /* 'ACLR' */
            Color11                    = 0x42434C52,  /* 'BCLR' */
            Color12                    = 0x43434C52,  /* 'CCLR' */
            Color13                    = 0x44434C52,  /* 'DCLR' */
            Color14                    = 0x45434C52,  /* 'ECLR' */
            Color15                    = 0x46434C52,  /* 'FCLR' */
      }

      public enum Intent {
            Perceptual           = 0,
            RelativeColorimetric = 1,
            Saturation           = 2,
            AbsoluteColorimetric = 3
      }

      public struct ColorCIExyY {
            public double x;
            public double y;
            public double Y;
            
            public ColorCIExyY (double x, double y, double Y)
            {
                  this.x = x;
                  this.y = y;
                  this.Y = Y;
            }

            public static ColorCIExyY WhitePointFromTemperature (int temp)
            {
                  double x, y;
                  CctTable.GetXY (temp, out x, out y);
                  return new ColorCIExyY (x, y, 1.0);
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern bool cmsWhitePointFromTemp(int TempSrc,  out ColorCIExyY white_point);

            public static ColorCIExyY WhitePointFromTemperatureCIE (int temp)
            {
                  ColorCIExyY wp;
                  cmsWhitePointFromTemp (temp, out wp);
                  return wp;
            }

            public static ColorCIExyY WhitePointFromTemperatureResource (int temp, string name)
            {
                  ColorCIExyY wp;
                  //const int line_size = 0x1e;

                  using (Stream stream = Assembly.GetExecutingAssembly ().GetManifestResourceStream (name)) {
                        StreamReader reader = new StreamReader (stream, System.Text.Encoding.ASCII);
                        string line = null;
                        for (int i = 0; i <= temp - 1000; i++) {
                              line = reader.ReadLine ();
                        }
                        
                        //System.Console.WriteLine (line);
                        string [] subs = line.Split ('\t');
                        int ptemp = int.Parse (subs [0]);
                        if (ptemp != temp)
                              throw new System.Exception (String.Format ("{0} != {1}", ptemp, temp));
                        
                        double x = double.Parse (subs [1]);
                        double y = double.Parse (subs [2]);
                        wp = new ColorCIExyY (x, y, 1.0);
                        return wp;
                  }                 
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern void cmsxyY2XYZ (out ColorCIEXYZ dest, ref ColorCIExyY src);

            public ColorCIEXYZ ToXYZ ()
            {
                  ColorCIEXYZ dest;
                  cmsxyY2XYZ (out dest, ref this);
                  
                  return dest;
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern IntPtr cmsD50_xyY();

            public static ColorCIExyY D50 {
                  get {
                        IntPtr ptr = cmsD50_xyY ();
                        return (ColorCIExyY) Marshal.PtrToStructure (ptr, typeof (ColorCIExyY));
                  }
            }

            public ColorCIELab ToLab (ColorCIExyY wp)
            {
                  return this.ToXYZ ().ToLab (wp);
            }

            public ColorCIELab ToLab (ColorCIEXYZ wp)
            {
                  return this.ToXYZ ().ToLab (wp);
            }

            public override string ToString ()
            {
                  return String.Format ("(x={0}, y={1}, Y={2})", x, y, Y);
            }
            
#if ENABLE_NUNIT
            [TestFixture]
            public class Tests {
                  [Test]
                  public void TestTempTable1000 ()
                  {
                        ColorCIExyY wp = WhitePointFromTemperature (1000);
                        Assert.AreEqual (0.652756059, wp.x);
                        Assert.AreEqual (0.344456906, wp.y);
                  }

                  [Test]
                  public void TestTempReader ()
                  {
                        for (int i = 1000; i <= 25000; i += 10000)
                              WhitePointFromTemperature (i);
                  }
                  
                  [Test]
                  public void TestTempTable10000 ()
                  {
                        ColorCIExyY wp = WhitePointFromTemperature (10000);
                        Assert.AreEqual (0.280635904, wp.x);
                        Assert.AreEqual (0.288290916, wp.y);
                  }
            }
#endif
      }

      public struct ColorCIEXYZ {
            public double x;
            public double y;
            public double z;
            
            public ColorCIEXYZ (double x, double y, double z)
            {
                  this.x = x;
                  this.y = y;
                  this.z = z;
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern void cmsXYZ2xyY (out ColorCIExyY dest, ref ColorCIEXYZ source);
            
            public ColorCIExyY ToxyY ()
            {
                  ColorCIExyY dest;
                  cmsXYZ2xyY (out dest, ref this);
                  
                  return dest;
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern void cmsXYZ2Lab (ref ColorCIEXYZ wp, out ColorCIELab lab, ref ColorCIEXYZ xyz);

            public ColorCIELab ToLab (ColorCIEXYZ wp)
            {
                  ColorCIELab lab;
                  cmsXYZ2Lab (ref wp, out lab, ref this);

                  return lab;
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern IntPtr cmsD50_XYZ();

            public static ColorCIEXYZ D50 {
                  get {
                        IntPtr ptr = cmsD50_XYZ ();
                        return (ColorCIEXYZ) Marshal.PtrToStructure (ptr, typeof (ColorCIEXYZ));
                  }
            }

            public ColorCIELab ToLab (ColorCIExyY wp)
            {
                  return ToLab (wp.ToXYZ ());
            }

            public override string ToString ()
            {
                  return String.Format ("(x={0}, y={1}, z={2})", x, y, z);
            }


      }

      public struct ColorCIELab {
            public double L;
            public double a;
            public double b;

            [DllImport("liblcms-1.0.0.dll")]
            static extern void cmsLab2LCh (out ColorCIELCh lch, ref ColorCIELab lab);

            public ColorCIELCh ToLCh ()
            {
                  ColorCIELCh lch;
                  cmsLab2LCh (out lch, ref this);

                  return lch;
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern void cmsLab2XYZ (ref ColorCIEXYZ wp, out ColorCIEXYZ xyz, ref ColorCIELab lab);
            
            public ColorCIEXYZ ToXYZ (ColorCIEXYZ wp)
            {
                  ColorCIEXYZ xyz;
                  cmsLab2XYZ (ref wp, out xyz, ref this);

                  return xyz;
            }

            public override string ToString ()
            {
                  return String.Format ("(L={0}, a={1}, b={2})", L, a, b);
            }
      }

      public struct ColorCIELCh {
            public double L;
            public double C;
            public double h;
            
            [DllImport("liblcms-1.0.0.dll")]
            static extern void cmsLCh2Lab (out ColorCIELab lab, ref ColorCIELCh lch);
            
            public ColorCIELab ToLab ()
            {
                  ColorCIELab lab;
                  cmsLCh2Lab (out lab, ref this);

                  return lab;
            }
      }

      public struct ColorCIExyYTriple {
            public ColorCIExyY Red;
            public ColorCIExyY Green;
            public ColorCIExyY Blue;

            public ColorCIExyYTriple (ColorCIExyY red, ColorCIExyY green, ColorCIExyY blue)
            {
                  Red = red;
                  Green = green;
                  Blue = blue;
            }
      }

      public struct ColorCIEXYZTriple {
            public ColorCIEXYZ Red;
            public ColorCIEXYZ Blue;
            public ColorCIEXYZ Green;

            ColorCIEXYZTriple (ColorCIEXYZ red, ColorCIEXYZ green, ColorCIEXYZ blue)
            {
                  Red = red;
                  Blue = blue;
                  Green = green;
            }
      }

      public class GammaTable : IDisposable {
            private HandleRef handle;
            public HandleRef Handle {
                  get {
                        return handle;
                  }
            }
            
            internal struct GammaTableStruct {
                  public int Count;
                  public ushort StartOfData;  // ushort array Count entries long
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern IntPtr cmsBuildGamma (int entry_count, double gamma);

            public GammaTable (int count, double gamma)
            {
                  handle = new HandleRef (this, cmsBuildGamma (count, gamma));
            }

            /*
              Does build a parametric curve based on parameters.
              Params[] does contain Gamma, a, b, c, d, e, f

              Type 1 :
              X = Y ^ Gamma   | Gamma = Params[0]
              
              Type 2 :
              CIE 122-1966
              Y = (aX + b)^Gamma  | X >= -b/a
              Y = 0               | else
              Type 3:
              
              IEC 61966-3
              Y = (aX + b)^Gamma | X <= -b/a
              Y = c              | else
              
              Type 4:
              IEC 61966-2.1 (sRGB)
              Y = (aX + b)^Gamma | X >= d
              Y = cX             | X < d
              
              Type 5:
              
              Y = (aX + b)^Gamma + e | X <= d
              Y = cX + f             | else
              
              Giving negative values for Type does result in reversed curve.
            */

            // FIXME type should be an enum
            [DllImport("liblcms-1.0.0.dll")]
            static extern IntPtr cmsBuildParametricGamma (int entry_count, int type, double [] values);
            
            public GammaTable (int entry_count, int type, double [] values)
            {
                  handle = new HandleRef (this, cmsBuildParametricGamma (entry_count, type, values));
            }
            

            [DllImport("liblcms-1.0.0.dll")]
            static extern IntPtr cmsAllocGamma (int entry_count);

            [DllImport ("libfspot")]
            static extern IntPtr f_cms_gamma_table_new (ushort [] values, int start, int length);

            [DllImport ("libfspot")]
            static extern IntPtr f_cms_gamma_table_get_values (HandleRef table);

            [DllImport ("libfspot")]
            static extern int f_cms_gamma_table_get_count (HandleRef table);

            public GammaTable (ushort [] values) : this (values, 0, values.Length)
            {
            }

            public int Count {
                  get {
                        return f_cms_gamma_table_get_count (handle);
                  }
            }

            public IntPtr Values {
                  get {
                        return f_cms_gamma_table_get_values (handle);
                  }
            }

            public ushort this [int index] {
                  get {
                        unsafe {
                              if (handle.Handle == (IntPtr)0)
                                    throw new ArgumentException ();
                              
                              if (index < 0 || index >= Count)
                                    throw new ArgumentOutOfRangeException (String.Format ("index {0} outside of count {1} for {2}", index, Count, handle.Handle));

                              ushort *data = (ushort *)Values;
                              return data [index];
                        }
                  }
                  set {
                        unsafe {
                              if (handle.Handle == (IntPtr)0)
                                    throw new ArgumentException ();
                              
                              if (index < 0 || index >= Count)
                                    throw new ArgumentOutOfRangeException (String.Format ("index {0} outside of count {1} for handle {2}", index, Count, handle.Handle));


                              ushort *data = (ushort *)Values;
                              data [index] = value;
                        }
                  }
            }
            
            public GammaTable (ushort [] values, int start_offset, int length)
            {
#if true
                  handle = new HandleRef (this, f_cms_gamma_table_new (values, start_offset, length));
                  //System.Console.WriteLine ("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXhandle = {0}", handle.Handle);
#else
                  handle = new HandleRef (this, cmsAllocGamma (length));
                  //System.Console.WriteLine ("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXhandle = {0}", handle.Handle);
                  for (int i = 0; i < length; i++)
                        this [i] = values [start_offset + i];
#endif
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern void cmsFreeGamma (HandleRef handle);
            
            protected virtual void Cleanup ()
            {
                  cmsFreeGamma (handle);
            }
            
            public void Dispose ()
            {
                  Cleanup ();
                  System.GC.SuppressFinalize (this);
            }
            
            ~GammaTable ()
            {
                  Cleanup ();
            }


#if ENABLE_NUNIT
            [TestFixture]
            public class Tests {
                  [Test]
                  public void TestAlloc ()
                  {
                        ushort [] values = new ushort [] { 0, 0x00ff, 0xffff };
                        GammaTable t = new GammaTable (values);
                        for (int i = 0; i < values.Length; i++) {
                              Assert.AreEqual (t[i], values [i]);
                        }
                  } 
            }
#endif 

      }
      
      public class Transform : IDisposable {
            private HandleRef handle;
            public HandleRef Handle {
                  get {
                        return handle;
                  }
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern IntPtr cmsCreateMultiprofileTransform (HandleRef [] hProfiles,
                                                     int nProfiles,
                                                     Format InputFormat,
                                                     Format OutputFormat,
                                                     int Intent,
                                                     uint dwFlags);

            public Transform (Profile [] profiles,
                          Format input_format,
                          Format output_format,
                          Intent intent, uint flags)
            {
                  HandleRef [] handles = new HandleRef [profiles.Length];
                  for (int i = 0; i < profiles.Length; i++) {
                        handles [i] = profiles [i].Handle;
                  }
                  
                  this.handle = new HandleRef (this, cmsCreateMultiprofileTransform (handles, handles.Length, 
                                                                     input_format,
                                                                     output_format, 
                                                                     (int)intent, flags));
            }
            
            [DllImport("liblcms-1.0.0.dll")]
            static extern IntPtr cmsCreateTransform(HandleRef Input,
                                          Format InputFormat,
                                          HandleRef Output,
                                          Format OutputFormat,
                                          int Intent,
                                          uint dwFlags);

            public Transform (Profile input, Format input_format,
                          Profile output, Format output_format,
                          Intent intent, uint flags)
            {
                  this.handle = new HandleRef (this, cmsCreateTransform (input.Handle, input_format,
                                                             output.Handle, output_format,
                                                             (int)intent, flags));
            }
            
            [DllImport("liblcms-1.0.0.dll")]
            static extern void cmsDoTransform (HandleRef hTransform, IntPtr InputBuffer, IntPtr OutputBuffer, uint size);
            
            // Fixme this should probably be more type stafe 
            public void Apply (IntPtr input, IntPtr output, uint size)
            {
                  cmsDoTransform (Handle, input, output, size);
            }
            
            [DllImport("liblcms-1.0.0.dll")]
            static extern void cmsDeleteTransform(HandleRef hTransform);
            
            public void Dispose () 
            {
                  Cleanup ();
                  System.GC.SuppressFinalize (this);
            }
            
            protected virtual void Cleanup ()
            {
                  cmsDeleteTransform (this.handle);
            }
            
            ~Transform () 
            {
                  Cleanup ();
            }
             
      }

      public class Profile : IDisposable {
            static Profile srgb = new Profile (cmsCreate_sRGBProfile());

            static Profile ()
            {
                  SetErrorAction (ErrorAction.Show);
            }

            private HandleRef handle;
            public HandleRef Handle {
                  get {
                        return handle;
                  }
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern IntPtr _cmsCreateProfilePlaceholder ();
            
            private Profile () : this (_cmsCreateProfilePlaceholder ())
            {
                  
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern IntPtr cmsCreate_sRGBProfile ();

            public static Profile CreateSRgb () 
            {
                  return CreateStandardRgb ();
            }
            

            public static Profile CreateStandardRgb () 
            {
                  return srgb;
            }
            
            public static Profile CreateAlternateRgb ()
            {
                  // FIXME I'm basing this off the values set in the camera
                  // exif data when the adobe profile is selected.  They could
                  // easily be off
                  ColorCIExyY wp = new ColorCIExyY (.3127, .329, 1.0);
                  ColorCIExyYTriple primaries = new ColorCIExyYTriple (
                        new ColorCIExyY (.64, .33, 1.0),
                        new ColorCIExyY (.21, .71, 1.0),
                        new ColorCIExyY (.15, .06, 1.0));
                  
                  GammaTable g = new GammaTable (4096, 2.2);
                  GammaTable [] gamma = new GammaTable [] { g, g, g, g};

                  return new Profile (wp, primaries, gamma);
            }

            [DllImport ("liblcms-1.0.0.dll")]
            static extern IntPtr cmsCreateLabProfile (out ColorCIExyY WhitePoint);

            public static Profile CreateLab (ColorCIExyY wp)
            {
                  return new Profile (cmsCreateLabProfile (out wp));
            }                 

            [DllImport ("liblcms-1.0.0.dll")]
            static extern IntPtr cmsCreateLabProfile (IntPtr foo);

            public static Profile CreateLab ()
            {
                  return new Profile (cmsCreateLabProfile (IntPtr.Zero));
            }                 

            [DllImport ("liblcms-1.0.0.dll")]
            static extern IntPtr cmsCreateGrayProfile (ref ColorCIExyY white_point,
                                             HandleRef transfer_function);
            
            public static Profile CreateGray (ColorCIExyY white_point, GammaTable transfer)
            {
                  if (transfer == null)
                        return new Profile (cmsCreateGrayProfile (ref white_point, new GammaTable (4096, 2.2).Handle));
                  else
                        return new Profile (cmsCreateGrayProfile (ref white_point, transfer.Handle));
            }

            [DllImport ("libfspot")]
            static extern IntPtr f_screen_get_profile (IntPtr screen);

            public static Profile GetScreenProfile (Gdk.Screen screen)
            {
                  IntPtr profile = f_screen_get_profile (screen.Handle);
                  
                  if (profile == IntPtr.Zero)
                        return null;
                  
                  return new Profile (profile);
            }


            [DllImport("liblcms-1.0.0.dll")]
            static extern IntPtr cmsCreateBCHSWabstractProfile(int nLUTPoints,
                                                   double Bright, 
                                                   double Contrast,
                                                   double Hue,
                                                   double Saturation,
                                                   int TempSrc, 
                                                   int TempDest);

            [DllImport("libfspot")]
            static extern IntPtr f_cmsCreateBCHSWabstractProfile(int nLUTPoints,
                                                     double Exposure,
                                                     double Bright, 
                                                     double Contrast,
                                                     double Hue,
                                                     double Saturation,
                                                     ref ColorCIExyY src_wp, 
                                                     ref ColorCIExyY dest_wp,
                                                     HandleRef [] tables);
            
            public static Profile CreateAbstract (int nLUTPoints,
                                          double Exposure,
                                          double Bright,
                                          double Contrast,
                                          double Hue,
                                          double Saturation,
                                          int TempSrc,
                                          int TempDest)
            {
#if true                
                  GammaTable gamma = new GammaTable (1024, Math.Pow (10, -Bright/100));
                  GammaTable line = new GammaTable (1024, 1.0);
                  GammaTable [] tables = new GammaTable [] { gamma, line, line };
                  return CreateAbstract (nLUTPoints, Exposure, 0.0, Contrast, Hue, Saturation, tables, 
                                     ColorCIExyY.WhitePointFromTemperature (TempSrc), 
                                     ColorCIExyY.WhitePointFromTemperature (TempDest));
#else
                  GammaTable [] tables = null;
                  return CreateAbstract (nLUTPoints, Exposure, Bright, Contrast, Hue, Saturation, tables, 
                                     ColorCIExyY.WhitePointFromTemperature (TempSrc), 
                                     ColorCIExyY.WhitePointFromTemperature (TempDest));
#endif
            }

            public static Profile CreateAbstract (int nLUTPoints,
                                          double Exposure,
                                          double Bright,
                                          double Contrast,
                                          double Hue,
                                          double Saturation,
                                          GammaTable [] tables,
                                          ColorCIExyY src_wp,
                                          ColorCIExyY dest_wp)
            {
                  if (tables == null) {
                        GammaTable gamma = new GammaTable (1024, Math.Pow (10, -Bright/100));
                        GammaTable line = new GammaTable (1024, 1.0);
                        tables = new GammaTable [] { gamma, line, line };
                  }

                  /*
                  System.Console.WriteLine ("e {0}", Exposure);
                  System.Console.WriteLine ("b {0}", Bright);
                  System.Console.WriteLine ("c {0}", Contrast);
                  System.Console.WriteLine ("h {0}", Hue);
                  System.Console.WriteLine ("s {0} {1} {2}", Saturation, src_wp, dest_wp);
                  */
                  return new Profile (f_cmsCreateBCHSWabstractProfile (nLUTPoints,
                                                           Exposure,
                                                           0.0, //Bright,
                                                           Contrast,
                                                           Hue,
                                                           Saturation,
                                                           ref src_wp,
                                                           ref dest_wp,
                                                           CopyHandles (tables)));
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern IntPtr cmsCreateLinearizationDeviceLink (IccColorSpace color_space, HandleRef [] tables);
            
            public Profile (IccColorSpace color_space, GammaTable [] gamma)
            {
                  handle = new HandleRef (this, cmsCreateLinearizationDeviceLink (color_space, CopyHandles (gamma)));
            }

            private static HandleRef [] CopyHandles (GammaTable [] gamma)
            {
                  if (gamma == null)
                        return null;

                  HandleRef [] gamma_handles = new HandleRef [gamma.Length];
                  for (int i = 0; i < gamma_handles.Length; i++)
                        gamma_handles [i] = gamma [i].Handle;
                  
                  return gamma_handles;
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern IntPtr cmsCreateRGBProfile (out ColorCIExyY whitepoint, 
                                              out ColorCIExyYTriple primaries,
                                            HandleRef [] gamma_table);

            public Profile (ColorCIExyY whitepoint, ColorCIExyYTriple primaries, GammaTable [] gamma)
            {
                  handle = new HandleRef (this, cmsCreateRGBProfile (out whitepoint, out primaries, CopyHandles (gamma)));
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern int cmsCloseProfile (HandleRef hprofile);

            [DllImport("liblcms-1.0.0.dll")]
            static extern IntPtr cmsOpenProfileFromFile (string ICCProfile, string sAccess);

            public Profile (string path) 
            {
                  handle = new HandleRef (this, cmsOpenProfileFromFile (path, "r"));

                  if (handle.Handle == IntPtr.Zero)
                        throw new Exception ("Error opening ICC profile in file " + path);
            }


            [DllImport("liblcms-1.0.0.dll")]
            static extern unsafe bool _cmsSaveProfileToMem (HandleRef profile, byte *mem, ref uint length);

            public byte [] Save ()
            {
                  unsafe {
                        uint length = 0;
                        if (_cmsSaveProfileToMem (this.Handle, null, ref length)) {
                              byte [] data = new byte [length];
                              fixed (byte * data_p = &data [0]) {
                                    if (_cmsSaveProfileToMem (this.Handle, data_p, ref length)) {
                                          return data;
                                    }
                              }
                        }
                  }
                  throw new SaveException ("Error Saving Profile");
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern unsafe IntPtr cmsOpenProfileFromMem (byte *data, uint length);

            public Profile (byte [] data) : this (data, 0, data.Length) {}

            public Profile (byte [] data, int start_offset, int length)
            {
                  if (start_offset < 0)
                        throw new System.ArgumentOutOfRangeException ("start_offset < 0");

                  if (data.Length - start_offset < 0)
                        throw new System.ArgumentOutOfRangeException ("start_offset > data.Length");

                  if (data.Length - length - start_offset < 0)
                        throw new System.ArgumentOutOfRangeException ("start_offset + length > data.Length");
                   
                  IntPtr profileh;
                  unsafe {
                        fixed (byte * start = & data [start_offset]) {
                              profileh = cmsOpenProfileFromMem (start, (uint)length);
                        }
                  }
                  
                  if (profileh == IntPtr.Zero)
                        throw new System.Exception ("Invalid Profile Data");
                  else 
                        this.handle = new HandleRef (this, profileh);
            }

            [DllImport("liblcms-1.0.0.dll")]
            extern static bool cmsTakeMediaWhitePoint (out ColorCIEXYZ wp, HandleRef handle);
            
            public ColorCIEXYZ MediaWhitePoint {
                  get {
                        ColorCIEXYZ wp;
                        if (!cmsTakeMediaWhitePoint (out wp, handle))
                              throw new ApplicationException ("unable to retrieve white point from profile");
                        return wp;
                  }
            }

            [DllImport("liblcms-1.0.0.dll")]
            extern static bool cmsTakeMediaBlackPoint (out ColorCIEXYZ black, HandleRef handle);
            
            public ColorCIEXYZ MediaBlackPoint {
                  get {
                        ColorCIEXYZ black;
                        if (!cmsTakeMediaBlackPoint (out black, handle))
                              throw new ApplicationException ("unable to retrieve white point from profile");
                        
                        return black;
                  }
            }
            
            [DllImport("liblcms-1.0.0.dll")]
            extern static bool cmsTakeColorants (out ColorCIEXYZTriple colors, HandleRef handle);

            public ColorCIEXYZTriple Colorants {
                  get {
                        ColorCIEXYZTriple colors;
                        if (! cmsTakeColorants (out colors, handle))
                              throw new ApplicationException ("Unable to retrieve profile colorants");
                        
                        return colors;
                  }                       
            }
            
            [DllImport("liblcms-1.0.0.dll")]
            extern static IntPtr cmsTakeModel (HandleRef handle);
            
            public string Model {
                  get {
                        lock (srgb) {
                              return Marshal.PtrToStringAnsi (cmsTakeModel (handle));
                        }
                  }
            }

            [DllImport("liblcms-1.0.0.dll")]
            extern static IntPtr cmsTakeProductName (HandleRef handle);

            public string ProductName {
                  get {
                        lock (srgb) {
                              return Marshal.PtrToStringAnsi (cmsTakeProductName (handle));
                        }
                  }
            }
            [DllImport("liblcms-1.0.0.dll")]
            extern static IntPtr cmsTakeProductDesc (HandleRef handle);

            public string ProductDescription {
                  get {
                        lock (srgb) {
                              return Marshal.PtrToStringAnsi (cmsTakeProductDesc (handle));
                        }
                  }
            }

            private enum ErrorAction {
                  Abort,
                  Show,
                  Ignore
            }

            [DllImport("liblcms-1.0.0.dll")]
            static extern void cmsErrorAction (ErrorAction action);

            private static void SetErrorAction (ErrorAction act)
            {
                  cmsErrorAction (act);
            }

            public override string ToString ()
            {
                  return ProductName;
            }

            protected Profile (IntPtr handle)
            {
                  this.handle = new HandleRef (this, handle);
            }

            public void Dispose () 
            {
                  Cleanup ();

                  System.GC.SuppressFinalize (this);
            }

            protected virtual void Cleanup ()
            {
                  if (cmsCloseProfile (this.Handle) == 0)
                        throw new Exception ("Error closing Handle");

            }

            ~Profile ()
            {
                  Cleanup ();
            }

#if ENABLE_NUNIT
            [TestFixture]
            public class Tests {
                  [Test]
                  public void LoadSave ()
                  {
                        Profile srgb = CreateStandardRgb ();
                        byte [] data = srgb.Save ();
                        Assert.IsNotNull (data);
                        Profile result = new Profile (data);
                        Assert.AreEqual (result.ProductName, srgb.ProductName);
                        Assert.AreEqual (result.ProductDescription, srgb.ProductDescription);
                        Assert.AreEqual (result.Model, srgb.Model);
                  }
            }
#endif            
      }

      public class SaveException : System.Exception {
            public SaveException (string message) : base (message)
            {
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index