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

  • 相关阅读:
    LeetCode 515. 在每个树行中找最大值(Find Largest Value in Each Tree Row)
    LeetCode 114. 二叉树展开为链表(Flatten Binary Tree to Linked List)
    LeetCode 199. 二叉树的右视图(Binary Tree Right Side View)
    LeetCode 1022. 从根到叶的二进制数之和(Sum of Root To Leaf Binary Numbers)
    LeetCode 897. 递增顺序查找树(Increasing Order Search Tree)
    LeetCode 617. 合并二叉树(Merge Two Binary Trees)
    LeetCode 206. 反转链表(Reverse Linked List) 16
    LeetCode 104. 二叉树的最大深度(Maximum Depth of Binary Tree)
    LeetCode 110. 平衡二叉树(Balanced Binary Tree) 15
    LeetCode 108. 将有序数组转换为二叉搜索树(Convert Sorted Array to Binary Search Tree) 14
  • 原文地址:https://www.cnblogs.com/zjoch/p/4108140.html
Copyright © 2011-2022 走看看