当前位置:编程学习 > C/C++ >>

C++图像处理 -- PCX格式图像(上)

 
 
    PCX是一个比较早的图像文件格式,它也有过一段时间的辉煌,但随着计算机硬、软件的发展,该图像格式基本已成过去时,主要是因为早期PCX格式图像是配合当时显卡硬件而设计的,如CGA/EGA/VGA等,现在显然已经过时了,虽然后来的版本增加了对256色和24位真彩色的支持,但仍然因其文件格式的先天不足,导致操作很不方便,如256色图像调色板就是以“补丁”形式追加到文件最后面的,24位真彩色用以前EGA图像卡按行以彩色面形式存放等;另外PCX的RLE编码对6位以下像素格式是比较有效的,对目前8位为主的像素格式压缩也不尽人意,如24位像素格式压缩后,有时比不压缩空间占用还大。
 
    虽然PCX格式图像目前使用不多,但还是有很多软件是支持这种格式的,如Photoshop。在图像处理编程时,偶尔也会遇到这种格式的图像,但不象BMP、JPEG、GIF等图像格式容易找到现存的库函数或组件,所以本文提供了PCX格式图像与GDI+位图的相互转换的代码,本文分上下两篇,上篇将PCX格式图像转换为GDI+位图,下篇将GDI+位图转换为PCX格式图像。下面是转换源码:
 
[cpp] 
typedef struct              // pcx文件头   
{  
    BYTE flag;              // 标记   
    BYTE version;           // 版本号   
    BYTE encodeing;         // 编码方式   
    BYTE bitsPrePixel;      // 平面像素位数   
    WORD xMin;              // 最小X   
    WORD yMin;              // 最小Y   
    WORD xMax;              // 最大X   
    WORD yMax;              // 最大Y   
    WORD hRes;              // 水平分辨率   
    WORD vRes;              // 垂直分辨率   
    BYTE palette[48];       // 16色调色板   
    BYTE reserved;          // 保留   
    BYTE planes;            // 平面数   
    WORD bytesPreLine;      // 每行字节数   
    WORD paletteType;       // 调色板类型。1:彩色或黑白,2:灰度   
    BYTE filler[58];  
}PcxFileHeader, *PPcxFileHeader;  
//---------------------------------------------------------------------------   
  
FORCEINLINE  
LPBYTE UnpackPckLine(LPBYTE dest, LPBYTE source, INT bytes)  
{  
    while (bytes > 0)  
    {  
        if (*source > 0xc0)  
        {  
            INT count = *source ++ & 0x3f;  
            BYTE c = *source ++;  
            bytes -= count;  
            for (; count > 0; *dest ++ = c, count --);  
        }  
        else  
        {  
            *dest ++ = *source ++;  
            bytes --;  
        }  
    }  
    return source;  
}  
//---------------------------------------------------------------------------   
  
// 单色或256色   
VOID UnpackPck(BitmapData *data, LPBYTE bitsMem, INT bytesPreLine)  
{  
    LPBYTE p = (LPBYTE)data->Scan0;  
    LPBYTE m = bitsMem;  
    for (UINT y = 0; y < data->Height; y ++, p += data->Stride)  
    {  
        m = UnpackPckLine(p, m, bytesPreLine);  
    }  
}  
//---------------------------------------------------------------------------   
  
// 16色   
VOID UnpackPck4(BitmapData *data, LPBYTE bitsMem, INT bytesPreLine)  
{  
    LPBYTE p = (LPBYTE)data->Scan0;  
    LPBYTE m = bitsMem;  
    INT datOffset = data->Stride -  
        ((GetPixelFormatSize(data->PixelFormat) * data->Width + 7) >> 3);  
    if (data->Width & 1) datOffset ++;  
    INT bytes1 = bytesPreLine;  
    INT bytes2 = bytes1 << 1;  
    INT bytes3 = bytes2 + bytes1;  
    INT bytes = bytes1 << 2;  
    LPBYTE buffer = new BYTE[bytes];  
    for (UINT y = 0; y < data->Height; y ++, p += datOffset)  
    {  
        m = UnpackPckLine(buffer, m, bytes);  
        LPBYTE b = buffer;  
        BYTE mask = 0x80;  
        for (UINT x = 0; x < data->Width; x ++)  
        {  
            if (*b & mask) *p |= 1;  
            if (*(b + bytes1) & mask) *p |= 2;  
            if (*(b + bytes2) & mask) *p |= 4;  
            if (*(b + bytes3) & mask) *p |= 8;  
            if (x & 1) p ++;  
            else *p <<= 4;  
            mask >>= 1;  
            if (!mask)  
            {  
                mask = 0x80;  
                b ++;  
            }  
        }  
    }  
    delete[] buffer;  
}  
//---------------------------------------------------------------------------   
  
// 24位真彩色   
VOID UnpackPck24(BitmapData *data, LPBYTE bitsMem, INT bytesPreLine)  
{  
    INT bytes1 = bytesPreLine;  
    INT bytes2 = bytes1 << 1;  
    INT bytes = bytes2 + bytes1;  
    INT width = (INT)data->Width > bytesPreLine? bytesPreLine : data->Width;  
    INT datOffset = data->Stride - width * 3;  
    PRGBTriple p = (PRGBTriple)data->Scan0;  
补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,