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位的图 .然后去保存..
全部代码...
- 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, _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位的图 .然后去保存..
全部代码.
-
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现