您的位置:首页 > 其它

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

2013-01-29 14:41 477 查看

问题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);

}

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: