程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> GDI+中常見的幾個問題(11)

GDI+中常見的幾個問題(11)

編輯:關於.NET

我在前面幾章裡面提到過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             //
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             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裡面,這樣用起來就方便了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved