此方法參照msdn上的畫8位灰階gif圖片的方法。
函數1,2為畫自定義彩色圖片方法。
函數3(GetColorPalette)和函數4(SaveGIFWithNewGrayscale)為msdn原方法。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Drawing.Imaging; namespace Em_Picture { class Class2 { public static List<Color> cl; //函數1: //此為原創,轉帖請加鏈接(http://www.cnblogs.com/wdh1983/admin/EditPosts.aspx?postid=1378468)! static void DrawPicture() { Image image = Image.FromFile("加載你的圖片:比如一個總共11色的股票行情走勢圖,其白色為背景色"); //獲取11色相對應的調色板 ColorPalette pal = GetColorPalette(11); //列出圖片中所包含的顏色 cl = new List<Color>(); cl.Add(Color.FromArgb(255, 0, 0, 0 )); cl.Add(Color.FromArgb(255, 255, 0, 0 )); cl.Add(Color.FromArgb(255, 51, 51, 102)); cl.Add(Color.FromArgb(255, 102, 102, 102)); cl.Add(Color.FromArgb(255, 0, 128, 0 )); cl.Add(Color.FromArgb(255, 128, 128, 128)); cl.Add(Color.FromArgb(255, 206, 158, 0 )); cl.Add(Color.FromArgb(255, 200, 200, 200)); cl.Add(Color.FromArgb(255, 206, 206, 206)); cl.Add(Color.FromArgb(255, 206, 207, 156)); cl.Add(Color.FromArgb(255, 255, 255, 255)); //重寫調色板前11色 for (int i = 0; i < cl.Count; i++) { pal.Entries[i] = cl[i]; } pal.EntrIEs[10] = Color.FromArgb(0, 255, 255, 255); // 將其alpha值修改為0,可使背景通透 //調用畫8位彩色圖函數 SaveGIFWithNewColorTable(image, pal, "你要保存新圖片的位置"); } //函數2: //此為原創,轉帖請加鏈接(http://www.cnblogs.com/wdh1983/admin/EditPosts.aspx?postid=1378468)! public static void SaveGIFWithNewColorTable(Image image, ColorPalette pal, string filename) { int Width = image.Width; int Height = image.Height; Bitmap bitmap = new Bitmap(Width, Height, PixelFormat.Format8bppIndexed); bitmap.Palette = pal; Bitmap BmpCopy = new Bitmap(Width, Height, PixelFormat.Format32bppArgb); { Graphics g = Graphics.FromImage(BmpCopy); g.PageUnit = GraphicsUnit.Pixel; g.DrawImage(image, 0, 0, Width, Height); g.Dispose(); } BitmapData bitmapData; Rectangle rect = new Rectangle(0, 0, Width, Height); bitmapData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); IntPtr pixels = bitmapData.Scan0; BitmapData bmData = BmpCopy.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); unsafe { byte* pBits; if (bitmapData.Stride > 0) pBits = (byte*)pixels.ToPointer(); else pBits = (byte*)pixels.ToPointer() + bitmapData.Stride * (Height - 1); uint stride = (uint)Math.Abs(bitmapData.Stride); // byte* p = (byte*)bmData.Scan0; int offset = bmData.Stride - Width * 4; // for (uint row = 0; row < Height; ++row) { for (uint col = 0; col < Width; ++col) { //取原圖中某個點顏色值 Color pixel = Color.FromArgb(p[3], p[2], p[1], p[0]); p += 4; //獲取新圖對應點的指針 byte* p8bppPixel = pBits + row * stride + col; //將原圖這個點的顏色所對應的顏色索引值賦給指針 *p8bppPixel = (byte)cl.IndexOf(pixel); //=========================================================== //其實上面的代碼比較消耗性能,改為如下代碼較好(也可使用switch函數) /* byte b = 0; //判斷的順序為建立顏色表的倒序 //因為白色為背景色,絕大多數判斷到這裡就會停止 if (p[1] == 255) b = 10; else if (p[1] == 207) b = 9; else if (p[1] == 206) b = 8; else if (p[1] == 200) b = 7; else if (p[1] == 158) b = 6; else if (p[1] == 128 && p[2] == 128) b = 5; else if (p[1] == 128 && p[2] == 0) b = 4; else if (p[1] == 102) b = 3; else if (p[1] == 51) b = 2; else if (p[1] == 0 && p[2] == 225) b = 1; else if (p[1] == 0 && p[2] == 0) b = 0; p += 4; byte* p8bppPixel = pBits + row * stride + col; *p8bppPixel = b; */ //=========================================================== } /* end loop for col */ p += offset; } /* end loop for row */ BmpCopy.UnlockBits(bmData); } /* end unsafe */ bitmap.UnlockBits(bitmapData); bitmap.Save(filename, ImageFormat.Gif); BmpCopy.Dispose(); bitmap.Dispose(); } //函數3:獲取顏色個數相對應的調色板 //此為原創,轉帖請加鏈接(http://www.cnblogs.com/wdh1983/admin/EditPosts.aspx?postid=1378468)! public static ColorPalette GetColorPalette(uint nColors) { // Assume monoChrome image. PixelFormat bitscolordepth = PixelFormat.Format1bppIndexed; ColorPalette palette; // The Palette we are stealing Bitmap bitmap; // The source of the stolen palette // Determine number of colors. if (nColors > 2) bitscolordepth = PixelFormat.Format4bppIndexed; if (nColors > 16) bitscolordepth = PixelFormat.Format8bppIndexed; // Make a new Bitmap object to get its Palette. bitmap = new Bitmap(1, 1, bitscolordepth); palette = bitmap.Palette; // Grab the palette bitmap.Dispose(); // cleanup the source Bitmap return palette; // Send the palette back } //函數4:畫8位灰階gif圖 //此為原創,轉帖請加鏈接(http://www.cnblogs.com/wdh1983/admin/EditPosts.ASPx?postid=1378468)! public static void SaveGIFWithNewGrayscale(Image image, string filename, uint nColors, bool fTransparent) { if (nColors > 256) nColors = 256; if (nColors < 2) nColors = 2; int Width = image.Width; int Height = image.Height; Bitmap bitmap = new Bitmap(Width, Height, PixelFormat.Format8bppIndexed); ColorPalette pal = GetColorPalette(nColors); for (uint i = 0; i < nColors; i++) { uint Alpha = 0xFF; // Colors are opaque. uint Intensity = i * 0xFF / (nColors - 1); // Even distribution. if (i == 0 && fTransparent) // Make this color index Alpha = 0; // Transparent pal.EntrIEs[i] = Color.FromArgb((int)Alpha, (int)Intensity, (int)Intensity, (int)Intensity); } bitmap.Palette = pal; Bitmap BmpCopy = new Bitmap(Width, Height, PixelFormat.Format32bppArgb); { Graphics g = Graphics.FromImage(BmpCopy); g.PageUnit = GraphicsUnit.Pixel; g.DrawImage(image, 0, 0, Width, Height); g.Dispose(); } BitmapData bitmapData; Rectangle rect = new Rectangle(0, 0, Width, Height); bitmapData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); IntPtr pixels = bitmapData.Scan0; unsafe { byte* pBits; if (bitmapData.Stride > 0) pBits = (byte*)pixels.ToPointer(); else pBits = (byte*)pixels.ToPointer() + bitmapData.Stride * (Height - 1); uint stride = (uint)Math.Abs(bitmapData.Stride); for (uint row = 0; row < Height; ++row) { for (uint col = 0; col < Width; ++col) { Color pixel; // The source pixel. byte* p8bppPixel = pBits + row * stride + col; pixel = BmpCopy.GetPixel((int)col, (int)row); double luminance = (pixel.R * 0.299) + (pixel.G * 0.587) + (pixel.B * 0.114); *p8bppPixel = (byte)(luminance * (nColors - 1) / 255 + 0.5); } /* end loop for col */ } /* end loop for row */ } /* end unsafe */ bitmap.UnlockBits(bitmapData); bitmap.Save(filename, ImageFormat.Gif); BmpCopy.Dispose(); bitmap.Dispose(); } } }