DIB(设备无关位图)是存储在磁盘上的位图文件,可以从磁盘读到内存中或从内存保存到磁盘上,它的磁盘文件结构是标准化的,在Linux、Unix及Windows上都可以以同样效果显示。位图是最接近硬件的图像格式,Windows显示的核心是位图,它的SDK API专门提供了一组用于操作DIB文件的函数。但是由于这样或那样的原因,高效合理的使用这些DIB API是需要了解不少历史和使用背景的,在这里我抽茧剥丝介绍和演示DIB的使用,相信对你更好的使用DIB文件有帮助,由于DIB函数比较多,这里分为三部分介绍,首先是DIB的读入、保存和显示。
关于DIB文件的组成很多地方有详细描述,这里不再详细赘述。主要分为如下几个部分:
其中
其中,信息表头和RGB调色板合称为位图信息。
我们要把DIB数据读入到内存中,那么就要分配相应的内存,把读入的数据写到对应的内存区中,这里SDK 提供的数据结构是各种结构体,结构体的各个字段对应磁盘文件中各个信息值。我们这里为了逻辑清楚,使用最常使用的DIB结构体。
如图,文件中的数据读到对应的内存结构中完成文件的读入,内存结构中的数据写到对应的文件中完成文件的保存。
其中
把BITMAPINFOHEADER和RGBQUAD[0]作为BITMAPINFO结构体成员,这样一方面是为了和磁盘文件对应,另一方面也是为了访问调色板数据方便。
这里的磁盘文件中各个段在磁盘上保存位置必须是连续的,但是对应的内存中文件信息头、位图信息和位图数据三大块不一定要是连续的。因此,在读入文件中你既可以一次性读入磁盘文件到连续的内存中,也可以分开读入到三个分别连续的内存中,后面会做相关演示。
int SetDIBitsToDevice( HDC hdc, // handle to DC int XDest, // x-coord of destination upper-left corner int YDest, // y-coord of destination upper-left corner DWORD dwWidth, // source rectangle width DWORD dwHeight, // source rectangle height int XSrc, // x-coord of source lower-left corner int YSrc, // y-coord of source lower-left corner UINT uStartScan, // first scan line in array UINT cScanLines, // number of scan lines CONST VOID *lpvBits, // array of DIB bits CONST BITMAPINFO *lpbmi, // bitmap information UINT fuColorUse // RGB or palette indexes );
int StretchDIBits( HDC hdc, // handle to DC int XDest, // x-coord of destination upper-left corner int YDest, // y-coord of destination upper-left corner int nDestWidth, // width of destination rectangle int nDestHeight, // height of destination rectangle int XSrc, // x-coord of source upper-left corner int YSrc, // y-coord of source upper-left corner int nSrcWidth, // width of source rectangle int nSrcHeight, // height of source rectangle CONST VOID *lpBits, // bitmap bits CONST BITMAPINFO *lpBitsInfo, // bitmap data UINT iUsage, // usage options DWORD dwRop // raster operation code );
BOOL DibTotalLoad(PTSTR szBmpFile,
PBITMAPFILEHEADER *ppbmfh,
PBITMAPINFO *ppbmi,
PBYTE *ppBits,
PLONG pBmpWidth,
PLONG pBmpHeight)
{
HANDLE hFile;
DWORD dwFileSize, dwBytesRead;
BOOL bSuccess;
//打开文件
hFile = CreateFile( szBmpFile,
GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
return FALSE;
}
//判断BMP文件大小(所有部分)
dwFileSize = GetFileSize(hFile, NULL);
//分配对应大小内存用于保存磁盘BMP文件内容
*ppbmfh = malloc(dwFileSize);
if (!(*ppbmfh))
{
CloseHandle(hFile);
return FALSE;
}
//读入文件内容
bSuccess = ReadFile(hFile, *ppbmfh, dwFileSize, &dwBytesRead, NULL);
CloseHandle(hFile);
//校验读入是否正确和文件是否为BMP文件
if (!bSuccess ||
(dwBytesRead != dwFileSize) ||
(*ppbmfh)->bfType != *(WORD *)"BM")
{
free(*ppbmfh);
return FALSE;
}
//计算剩余的返回参数
*ppbmi = (PBITMAPINFO)(*ppbmfh+1);
*ppBits = (PBYTE)(*ppbmfh) + (*ppbmfh)->bfOffBits;
*pBmpWidth = (*ppbmi)->bmiHeader.biWidth;
*pBmpHeight = (*ppbmi)->bmiHeader.biHeight;
return TRUE;
}
BOOL DibTotalSave(PTSTR szBmpFile, PBITMAPFILEHEADER pbmfh)
{
BOOL bSuccess;
DWORD dwBytesWrite;
HANDLE hFile;
//打开要写入的文件
hFile = CreateFile(szBmpFile,
GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
return FALSE;
}
//写入文件
bSuccess = WriteFile(hFile, pbmfh, pbmfh->bfSize, &dwBytesWrite, NULL);
CloseHandle(hFile);
if (!bSuccess || dwBytesWrite != pbmfh->bfSize)
{
DeleteFile(hFile);
return FALSE;
}
return TRUE;
}
void ShowDib(HDC hdc,
PBITMAPINFO pbmi, PBYTE pBits,
long nBmpWidth, long nBmpHeight,
long cxClient, long cyClient,
BOOL bFull)
{
if (FALSE == bFull)//居中显示
{
SetDIBitsToDevice( hdc,
(cxClient-nBmpWidth)/2, (cyClient-nBmpHeight)/2,
nBmpWidth, nBmpHeight,
0, 0,
0, nBmpHeight,
pBits, pbmi,
DIB_RGB_COLORS);
}
else//拉伸显示
{
SetStretchBltMode(hdc, COLORONCOLOR);
StretchDIBits(hdc,
0, 0,
cxClient, cyClient,
0, 0,
nBmpWidth, nBmpHeight,
pBits, pbmi,
DIB_RGB_COLORS,
SRCCOPY);
}
}
Windows DIB文件操作详解-1.DIB的读入、保存和显示,布布扣,bubuko.com
Windows DIB文件操作详解-1.DIB的读入、保存和显示
原文:http://blog.csdn.net/wenzhou1219/article/details/26162869