已知 BITMAPINFO 如何保存为BMP文件

rivern 2012-08-22 01:16:15
代码如下:以下代码能正常显示在C语言的控件面板上,我想将其已知的BITMAPINFO 保存为 BMP文件,如何写,最好写出代码。


static void
Paint(HWND h)
{
int iSel;
HDC hDC;
PAINTSTRUCT ps;
char bmpBuffer[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)] = { 0 };
BITMAPINFO* pBmpInfo;
BYTE* pBmpData;
ABS_DWORD i;

if(pImage == NULL)
return;
iSel = TabCtrl_GetCurSel(hwndTab);
if(iSel != 0)
return;
/* Create windows bitmap header in memory for our sample image. */
pBmpInfo = (BITMAPINFO*) bmpBuffer;
pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pBmpInfo->bmiHeader.biWidth = pImage->Width;
/* The following minus sign tells GDI to draw it in the right vertical
* direction: */
pBmpInfo->bmiHeader.biHeight = -((LONG)pImage->Height);
pBmpInfo->bmiHeader.biPlanes = 1;
pBmpInfo->bmiHeader.biBitCount = 8;
pBmpInfo->bmiHeader.biCompression = BI_RGB;
/* The colormap of the bitmap has to contain grayscale colors,
* spread lineary from black (0) to white (pImage->ColorCount - 1) */
for(i = 0; i < pImage->ColorCount; i++) {
BYTE byGray = (BYTE) ((255 * i) / (pImage->ColorCount - 1));
pBmpInfo->bmiColors[i].rgbRed = byGray;
pBmpInfo->bmiColors[i].rgbGreen = byGray;
pBmpInfo->bmiColors[i].rgbBlue = byGray;
}

/* Each scan line of the image must end on 4-byte boundary, so if
* width of the image is not divisible by 4, we have to rearrange
* the bytes in a temporary buffer. */
if(pImage->Width % 4 == 0) {
pBmpData = NULL;
} else {
ABS_DWORD scanLineLen;
ABS_DWORD scanLineNo;

scanLineLen = pImage->Width + (4 - pImage->Width % 4);
pBmpData = (BYTE*) malloc(scanLineLen * pImage->Height);
for(scanLineNo = 0; scanLineNo < pImage->Height; scanLineNo++) {
memcpy(
pBmpData + scanLineLen * scanLineNo,
pImage->ImageData + pImage->Width * scanLineNo,
pImage->Width
);
}
}
/* Draw the bitmap to the window */
hDC = BeginPaint(h, &ps);
StretchDIBits(hDC,
175, 10, pImage->Width, pImage->Height,
0, 0, pImage->Width, pImage->Height,
(void*) (pBmpData != NULL ? pBmpData : pImage->ImageData),
pBmpInfo,
DIB_RGB_COLORS,
SRCCOPY
);

EndPaint(h, &ps);
/* If we used the temporary buffer for image data, we have to release it */
if(pBmpData != NULL)
free(pBmpData);
}
...全文
374 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
kissif 2012-09-24
  • 打赏
  • 举报
回复
已经发到你邮件
赵4老师 2012-08-24
  • 打赏
  • 举报
回复
楼主不妨在这里贴出“勉强能生成一个BMP指纹图”的链接让俺也学习学习。(^_^)
roak 2012-08-24
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]

或者楼主移驾VC/MFC论坛?
[/Quote]

这个是个好提议,我说这C版板没什么人回复。你给我的例子可以截屏保存成BMP图,我试着改了下未成功。但我今天在网上找其它的找到一个,勉强能生成一个BMP指纹图。有何问题再发贴吧。谢了。
赵4老师 2012-08-24
  • 打赏
  • 举报
回复
或者楼主移驾VC/MFC论坛?
赵4老师 2012-08-24
  • 打赏
  • 举报
回复
等楼下高手出现中……
roak 2012-08-24
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]

再参考C/C++ code
#pragma comment(lib,"gdi32")
#include <windows.h>
#include <stdio.h>

