快捷搜索:

GDI+中常见的几个问题(11)

我在前面几章里面提到过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里面,这样用起来就方便了。

系列文章:

GDI+中常见的几个问题(1)

GDI+中常见的几个问题(2)

GDI+中常见的几个问题(3)

GDI+中常见的几个问题(4)

GDI+中常见的几个问题(5)

GDI+中常见的几个问题(6)

GDI+中常见的几个问题(7)

GDI+中常见的几个问题(8.别传1)

GDI+中常见的几个问题(8)

GDI+中常见的几个问题(9)

GDI+中常见的几个问题(10)

您可能还会对下面的文章感兴趣: