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

posted @ 2014-11-19 14:13  遥望星空  阅读(2385)  评论(0编辑  收藏  举报