此方法參照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:
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:
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:獲取顏色個數相對應的調色板
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圖
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();
}
}
}
新聞熱點
疑難解答