zoukankan      html  css  js  c++  java
  • GDI+中常见的几个问题(11)

    好久没有写了,真是灰常地惭愧。Heroes都已经放到第24集了,而我只写到第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, falsefalse);
    211                 Bitmap bmp = new Bitmap(bmpTemp);
    212                 fs.Close();
    213                 bmpTemp.Dispose();
    214 
    215                 BitmapData bmData = bmp.LockBits(new Rectangle(00, 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, null0);
    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里面,这样用起来就方便了。

  • 相关阅读:
    ThreadLocal内存泄漏真因探究(转)
    JAVA设计模式工厂模式
    java设计模式单例模式
    Java-Socket
    Java-Queue总结
    Java-Reentrantlock
    Java-Iterator遍历集合
    安装和启动docker
    C# System.Reflection.Assembly动态加载资源文件
    C#调用 kernel32.dll
  • 原文地址:https://www.cnblogs.com/hotcan/p/1441680.html
Copyright © 2011-2022 走看看