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

2014-11-24 08:19:01 · 作者: · 浏览: 3
}
return PackPcxLine(dest, dest + bytes, bytes, 1);
}
//---------------------------------------------------------------------------
VOID ARGBQuadToRGBTriple(PRGBTriple dest, PRGBQuad source, INT count)
{
for (INT i = 0; i < count; i++)
{
dest[i].rgbtBlue = source[i].rgbRed;
dest[i].rgbtGreen = source[i].rgbGreen;
dest[i].rgbtRed = source[i].rgbBlue;
}
}
//---------------------------------------------------------------------------
BOOL SavePcxImageToStream(IStream *stream, Bitmap *bmp)
{
PixelFormat format = bmp->GetPixelFormat();
if (format == PixelFormatUndefined)
return FALSE;
PcxFileHeader header;
ColorPalette *pal = NULL;
BYTE palette[256 * 3 + 1];
ZeroMemory(&header, sizeof(PcxFileHeader));
header.bitsPrePixel = GetPixelFormatSize(format);
header.planes = 1;
if (header.bitsPrePixel > 8)
{
format = PixelFormat24bppRGB;
header.planes = 3;
header.bitsPrePixel = 8;
}
else //if (header.bitsPrePixel > 1)
{
pal = (ColorPalette*)new BYTE[256 * sizeof(ARGB) + sizeof(ColorPalette)];
bmp->GetPalette(pal, bmp->GetPaletteSize());
PRGBTriple ppal = (PRGBTriple)&palette[1];
// 如果是16色位图,调色板保存到文件头
if (format == PixelFormat4bppIndexed)
{
header.planes = header.bitsPrePixel;
header.bitsPrePixel = 1;
ppal = (PRGBTriple)header.palette;
}
ARGBQuadToRGBTriple(ppal, (PRGBQuad)pal->Entries, pal->Count);
delete[] pal;
}
Gdiplus::Rect r(0, 0, bmp->GetWidth(), bmp->GetHeight());
header.flag = 0x0A;
header.version = 5;
header.encodeing = 1;
header.xMax = r.Width - 1;
header.yMax = r.Height - 1;
header.hRes = 96;
header.vRes = 96;
header.paletteType = 1;
header.bytesPreLine = (r.Width * header.bitsPrePixel + 7) >> 3;
if (header.bytesPreLine & 1)
header.bytesPreLine ++;
// 保存PCX文件头
if (stream->Write(&header, sizeof(PcxFileHeader), NULL) != S_OK)
return FALSE;
// 获取GDI+位图数据到位图数据结构
BitmapData data;
data.Stride = ((r.Width * GetPixelFormatSize(format) + 31) & -32) >> 3;
INT size = r.Height * data.Stride;
// size为位图数据字节数,header.bytesPreLine*header.planes*2为编码缓冲区字节数
data.Scan0 = (LPVOID)new BYTE[size + header.bytesPreLine * header.planes * 2];
bmp->LockBits(&r, ImageLockModeRead | ImageLockModeUserInputBuf, format, &data);
bmp->UnlockBits(&data);
// 如果单色位图调色板首项不为0,位图数据反向
if (format == PixelFormat1bppIndexed && (*(ARGB*)&palette[1] & 0xffffff))
{
INT count = data.Height * (data.Stride >> 2);
LPDWORD pd = (LPDWORD)data.Scan0;
for (INT i = 0; i < count; pd[i] ^= (DWORD)(-1), i ++);
}
LPBYTE p = (LPBYTE)data.Scan0;
LPBYTE buffer = p + size;
INT bytes;
// 逐行进行RLE编码并保存到流
for (UINT y = 0; y < data.Height; y ++, p += data.Stride)
{
if (format == PixelFormat4bppIndexed)
bytes = PackPcx4Line(buffer, p, header.bytesPreLine, data.Width);
else
bytes = PackPcxLine(buffer, p, header.bytesPreLine, header.planes);
stream->Write(buffer, bytes, NULL);
}
delete[] data.Scan0;
// 如果是256色位图,调色板保存到流的尾部
if (format == PixelFormat8bppIndexed)
{
palette[0] = 0x0c;
stream->Write(palette, 256 * 3 + 1, NULL);
}
return TRUE;
}
//---------------------------------------------------------------------------
BOOL SavePcxImageToFile(LPTSTR fileName, Bitmap *bmp)
{
IStream *stream = new FileStream(fileName, FALSE);
stream->Ad