int main() {
const DWORD uWidth = 18 + 17 * 256, uHeight = 18 + 17 * 128;

PBITMAPINFO pbmi = (PBITMAPINFO……
[/Quote]

都不管用.
赵4老师 2012-08-22
  • 打赏
  • 举报
回复
再参考
#pragma comment(lib,"gdi32")
#include <windows.h>
#include <stdio.h>

int main() {
const DWORD uWidth = 18 + 17 * 256, uHeight = 18 + 17 * 128;

PBITMAPINFO pbmi = (PBITMAPINFO) LocalAlloc (LPTR, sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * 2);
pbmi->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = uWidth;
pbmi->bmiHeader.biHeight = uHeight;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = 1;
pbmi->bmiHeader.biSizeImage = ((uWidth + 31) & ~31) / 8 * uHeight;
pbmi->bmiColors[0].rgbBlue = 0;
pbmi->bmiColors[0].rgbGreen = 0;
pbmi->bmiColors[0].rgbRed = 0;
pbmi->bmiColors[1].rgbBlue = 255;
pbmi->bmiColors[1].rgbGreen = 255;
pbmi->bmiColors[1].rgbRed = 255;

HDC hDC = CreateCompatibleDC (0);
void * pvBits;
HBITMAP hBitmap = CreateDIBSection (hDC, pbmi, 0, &pvBits, NULL, 0);
SelectObject (hDC, hBitmap);
HFONT hFont = CreateFont (16, 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, 0, 0, 0, 0, "宋体");
SelectObject (hDC, hFont);
BitBlt (hDC, 0, 0, uWidth, uHeight, NULL, 0, 0, WHITENESS);

char c[4];
int i, j;
for (i = 128; i < 256; i++) {
sprintf (c, "%02X", i);
TextOut (hDC, 1, (i - 127) * 17 + 1, c, 2);
}
for (j = 0; j < 256; j++) {
sprintf (c, "%02X", j);
TextOut (hDC, (j + 1)* 17 + 1, 1, c, 2);
}
for (i = 128; i < 256; i++) {
for (j = 0; j < 256; j++) {
c[0] = (char) i;
c[1] = (char) j;
TextOut (hDC, (j + 1) * 17 + 1, (i - 127) * 17 + 1, c, 2);
}
}
for (i = 0; i < 130; i++) {
MoveToEx (hDC, 0, i * 17, NULL);
LineTo (hDC, uWidth, i * 17);
}
for (j = 0; j < 258; j++) {
MoveToEx (hDC, j * 17, 0, NULL);
LineTo (hDC, j * 17, uHeight);
}

BITMAPFILEHEADER bmfh;
bmfh.bfType = *(PWORD) "BM";
bmfh.bfReserved1 = 0;
bmfh.bfReserved2 = 0;
bmfh.bfOffBits = sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * 2;
bmfh.bfSize = bmfh.bfOffBits + pbmi->bmiHeader.biSizeImage;

HANDLE hFile = CreateFile ("goal.bmp", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
if (hFile != INVALID_HANDLE_VALUE) {
DWORD dwWritten;
WriteFile (hFile, &bmfh, sizeof (BITMAPFILEHEADER), &dwWritten, NULL);
WriteFile (hFile, pbmi, sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * 2, &dwWritten, NULL);
WriteFile (hFile, pvBits, pbmi->bmiHeader.biSizeImage, &dwWritten, NULL);

CloseHandle (hFile);
}

DeleteObject (hFont);
DeleteObject (hBitmap);
DeleteDC (hDC);
LocalFree (pbmi);

return 0;
}
赵4老师 2012-08-22
  • 打赏
  • 举报
回复
参考
int GetBitmapFromScreen(char *lpFileName) {
char *lpBuf;
HBITMAP hBitmap,hOld ;
HDC hDC,hcDC;
BITMAP bb;
BITMAPINFO b;
HANDLE hp,fh=NULL;
DWORD dwX,dwY;

dwX=GetSystemMetrics(SM_CXSCREEN);
dwY=GetSystemMetrics(SM_CYSCREEN);
hDC=GetDC(NULL);
hcDC=CreateCompatibleDC(hDC);
hBitmap=CreateCompatibleBitmap(hDC,dwX,dwY);
hOld=(HBITMAP)SelectObject(hcDC,hBitmap);
BitBlt(hcDC,0, 0,dwX,dwY, hDC, 0, 0, SRCCOPY);
bb.bmWidth=dwX;
bb.bmHeight =dwY;
bb.bmPlanes = 1;
bb.bmWidthBytes=bb.bmWidth*3;
bb.bmBitsPixel=3;
bb.bmType=0;
b.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
b.bmiHeader.biWidth =dwX;
b.bmiHeader.biHeight =dwY;
b.bmiHeader.biPlanes =1;
b.bmiHeader.biBitCount =3*8;
b.bmiHeader.biCompression =BI_RGB;
b.bmiHeader.biSizeImage =0;
b.bmiHeader.biXPelsPerMeter=0;
b.bmiHeader.biYPelsPerMeter=0;
b.bmiHeader.biClrUsed =0;
b.bmiHeader.biClrImportant =0;
b.bmiColors[0].rgbBlue =8;
b.bmiColors[0].rgbGreen =8;
b.bmiColors[0].rgbRed =8;
b.bmiColors[0].rgbReserved =0;
hp=GetProcessHeap();
lpBuf=(char *)HeapAlloc(hp,HEAP_ZERO_MEMORY,bb.bmHeight*bb.bmWidth*4);
GetDIBits(hcDC,hBitmap,0,dwY,lpBuf,&b,DIB_RGB_COLORS);
SaveBitmapToFile(&bb,lpFileName,lpBuf);
ReleaseDC(NULL,hDC);
DeleteDC(hcDC);
DeleteObject(hBitmap);
DeleteObject(hOld);
HeapFree(hp,0,lpBuf);
return true;
}
roak 2012-08-22
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

仅供参考C/C++ code
int SaveBitmapToFile(BITMAP *bitmap, LPSTR lpFileName,char *lpBuf) {
DWORD dwWritten;
BITMAPFILEHEADER bmfHdr;
BITMAPINFOHEADER bi;
HANDLE fh=NULL;
bi.biSi……
[/Quote]

BITMAP *bitmap,char *lpBuf

分别传什么参数?
赵4老师 2012-08-22
  • 打赏
  • 举报
回复
仅供参考
int SaveBitmapToFile(BITMAP *bitmap, LPSTR lpFileName,char *lpBuf) {
DWORD dwWritten;
BITMAPFILEHEADER bmfHdr;
BITMAPINFOHEADER bi;
HANDLE fh=NULL;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth= bitmap->bmWidth;
bi.biHeight = bitmap->bmHeight;
bi.biPlanes = 1;
bi.biBitCount = bitmap->bmBitsPixel*8;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (fh == INVALID_HANDLE_VALUE) return FALSE;
bmfHdr.bfType = 0x4D42; // "BM"
bmfHdr.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+bitmap->bmWidth*bitmap->bmHeight*bitmap->bmBitsPixel;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
WriteFile(fh, (char *)&bi,sizeof(BITMAPINFOHEADER), &dwWritten, NULL);
WriteFile(fh, (char *)lpBuf,bitmap->bmWidth*bitmap->bmHeight*bitmap->bmBitsPixel, &dwWritten, NULL);
FlushFileBuffers(fh);
CloseHandle(fh);
return true;
}
JinCraft 2012-08-22
  • 打赏
  • 举报
回复
网上有BMP文件结构的文档,你找找看
我印象中BMP由一两个头结构体和下边的图像数据组成

把结构体每个成员赋值,注意结构体里关于图像字节数以及长宽等的关键成员变量赋值一定要正确。
建一个unsigned char型数组把每个像素数据填充进数组。
最后用fwrite函数把结构体,像素数组先后写进一个文件就OK了,文件打开时用二进制方式打开。
JinCraft 2012-08-22
  • 打赏
  • 举报
回复
网上有BMP文件结构的文档,你找找看
我印象中BMP由一两个头结构体和下边的图像数据组成

把结构体每个成员赋值,注意结构体里关于图像字节数以及长宽等的关键成员变量赋值一定要正确。
建一个unsigned char型数组把每个像素数据填充进数组。
最后用fwrite函数把结构体,像素数组先后写进一个文件就OK了,文件打开时用二进制方式打开。

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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