我在前面几章里面提到过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映射的算法。
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);
}
}
}
}
相关推荐
GDI+开发包,解压文件,并将其中的Includes和Lib中的文件复制到VS安装目录中VC98目录下的Includes和Lib文件夹中
对于初学者,还有一个问题就是,如果想要进行GDI+开发, 需要下载一个GDI+的开发包(SDK). 网上搜到的一般只包含一个DLL,没法用. 在我另外一个资源中提供了一个详细的SDK,包含了进行开发所需要的全部内容:头文件,库文件...
Visual C++6.0使用GDI+的一般方法 1. 载解压GDI+开发包; 2. 正确设置include & lib 目录; 3. stdafx.h 添加: #ifndef ULONG_PTR #define ULONG_PTR unsigned long* #endif #include 或者 将Visual...
GDI+开发库
本书从介绍GDI+Windows图形程序设计的基本知识开始,其核心是对一些实际问题的指导,包括如何使用Windows Forms及如何优化GDI+的性能。本书通过一些例子来说明如何开发真实世界的工具,如GDI+Painter、GDI+Editro...
1. 载解压GDI+开发包; 2. 正确设置include & lib 目录; 3. stdafx.h 添加: #ifndef ULONG_PTR #define ULONG_PTR unsigned long* #endif #include 4. 程序中添加GDI+的包含文件gdiplus.h以及附加的类库...
包含GDI+开发所必需的开发包,并且包括配置使用方法,
因为GDI+对GDI的很多性能进行了优化,同时还提供了其他的一些特性。 一个图形设备接口,例如GDI+, 允许应用程序开发人员在打印机或屏幕上显示信息,而不用去考虑显示设备的具体细节。应用程序开发人员调用GDI+ ...
2.4 一些基本的GDI+ 对象 总结 第3章 Graphics类 3.1 Graphics类的属性 3.2 Graphics类的方法 3.3 GDI+ Painter应用程序 3.4 绘制饼图 总结 第4章 使用画笔和钢笔 4.1 理解和使用画笔 4.2 在GDI+ 中使用...
使用VC6和GDI+开发图形界面.首先在VC6加载GDI+动态库,然后根据自己的要求建立控件,在控件中使用GDI+绘图.使用GDI+比使用GDI思路更清晰,界面更美观.
顾名思义,GDI+是以前版本GDI的继承者,出于兼容性考虑,Windows XP仍然支持以前版本的GDI,但是在开发新应用程序的时候,开发人员为了满足图形输出需要应该使用GDI+,因为GDI+对以前的Windows版本中GDI进行了优化,...
顾名思义,GDI+是以前版本GDI的继承者,出于兼容性考虑,Windows XP仍然支持以前版本的GDI,但是在开发新应用程序的时候,开发人员为了满足图形输出需要应该使用GDI+,因为GDI+对以前的Windows版本中GDI进行了优化,...
GDI+SDK开发手册 翻译版本,GDI+详细开发说明
GDI+是GDI的延生,应用于WinXP及更新版的Windows系统。...现有的很多介绍GDI+的资料不少,但几乎都是基于.Net的,而介绍用VB6开发GDI+的资料却少之又少,偏偏又不少人需要用VB6来开发GDI+程序。所以这个资料不可多得。
GDI+的开发组件,包括了所有的头文件,动态链接库文件和lib文件
GDI+开发资料 类库及说明文档
GDI+油量表开发
基于VC++语言,VS平台开发,应用GDI+库,双缓冲,实现图片旋转,屏幕不闪烁。代码量不大,简单易学。