C# 转换图形为PCX 格式 增加了对1位色的PCX的读取

C# 转换图形为PCX 格式 增加了对1位色的PCX的读取

2009-6 -12

RLE数据压缩更改 颜色RGB在RLE压缩不换行处理.....

.NET 支持的格式..保存成PCX格式..

目前只支持两种结果 256色图  和24位图... 其他位的以后在说把..

使用方法

  Zgke.MyImage.ImageFile.ImagePcx _Pcx = new Zgke.MyImage.ImageFile.ImagePcx();
            _Pcx.PcxImage = this.Icon.ToBitmap();
            _Pcx.Save(@"C:/1.pcx");

如果你看这篇文章...上篇

 http://blog.csdn.net/zgke/archive/2009/05/19/4201621.aspx C#解析PCX图形文件

可以忽略了.下面的代码包含读和保存的功能..目前能保存256色图 和24位图..如果你的图形不是这两种 ..代码里把你的图形复制成24位的图 .然后去保存..

全部代码...

view plaincopy to clipboardprint?
using System;  
using System.Collections.Generic;  
using System.Text;  
using System.Drawing;  
using System.Drawing.Imaging;  
using System.IO;  
using System.Runtime.InteropServices;  
 
namespace Zgke.MyImage.ImageFile  
{  
    /// <summary>  
    /// PCX操作类  
    /// zgke@sina.com  
    /// qq:116149  
    /// </summary>  
    public class ImagePcx  
    {  
        /// <summary>  
        /// PCX文件头  
        /// </summary>  
        private class PCXHEAD  
        {  
            public byte[] m_Data = new byte[128];  
 
            /// <summary>  
            /// 文件头必须为 0A;  
            /// </summary>  
            public byte Manufacturer { get { return m_Data[0]; } }  
            /// <summary>  
            /// 0:PC Paintbrush 2.5 版   2:PC Paintbrush 2.8 版  5:PC Paintbrush 3.0 版  
            /// </summary>  
            public byte Version { get { return m_Data[1]; } set { m_Data[1] = value; } }  
            /// <summary>  
            /// 其值为1时表示采用RLE压缩编码的方法  
            /// </summary>  
            public byte Encoding { get { return m_Data[2]; } set { m_Data[2] = value; } }  
            /// <summary>  
            /// 每个相素的位数  
            /// </summary>  
            public byte Bits_Per_Pixel { get { return m_Data[3]; } set { m_Data[3] = value; } }  
 
            public ushort Xmin { get { return BitConverter.ToUInt16(m_Data, 4); } set { SetUshort(4, value); } }  
            public ushort Ymin { get { return BitConverter.ToUInt16(m_Data, 6); } set { SetUshort(6, value); } }  
            public ushort Xmax { get { return BitConverter.ToUInt16(m_Data, 8); } set { SetUshort(8, value); } }  
            public ushort Ymax { get { return BitConverter.ToUInt16(m_Data, 10); } set { SetUshort(10, value); } }  
            /// <summary>  
            /// 水平分辨率  
            /// </summary>  
            public ushort Hres1 { get { return BitConverter.ToUInt16(m_Data, 12); } set { SetUshort(12, value); } }  
            /// <summary>  
            /// 垂直分辨率  
            /// </summary>  
            public ushort Vres1 { get { return BitConverter.ToUInt16(m_Data, 14); } set { SetUshort(14, value); } }  
 
            public byte[] Palette  
            {  
                get 
                {  
                    byte[] _Palette = new byte[48];  
                    Array.Copy(m_Data,16,_Palette,0,48);  
                    return _Palette;  
                }  
                set 
                {  
                    if(value.Length!=48)throw new Exception("错误的byte[]长度不是48");  
                    Array.Copy(value, 0, m_Data, 16, 48);  
                }  
 
            }  
            /// <summary>  
            /// 位知  
            /// </summary>  
            public byte Reserved { get { return m_Data[64]; } set { m_Data[64] = value; } }  
            /// <summary>  
            /// 未知  
            /// </summary>  
            public byte Colour_Planes { get { return m_Data[65]; } set { m_Data[65] = value; } }  
            /// <summary>  
            /// 解码缓冲区  
            /// </summary>  
            public ushort Bytes_Per_Line { get { return BitConverter.ToUInt16(m_Data, 66); } set { SetUshort(66, value); } }  
            /// <summary>  
            /// 位知  
            /// </summary>  
            public ushort Palette_Type { get { return BitConverter.ToUInt16(m_Data, 68); } set { SetUshort(68, value); } }  
            /// <summary>  
            /// 填充  
            /// </summary>  
            public byte[] Filler  
            {  
                get 
                {  
                    byte[] m_Bytes = new byte[58];  
                    Array.Copy(m_Data, 70, m_Bytes, 0, 58);  
                    return m_Bytes;  
                }  
            }  
 
