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. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    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 @   遥望星空  阅读(2422)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示