發現一個GIF檔案大小錯很多.發現主要是3個地方的問題.
一是色彩表的問題.GIF有全局色彩表和圖形色彩表.
二是GIF圖形的大小并不一定是一樣的 桢1可能是100*100的 桢2可能是10*10 比如天空是黑色100*100 星星在是10*10
三是描述區,沒什麼作用就是描述
圖形一樣大小不一樣的就這兩個地方差別大.
用C#來實作下
并沒用LZW是通過.NET來實作LZW的.這裡隻是進行了檔案頭的更改和合并.
如果你用這個類打開一個GIF 你通過SAVE方法再儲存一次 描述類會放到圖形類的後面.
使用方式
Zgke.MyImage.ImageGif _Gif = new Zgke.MyImage.ImageGif(20, 32);
int _Temp =(int)'A';
for (int i = 0; i != 26; i++)
{
Bitmap _BitMap = new Bitmap(20, 32);
Graphics _G = Graphics.FromImage(_BitMap);
char T = (char)_Temp;
_G.DrawString(T.ToString(), new Font("宋體", 20), Brushes.Black, 0, 0);
_Gif.AddImage(_BitMap, 1, true, Zgke.MyImage.ImageGif.DisposalMethod.NoDisposalImage);
_G.Dispose();
_Temp++;
_BitMap.Dispose();
}
pictureBox1.Image = _Gif.Image;
_Gif.SaveFile(@"C:\1.gif");
下面是全部的類
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
namespace Zgke.MyImage
{
/// <summary>
/// GIF操作類
/// QQ:116149
/// </summary>
public class ImageGif
{
private Header m_Header;
private LogicalScreen m_LogicalScreen;
private ColorTable m_GlobalColorTable;
private IList<ExtensionIntroducer> m_ExtensionIntroducer = new List<ExtensionIntroducer>();
private ApplicationExtension m_ApplicationExtension;
private IList<GraphicControlExtension> m_GraphicControlExtension = new List<GraphicControlExtension>();
/// <summary>
/// 目前位置
/// </summary>
private int m_Index = 0;
private bool m_Open = false;
/// 是否正常打開
public bool OpenOK { get { return m_Open; } }
/// 圖形數量
public int ImageCount { get { return m_GraphicControlExtension.Count; } }
/// 擷取GIF圖形
public Image Image
{
get
{
if (m_GraphicControlExtension.Count == 0) return null;
MemoryStream _MemoryImage = new MemoryStream();
_MemoryImage.Position = 0;
byte[] _Temp = m_Header.GetByte();
_MemoryImage.Write(_Temp, 0, _Temp.Length);
_Temp = m_LogicalScreen.GetByte();
_Temp = m_GlobalColorTable.GetByte();
_Temp = m_ApplicationExtension.GetByte();
for (int i = 0; i != m_GraphicControlExtension.Count; i++) //儲存圖形
{
_Temp = m_GraphicControlExtension[i].GetByte();
_MemoryImage.Write(_Temp, 0, _Temp.Length);
}
for (int i = 0; i != m_ExtensionIntroducer.Count; i++) //儲存描述
_Temp = m_ExtensionIntroducer[i].GetByte();
_MemoryImage.WriteByte(0x3B);
return Image.FromStream(_MemoryImage);
}
}
/// 由檔案打開
/// <param name="p_GifFileName"></param>
public ImageGif(string p_GifFileName)
System.IO.FileStream _FileStream = new FileStream(p_GifFileName, FileMode.Open);
byte[] _GifByte = new byte[_FileStream.Length];
_FileStream.Read(_GifByte, 0, _GifByte.Length);
_FileStream.Close();
m_Header = new Header(_GifByte, ref m_Index, ref m_Open);
if (m_Open == false) return;
m_LogicalScreen = new LogicalScreen(_GifByte, ref m_Index, ref m_Open);
m_GlobalColorTable = new ColorTable(m_LogicalScreen.GlobalPal, m_LogicalScreen.GlobalColorSize, _GifByte, ref m_Index, ref m_Open);
//固定位置資訊讀取完成
m_Open = false;
while (true) //不知道有多少個子產品一直循環吧
#region 判斷位置
switch (_GifByte[m_Index])
case 0x21:
m_Index += 2; //坐标移動到類别後面 取類類别用-1方式 少一行代碼
switch (_GifByte[m_Index - 1])
{
case 0xFE:
m_ExtensionIntroducer.Add(new ExtensionIntroducer(_GifByte, ref m_Index, ref m_Open));
if (m_Open == false) return; //擷取失敗每必要繼續了直接傳回
break;
case 0xFF:
m_ApplicationExtension = new ApplicationExtension(_GifByte, ref m_Index, ref m_Open);
if (m_Open == false) return;
case 0xF9: //圖形在這個區 LZW資料
m_GraphicControlExtension.Add(new GraphicControlExtension(_GifByte, ref m_Index, ref m_Open));
default: //找不到類别 直接結束
System.Windows.Forms.MessageBox.Show(_GifByte[m_Index - 1].ToString("X02"));
return;
}
break;
case 0x3B:
m_Open = true;
return;
default:
m_Open = false;
System.Windows.Forms.MessageBox.Show(_GifByte[m_Index].ToString("X02"), m_Index.ToString());
}
#endregion
}
/// 建立新的圖形
/// <param name="p_Width"></param>
/// <param name="p_Height"></param>
public ImageGif(ushort p_Width, ushort p_Height)
m_Header = new Header();
m_LogicalScreen = new LogicalScreen(p_Width, p_Height);
m_ApplicationExtension = new ApplicationExtension();
}
#region 添加圖形 删除 插入
/// 添加一個圖形
/// <param name="Image">圖形</param>
/// <param name="p_DelayTime">顯示時間</param>
/// <param name="p_UserColorTable">是否使用全局色彩表 true使用 false 不使用</param>
private GraphicControlExtension GetGraphicsControl(Image p_Image, ushort p_DelayTime, bool p_UserColorTable, DisposalMethod p_Disposal)
MemoryStream _MemOry = new MemoryStream();
Image _Image = ToImageGif((Bitmap)p_Image, Color.White); //透明的方法可以加到這裡
_Image.Save(_MemOry, ImageFormat.Gif); //儲存成GIF圖形
int _Index = 783; //開始位置781 0x21 0xF9 已經計算
bool _Open = false;
GraphicControlExtension _Graphics = new GraphicControlExtension(_MemOry.GetBuffer(), ref _Index, ref _Open);
_Graphics.DelayTime = p_DelayTime;
_Graphics.TransparentColorFlag = true;
_Graphics.TransparentColorIndex = 16;
ColorTable _Table = new ColorTable();
Image _AddImage = Image.FromStream(_MemOry); //擷取壓縮後的圖形
for (int i = 0; i != _AddImage.Palette.Entries.Length; i++) //擷取圖形顔色表
_Table.ColorTableList.Add(_AddImage.Palette.Entries[i]);
if (m_GlobalColorTable == null) m_GlobalColorTable = _Table; //不管怎麼樣都要全局色彩表
if (p_UserColorTable == false)
_Graphics.ColorTable = _Table; //根據需要設定全局顔色表
_Graphics.UserColorTable = !p_UserColorTable;
_Graphics.Disposal = p_Disposal;
return _Graphics;
/// 添加一個圖形 圖形可以大于虛拟螢幕 就是顯示不出來而已........
public void AddImage(Image p_Image, ushort p_DelayTime, bool p_UserColorTable, DisposalMethod p_Disposal)
GraphicControlExtension _Info = GetGraphicsControl(p_Image, p_DelayTime, p_UserColorTable, p_Disposal);
if (_Info != null) m_GraphicControlExtension.Add(_Info);
/// 删除一個圖形
/// <param name="p_Index"></param>
public void RemoveImage(int p_Index)
if (p_Index > m_GraphicControlExtension.Count - 1) return;
m_GraphicControlExtension.RemoveAt(p_Index);
/// 插入一個圖形
public void InsertImage(Image p_Image, ushort p_DelayTime, bool p_UserColorTable, int p_Index, DisposalMethod p_Disposal)
if (_Info != null) m_GraphicControlExtension.Insert(p_Index, _Info);
#endregion
/// 設定一個圖形播放的時間
/// <param name="p_Index">索引</param>
/// <param name="p_DelayTime">播放時間</param>
public void SetImageTime(int p_Index, ushort p_DelayTime)
m_GraphicControlExtension[p_Index].DelayTime = p_DelayTime;
/// 設定一個圖形開始位置
/// <param name="p_X">X坐标</param>
/// <param name="p_Y">Y坐标</param>
public void SetImageLocatch(int p_Index, Point p_Point)
m_GraphicControlExtension[p_Index].Point = p_Point;
/// 設定處理模式
/// <param name="p_DisposalMethod">處理模式</param>
public void SetImageDisposalMethod(int p_Index, DisposalMethod p_DisposalMethod)
m_GraphicControlExtension[p_Index].Disposal = p_DisposalMethod;
/// 儲存檔案
/// <param name="p_FileName"></param>
public void SaveFile(string p_FileName)
if (m_GraphicControlExtension.Count == 0) return ;
FileStream _File = new FileStream(p_FileName, FileMode.Create);
_File.Position = 0;
byte[] _Temp = m_Header.GetByte();
_File.Write(_Temp, 0, _Temp.Length);
_Temp = m_LogicalScreen.GetByte();
_Temp = m_GlobalColorTable.GetByte();
_Temp = m_ApplicationExtension.GetByte();
for (int i = 0; i != m_GraphicControlExtension.Count; i++) //儲存圖形
_Temp = m_GraphicControlExtension[i].GetByte();
_File.Write(_Temp, 0, _Temp.Length);
for (int i = 0; i != m_ExtensionIntroducer.Count; i++) //儲存描述
_Temp = m_ExtensionIntroducer[i].GetByte();
_File.WriteByte(0x3B);
_File.Close();
#region 擷取圖形
/// 内部方法 儲存一個圖形
/// <param name="m_Stream">資料流</param>
/// <param name="p_Index">圖形索引</param>
/// <returns>圖形</returns>
private Stream GetImage(Stream m_Stream, int p_Index)
if (p_Index < 0 || p_Index > ImageCount) return null;
m_Stream.Position = 0;
m_Stream.Write(_Temp, 0, _Temp.Length);
_Temp = m_GraphicControlExtension[p_Index].GetByte();
m_Stream.Write(_Temp, 0, _Temp.Length);
m_Stream.WriteByte(0x3B);
return m_Stream;
/// 根據索引擷取圖形
public Image GetImage(int p_Index)
MemoryStream _Memory = new MemoryStream();
return Image.FromStream(GetImage(_Memory, p_Index));
public void GetImage(int p_Index, string p_FileName)
GetImage(_File, p_Index);
/// 處理模式
public enum DisposalMethod
/// <summary>
/// 不使用處置方法 一般的GIF都是這個
/// </summary>
NoDisposalMethod = 0,
/// 不處置圖形,把圖形從目前位置移去
NoDisposalImage = 1,
/// 回複到背景色
RestoreBackgroundColor = 2,
/// 回複到先前狀态
RestoreFrontState = 3,
/// 為定義4-7
Null
#region 類定義
/// GIF檔案頭
private class Header
///檔案頭 必須是GIF
private byte[] _Signature = new byte[] { 0x47, 0x49, 0x46 };
/// 版本資訊
private byte[] _Version = new byte[] { 0x38, 0x39, 0x61 };
public Header(byte[] p_Byte, ref int p_Index, ref bool p_Open)
p_Open = false;
if (p_Byte[0] != _Signature[0] || p_Byte[1] != _Signature[1] || p_Byte[2] != _Signature[2])
return;
_Version[0] = p_Byte[3];
_Version[1] = p_Byte[4];
_Version[2] = p_Byte[5];
p_Index += 6;
p_Open = true;
public Header()
/// 傳回版本号
public string Version
get
{ return Encoding.ASCII.GetString(_Version); }
set
if (value == "87a") _Version[1] = 0x37;
public byte[] GetByte()
byte[] _Temp = new byte[6];
_Temp[0] = _Signature[0];
_Temp[1] = _Signature[1];
_Temp[2] = _Signature[2];
_Temp[3] = _Version[0];
_Temp[4] = _Version[1];
_Temp[5] = _Version[2];
return _Temp;
/// 邏輯螢幕辨別符
private class LogicalScreen
/// 圖形寬
private byte[] _Width = new byte[2];
/// 圖形高
private byte[] _Height = new byte[2];
/// 第8位 - 全局顔色清單标志(Global Color Table Flag),當置位時表示有全局顔色清單,pixel值有意義.
/// 第5位 第6位 第7位 顔色深度(Color ResoluTion),cr+1确定圖象的顔色深度.
/// 第4位 分類标記 如果置位表示全局顔色清單分類排列.
/// 第1位 第2位 第3位 全局顔色清單大小,pixel+1确定顔色清單的索引數(2的pixel+1次方).
private byte[] _BitArray = new byte[1];
/// 背景色索引
private byte _Blackground = 0;
/// 像素寬高比
private byte _PixelAspectRadio = 0;
public LogicalScreen(byte[] p_Byte, ref int p_Index, ref bool p_Open)
_Width[0] = p_Byte[p_Index];
_Width[1] = p_Byte[p_Index + 1];
_Height[0] = p_Byte[p_Index + 2];
_Height[1] = p_Byte[p_Index + 3];
_BitArray[0] = p_Byte[p_Index + 4];
_Blackground = p_Byte[p_Index + 5];
_PixelAspectRadio = p_Byte[p_Index + 6];
p_Index += 7;
public LogicalScreen(ushort p_Width, ushort p_Height)
Width = p_Width;
Height = p_Height;
_Blackground = 0;
_PixelAspectRadio = 0;
_BitArray[0] = 135;
/// 高
public ushort Width { get { return BitConverter.ToUInt16(_Width, 0); } set { _Width = BitConverter.GetBytes(value); } }
/// 寬
public ushort Height { get { return BitConverter.ToUInt16(_Height, 0); } set { _Height = BitConverter.GetBytes(value); } }
/// 背景索引
public byte Blackground { get { return _Blackground; } set { _Blackground = value; } }
public byte PixelAspectRadio { get { return _PixelAspectRadio; } set { _PixelAspectRadio = value; } }
/// 全局顔色清單标志
public bool GlobalPal
BitArray _BitList = new BitArray(_BitArray);
return _BitList[7];
_BitList[7] = value;
_BitList.CopyTo(_BitArray, 0);
/// RGB顔色值是否按照使用率進行從高到底的 次序排序的
public bool SortFlag
return _BitList[3];
_BitList[3] = value;
/// 色彩表數量
public int GlobalColorSize
BitArray _Bit = new BitArray(3);
_Bit[0] = _BitList[0];
_Bit[1] = _BitList[1];
_Bit[2] = _BitList[2];
byte[] _Count = new byte[1];
_Bit.CopyTo(_Count, 0);
return (int)Math.Pow(2, _Count[0] + 1);
/// 彩色分辨率
public byte ColorResolution
_Bit[0] = _BitList[4];
_Bit[1] = _BitList[5];
_Bit[2] = _BitList[6];
return _Count[0];
byte[] _Temp = new byte[7];
_Temp[0] = _Width[0];
_Temp[1] = _Width[1];
_Temp[2] = _Height[0];
_Temp[3] = _Height[1];
_Temp[4] = _BitArray[0];
_Temp[5] = _Blackground;
_Temp[6] = _PixelAspectRadio;
/// 色彩表
private class ColorTable
private IList<Color> _ColorTable = new List<Color>();
public ColorTable(bool p_GlobalPal, int p_ColorNumb, byte[] p_Byte, ref int p_Index, ref bool p_Open)
if (p_GlobalPal)
for (int i = 0; i != p_ColorNumb; i++)
{
_ColorTable.Add(Color.FromArgb((int)p_Byte[p_Index], (int)p_Byte[p_Index + 1], (int)p_Byte[p_Index + 2]));
p_Index += 3;
}
public ColorTable()
/// 擷取全局色彩表
/// <returns></returns>
public IList<Color> ColorTableList { get { return _ColorTable; } set { _ColorTable = value; } }
byte[] _Temp = new byte[_ColorTable.Count * 3];
for (int i = 0; i != _ColorTable.Count; i++)
_Temp[(i * 3)] = (byte)_ColorTable[i].R;
_Temp[(i * 3) + 1] = (byte)_ColorTable[i].G;
_Temp[(i * 3) + 2] = (byte)_ColorTable[i].B;
/// 注釋~~~
private class ExtensionIntroducer
private byte[] _Header = new byte[] { 0x21, 0xFE };
private MemoryStream _Text = new MemoryStream();
public ExtensionIntroducer(byte[] p_Byte, ref int p_Index, ref bool p_Open)
while (true)
if (p_Index > p_Byte.Length - 1) return;
if (p_Byte[p_Index] == 0) break;
_Text.WriteByte(p_Byte[p_Index]);
p_Index++;
_Text.WriteByte(0);
p_Index++;
public ExtensionIntroducer(string p_Text)
Text = p_Text;
public string Text
get { return Encoding.ASCII.GetString(_Text.GetBuffer()); }
set { _Text = new MemoryStream(Encoding.ASCII.GetBytes(value)); _Text.WriteByte(0); }
//設定資料的時候一定要再寫個0
byte[] _Temp = new byte[2 + _Text.Length];
_Temp[0] = _Header[0];
_Temp[1] = _Header[1];
_Text.Position = 0;
for (int i = 0; i != _Text.Length - 1; i++)
_Temp[2 + i] = (byte)_Text.ReadByte();
/// 應用程式擴充
private class ApplicationExtension
private byte[] _Header = new byte[] { 0x21, 0xFF };
private byte _BlockSize = 0x0B; //11大小
private byte[] _Identifier = new byte[8]; //8個ASCII
private byte[] _AuthenticationCode = new byte[3]; //3個ASCII
private MemoryStream _Data = new MemoryStream();
public ApplicationExtension(byte[] p_Byte, ref int p_Index, ref bool p_Open)
_BlockSize = p_Byte[p_Index];
_Identifier[0] = p_Byte[p_Index + 1];
_Identifier[1] = p_Byte[p_Index + 2];
_Identifier[2] = p_Byte[p_Index + 3];
_Identifier[3] = p_Byte[p_Index + 4];
_Identifier[4] = p_Byte[p_Index + 5];
_Identifier[5] = p_Byte[p_Index + 6];
_Identifier[6] = p_Byte[p_Index + 7];
_Identifier[7] = p_Byte[p_Index + 8];
_AuthenticationCode[0] = p_Byte[p_Index + 9];
_AuthenticationCode[1] = p_Byte[p_Index + 10];
_AuthenticationCode[2] = p_Byte[p_Index + 11];
p_Index += 12;
if (p_Index + 1 > p_Byte.Length - 1) return;
if (p_Byte[p_Index] == 0 && p_Byte[p_Index + 1] != 0) break;
_Data.WriteByte(p_Byte[p_Index]);
_Data.WriteByte(0);
public ApplicationExtension()
_Identifier[0] = 0x4E;
_Identifier[1] = 0x45;
_Identifier[2] = 0x54;
_Identifier[3] = 0x53;
_Identifier[4] = 0x43;
_Identifier[5] = 0x41;
_Identifier[6] = 0x50;
_Identifier[7] = 0x45;
_AuthenticationCode[0] = 0x32;
_AuthenticationCode[1] = 0x2E;
_AuthenticationCode[2] = 0x30;
_Data.Position = 0;
_Data.WriteByte(3);
_Data.WriteByte(1);
_Data.WriteByte(232);
byte[] _Temp = new byte[14 + _Data.Length];
_Temp[2] = _BlockSize;
_Temp[3] = _Identifier[0];
_Temp[4] = _Identifier[1];
_Temp[5] = _Identifier[2];
_Temp[6] = _Identifier[3];
_Temp[7] = _Identifier[4];
_Temp[8] = _Identifier[5];
_Temp[9] = _Identifier[6];
_Temp[10] = _Identifier[7];
_Temp[11] = _AuthenticationCode[0];
_Temp[12] = _AuthenticationCode[1];
_Temp[13] = _AuthenticationCode[2];
for (int i = 0; i != _Data.Length - 1; i++)
_Temp[14 + i] = (byte)_Data.ReadByte();
/// 圖形控制擴充
private class GraphicControlExtension
private byte[] _Header = new byte[] { 0x21, 0xF9 };
private byte _BlockSize = 0x4; //4大小
private byte[] _DelayTime = new byte[2];
private byte _TransparentColorIndex = 0;
private byte _BlockEnd = 0;
private ImageDescriptor _Image;
public GraphicControlExtension(byte[] p_Byte, ref int p_Index, ref bool p_Open)
_BitArray[0] = p_Byte[p_Index + 1];
_DelayTime[0] = p_Byte[p_Index + 2];
_DelayTime[1] = p_Byte[p_Index + 3];
_TransparentColorIndex = p_Byte[p_Index + 4];
_BlockEnd = p_Byte[p_Index + 5];
_Image = new ImageDescriptor(p_Byte, ref p_Index, ref p_Open);
/// 設定顔色索引表
public ColorTable ColorTable { get { return _Image.ColorList; } set { _Image.ColorList = value; } }
public bool UserColorTable { get { return _Image.LocalColorTableFlag; } set { _Image.LocalColorTableFlag = value; } }
public int UserColorTableNumb { get { return _Image.PixelNumb; } set { _Image.PixelNumb = value; } }
/// 播放時間
public ushort DelayTime { get { return BitConverter.ToUInt16(_DelayTime, 0); } set { _DelayTime = BitConverter.GetBytes(value); } }
/// 設定透明色
public byte TransparentColorIndex { get { return _TransparentColorIndex; } set { _TransparentColorIndex = value; } }
/// 置位表示使用透明顔色
public bool TransparentColorFlag
return _BitList[0];
_BitList[0] = value;
/// 指出是否期待使用者有輸入之後才繼續進行下去
public bool UseInputFlag
return _BitList[1];
_BitList[1] = value;
/// 處理模式
public DisposalMethod Disposal
_Bit[0] = _BitList[2];
_Bit[1] = _BitList[3];
_Bit[2] = _BitList[4];
switch (_Count[0])
case 1:
return DisposalMethod.NoDisposalMethod;
case 2:
return DisposalMethod.NoDisposalImage;
case 3:
return DisposalMethod.RestoreBackgroundColor;
case 4:
return DisposalMethod.RestoreFrontState;
default:
return DisposalMethod.Null;
bool[] _Value = new bool[3];
switch (value)
case DisposalMethod.NoDisposalMethod:
_Value[0] = true;
break;
case DisposalMethod.NoDisposalImage:
_Value[1] = true;
case DisposalMethod.RestoreBackgroundColor:
case DisposalMethod.RestoreFrontState:
_Value[2] = true;
case DisposalMethod.Null:
BitArray _Bit = new BitArray((int)value);
_BitList[2] = _Value[0];
_BitList[3] = _Value[1];
_BitList[4] = _Value[2];
_BitList.CopyTo(_Count, 0);
_BitArray[0] = _Count[0];
/// 擷取資料
byte[] _ImageByte = _Image.GetByte();
byte[] _Bytes = new byte[8 + _ImageByte.Length];
_Bytes[0] = _Header[0];
_Bytes[1] = _Header[1];
_Bytes[2] = _BlockSize;
_Bytes[3] = _BitArray[0];
_Bytes[4] = _DelayTime[0];
_Bytes[5] = _DelayTime[1];
_Bytes[6] = _TransparentColorIndex;
_Bytes[7] = _BlockEnd;
_Image.PixelNumb = 256;
Array.Copy(_ImageByte, 0, _Bytes, 8, _ImageByte.Length);
return _Bytes;
public Point Point
return new Point(_Image.Left, _Image.Top);
_Image.Left = (ushort)value.X;
_Image.Top = (ushort)value.Y;
/// 圖形區域
private class ImageDescriptor
private byte[] _Header = new byte[] { 0x2C };
private byte[] _Left = new byte[2];
private byte[] _Top = new byte[2];
private ColorTable _ColorTable = new ColorTable();
private MemoryStream _Lzw = new MemoryStream();
public ImageDescriptor(byte[] p_Byte, ref int p_Index, ref bool p_Open)
if (p_Byte[p_Index] != _Header[0]) return;
_Left[0] = p_Byte[p_Index + 1]; //790
_Left[1] = p_Byte[p_Index + 2];
_Top[0] = p_Byte[p_Index + 3];
_Top[1] = p_Byte[p_Index + 4];
_Width[0] = p_Byte[p_Index + 5];
_Width[1] = p_Byte[p_Index + 6];
_Height[0] = p_Byte[p_Index + 7];
_Height[1] = p_Byte[p_Index + 8];
_BitArray[0] = p_Byte[p_Index + 9]; //798
p_Index += 10;
_ColorTable = new ColorTable(LocalColorTableFlag, PixelNumb, p_Byte, ref p_Index, ref p_Open);
_Lzw.WriteByte(p_Byte[p_Index]);
int _BlockByteSize = p_Byte[p_Index]; //判斷後面的塊大小
_Lzw.WriteByte(p_Byte[p_Index]); //不管是什麼先寫入
if (_BlockByteSize > 0)
_Lzw.Write(p_Byte, p_Index, _BlockByteSize);
p_Index += _BlockByteSize;
else
/// 局部顔色清單标志
public bool LocalColorTableFlag
if (value)
PixelNumb = 256;
PixelNumb = 0;
/// 交織标志
public bool InterlaceFlag
return _BitList[6];
_BitList[6] = value;
/// 表示緊跟着的局部顔色清單分類排列
return _BitList[5];
_BitList[5] = value;
/// 顔色标數量
public int PixelNumb
case 0:
_BitList[0] = false;
_BitList[1] = false;
_BitList[2] = false;
_BitList.CopyTo(_Count, 0);
_BitArray[0] = _Count[0];
_BitList[0] = true;
_BitList[1] = true;
_BitList[2] = true;
/// 開始位置X
public ushort Left
get { return BitConverter.ToUInt16(_Left, 0); }
set { _Left = BitConverter.GetBytes(value); }
/// 結束位置Y
public ushort Top
get { return BitConverter.ToUInt16(_Top, 0); }
set { _Top = BitConverter.GetBytes(value); }
public short Width
get { return BitConverter.ToInt16(_Width, 0); }
set { _Width = BitConverter.GetBytes(value); }
public short Height
get { return BitConverter.ToInt16(_Height, 0); }
set { _Height = BitConverter.GetBytes(value); }
/// 色彩表
public ColorTable ColorList { get { return _ColorTable; } set { _ColorTable = value; } }
public MemoryStream LzwData { get { return _Lzw; } set { _Lzw = value; } }
int _ColorCount = _ColorTable.ColorTableList.Count * 3;
byte[] _Temp = new byte[10 + _ColorCount + _Lzw.Length];
//這裡2009-05-04修改為10 原來的11 圖形在IE和QQ的EDIT裡不會動.
_Temp[1] = _Left[0];
_Temp[2] = _Left[1];
_Temp[3] = _Top[0];
_Temp[4] = _Top[1];
_Temp[5] = _Width[0];
_Temp[6] = _Width[1];
_Temp[7] = _Height[0];
_Temp[8] = _Height[1];
_Temp[9] = _BitArray[0];
int _Index = 10;
if (PixelNumb != 0)
for (int i = 0; i != _ColorTable.ColorTableList.Count; i++)
_Temp[_Index] = (byte)_ColorTable.ColorTableList[i].R;
_Temp[_Index + 1] = (byte)_ColorTable.ColorTableList[i].G;
_Temp[_Index + 2] = (byte)_ColorTable.ColorTableList[i].B;
_Index += 3;
_Lzw.Position = 0;
for (int i = 0; i != _Lzw.Length - 1; i++)
_Temp[_Index] = (byte)_Lzw.ReadByte();
_Index++;
#region GIF透明處理
/// 轉換為GIF透明 儲存 Image.Save(@"c:\1.GIF", ImageFormat.Gif); ALPHA 0為透明
/// <param name="p_MyBitMap">原始圖形</param>
/// <param name="p_Transparent">透明色如果預設為黑色</param>
/// <returns>GIF格式的IMAGE</returns>
public static Bitmap ToImageGif(Bitmap p_MyBitMap, Color p_Transparent)
// int _Width = p_MyBitMap.Width;
// int _Height = p_MyBitMap.Height;
// System.IO.MemoryStream _MemoryStream = new MemoryStream();
// p_MyBitMap.Save(_MemoryStream, ImageFormat.Gif);
// Bitmap _MyBitMap256 = (Bitmap)Image.FromStream(_MemoryStream); //儲存成GIF 256色
// _MemoryStream.Dispose();
// System.Drawing.Imaging.ColorPalette _ColorPalette = _MyBitMap256.Palette; //擷取顔色索引
// Hashtable _ColorHash = new Hashtable();
// for (int i = 0; i != _ColorPalette.Entries.Length; i++) //擷取全部色彩
// {
// string _Key = _ColorPalette.Entries[i].R.ToString("X02") + _ColorPalette.Entries[i].G.ToString("X02") + _ColorPalette.Entries[i].B.ToString("X02");
// if (_ColorHash[_Key] == null) _ColorHash.Add(_Key, i);
// }
//_ColorPalette.Entries[16] = Color.FromArgb(_ColorPalette.Entries[16].A, p_Transparent.R, p_Transparent.G, p_Transparent.B);
// ////建立新的圖形
// Bitmap _Newbitmap = new Bitmap(_Width, _Height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
// _Newbitmap.Palette = _ColorPalette; //設定索引
// Rectangle _Rect = new Rectangle(0, 0, _Width, _Height);
// //擷取IMAGE資料
// System.Drawing.Imaging.BitmapData _BitmapData = _Newbitmap.LockBits(_Rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
// Int32 _BitsInt = 0;
// if (_BitmapData.Stride > 0)
// _BitsInt = _BitmapData.Scan0.ToInt32();
// else
// _BitsInt = _BitmapData.Scan0.ToInt32() + _BitmapData.Stride * (_Height - 1);
// int _Stride = Math.Abs(_BitmapData.Stride);
// byte[] _Bits = new byte[_Width * _Height + _Stride];
// for (int i = 0; i != _Height; i++)
// for (int y = 0; y != _Width; y++)
// {
// int _8BppPixel = i * _Stride + y;
// Color _TempColor = _MyBitMap256.GetPixel(y, i);
// int _Alpha = p_MyBitMap.GetPixel(y, i).A;
// if (_Alpha == 0)
// {
// _Bits[_8BppPixel] = (byte)16; //如果ALPHA==0 設定為透明色
// }
// else
// string _Key = _TempColor.R.ToString("X02") + _TempColor.G.ToString("X02") + _TempColor.B.ToString("X02");
// object _ValueIndex = _ColorHash[_Key];
// if (_ValueIndex == null) _Bits[_8BppPixel] = (byte)16; //如果色彩不存在設定為透明色
// _Bits[_8BppPixel] = (byte)((int)_ValueIndex); //設定色彩
// }
// Marshal.Copy(_Bits, 0, new IntPtr(_BitsInt), _Height * _Stride);
// _Newbitmap.UnlockBits(_BitmapData);
// return _Newbitmap;
// 2009-06-03 修改方法 上面的byte計算可能有錯誤.
int _Width = p_MyBitMap.Width;
int _Height = p_MyBitMap.Height;
System.IO.MemoryStream _MemoryStream = new MemoryStream();
p_MyBitMap.Save(_MemoryStream, ImageFormat.Gif);
Bitmap _SaveImage = (Bitmap)Image.FromStream(_MemoryStream); //儲存成GIF 256色
_MemoryStream.Dispose();
//擷取顔色索引
System.Drawing.Imaging.ColorPalette _ColorPalette = _SaveImage.Palette;
_ColorPalette.Entries[16] = Color.FromArgb(_ColorPalette.Entries[16].A, p_Transparent.R, p_Transparent.G, p_Transparent.B);
BitmapData _SaveData = _SaveImage.LockBits(new Rectangle(0, 0, _Width, _Height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
byte[] _SaveBytes = new byte[_SaveData.Stride * _SaveData.Height]; //擷取儲存後的顔色
Marshal.Copy(_SaveData.Scan0, _SaveBytes, 0, _SaveData.Stride * _SaveData.Height);
Bitmap _LoadBitmap = new Bitmap(_Width, _Height, PixelFormat.Format32bppArgb);
Graphics _Graphcis = Graphics.FromImage(_LoadBitmap);
_Graphcis.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
_Graphcis.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
_Graphcis.DrawImage(p_MyBitMap, new Rectangle(0, 0, _Width, _Height));
_Graphcis.Dispose();
BitmapData _LoadData = _LoadBitmap.LockBits(new Rectangle(0, 0, _Width, _Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte[] _LoadByte = new byte[_LoadData.Stride * _SaveData.Height]; //擷取土星的原始顔色
Marshal.Copy(_LoadData.Scan0, _LoadByte, 0, _LoadData.Stride * _LoadData.Height);
int _ReadIndex = 0;
int _WriteIndex = 0;
int _ReadWidthIndex = 0;
Color _ReadColor = Color.Transparent;
int _Transparent = p_Transparent.ToArgb();
for (int i = 0; i != _Height; i++)
_ReadIndex = i * _LoadData.Stride;
_WriteIndex = i * _SaveData.Stride;
for (int z = 0; z != _Width; z++)
_ReadWidthIndex = z * 4;
_ReadColor = Color.FromArgb(_LoadByte[_ReadIndex + _ReadWidthIndex + 3], _LoadByte[_ReadIndex + _ReadWidthIndex + 2], _LoadByte[_ReadIndex + _ReadWidthIndex + 1], _LoadByte[_ReadIndex + _ReadWidthIndex]);
if (_ReadColor.A == 0 || _ReadColor.ToArgb() == _Transparent)
_SaveBytes[_WriteIndex + z] = (byte)16;
_LoadBitmap.UnlockBits(_LoadData);
_LoadBitmap.Dispose();
Marshal.Copy(_SaveBytes, 0, _SaveData.Scan0, _SaveBytes.Length);
_SaveImage.UnlockBits(_SaveData);
_SaveImage.Palette = _ColorPalette;
return _SaveImage;
}
}
本文轉自94cool部落格園部落格,原文連結:http://www.cnblogs.com/94cool/archive/2011/02/17/1956770.html,如需轉載請自行聯系原作者