            public PCXHEAD(byte[] p_Data)  
            {  
                Array.Copy(p_Data, m_Data, 128);  
            }  
 
            public PCXHEAD()  
            {  
                m_Data[0] = 0xA;  
                Version = 0x5;  
                Encoding = 0x1;  
                Bits_Per_Pixel = 0x8;  
                Palette = new byte[] { 0x00, 0x00, 0xCD, 0x00, 0x90, 0xE7, 0x37, 0x01, 0x80, 0xF6, 0x95, 0x7C, 0x28, 0xFB, 0x95, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0xFB, 0x95, 0x7C, 0xB3, 0x16, 0x34, 0x7C, 0x00, 0x00, 0xCD, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0x16, 0x34, 0x7C, 0x64, 0xF3, 0x37, 0x01, 0xD8, 0x54, 0xB8, 0x00 };  
                Reserved = 0x01;  
                Colour_Planes = 0x03;  
                Palette_Type = 1;  
            }  
 
            public int Width { get { return Xmax - Xmin + 1; } }  
 
            public int Height { get { return Ymax - Ymin + 1; } }  
 
            /// <summary>  
            /// 设置16位数据保存到数据表  
            /// </summary>  
            /// <param name="p_Index">索引</param>  
            /// <param name="p_Data">数据</param>  
            private void SetUshort(int p_Index, ushort p_Data)  
            {  
                byte[] _ValueBytes = BitConverter.GetBytes(p_Data);  
                m_Data[p_Index] = _ValueBytes[0];  
                m_Data[p_Index + 1] = _ValueBytes[1];  
            }  
        }  
 
        private PCXHEAD m_Head = new PCXHEAD();  
 
        private Bitmap m_Image;  
 
        /// <summary>  
        /// 获取图形  
        /// </summary>  
        public Bitmap PcxImage { get { return m_Image; } set { m_Image = value; } }  
 
        public ImagePcx(string p_FileFullName)  
        {  
            if (!File.Exists(p_FileFullName)) return;  
            Load(File.ReadAllBytes(p_FileFullName));  
        }  
 
        public ImagePcx(byte[] p_Data)  
        {  
            Load(p_Data);  
        }  
 
        public ImagePcx()  
        {             
            
        }  
 
        /// <summary>  
        /// 开始获取数据  
        /// </summary>  
        /// <param name="p_Bytes">PCX文件信息</param>  
        private void Load(byte[] p_Bytes)  
        {  
            byte[] _Bytes = p_Bytes;  
            if (_Bytes[0] != 0x0A) return;              
            m_Head = new PCXHEAD(_Bytes);  
            m_ReadIndex = 128;  
            PixelFormat _PixFormate = PixelFormat.Format24bppRgb;  
            if (m_Head.Colour_Planes == 1)  
            {  
                switch (m_Head.Bits_Per_Pixel)  
                {  
                    case 8:  
                        _PixFormate = PixelFormat.Format8bppIndexed;  
                        break;  
                    case 1:  
                        _PixFormate = PixelFormat.Format1bppIndexed;  
                        break;  
                }  
            }  
 
            m_Image = new Bitmap(m_Head.Width, m_Head.Height, _PixFormate);  
            BitmapData _Data = m_Image.LockBits(new Rectangle(0, 0, m_Image.Width, m_Image.Height), ImageLockMode.ReadWrite, _PixFormate);  
            byte[] _BmpData = new byte[_Data.Stride * _Data.Height];  
 
            for (int i = 0; i != m_Head.Height; i++)  
            {  
                byte[] _RowColorValue=new byte[0];  
                switch (m_Head.Colour_Planes)  
                {  
                    case 3: //24位  
                        _RowColorValue = LoadPCXLine24(_Bytes);  
                        break;  
                    case 1: //256色  
                        switch (m_Head.Bits_Per_Pixel)  
                        {  
                            case 8:  
                                _RowColorValue = LoadPCXLine8(_Bytes);  
                                break;  
                            case 1:  
                                _RowColorValue = LoadPCXLine1(_Bytes);  
                                break;  
                        }  
                          
                        break;  
                }             
                int _Count = _RowColorValue.Length;  
                Array.Copy(_RowColorValue, 0, _BmpData, i * _Data.Stride, _Count);  
            }  
            Marshal.Copy(_BmpData, 0, _Data.Scan0, _BmpData.Length);  
            m_Image.UnlockBits(_Data);  
 
            switch (m_Head.Colour_Planes)  
            {  
                case 1:  
                    if (m_Head.Bits_Per_Pixel == 8)  
                    {  
                        ColorPalette _Palette = m_Image.Palette;  
                        m_ReadIndex = p_Bytes.Length - 256 * 3;  
                        for (int i = 0; i != 256; i++)  
                        {  
                            _Palette.Entries[i] = Color.FromArgb(p_Bytes[m_ReadIndex], p_Bytes[m_ReadIndex + 1], p_Bytes[m_ReadIndex + 2]);  
                            m_ReadIndex += 3;  
                        }  
                        m_Image.Palette = _Palette;  
                    }  
                    break;  
            }  
        }  
 
