使用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);

            }

       }

   }

}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值