C# 画8位彩色图片(自定义调色板)

此为原创,转帖请加链接(http://www.cnblogs.com/wdh1983/admin/EditPosts.aspx?postid=1378468)!

此方法参照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(
2550,   0,   0  ));
            cl.Add(Color.FromArgb(
2552550,   0  ));
            cl.Add(Color.FromArgb(
25551,  51,  102));
            cl.Add(Color.FromArgb(
255102102102));
            cl.Add(Color.FromArgb(
2550,   1280  ));
            cl.Add(Color.FromArgb(
255128128128));
            cl.Add(Color.FromArgb(
2552061580  ));
            cl.Add(Color.FromArgb(
255200200200));
            cl.Add(Color.FromArgb(
255206206206));
            cl.Add(Color.FromArgb(
255206207156));
            cl.Add(Color.FromArgb(
255255255255));
            
//重写调色板前11色
            for (int i = 0; i < cl.Count; i++)
            {
                pal.Entries[i] 
= cl[i];
            }
            pal.Entries[
10= Color.FromArgb(0255255255); // 将其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, 
00, Width, Height);
                g.Dispose();
            }
            BitmapData bitmapData;
            Rectangle rect 
= new Rectangle(00, 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(11, 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, 
00, Width, Height);
                g.Dispose();
            }
            BitmapData bitmapData;
            Rectangle rect 
= new Rectangle(00, 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();
        }
    }
}

此为原创,转帖请加链接(
http://www.cnblogs.com/wdh1983/admin/EditPosts.aspx?postid=1378468)!

posted on 2009-01-20 11:33  魏东海  阅读(8130)  评论(4)    收藏  举报

导航