使用GDI+进行开发的一些问题(11)

问题11,ICM 2.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/dd372446(VS.85).aspx 。其中包括了显示,设备以及Gamut映射的算法。


刚才顺手抄了一个使用ICM 2.0转换图像的算法,用C#把ICM的几个API 封装了一下,这样就可以使用ICC来转换不同的图像了。

using System;

using System.Collections.Generic;

using System.Text;

using System.Runtime.InteropServices;

using System.Drawing;

using System.Drawing.Imaging;

using System.IO;

namespace ICCConverter

{

publicclassICM

{

#region Consts

constuint PROFILE_FILENAME = 1; // profile data is NULLterminated filename

constuint PROFILE_READ = 1; // opened for read access

constuint FILE_SHARE_READ = 0x00000001;

constuint OPEN_EXISTING = 3;

constuint PROOF_MODE = 0x00000001;

constuint NORMAL_MODE = 0x00000002;

constuint BEST_MODE = 0x00000003;

constuint ENABLE_GAMUT_CHECKING = 0x00010000;

constuint USE_RELATIVE_COLORIMETRIC = 0x00020000;

constuint FAST_TRANSLATE = 0x00040000;

constint LCS_SIGNATURE = 0x50534F43; /* PSOC */

#endregion

#region Types

publicenumBMFORMAT

{

//

// 16bpp - 5 bits per channel. The mostsignificant bit is ignored.

//

BM_x555RGB = 0x0000,

BM_x555XYZ = 0x0101,

BM_x555Yxy,

BM_x555Lab,

BM_x555G3CH,

//

// Packed 8 bits per channel => 8bppfor GRAY and

// 24bpp for the 3 channel colors, morefor hifi channels

//

BM_RGBTRIPLETS = 0x0002,

BM_BGRTRIPLETS = 0x0004,

BM_XYZTRIPLETS = 0x0201,

BM_YxyTRIPLETS,

BM_LabTRIPLETS,

BM_G3CHTRIPLETS,

BM_5CHANNEL,

BM_6CHANNEL,

BM_7CHANNEL,

BM_8CHANNEL,

BM_GRAY,

//

// 32bpp - 8 bits per channel. The mostsignificant byte is ignored

// for the 3 channel colors.

//

BM_xRGBQUADS = 0x0008,

BM_xBGRQUADS = 0x0010,

BM_xG3CHQUADS = 0x0304,

BM_KYMCQUADS,

BM_CMYKQUADS = 0x0020,

//

// 32bpp - 10 bits per channel. The 2most significant bits are ignored.

//

BM_10b_RGB = 0x0009,

BM_10b_XYZ = 0x0401,

BM_10b_Yxy,

BM_10b_Lab,

BM_10b_G3CH,

//

// 32bpp - named color indices (1-based)

//

BM_NAMED_INDEX,

//

// Packed 16 bits per channel => 16bppfor GRAY and

// 48bpp for the 3 channel colors.

//

BM_16b_RGB = 0x000A,

BM_16b_XYZ = 0x0501,

BM_16b_Yxy,

BM_16b_Lab,

BM_16b_G3CH,

BM_16b_GRAY,

//

// 16 bpp - 5 bits for Red & Blue, 6bits for Green

//

BM_565RGB = 0x0001,

//#if NTDDI_VERSION >= NTDDI_LONGHORN

//

// scRGB - 32 bits per channel floatingpoint

//16 bits per channel floating point

//

BM_32b_scRGB = 0x0601,

BM_32b_scARGB = 0x0602,

BM_S2DOT13FIXED_scRGB = 0x0603,

BM_S2DOT13FIXED_scARGB = 0x0604

//#endif // NTDDI_VERSION >=NTDDI_LONGHORN

}

[StructLayout(LayoutKind.Sequential)]

publicstructCIEXYZ

{

publicint ciexyzX, ciexyzY, ciexyzZ;

}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]

publicstructtagPROFILE

{

publicuint dwType;

publicstring pProfileData;

publicuint cbDataSize;

}

[StructLayout(LayoutKind.Sequential)]

publicstructCIEXYZTRIPLE

{

publicCIEXYZ ciexyzRed, ciexyzGreen, ciexyBlue;

}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]

