Welcome

首页 / 软件开发 / C# / C#画8位彩色图片(自定义调色板)

C#画8位彩色图片(自定义调色板)2011-07-07 博客园 魏东海此方法参照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();elsepBits = (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 stealingBitmap 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 palettebitmap.Dispose(); // cleanup the source Bitmapreturn 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 indexAlpha = 0;// Transparentpal.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();elsepBits = (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();}}}