关于用C++读取BMP文件的一些问题

2024-12-05 04:11:39
推荐回答(5个)
回答1:

BMP 文件分几个层次 读下去。
第一部分是 文件头:
BITMAPFILEHEADER bmfHeader;
读入的字节数是 sizeof(bmfHeader)
后面几个部分的读法,与前面获得的参数有关。
信息头偏移量:read_bmp_o = bmfHeader.bfOffBits / 8;
BITMAPINFOHEADER 读 信息头 结构
BITMAPINFO 读 信息
再由上面信息决定如何读下面的。几位颜色的 BMP,用调色盘的 还是RGB, 还是黑白,还是灰色。是否压缩,是否word对齐。
下面给你MFC的码,你看懂后可以改写成你的普通C++程序:
BOOL CVPICDoc::LoadBMPImage(LPCTSTR sBMPFile, CBitmap &bitmap, CPalette *pPal)
{
BITMAPFILEHEADER bmfHeader;
Read file header
CFile file;
if( !file.Open( sBMPFile, CFile::modeRead) ) return FALSE;
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) return FALSE;
// Check File type should be 'BM'
if (bmfHeader.bfType != ((WORD) ('M' << 8) | 'B'))
return FALSE;
read_bmp_o = bmfHeader.bfOffBits / 8;
// Get length of the remainder of the file and allocate memory
DWORD nPackedDIBLen = file.GetLength() - sizeof(BITMAPFILEHEADER);
HGLOBAL hDIB = ::GlobalAlloc(GMEM_FIXED, nPackedDIBLen);
if (hDIB == 0) return FALSE;
// Read the remainder of the bitmap file.
// BITMAPINFOHEADER + possible-Color-Table + DIB-bits
if (file.ReadHuge((LPSTR)hDIB, nPackedDIBLen) != nPackedDIBLen )
{::GlobalFree(hDIB);
return FALSE;
}
BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB ;
BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;
read_bmp_w = bmiHeader.biWidth;
read_bmp_h = bmiHeader.biHeight;
read_bmp_c = bmiHeader.biBitCount;
read_bmp_size = bmiHeader.biSizeImage;
if (read_bmp_size == 0) {
read_bmp_size = ((((read_bmp_w * read_bmp_c) + 31) & ~31) >> 3) * read_bmp_h;
};
read_bmp_l = read_bmp_size / read_bmp_h; // scan line width
// If bmiHeader.biClrUsed is zero we have to infer the number
// of colors from the number of bits used to specify it.
int nColors = bmiHeader.biClrUsed ? bmiHeader.biClrUsed :
1 << bmiHeader.biBitCount;
LPVOID lpDIBBits;
if( bmInfo.bmiHeader.biBitCount > 8 )
lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors + bmInfo.bmiHeader.biClrUsed) +
((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
else
lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors);
// Create the logical palette
if( pPal != NULL )
{
// Create the palette
if( nColors <= 256 )
{
UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
pLP->palVersion = 0x300;
pLP->palNumEntries = nColors;
for( int i=0; i < nColors; i++)
{
pLP->palPalEntry[i].peRed = bmInfo.bmiColors[i].rgbRed;
pLP->palPalEntry[i].peGreen = bmInfo.bmiColors[i].rgbGreen;
pLP->palPalEntry[i].peBlue = bmInfo.bmiColors[i].rgbBlue;
pLP->palPalEntry[i].peFlags = 0;
}
pPal->CreatePalette( pLP );
delete[] pLP;
}
}
CClientDC dc(NULL);
CPalette* pOldPalette = NULL;
if( pPal )
{
pOldPalette = dc.SelectPalette( pPal, FALSE );
dc.RealizePalette();
}
HBITMAP hBmp = CreateDIBitmap( dc.m_hDC,// handle to device context &bmiHeader, // pointer to BITMAPINFOHEADER
CBM_INIT, // initialization flag
lpDIBBits, // pointer to initialization data
&bmInfo, // pointer to bitmap color-format data
DIB_RGB_COLORS); // color-data usage
bitmap.Attach( hBmp );
if( pOldPalette )
dc.SelectPalette( pOldPalette, FALSE );
::GlobalFree(hDIB);
return TRUE;
}
--------------------------
得到 bitmap 后就可以画(显示)了。
if (pDoc->m_load_bmp == 1){
CPalette *pOldPal = pDC->SelectPalette(&GetDocument()->m_pPal, false);
pDC->RealizePalette();
CDC tmpDC;
tmpDC.CreateCompatibleDC(pDC);
CBitmap* oldBitmap = tmpDC.SelectObject(&pDoc->m_bitmap);
use_cx = pDoc->bmp_info.bmWidth;
use_cy = pDoc->bmp_info.bmHeight;
if (iIsFullScreen){ //如果全屏。。。}
pDC->StretchBlt( use_x0, use_y0, use_cx, use_cy, &tmpDC, 0, 0, pDoc->bmp_info.bmWidth, pDoc->bmp_info.bmHeight, SRCCOPY );
tmpDC.SelectObject(oldBitmap);
pDC->SelectPalette(pOldPal, false);
goto Lab_end_draw;
----------------------------
以上是MFC的,你可以改成 API

回答2:

我想你sizeof的那个变量是个结构体,里面有存放bmp文件地址的指针,纯粹个人猜测,说错了大家不要骂我

回答3:

先获取这个bmp文件的id,用load什么函数就可以了……

回答4:

你大可以这样:
用fopen打开bmp文件得到文件指针,然后用fread读取数据,之后可以直接用BITMAPFILEHEADER结构读取数据就可以了
我不想和其它人抢分
显示你可以用loadbitmap读取bmp文件,然后用selectObject选入HDC就可以了。以上两个函数都可以查得到
BeginPaint或GetDC可以得到HDC
然后响应WM_PAINT消息选入HDC
或者你可以用双缓冲也行,但你必须创建内存DC选入位图,才可以用Bitblt复制到DC上。回答完毕

回答5:

O,my god!

1。ifstream里面存放的文件的句柄,而是整张bmp图。

2。buffer是你要读出内容的临时存放点,*FILE则是文件句柄。

3。查bmp的文件格式,网上应该有,很久不用了想不起来,按字节数一个一个fwrite就可以了。用结构一次性导入容易有错。