        /// <summary>  
        /// 保存成PCX文件  
        /// </summary>  
        /// <param name="p_FileFullName">完成路径</param>  
        public void Save(string p_FileFullName)  
        {  
            if (m_Image == null) return;  
            m_Head.Xmax = (ushort)(m_Image.Width - 1);  
            m_Head.Ymax = (ushort)(m_Image.Height - 1);  
            m_Head.Vres1 = (ushort)(m_Head.Xmax + 1);  
            m_Head.Hres1 = (ushort)(m_Head.Ymax + 1);  
            m_Head.Bytes_Per_Line = (ushort)m_Head.Width;  
 
            MemoryStream _SaveData = new MemoryStream();  
 
            switch (m_Image.PixelFormat)  
            { 
                #region 8位  
                case PixelFormat.Format8bppIndexed:  
                    m_Head.Colour_Planes = 1;  
                    BitmapData _ImageData = m_Image.LockBits(new Rectangle(0, 0, m_Head.Width, m_Head.Height), ImageLockMode.ReadOnly, m_Image.PixelFormat);  
                    byte[] _ImageByte = new byte[_ImageData.Stride * _ImageData.Height];  
                    Marshal.Copy(_ImageData.Scan0, _ImageByte, 0, _ImageByte.Length);  
                    m_Image.UnlockBits(_ImageData);  
 
                    m_SaveIndex = 0;  
                    byte[] _RowBytes = SavePCXLine8(_ImageByte);  
                    _SaveData.Write(_RowBytes, 0, _RowBytes.Length);  
 
                    _SaveData.WriteByte(0x0C);  
                    for (int i = 0; i != 256; i++)  
                    {  
                        _SaveData.WriteByte((byte)m_Image.Palette.Entries[i].R);  
                        _SaveData.WriteByte((byte)m_Image.Palette.Entries[i].G);  
                        _SaveData.WriteByte((byte)m_Image.Palette.Entries[i].B);  
                    }                      
                    break; 
                #endregion 
                #region 其他都按24位保存  
                default:  
                    m_Head.Colour_Planes = 3;  
                    Bitmap _Bitamp24 = new Bitmap(m_Head.Width, m_Head.Height, PixelFormat.Format24bppRgb);  
                    Graphics _Graphics = Graphics.FromImage(_Bitamp24);  
                    _Graphics.DrawImage(m_Image, 0, 0, m_Head.Width, m_Head.Height);  
                    _Graphics.Dispose();  
                    BitmapData _ImageData24 = _Bitamp24.LockBits(new Rectangle(0, 0, m_Head.Width, m_Head.Height), ImageLockMode.ReadOnly, _Bitamp24.PixelFormat);  
                    byte[] _ImageByte24 = new byte[_ImageData24.Stride * _ImageData24.Height];  
                    Marshal.Copy(_ImageData24.Scan0, _ImageByte24, 0, _ImageByte24.Length);  
                    _Bitamp24.UnlockBits(_ImageData24);  
                    m_SaveIndex = 0;  
                    for (int i = 0; i != _ImageData24.Height; i++)  
                    {  
                        m_SaveIndex = i * _ImageData24.Stride;  //2009-10-11 更新 PCX读取位置  
                        byte[] _RowBytes24 = SavePCXLine24(_ImageByte24);  
                        _SaveData.Write(_RowBytes24, 0, _RowBytes24.Length);  
                    }  
                    _SaveData.WriteByte(0x0C);  
                    _SaveData.Write(new byte[768], 0, 768);  
                     
                    break; 
                #endregion  
            }  
            FileStream _FileStream = new FileStream(p_FileFullName, FileMode.Create, FileAccess.Write);  
            _FileStream.Write(m_Head.m_Data, 0, 128);  
            byte[] _FileData = _SaveData.ToArray();  
            _FileStream.Write(_FileData, 0, _FileData.Length);  
            _FileStream.Close();  
        } 
        
