当前位置:主页   - 电脑 - 网站开发 - ASP.Net
GDI+中常见的几个问题(11)
来源:网络   作者:   更新时间:2012-05-13
收藏此页】    【字号    】    【打印】    【关闭

  我在前面几章里面提到过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/dd372446(VS.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             //
 44             // Packed 8 bits per channel => 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     0       //
 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             //
 88             // Packed 16 bits per channel => 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
105             //#if NTDDI_VERSION >= 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
115             //#endif // NTDDI_VERSION >= 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        U    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 

其它资源
来源声明

版权与免责声明
1、本站所发布的文章仅供技术交流参考,本站不主张将其做为决策的依据,浏览者可自愿选择采信与否,本站不对因采信这些信息所产生的任何问题负责。
2、本站部分文章来源于网络,其版权为原权利人所有。由于来源之故,有的文章未能获得作者姓名,署“未知”或“佚名”。对于这些文章,有知悉作者姓名的请告知本站,以便及时署名。如果作者要求删除,我们将予以删除。除此之外本站不再承担其它责任。
3、本站部分文章来源于本站原创,本站拥有所有权利。
4、如对本站发布的信息有异议,请联系我们,经本站确认后,将在三个工作日内做出修改或删除处理。
请参阅权责声明