只知道图像数据,如何转换成一个完整的位图缓存,或者是一个位图文件.

EnochShen 2004-11-18 01:20:42
BITMAPINFOHEADER可以自己填充:

typedef struct tagBITMAPINFOHEADER{
DWORD biSize; //指定 BITMAPINFOHEADER 结构所需的字节数。 sizeof(BITMAPINFOHEADER),一般是40;
LONG biWidth; //指定位图的宽度(以象素为单位)。
LONG biHeight; //指定位图的高度(以象素为单位)。
WORD biPlanes; //指定目标设备的位面数。这个成员变量的值必须为 1。
WORD biBitCount //指定每个象素的位数。
DWORD biCompression; //指定压缩位图的压缩类型。 如果未经压缩(BMP):BI_RGB;JPG:BI_JPEG;PNG:BI_PNG。
DWORD biSizeImage; //指定图像的大小(以字节为单位)。注意4位对齐;一般是(((图像的宽度*图像的位数+7)/8)+3)/4*4*图像的高度
LONG biXPelsPerMeter; //为位图指定目标设备的水平分辨率(以“象素/米”为单位)。应用程序可用该值从最符合当前设备特征的资源群组中选择一个位图。
LONG biYPelsPerMeter; //为位图指定目标设备的垂直分辨率(以“象素/米”为单位)。应用程序可用该值从最符合当前设备特征的资源群组中选择一个位图。
DWORD biClrUsed; //指定位图实际所用的颜色表中的颜色索引数。如果 biBitCount 设为 24,则 biClrUsed 指定用来优化 Windows 调色板性能的参考颜色表。
DWORD biClrImportant; //指定对位图的显示有重要影响的颜色索引数。如果此值为 0,则所有颜色都很重要。
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
//例如biBitCount = 24的时候,biXPelsPerMeter = 0;biYPelsPerMeter = 0;biClrUsed = 0;biClrImportant = 0;

另外:在 24 位格式中,图像中的每个象素都由存储为 BRG 的三字节 RGB 序列表示。每个扫描行都被补足到 4 位。为了使这个过程稍复杂一点,图像是自底而上存储的,即第一个扫描行是图像中的最后一个扫描行。下图显示了标头 (BITMAPHEADER) 和 (BITMAPINFOHEADER) 以及部分图像。各个部分由垂线分隔:

0000000000 4D42 B536 0002 0000 0000 0036 0000 | 0028
0000000020 0000 0107 0000 00E0 0000 0001 0018 0000
0000000040 0000 B500 0002 0EC4 0000 0EC4 0000 0000
0000000060 0000 0000 0000 | FFFF FFFF FFFF FFFF FFFF
0000000100 FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF


下面是转换函数:

LPBITMAPINFOHEADER lpbi; //图像格式文件头
LPSTR lpdib; //图像数据

BYTE* SaveBMPBuffer(DWORD &dwBMPBufSize)//保存成一个BMP的Buffer,dwBMPBufSize是Buffer的大小
{
//确保为4的倍数;
DWORD dwBytesPerLine = (((lpbi->biWidth*lpbi->biBitCount+7)/8)+3)/4*4;
DWORD dwSize = dwBytesPerLine*lpbi->biHeight;
//定义调色板大小
DWORD dwPaletteSize = 0;
switch(lpbi->biBitCount)
{
case 1:
dwPaletteSize = 2;
break;
case 4:
dwPaletteSize = 16;
break;
case 8:
dwPaletteSize = 256;
break;
}
DWORD dwOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwPaletteSize*sizeof(RGBQUAD);

BITMAPFILEHEADER bfh;
bfh.bfType = 0x4D42; //文件类型,必须是'BM'
bfh.bfSize = dwOffBits+dwSize;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = dwOffBits;

BITMAPINFO *pBMPInfo = (BITMAPINFO *)lpbi;

DWORD dwBufSize = sizeof(BITMAPFILEHEADER)+
sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*dwPaletteSize+dwSize;

BYTE *pBuffer = new BYTE[dwBufSize];
BYTE *pOldPtr = pBuffer;

memcpy(pBuffer,&bfh,sizeof(BITMAPFILEHEADER));
pBuffer+=sizeof(BITMAPFILEHEADER);

memcpy(pBuffer,pBMPInfo,sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*dwPaletteSize);
pBuffer+=sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*dwPaletteSize;

memcpy(pBuffer,(LPBYTE)lpdib,dwSize);
pBuffer = pOldPtr;

dwBMPBufSize = dwBufSize;

return pBuffer;
}

BOOL SaveBMPFile(LPCTSTR lpszFileName)//保存成一个BMP的文件
{

//确保为4的倍数;
DWORD dwBytesPerLine = (((lpbi->biWidth*lpbi->biBitCount+7)/8)+3)/4*4;
DWORD dwSize = dwBytesPerLine*lpbi->biHeight;
//定义调色板大小
DWORD dwPaletteSize = 0;
switch(lpbi->biBitCount)
{
case 1:
dwPaletteSize = 2;
break;
case 4:
dwPaletteSize = 16;
break;
case 8:
dwPaletteSize = 256;
break;
}
DWORD dwOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwPaletteSize*sizeof(RGBQUAD);

BITMAPFILEHEADER bfh;
bfh.bfType = 0x4D42; //文件类型,必须是'BM'
bfh.bfSize = dwOffBits+dwSize;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = dwOffBits;

BITMAPINFO *pBMPInfo = (BITMAPINFO *)lpbi;
CFile file;
file.Open(lpszFileName,CFile::modeCreate|CFile::modeWrite|CFile::typeBinary);

file.Write(&bfh,sizeof(BITMAPFILEHEADER));
file.Write(pBMPInfo,sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*dwPaletteSize);
file.Write((LPBYTE)lpdib,dwSize);

file.Close();
return TRUE;
}
...全文
174 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
EnochShen 2004-11-18
  • 打赏
  • 举报
回复
呵呵,自己顶一下先!

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