        #region 取数据行  
        /// <summary>  
        /// 读取标记  
        /// </summary>  
        private int m_ReadIndex = 0;  
        /// <summary>  
        /// 获取PCX一行信息 24位色  
        /// </summary>  
        /// <param name="p_Data">数据</param>  
        /// <returns>BMP的行信息</returns>  
        private byte[] LoadPCXLine24(byte[] p_Data)  
        {  
            int _LineWidth = m_Head.Bytes_Per_Line;  
            byte[] _ReturnBytes = new byte[_LineWidth * 3];  
            int _EndBytesLength = p_Data.Length - 1;  
            int _WriteIndex = 2;  
            int _ReadIndex = 0;  
            while (true)  
            {  
                if (m_ReadIndex > _EndBytesLength) break; //判断行扫描结束返回码  
                byte _Data = p_Data[m_ReadIndex];  
                 
                if (_Data > 0xC0)  
                {  
                    int _Count = _Data - 0xC0;  
                    m_ReadIndex++;  
                    for (int i = 0; i != _Count; i++)  
                    {  
                        if (i + _ReadIndex >= _LineWidth)          //2009-6-12 RLE数据 会换行  
                        {  
                            _WriteIndex--;  
                            _ReadIndex = 0;  
                            _Count = _Count - i;  
                            i = 0;  
                        }  
                        int _RVA = ((i + _ReadIndex) * 3) + _WriteIndex;                          
                        _ReturnBytes[_RVA] = p_Data[m_ReadIndex];  
                    }  
                    _ReadIndex += _Count;  
                    m_ReadIndex++;  
                }  
                else 
                {  
                    int _RVA = (_ReadIndex * 3) + _WriteIndex;  
                    _ReturnBytes[_RVA] = _Data;  
                    m_ReadIndex++;  
                    _ReadIndex++;  
                }  
                if (_ReadIndex >= _LineWidth)  
                {  
                    _WriteIndex--;  
                    _ReadIndex = 0;  
                }  
 
                if (_WriteIndex == -1) break;  
            }  
            return _ReturnBytes;  
        }  
        /// <summary>  
        /// 获取PCX一行信息 8位色  
        /// </summary>  
        /// <param name="p_Data">数据</param>  
        /// <returns>BMP的行信息</returns>  
        private byte[] LoadPCXLine8(byte[] p_Data)  
        {  
            int _LineWidth = m_Head.Bytes_Per_Line;  
            byte[] _ReturnBytes = new byte[_LineWidth];  
            int _EndBytesLength = p_Data.Length - 1 - (256 * 3);         //数据行不够就不执行了。。  
            int _ReadIndex = 0;  
            while (true)  
            {  
                if (m_ReadIndex > _EndBytesLength) break; //判断行扫描结束返回码    
 
                byte _Data = p_Data[m_ReadIndex];  
                if (_Data > 0xC0)  
                {  
                    int _Count = _Data - 0xC0;  
                    m_ReadIndex++;  
                    for (int i = 0; i != _Count; i++)  
                    {  
                        _ReturnBytes[i + _ReadIndex] = p_Data[m_ReadIndex];  
                    }  
                    _ReadIndex += _Count;  
                    m_ReadIndex++;  
                }  
                else 
                {  
                    _ReturnBytes[_ReadIndex] = _Data;  
                    m_ReadIndex++;  
                    _ReadIndex++;  
                }  
                if (_ReadIndex >= _LineWidth) break;  
            }  
            return _ReturnBytes;  
        }  
        /// <summary>  
        /// 获取PCX一行信息 1位色  
        /// </summary>  
        /// <param name="p_Data">数据</param>  
        /// <returns>BMP的行信息</returns>  
        private byte[] LoadPCXLine1(byte[] p_Data)  
        {  
            int _LineWidth = m_Head.Bytes_Per_Line;  
            byte[] _ReturnBytes = new byte[_LineWidth];         
            int _ReadIndex = 0;  
            while (true)  
            {   
                byte _Data = p_Data[m_ReadIndex];  
                if (_Data > 0xC0)  
                {  
                    int _Count = _Data - 0xC0;  
                    m_ReadIndex++;  
                    for (int i = 0; i != _Count; i++)  
                    {  
                        _ReturnBytes[i + _ReadIndex] = p_Data[m_ReadIndex];  
                    }  
                    _ReadIndex += _Count;  
                    m_ReadIndex++;  
                }  
                else 
                {  
                    _ReturnBytes[_ReadIndex] = _Data;  
                    m_ReadIndex++;  
                    _ReadIndex++;  
                }  
                if (_ReadIndex >= _LineWidth) break;  
            }  
            return _ReturnBytes;  
        } 
        #endregion 
 
         
        #region 存数据行  
        private int m_SaveIndex = 0;  
        /// <summary>  
        /// 返回PCX8位色数据  
        /// </summary>  
        /// <param name="p_Data">原始数据</param>  
        /// <returns>数据</returns>  
        private byte[] SavePCXLine8(byte[] p_Data)  
        {  
            MemoryStream _Memory = new MemoryStream();              
            byte  _Value = p_Data[m_SaveIndex];  
            byte _Count = 1;  
            for (int i = 1; i != p_Data.Length; i++)  
            {  
                byte _Temp = p_Data[m_SaveIndex+i];  
                if (_Temp == _Value)  
                {                      
                    _Count++;  
                    if (_Count == 63)  
                    {  
                        _Memory.WriteByte(0xFF);  
                        _Memory.WriteByte(_Value);  
                        _Count = 0;  
                    }  
                }  
                else 
                {  
                    if (_Count == 1 && _Value< 0xC0 && _Value!=0x00)  
                    {  
                        _Memory.WriteByte(_Value);      
                    }  
                    else 
                    {  
                        _Memory.WriteByte((byte)(0xC0 + _Count));  
                        _Memory.WriteByte(_Value);  
                    }  
                    _Count = 1;  
                    _Value = _Temp;  
                }  
            }  
            if (_Count == 1 && _Value < 0xC0 && _Value != 0x00)  
            {  
                _Memory.WriteByte(_Value);  
            }  
            else 
            {  
                _Memory.WriteByte((byte)(0xC0 + _Count));  
                _Memory.WriteByte(_Value);  
            }                         
            return _Memory.ToArray();  
        }  
        /// <summary>  
        /// 返回24位色数据  
        /// </summary>  
        /// <param name="p_Data">原始数据</param>  
        /// <returns>数据</returns>  
        private byte[] SavePCXLine24(byte[] p_Data)  
        {  
            MemoryStream _Read = new MemoryStream();  
            MemoryStream _Green = new MemoryStream();  
            MemoryStream _Blue = new MemoryStream();  
 
            for (int i = 0; i != m_Head.Width; i++)  
            {  
                _Read.WriteByte(p_Data[m_SaveIndex+2]);  
                _Green.WriteByte(p_Data[m_SaveIndex+1]);  
                _Blue.WriteByte(p_Data[m_SaveIndex]);  
                m_SaveIndex += 3;  
            }  
 
            MemoryStream _All = new MemoryStream();  
            int _OleIndex = m_SaveIndex;  
            m_SaveIndex = 0;  
            byte[] _Bytes = SavePCXLine8(_Read.ToArray());  
            _All.Write(_Bytes, 0, _Bytes.Length);  
            m_SaveIndex = 0;  
            _Bytes = SavePCXLine8(_Green.ToArray());  
            _All.Write(_Bytes, 0, _Bytes.Length);  
            m_SaveIndex = 0;  
            _Bytes = SavePCXLine8(_Blue.ToArray());  
            _All.Write(_Bytes, 0, _Bytes.Length);  
            m_SaveIndex = _OleIndex;  
            return _All.ToArray();  
        } 
        #endregion  
 
    }  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值