您当前位置: 圣才学习网首页 >> IT类 >> .NET程序设计

GDI+高频问题思考(12)

扫码手机阅读
用圣才电子书APP或微信扫一扫,在手机上阅读本文,也可分享给你的朋友。
评论(0
   
来源:网络 作者:未知
 
  我在前面几章里面提到过ColorMatrix,可以将图像的色彩进行仿射变换。但是如果要对图像的色彩进行非线性变换的话,那就必须用到更强悍的API了。在Windows早期,有一套标准的色彩管理的API,叫做ICM 2.0 Image Color Management 2.0)。在Windows Vista 以后,这套API升级成了WCS 1.0 Windows Color System 1.0)。 这套API实现了www.color.org 上说的色彩管理的算法,具体的内容在http://msdn.microsoft.com/en- us/library/dd372446VS.85.aspx。其中包括了显示,设备以及Gamut影射的算法。
 
  刚才顺手抄了一个使用ICM 2.0转换图像的算法,用C#ICM的几个API 封装了一下,这样就可以使用ICC来转换不同的图像了。
 
  1 using System;
 
  2 using System.Collections.Generic;
 
  3 using System.Text;
 
  4 using System.Runtime.InteropServices;
 
  5 using System.Drawing;
 
  6 using System.Drawing.Imaging;
 
  7 using System.IO;
 
  8
 
  9 namespace ICCConverter
 
  10 {
 
  11     public class ICM
 
  12     {
 
  13         #region Consts
 
  14
 
  15         const uint PROFILE_FILENAME = 1; // profile data is NULL terminated filename
 
  16         const uint PROFILE_READ = 1; // opened for read access
 
  17         const uint FILE_SHARE_READ = 0x00000001;
 
  18         const uint OPEN_EXISTING = 3;
 
  19         const uint PROOF_MODE = 0x00000001;
 
  20         const uint NORMAL_MODE = 0x00000002;
 
  21         const uint BEST_MODE = 0x00000003;
 
  22         const uint ENABLE_GAMUT_CHECKING = 0x00010000;
 
  23         const uint USE_RELATIVE_COLORIMETRIC = 0x00020000;
 
  24         const uint FAST_TRANSLATE = 0x00040000;
 
  25         const int LCS_SIGNATURE = 0x50534F43; /* PSOC */
 
  26
 
  27         #endregion
 
  28
 
  29         #region Types
 
  30
 
  31         public enum BMFORMAT
 
  32         {
 
  33             //
 
  34             // 16bpp - 5 bits per channel. The most significant bit is ignored.
 
  35             //
 
  36
 
  37             BM_x555RGB = 0x0000,
 
  38             BM_x555XYZ = 0x0101,
 
  39             BM_x555Yxy,
 
  40             BM_x555Lab,
 
  41             BM_x555G3CH,
 
  42
 
  43             //
 
  8bpp for GRAY and
 
  45             // 24bpp for the 3 channel colors, more for hifi channels
 
  46             //
 
  47
 
  48             BM_RGBTRIPLETS = 0x0002,
 
  49             BM_BGRTRIPLETS = 0x0004,
 
  50             BM_XYZTRIPLETS = 0x0201,
 
  51             BM_YxyTRIPLETS,
 
  52             BM_LabTRIPLETS,
 
  53             BM_G3CHTRIPLETS,
 
  54             BM_5CHANNEL,
 
  55             BM_6CHANNEL,
 
  56             BM_7CHANNEL,
 
  57             BM_8CHANNEL,
 
  58             BM_GRAY,
 
  59
 
  60             //
 
  61             // 32bpp - 8 bits per channel. The most significant byte is ignored
 
  62             // for the 3 channel colors.
 
  63             //
 
  64
 
  65             BM_xRGBQUADS = 0x0008,
 
  66             BM_xBGRQUADS = 0x0010,
 
  67             BM_xG3CHQUADS = 0x0304,
 
  68             BM_KYMCQUADS,
 
  69             BM_CMYKQUADS = 0x0020,
 
  70
 
  71             //
 
  72             // 32bpp - 10 bits per channel. The 2 most significant bits are ignored.
 
  73             //
 
  74
 
  75             BM_10b_RGB = 0x0009,
 
  76             BM_10b_XYZ = 0x0401,
 
  77             BM_10b_Yxy,
 
  78             BM_10b_Lab,
 
  79             BM_10b_G3CH,
 
  80
 
  81             //
 
  82             // 32bpp - named color indices (1-based)
 
  83             //
 
  84
 
  85             BM_NAMED_INDEX,
 
  86
 
  87             //
 
  16bpp for GRAY and
 
  89             // 48bpp for the 3 channel colors.
 
  90             //
 
  91
 
  92             BM_16b_RGB = 0x000A,
 
  93             BM_16b_XYZ = 0x0501,
 
  94             BM_16b_Yxy,
 
  95             BM_16b_Lab,
 
  96             BM_16b_G3CH,
 
  97             BM_16b_GRAY,
 
  98
 
  99             //
 
  100             // 16 bpp - 5 bits for Red & Blue, 6 bits for Green
 
  101             //
 
  102
 
  103             BM_565RGB = 0x0001,
 
  104
 
  = NTDDI_LONGHORN
 
  106             //
 
  107             // scRGB - 32 bits per channel floating point
 
  108             //         16 bits per channel floating point
 
  109             //
 
  110
 
  111             BM_32b_scRGB = 0x0601,
 
  112             BM_32b_scARGB = 0x0602,
 
  113             BM_S2DOT13FIXED_scRGB = 0x0603,
 
  114             BM_S2DOT13FIXED_scARGB = 0x0604
 
  = NTDDI_LONGHORN
 
  116
 
  117         }
 
  118
 
  119         [StructLayout(LayoutKind.Sequential)]
 
  120         public struct CIEXYZ
 
  121         {
 
  122             public int ciexyzX, ciexyzY, ciexyzZ;
 
  123         }
 
  124
 
  125         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
 
  126         public struct tagPROFILE
 
  127         {
 
  128             public uint dwType;
 
  129             public string pProfileData;
 
  130             public uint cbDataSize;
 
  131         }
 
  132
 
  133         [StructLayout(LayoutKind.Sequential)]
 
  134         public struct CIEXYZTRIPLE
 
  135         {
 
  136             public CIEXYZ ciexyzRed, ciexyzGreen, ciexyBlue;
 
  137         }
 
  138
 
  139         [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
 
  140         struct LOGCOLORSPACE
 
  141         {
 
  142             public uint Signature, Version, Size;
 
  143             public int CSType, Intent, GammaRed, GammaGreen, GammaBlue;
 
  144             public CIEXYZTRIPLE Endpoints;
 
  145
 
  146             [MarshalAs (UnmanagedType.ByValTStr, SizeConst = 260)]
 
  147             public string Filename;
 
  148         }
 
  149
 
  150         public enum GamutMappingIntent
 
  151         {
 
  152             LCS_GM_ABS_COLORIMETRIC = 0x00000008,
 
  153             LCS_GM_BUSINESS = 0x00000001,
 
  154             LCS_GM_GRAPHICS = 0x00000002,
 
  155             LCS_GM_IMAGES = 0x00000004
 
  156         }
 
  157
 
  158         public enum LogicalColorSpace
 
  159         {
 
  160             LCS_CALIBRATED_RGB = 0x00000000,
 
  161             LCS_sRGB = 0x73524742,
 
  162             LCS_WINDOWS_COLOR_SPACE = 0x57696E20
 
  163         }
 
  164
 
  165
 
  166
 
  167         #endregion
 
  168
 
  169         public delegate bool ICMProgressProcCallback(uint ulMax, uint ulCurrent, int ulCallbackData);
 
  170
 
  171         [DllImport("mscms.dll", SetLastError = true)]
 
  172         static extern IntPtr OpenColorProfile(ref tagPROFILE pProfile, uint AccessMode, uint ShareMode, uint CreateMode);
 
  173
 
  174
 
  175
 
  176         [DllImport("mscms.dll", SetLastError = true)]
 
  177         static extern bool TranslateBitmapBits(IntPtr pTransform, IntPtr inBuffer, BMFORMAT inFormat, uint width, uint height, uint stride, IntPtr outBuffer, BMFORMAT outFormat, uint outStride, ICMProgressProcCallback pfCallback, int CallBackParam);
 
  178
 
  179         [DllImport("mscms.dll", SetLastError = true)]
 
  180         static extern bool CloseColorProfile(IntPtr profile);
 
  181
 
  182         [DllImport("mscms.dll", SetLastError = true)]
 
  183         static extern bool DeleteColorTransform(IntPtr transform);
 
  184
 
  185         [DllImport("mscms.dll", SetLastError = true)]
 
  186         static extern IntPtr CreateColorTransform(ref LOGCOLORSPACE pLogColorSpace, IntPtr hDestProfile, IntPtr hTargetProfile, uint dwFlags);
 
  187
 
  188         public void Convert(string profilePath, string imageFilePath, string outputPath)
 
  189         {
 
  190
 
  191             LOGCOLORSPACE logColorSpace = new LOGCOLORSPACE();
 
  192
 
  193             logColorSpace.Signature = LCS_SIGNATURE; /* LCS_SIGNATURE */
 
  194             logColorSpace.Intent = (int) GamutMappingIntent.LCS_GM_IMAGES; /* LCS_GM_IMAGES */
 
  195             logColorSpace.Version = 0x0400;
 
  196             logColorSpace.Size = (uint)Marshal.SizeOf(logColorSpace);
 
  197             logColorSpace.CSType = (int)LogicalColorSpace.LCS_sRGB; /* LCS_sRGB */
 
  198             IntPtr Destprofile;
 
  199
 
  200             tagPROFILE profile = new tagPROFILE();
 
  201             profile.dwType = PROFILE_FILENAME;
 
  202             profile.pProfileData = profilePath;
 
  203             profile.cbDataSize = (uint)profile.pProfileData.Length + 1;
 
  204             Destprofile = OpenColorProfile(ref profile, PROFILE_READ, FILE_SHARE_READ, OPEN_EXISTING);
 
  205             IntPtr pTransforms = CreateColorTransform(ref logColorSpace, Destprofile, IntPtr.Zero, BEST_MODE);
 
  206
 
  207             if (pTransforms != IntPtr.Zero)
 
  208             {
 
  209                 FileStream fs = new FileStream(imageFilePath, FileMode.Open, FileAccess.Read);
 
  210                 Bitmap bmpTemp = (Bitmap)Image.FromStream(fs, false, false);
 
  211                 Bitmap bmp = new Bitmap(bmpTemp);
 
  212                 fs.Close();
 
  213                 bmpTemp.Dispose ();
 
  214
 
  215                 BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
 
  216                 bool success = TranslateBitmapBits
 
  217                     pTransforms,
 
  218                     bmData.Scan0,
 
  219                     BMFORMAT.BM_RGBTRIPLETS,
 
  220                     (uint)bmData.Width,
 
  221                     (uint)bmData.Height,
 
  222                     (uint)bmData.Stride,
 
  223                     bmData.Scan0,
 
  224                     BMFORMAT.BM_RGBTRIPLETS,
 
  225                     (uint) bmData.Stride, null, 0);
 
  226
 
  227                 bmp.UnlockBits(bmData);
 
  228                 bmp.Save(outputPath, ImageFormat.Jpeg);
 
  229                 CloseColorProfile(Destprofile);
 
  230                 DeleteColorTransform(Destprofile);
 
  231             }
 
  232             else
 
  233             {
 
  234                 int errorCode = Marshal.GetLastWin32Error();
 
  235                 throw new COMException("Error", errorCode);
 
  236             }
 
  237         }
 
  238     }
 
  239 }
 
  240
 
  241
 
  这一章其实跟GDI+并没有什么太大的关系,不知道什么时候这些代码会直接放在.NET Framework Code里面,这样用起来就方便了。
 
相关阅读
 
 

小编工资已与此挂钩!一一分钱!求打赏↓ ↓ ↓

如果你喜欢本文章,请赐赏:

已赐赏的人
最新评论(共0条)评论一句