天天看點

C#制作透明色GIF動畫的類(轉)

發現一個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,如需轉載請自行聯系原作者