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里面,这样用起来就方便了。

  • 相关阅读:
    SoapUI 使用笔记
    git 使用笔记(二)
    git 使用笔记(一)
    jquery 拓展
    hdu 1024 Max Sum Plus Plus (DP)
    hdu 2602 Bone Collector (01背包)
    hdu 1688 Sightseeing (最短路径)
    hdu 3191 How Many Paths Are There (次短路径数)
    hdu 2722 Here We Go(relians) Again (最短路径)
    hdu 1596 find the safest road (最短路径)
  • 原文地址:https://www.cnblogs.com/hotcan/p/1441680.html
Copyright © 2011-2022 走看看