分享
 
 
 

PCX 图象文件格式的读写

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

PCX 图象文件格式的读写

PCX图象文件格式最早出现于Zsoft公司开发的PC Paintbrush绘图软件,由于该绘图软件功能强大并成功移植到Windows操作系统,

加上PCX是最早支持彩色的图象格式之一,PCX成为目前比较流行的图象格式。

对于开发图象浏览、处理软件的程序员来讲,如何读取、保存PCX图象格式是最为基本的话题,作者根据自己对PCX图象格式理解,

开发了相应的代码,希望对读者有用,由于篇幅限制,在此对文件格式不予介绍,读者可以参考相关数目。

代码如下,调用方法程序段之后简单讲解,水平有限,还请包涵;我的电子信箱是:cadinfo@263.net,欢迎探讨。

========================================================

/****************************************************************************

* 函数名称:LoadPCXLine(PPCXHEAD ppcxHdr, LPBYTE ppcxImg, LPBYTE ppcxBits) const

*

* 参数:PPCXHEAD ppcxHdr -指向PCXHEAD结构的指针!NULL,导入BitPlane,BytePerLine,=>clScanLineSize

* LPBYTE ppcxImg -指向PCX图象区指针!NULL,RLE压缩编码,位置递增+=rec。

* 调用之前获得首地址指针:

* LPBYTE ppcxBits -指向DIB数据区的指针,按扫描行(scanline)长度递增

*

* 返回:UINT rec -返回每行解压以后的字节数目

*

* 说明:根据PCX图象数据指针,对RLE进行解码

****************************************************************************/

UINT CPcxImage::LoadPCXLine(PPCXHEAD ppcxHdr, LPBYTE ppcxImg, LPBYTE ppcxBits) const

{

ASSERT(ppcxHdr!=NULL&&ppcxImg!=NULL&&ppcxBits!=NULL);

// because in bitmap bits order, it's blue=>green=>red

// however pcx is red=>green=>blue so use decrease order

//-----------------------------------------

UINT lPos(0), // 记录存入ppcxBits的总数

iX(0), // 记录每个位平面字节序号

rec(0); // 读取_ppcxImg_ 字节序号

for ( int bp=ppcxHdr->BitPlane-1; bp >= 0; bp-- )

{

// RLE 解码=======

iX=0;

while ( iX<ppcxHdr->BytePerLine )

{

BYTE uiValue = ppcxImg[rec++];

if ( (uiValue & 0xc0) == 0xc0 ) // 判断高位字节是否设置 0xc0

{

uiValue = uiValue & 0x3f ; // 计算重复

BYTE Color = ppcxImg[rec++]; // 提取颜色

// 存放到内存DIB

for ( BYTE bRepeat=0; bRepeat < uiValue; bRepeat++ )

{

ppcxBits[(iX++)*ppcxHdr->BitPlane+bp] = Color;

lPos++;

}

}

else

{

ppcxBits[(iX++)*ppcxHdr->BitPlane+bp] = uiValue;

lPos++;

}

}

}

return rec;

}

/****************************************************************************

* 函数名称:PackPCXLine(PPCXHEAD ppcxHdr, LPBYTE ppcxImg, LPBYTE ppcxBits) const

*

* 参数:PPCXHEAD ppcxHdr -指向PCXHEAD结构的指针!NULL,导入BitPlane,BytePerLine,=>clScanLineSize

* LPBYTE ppcxBits -指向DIB数据区的指针,按扫描行(scanline)长度递增

* LPBYTE ppcxImg -指向PCX图象区指针!NULL,RLE压缩编码。

* 调用之前声明: LPBYTE ppcxImg=new BYTE[2*BitPlane*BytePerLine]

*

* 返回:UINT rec -返回每行压缩以后的字节数目

*

* 说明:根据DIB图象数据指针,进行RLE编码(经过测试算法很完善,支持256和24bit真彩色)

****************************************************************************/

UINT CPcxImage::PackPCXLine(PPCXHEAD ppcxHdr, LPBYTE ppcxBits, LPBYTE ppcxImg) const

{

//----------------------------------------

// RLE压缩

ASSERT(ppcxHdr!=NULL && ppcxBits!=NULL && ppcxImg!=NULL);

BYTE i(1);

UINT lPos(0), rec(0);

// ☆RLE编码,最大重复<=63☆

for(int bp=ppcxHdr->BitPlane-1; bp>=0; bp--)

{

lPos=0; // 处理到的RGB序列

while(lPos<ppcxHdr->BytePerLine) // 等价小于图象宽度

{

i=1; // 重置步长-1

//----------------->以下代码检查

while((ppcxBits[(i-1+lPos)*ppcxHdr->BitPlane+bp]==ppcxBits[(i+lPos)*ppcxHdr->BitPlane+bp])

&&((lPos+i)<ppcxHdr->BytePerLine)&&(i<63)) i++;

if(i>1 && i<64)

{

// 表明当前象素位置开始存在i个重复象素值,依次写入PCX图象数据Buffer

// 1.重复次数

ppcxImg[rec++]=i|0xc0;

// 2.象素值

ppcxImg[rec++]=ppcxBits[lPos*ppcxHdr->BitPlane+bp];

lPos+=i; // lPos-记录当前扫描行中已经处理的字节数

// rec -记录当前已经写入PCX文件的字节数

}

else

{

// 表明当前象素位置开始不存在重复象素值

// 象素值大于0xc0(192),写标志0xc1

if((ppcxBits[lPos*ppcxHdr->BitPlane+bp]&0xc0)==0xc0) ppcxImg[rec++]=0xc1;

ppcxImg[rec++]=ppcxBits[lPos*ppcxHdr->BitPlane+bp]; lPos++;

}

}

}

// 写图象数据结束

return rec;

}

===========================================================

调用如下:

1.// RLE解码-------------> 已经包含8、24bit图象

for( int iY=0; iY<=ppcxHdr->YMax; iY++ )

{

ZeroMemory(ppcxBits, clScanLineSize);

ppcxImg+=LoadPCXLine(ppcxHdr, ppcxImg, ppcxBits); // 读取扫描行数据

ppcxBits+=clScanLineSize;

}

ppcxHdr是指向PCXHEAD结构(128BYTE)的指针,ppcxBits是存放解码后图象数据的buffer,ppcxImg是指向pcx图象文件

中图象数据的指针,此处随扫描行递增。完成功能是从pcx文件中解码图象数据到windows位图格式的图象数据。

2.// RLE压缩-------------> 已经包含8、24bit图象

// 最坏情况下申请2倍的缓冲,相邻都不重复,并且都大于0xc0

LPBYTE ppcxImg=new BYTE[2*pcxHdr.BitPlane*pcxHdr.BytePerLine]; // 存放临时扫描行

UINT rec(0); // 计数器,写如PCX文件字节数

for( int iY=0; iY<=pcxHdr.YMax; iY++ )

{

ZeroMemory(ppcxImg,2*pcxHdr.BitPlane*pcxHdr.BytePerLine);

rec=PackPCXLine(&pcxHdr, ppcxBits, ppcxImg);

// DIB 扫描行递增

ppcxBits+=clScanLineSize;

pFile->Write(ppcxImg,rec);

}

delete []ppcxImg;

具体参数大致同1.ppcxImg为临时RLE压缩后的buffer。

------【OVER】------

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有