网页功能: 加入收藏 设为首页 网站搜索  
PCX 图象文件格式的读写
发表日期:2007-01-18作者:[转贴] 出处:  


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。

我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 PCX 图象文件格式的读写
本类热点文章
  DirectShow应用——支持Windows Media格..
  DirectShow PIN 連接教學
  游戏UI设计1
  PSD格式文件的读取
  将RGB值转换为灰度值的简单算法
  貼圖 filtering 與 MIP map 簡介
  读取万能图片以及DShow的另类用法
  TGA图像文件格式资料
  DirectShow初探
  PNG格式
  DirectShow应用——支持DVD播放
  DirectShow的中文资料之建立一个捕捉程序
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00402