structLOGCOLORSPACE

{

publicuint Signature, Version, Size;

publicint CSType, Intent, GammaRed, GammaGreen,GammaBlue;

publicCIEXYZTRIPLE Endpoints;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]

publicstring Filename;

}

publicenumGamutMappingIntent

{

LCS_GM_ABS_COLORIMETRIC =0x00000008,

LCS_GM_BUSINESS = 0x00000001,

LCS_GM_GRAPHICS = 0x00000002,

LCS_GM_IMAGES = 0x00000004

}

publicenumLogicalColorSpace

{

LCS_CALIBRATED_RGB = 0x00000000,

LCS_sRGB = 0x73524742,

LCS_WINDOWS_COLOR_SPACE =0x57696E20

}

#endregion

publicdelegateboolICMProgressProcCallback(uint ulMax, uint ulCurrent, int ulCallbackData);

[DllImport("mscms.dll", SetLastError = true)]

staticexternIntPtr OpenColorProfile(reftagPROFILE pProfile, uint AccessMode, uint ShareMode, uint CreateMode);

[DllImport("mscms.dll", SetLastError = true)]

staticexternbool TranslateBitmapBits(IntPtr pTransform, IntPtr inBuffer, BMFORMAT inFormat, uint width, uint height, uint stride, IntPtr outBuffer, BMFORMAT outFormat, uint outStride, ICMProgressProcCallback pfCallback, int CallBackParam);

[DllImport("mscms.dll", SetLastError = true)]

staticexternbool CloseColorProfile(IntPtr profile);

[DllImport("mscms.dll", SetLastError = true)]

staticexternbool DeleteColorTransform(IntPtr transform);

[DllImport("mscms.dll", SetLastError = true)]

staticexternIntPtr CreateColorTransform(refLOGCOLORSPACE pLogColorSpace, IntPtr hDestProfile, IntPtr hTargetProfile, uint dwFlags);

publicvoid Convert(string profilePath, string imageFilePath, string outputPath)

{

LOGCOLORSPACE logColorSpace = newLOGCOLORSPACE();

logColorSpace.Signature =LCS_SIGNATURE; /* LCS_SIGNATURE */

logColorSpace.Intent = (int)GamutMappingIntent.LCS_GM_IMAGES; /* LCS_GM_IMAGES */

logColorSpace.Version = 0x0400;

logColorSpace.Size = (uint)Marshal.SizeOf(logColorSpace);

logColorSpace.CSType = (int)LogicalColorSpace.LCS_sRGB; /* LCS_sRGB */

IntPtr Destprofile;

tagPROFILE profile = newtagPROFILE();

profile.dwType = PROFILE_FILENAME;

profile.pProfileData = profilePath;

profile.cbDataSize = (uint)profile.pProfileData.Length + 1;

Destprofile = OpenColorProfile(ref profile, PROFILE_READ, FILE_SHARE_READ,OPEN_EXISTING);

IntPtr pTransforms = CreateColorTransform(ref logColorSpace, Destprofile, IntPtr.Zero, BEST_MODE);

if (pTransforms != IntPtr.Zero)

{

FileStream fs = newFileStream(imageFilePath, FileMode.Open, FileAccess.Read);

Bitmap bmpTemp = (Bitmap)Image.FromStream(fs, false, false);

Bitmap bmp = newBitmap(bmpTemp);

fs.Close();

bmpTemp.Dispose();

BitmapData bmData = bmp.LockBits(newRectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

bool success = TranslateBitmapBits(

pTransforms,

bmData.Scan0,

BMFORMAT.BM_RGBTRIPLETS,

(uint)bmData.Width,

(uint)bmData.Height,

(uint)bmData.Stride,

bmData.Scan0,

BMFORMAT.BM_RGBTRIPLETS,

(uint)bmData.Stride, null, 0);

bmp.UnlockBits(bmData);

bmp.Save(outputPath, ImageFormat.Jpeg);

CloseColorProfile(Destprofile);

DeleteColorTransform(Destprofile);

}

else

{

int errorCode = Marshal.GetLastWin32Error();

thrownewCOMException("Error", errorCode);

}

}

}

}


你可能感兴趣的:(DI)