zoukankan      html  css  js  c++  java
  • C# 转换图形为PCX 格式

    2010-5-27

    PCX RLE压缩图形的行对齐比.NET多了一位.已经修正了.

    2009 -7-25

    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位的图 .然后去保存..

    全部代码...

    [c-sharp] view plaincopy
     
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Text;  
    4. using System.Drawing;  
    5. using System.Drawing.Imaging;  
    6. using System.IO;  
    7. using System.Runtime.InteropServices;  
    8.   
    9. namespace Zgke.MyImage.ImageFile  
    10. {  
    11.     /// <summary>  
    12.     /// PCX操作类  
    13.     /// zgke@sina.com  
    14.     /// qq:116149  
    15.     /// </summary>  
    16.     public class ImagePcx  
    17.     {  
    18.         /// <summary>  
    19.         /// PCX文件头  
    20.         /// </summary>  
    21.         private class PCXHEAD  
    22.         {  
    23.             public byte[] m_Data = new byte[128];  
    24.   
    25.             /// <summary>  
    26.             /// 文件头必须为 0A;  
    27.             /// </summary>  
    28.             public byte Manufacturer { get { return m_Data[0]; } }  
    29.             /// <summary>  
    30.             /// 0:PC Paintbrush 2.5 版   2:PC Paintbrush 2.8 版  5:PC Paintbrush 3.0 版  
    31.             /// </summary>  
    32.             public byte Version { get { return m_Data[1]; } set { m_Data[1] = value; } }  
    33.             /// <summary>  
    34.             /// 其值为1时表示采用RLE压缩编码的方法  
    35.             /// </summary>  
    36.             public byte Encoding { get { return m_Data[2]; } set { m_Data[2] = value; } }  
    37.             /// <summary>  
    38.             /// 每个相素的位数  
    39.             /// </summary>  
    40.             public byte Bits_Per_Pixel { get { return m_Data[3]; } set { m_Data[3] = value; } }  
    41.   
    42.             public ushort Xmin { get { return BitConverter.ToUInt16(m_Data, 4); } set { SetUshort(4, value); } }  
    43.             public ushort Ymin { get { return BitConverter.ToUInt16(m_Data, 6); } set { SetUshort(6, value); } }  
    44.             public ushort Xmax { get { return BitConverter.ToUInt16(m_Data, 8); } set { SetUshort(8, value); } }  
    45.             public ushort Ymax { get { return BitConverter.ToUInt16(m_Data, 10); } set { SetUshort(10, value); } }  
    46.             /// <summary>  
    47.             /// 水平分辨率  
    48.             /// </summary>  
    49.             public ushort Hres1 { get { return BitConverter.ToUInt16(m_Data, 12); } set { SetUshort(12, value); } }  
    50.             /// <summary>  
    51.             /// 垂直分辨率  
    52.             /// </summary>  
    53.             public ushort Vres1 { get { return BitConverter.ToUInt16(m_Data, 14); } set { SetUshort(14, value); } }  
    54.   
    55.             public byte[] Palette  
    56.             {  
    57.                 get  
    58.                 {  
    59.                     byte[] _Palette = new byte[48];  
    60.                     Array.Copy(m_Data,16,_Palette,0,48);  
    61.                     return _Palette;  
    62.                 }  
    63.                 set  
    64.                 {  
    65.                     if(value.Length!=48)throw new Exception("错误的byte[]长度不是48");  
    66.                     Array.Copy(value, 0, m_Data, 16, 48);  
    67.                 }  
    68.   
    69.             }  
    70.             /// <summary>  
    71.             /// 位知  
    72.             /// </summary>  
    73.             public byte Reserved { get { return m_Data[64]; } set { m_Data[64] = value; } }  
    74.             /// <summary>  
    75.             /// 未知  
    76.             /// </summary>  
    77.             public byte Colour_Planes { get { return m_Data[65]; } set { m_Data[65] = value; } }  
    78.             /// <summary>  
    79.             /// 解码缓冲区  
    80.             /// </summary>  
    81.             public ushort Bytes_Per_Line { get { return BitConverter.ToUInt16(m_Data, 66); } set { SetUshort(66, value); } }  
    82.             /// <summary>  
    83.             /// 位知  
    84.             /// </summary>  
    85.             public ushort Palette_Type { get { return BitConverter.ToUInt16(m_Data, 68); } set { SetUshort(68, value); } }  
    86.             /// <summary>  
    87.             /// 填充  
    88.             /// </summary>  
    89.             public byte[] Filler  
    90.             {  
    91.                 get  
    92.                 {  
    93.                     byte[] m_Bytes = new byte[58];  
    94.                     Array.Copy(m_Data, 70, m_Bytes, 0, 58);  
    95.                     return m_Bytes;  
    96.                 }  
    97.             }  
    98.   
    99.             public PCXHEAD(byte[] p_Data)  
    100.             {  
    101.                 Array.Copy(p_Data, m_Data, 128);  
    102.             }  
    103.   
    104.             public PCXHEAD()  
    105.             {  
    106.                 m_Data[0] = 0xA;  
    107.                 Version = 0x5;  
    108.                 Encoding = 0x1;  
    109.                 Bits_Per_Pixel = 0x8;  
    110.                 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 };  
    111.                 Reserved = 0x01;  
    112.                 Colour_Planes = 0x03;  
    113.                 Palette_Type = 1;  
    114.             }  
    115.   
    116.             public int Width { get { return Xmax - Xmin + 1; } }  
    117.   
    118.             public int Height { get { return Ymax - Ymin + 1; } }  
    119.   
    120.             /// <summary>  
    121.             /// 设置16位数据保存到数据表  
    122.             /// </summary>  
    123.             /// <param name="p_Index">索引</param>  
    124.             /// <param name="p_Data">数据</param>  
    125.             private void SetUshort(int p_Index, ushort p_Data)  
    126.             {  
    127.                 byte[] _ValueBytes = BitConverter.GetBytes(p_Data);  
    128.                 m_Data[p_Index] = _ValueBytes[0];  
    129.                 m_Data[p_Index + 1] = _ValueBytes[1];  
    130.             }  
    131.         }  
    132.   
    133.         private PCXHEAD m_Head = new PCXHEAD();  
    134.   
    135.         private Bitmap m_Image;  
    136.   
    137.         /// <summary>  
    138.         /// 获取图形  
    139.         /// </summary>  
    140.         public Bitmap PcxImage { get { return m_Image; } set { m_Image = value; } }  
    141.   
    142.         public ImagePcx(string p_FileFullName)  
    143.         {  
    144.             if (!File.Exists(p_FileFullName)) return;  
    145.             Load(File.ReadAllBytes(p_FileFullName));  
    146.         }  
    147.   
    148.         public ImagePcx(byte[] p_Data)  
    149.         {  
    150.             Load(p_Data);  
    151.         }  
    152.   
    153.         public ImagePcx()  
    154.         {             
    155.             
    156.         }  
    157.   
    158.         /// <summary>  
    159.         /// 开始获取数据  
    160.         /// </summary>  
    161.         /// <param name="p_Bytes">PCX文件信息</param>  
    162.         private void Load(byte[] p_Bytes)  
    163.         {  
    164.             byte[] _Bytes = p_Bytes;  
    165.             if (_Bytes[0] != 0x0A) return;              
    166.             m_Head = new PCXHEAD(_Bytes);  
    167.             m_ReadIndex = 128;  
    168.             PixelFormat _PixFormate = PixelFormat.Format24bppRgb;  
    169.             if (m_Head.Colour_Planes == 1)  
    170.             {  
    171.                 switch (m_Head.Bits_Per_Pixel)  
    172.                 {  
    173.                     case 8:  
    174.                         _PixFormate = PixelFormat.Format8bppIndexed;  
    175.                         break;  
    176.                     case 1:  
    177.                         _PixFormate = PixelFormat.Format1bppIndexed;  
    178.                         break;  
    179.                 }  
    180.             }  
    181.   
    182.             m_Image = new Bitmap(m_Head.Width, m_Head.Height, _PixFormate);  
    183.             BitmapData _Data = m_Image.LockBits(new Rectangle(0, 0, m_Image.Width, m_Image.Height), ImageLockMode.ReadWrite, _PixFormate);  
    184.             byte[] _BmpData = new byte[_Data.Stride * _Data.Height];  
    185.   
    186.             for (int i = 0; i != m_Head.Height; i++)  
    187.             {  
    188.                 byte[] _RowColorValue=new byte[0];  
    189.                 switch (m_Head.Colour_Planes)  
    190.                 {  
    191.                     case 3: //24位  
    192.                         _RowColorValue = LoadPCXLine24(_Bytes);  
    193.                         break;  
    194.                     case 1: //256色  
    195.                         switch (m_Head.Bits_Per_Pixel)  
    196.                         {  
    197.                             case 8:  
    198.                                 _RowColorValue = LoadPCXLine8(_Bytes);  
    199.                                 break;  
    200.                             case 1:  
    201.                                 _RowColorValue = LoadPCXLine1(_Bytes);  
    202.                                 break;  
    203.                         }  
    204.                           
    205.                         break;  
    206.                 }             
    207.                 int _Count = _RowColorValue.Length;  
    208.                 Array.Copy(_RowColorValue, 0, _BmpData, i * _Data.Stride, _Data.Stride);  
    209.             }  
    210.             Marshal.Copy(_BmpData, 0, _Data.Scan0, _BmpData.Length);  
    211.             m_Image.UnlockBits(_Data);  
    212.   
    213.             switch (m_Head.Colour_Planes)  
    214.             {  
    215.                 case 1:  
    216.                     if (m_Head.Bits_Per_Pixel == 8)  
    217.                     {  
    218.                         ColorPalette _Palette = m_Image.Palette;  
    219.                         m_ReadIndex = p_Bytes.Length - 256 * 3;  
    220.                         for (int i = 0; i != 256; i++)  
    221.                         {  
    222.                             _Palette.Entries[i] = Color.FromArgb(p_Bytes[m_ReadIndex], p_Bytes[m_ReadIndex + 1], p_Bytes[m_ReadIndex + 2]);  
    223.                             m_ReadIndex += 3;  
    224.                         }  
    225.                         m_Image.Palette = _Palette;  
    226.                     }  
    227.                     break;  
    228.             }  
    229.         }  
    230.   
    231.         /// <summary>  
    232.         /// 保存成PCX文件  
    233.         /// </summary>  
    234.         /// <param name="p_FileFullName">完成路径</param>  
    235.         public void Save(string p_FileFullName)  
    236.         {  
    237.             if (m_Image == null) return;  
    238.             m_Head.Xmax = (ushort)(m_Image.Width - 1);  
    239.             m_Head.Ymax = (ushort)(m_Image.Height - 1);  
    240.             m_Head.Vres1 = (ushort)(m_Head.Xmax + 1);  
    241.             m_Head.Hres1 = (ushort)(m_Head.Ymax + 1);  
    242.             m_Head.Bytes_Per_Line = (ushort)m_Head.Width;  
    243.   
    244.             MemoryStream _SaveData = new MemoryStream();  
    245.   
    246.             switch (m_Image.PixelFormat)  
    247.             {  
    248.                 #region 8位  
    249.                 case PixelFormat.Format8bppIndexed:  
    250.                     m_Head.Colour_Planes = 1;  
    251.                     BitmapData _ImageData = m_Image.LockBits(new Rectangle(0, 0, m_Head.Width, m_Head.Height), ImageLockMode.ReadOnly, m_Image.PixelFormat);  
    252.                     byte[] _ImageByte = new byte[_ImageData.Stride * _ImageData.Height];  
    253.                     Marshal.Copy(_ImageData.Scan0, _ImageByte, 0, _ImageByte.Length);  
    254.                     m_Image.UnlockBits(_ImageData);  
    255.   
    256.                     m_SaveIndex = 0;  
    257.                     byte[] _RowBytes = SavePCXLine8(_ImageByte);  
    258.                     _SaveData.Write(_RowBytes, 0, _RowBytes.Length);  
    259.   
    260.                     _SaveData.WriteByte(0x0C);  
    261.                     for (int i = 0; i != 256; i++)  
    262.                     {  
    263.                         _SaveData.WriteByte((byte)m_Image.Palette.Entries[i].R);  
    264.                         _SaveData.WriteByte((byte)m_Image.Palette.Entries[i].G);  
    265.                         _SaveData.WriteByte((byte)m_Image.Palette.Entries[i].B);  
    266.                     }                      
    267.                     break;  
    268.                 #endregion  
    269.                 #region 其他都按24位保存  
    270.                 default:  
    271.                     m_Head.Colour_Planes = 3;  
    272.                     Bitmap _Bitamp24 = new Bitmap(m_Head.Width, m_Head.Height, PixelFormat.Format24bppRgb);  
    273.                     Graphics _Graphics = Graphics.FromImage(_Bitamp24);  
    274.                     _Graphics.DrawImage(m_Image, 0, 0, m_Head.Width, m_Head.Height);  
    275.                     _Graphics.Dispose();  
    276.                     BitmapData _ImageData24 = _Bitamp24.LockBits(new Rectangle(0, 0, m_Head.Width, m_Head.Height), ImageLockMode.ReadOnly, _Bitamp24.PixelFormat);  
    277.                     byte[] _ImageByte24 = new byte[_ImageData24.Stride * _ImageData24.Height];  
    278.                     Marshal.Copy(_ImageData24.Scan0, _ImageByte24, 0, _ImageByte24.Length);  
    279.                     _Bitamp24.UnlockBits(_ImageData24);  
    280.                     m_SaveIndex = 0;  
    281.                     for (int i = 0; i != _ImageData24.Height; i++)  
    282.                     {  
    283.                         m_SaveIndex = i * _ImageData24.Stride;  //2009-10-11 更新 PCX读取位置  
    284.                         byte[] _RowBytes24 = SavePCXLine24(_ImageByte24);  
    285.                         _SaveData.Write(_RowBytes24, 0, _RowBytes24.Length);  
    286.                     }  
    287.                     _SaveData.WriteByte(0x0C);  
    288.                     _SaveData.Write(new byte[768], 0, 768);  
    289.                      
    290.                     break;  
    291.                 #endregion  
    292.             }  
    293.             FileStream _FileStream = new FileStream(p_FileFullName, FileMode.Create, FileAccess.Write);  
    294.             _FileStream.Write(m_Head.m_Data, 0, 128);  
    295.             byte[] _FileData = _SaveData.ToArray();  
    296.             _FileStream.Write(_FileData, 0, _FileData.Length);  
    297.             _FileStream.Close();  
    298.         }  
    299.         
    300.         #region 取数据行  
    301.         /// <summary>  
    302.         /// 读取标记  
    303.         /// </summary>  
    304.         private int m_ReadIndex = 0;  
    305.         /// <summary>  
    306.         /// 获取PCX一行信息 24位色  
    307.         /// </summary>  
    308.         /// <param name="p_Data">数据</param>  
    309.         /// <returns>BMP的行信息</returns>  
    310.         private byte[] LoadPCXLine24(byte[] p_Data)  
    311.         {  
    312.             int _LineWidth = m_Head.Bytes_Per_Line;  
    313.             byte[] _ReturnBytes = new byte[_LineWidth * 3];  
    314.             int _EndBytesLength = p_Data.Length - 1;  
    315.             int _WriteIndex = 2;  
    316.             int _ReadIndex = 0;  
    317.             while (true)  
    318.             {  
    319.                 if (m_ReadIndex > _EndBytesLength) break; //判断行扫描结束返回码  
    320.                 byte _Data = p_Data[m_ReadIndex];  
    321.                  
    322.                 if (_Data > 0xC0)  
    323.                 {  
    324.                     int _Count = _Data - 0xC0;  
    325.                     m_ReadIndex++;  
    326.                     for (int i = 0; i != _Count; i++)  
    327.                     {  
    328.                         if (i + _ReadIndex >= _LineWidth)          //2009-6-12 RLE数据 会换行  
    329.                         {  
    330.                             _WriteIndex--;  
    331.                             _ReadIndex = 0;  
    332.                             _Count = _Count - i;  
    333.                             i = 0;  
    334.                         }  
    335.                         int _RVA = ((i + _ReadIndex) * 3) + _WriteIndex;  
    336.                         _ReturnBytes[_RVA] = p_Data[m_ReadIndex];  
    337.                     }  
    338.                     _ReadIndex += _Count;  
    339.                     m_ReadIndex++;  
    340.                 }  
    341.                 else  
    342.                 {  
    343.                     int _RVA = (_ReadIndex * 3) + _WriteIndex;  
    344.                     _ReturnBytes[_RVA] = _Data;  
    345.                     m_ReadIndex++;  
    346.                     _ReadIndex++;  
    347.                 }  
    348.                 if (_ReadIndex >= _LineWidth)  
    349.                 {  
    350.                     _WriteIndex--;  
    351.                     _ReadIndex = 0;  
    352.                 }  
    353.   
    354.                 if (_WriteIndex == -1) break;  
    355.             }  
    356.              
    357.             return _ReturnBytes;  
    358.         }  
    359.         /// <summary>  
    360.         /// 获取PCX一行信息 8位色  
    361.         /// </summary>  
    362.         /// <param name="p_Data">数据</param>  
    363.         /// <returns>BMP的行信息</returns>  
    364.         private byte[] LoadPCXLine8(byte[] p_Data)  
    365.         {  
    366.             int _LineWidth = m_Head.Bytes_Per_Line;  
    367.             byte[] _ReturnBytes = new byte[_LineWidth];  
    368.             int _EndBytesLength = p_Data.Length - 1 - (256 * 3);         //数据行不够就不执行了。。  
    369.             int _ReadIndex = 0;  
    370.             while (true)  
    371.             {  
    372.                 if (m_ReadIndex > _EndBytesLength) break; //判断行扫描结束返回码    
    373.   
    374.                 byte _Data = p_Data[m_ReadIndex];  
    375.                 if (_Data > 0xC0)  
    376.                 {  
    377.                     int _Count = _Data - 0xC0;  
    378.                     m_ReadIndex++;  
    379.                     for (int i = 0; i != _Count; i++)  
    380.                     {  
    381.                         _ReturnBytes[i + _ReadIndex] = p_Data[m_ReadIndex];  
    382.                     }  
    383.                     _ReadIndex += _Count;  
    384.                     m_ReadIndex++;  
    385.                 }  
    386.                 else  
    387.                 {  
    388.                     _ReturnBytes[_ReadIndex] = _Data;  
    389.                     m_ReadIndex++;  
    390.                     _ReadIndex++;  
    391.                 }  
    392.                 if (_ReadIndex >= _LineWidth) break;  
    393.             }  
    394.             return _ReturnBytes;  
    395.         }  
    396.         /// <summary>  
    397.         /// 获取PCX一行信息 1位色  
    398.         /// </summary>  
    399.         /// <param name="p_Data">数据</param>  
    400.         /// <returns>BMP的行信息</returns>  
    401.         private byte[] LoadPCXLine1(byte[] p_Data)  
    402.         {  
    403.             int _LineWidth = m_Head.Bytes_Per_Line;  
    404.             byte[] _ReturnBytes = new byte[_LineWidth];         
    405.             int _ReadIndex = 0;  
    406.             while (true)  
    407.             {   
    408.                 byte _Data = p_Data[m_ReadIndex];  
    409.                 if (_Data > 0xC0)  
    410.                 {  
    411.                     int _Count = _Data - 0xC0;  
    412.                     m_ReadIndex++;  
    413.                     for (int i = 0; i != _Count; i++)  
    414.                     {  
    415.                         _ReturnBytes[i + _ReadIndex] = p_Data[m_ReadIndex];  
    416.                     }  
    417.                     _ReadIndex += _Count;  
    418.                     m_ReadIndex++;  
    419.                 }  
    420.                 else  
    421.                 {  
    422.                     _ReturnBytes[_ReadIndex] = _Data;  
    423.                     m_ReadIndex++;  
    424.                     _ReadIndex++;  
    425.                 }  
    426.                 if (_ReadIndex >= _LineWidth) break;  
    427.             }  
    428.             return _ReturnBytes;  
    429.         }  
    430.         #endregion  
    431.  
    432.          
    433.         #region 存数据行  
    434.         private int m_SaveIndex = 0;  
    435.         /// <summary>  
    436.         /// 返回PCX8位色数据  
    437.         /// </summary>  
    438.         /// <param name="p_Data">原始数据</param>  
    439.         /// <returns>数据</returns>  
    440.         private byte[] SavePCXLine8(byte[] p_Data)  
    441.         {  
    442.             MemoryStream _Memory = new MemoryStream();              
    443.             byte  _Value = p_Data[m_SaveIndex];  
    444.             byte _Count = 1;  
    445.             for (int i = 1; i != p_Data.Length; i++)  
    446.             {  
    447.                 byte _Temp = p_Data[m_SaveIndex+i];  
    448.                 if (_Temp == _Value)  
    449.                 {                      
    450.                     _Count++;  
    451.                     if (_Count == 63)  
    452.                     {  
    453.                         _Memory.WriteByte(0xFF);  
    454.                         _Memory.WriteByte(_Value);  
    455.                         _Count = 0;  
    456.                     }  
    457.                 }  
    458.                 else  
    459.                 {  
    460.                     if (_Count == 1 && _Value< 0xC0 && _Value!=0x00)  
    461.                     {  
    462.                         _Memory.WriteByte(_Value);      
    463.                     }  
    464.                     else  
    465.                     {  
    466.                         _Memory.WriteByte((byte)(0xC0 + _Count));  
    467.                         _Memory.WriteByte(_Value);  
    468.                     }  
    469.                     _Count = 1;  
    470.                     _Value = _Temp;  
    471.                 }  
    472.             }  
    473.             if (_Count == 1 && _Value < 0xC0 && _Value != 0x00)  
    474.             {  
    475.                 _Memory.WriteByte(_Value);  
    476.             }  
    477.             else  
    478.             {  
    479.                 _Memory.WriteByte((byte)(0xC0 + _Count));  
    480.                 _Memory.WriteByte(_Value);  
    481.             }                         
    482.             return _Memory.ToArray();  
    483.         }  
    484.         /// <summary>  
    485.         /// 返回24位色数据  
    486.         /// </summary>  
    487.         /// <param name="p_Data">原始数据</param>  
    488.         /// <returns>数据</returns>  
    489.         private byte[] SavePCXLine24(byte[] p_Data)  
    490.         {  
    491.             MemoryStream _Read = new MemoryStream();  
    492.             MemoryStream _Green = new MemoryStream();  
    493.             MemoryStream _Blue = new MemoryStream();  
    494.   
    495.             for (int i = 0; i != m_Head.Width; i++)  
    496.             {  
    497.                 _Read.WriteByte(p_Data[m_SaveIndex+2]);  
    498.                 _Green.WriteByte(p_Data[m_SaveIndex+1]);  
    499.                 _Blue.WriteByte(p_Data[m_SaveIndex]);  
    500.                 m_SaveIndex += 3;  
    501.             }  
    502.   
    503.             MemoryStream _All = new MemoryStream();  
    504.             int _OleIndex = m_SaveIndex;  
    505.             m_SaveIndex = 0;  
    506.             byte[] _Bytes = SavePCXLine8(_Read.ToArray());  
    507.             _All.Write(_Bytes, 0, _By

      2010-5-27

      PCX RLE压缩图形的行对齐比.NET多了一位.已经修正了.

      2009 -7-25

      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位的图 .然后去保存..

      全部代码.

    508. 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, _Data.Stride);
                  }
                  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
      
          }
      }
      

       转自:http://blog.csdn.net/zgke/article/details/4204090

  • 相关阅读:
    数据访问之注册审核(重点是审核!!!)常用于企业、公司、医院等网站---2017-05-04
    5个简约的网站---2017-05-03
    数据访问(租房子多条件查询)---2017-05-03
    数据访问之 批量删除 ---2017-05-03
    数据访问之查询数据 ---2017--05-02
    php部分--数组(包含指针思想遍历数组);
    php部分---面向对象静态、抽象类、oop接口、加载类、魔术方法、关键字。
    PHP部分---字符串处理(文中例子不断更新);
    php部分--面向对象三大特性-封装(另加连续调用的一个例子)、继承(重写、重载的例子)、多态;
    php部分---面向对象:定义、实例化、构造函数、析构函数;
  • 原文地址:https://www.cnblogs.com/zjoch/p/4108140.html
Copyright © 2011-2022 走看看