Windows DIB文件操作详解-1.DIB的读入、保存和显示
来源:互联网 发布:sweetalert.min.js 编辑:程序博客网 时间:2024/05/17 07:03
DIB(设备无关位图)是存储在磁盘上的位图文件,可以从磁盘读到内存中或从内存保存到磁盘上,它的磁盘文件结构是标准化的,在Linux、Unix及Windows上都可以以同样效果显示。位图是最接近硬件的图像格式,Windows显示的核心是位图,它的SDK API专门提供了一组用于操作DIB文件的函数。但是由于这样或那样的原因,高效合理的使用这些DIB API是需要了解不少历史和使用背景的,在这里我抽茧剥丝介绍和演示DIB的使用,相信对你更好的使用DIB文件有帮助,由于DIB函数比较多,这里分为三部分介绍,首先是DIB的读入、保存和显示。
1.DIB文件的组成
关于DIB文件的组成很多地方有详细描述,这里不再详细赘述。主要分为如下几个部分:
- 文件表头
- 信息表头
- RGB色彩对照表(不一定有)
- 位图像素位
其中
- 文件表头包含了文件类型(BMP)、文件大小及文件中实际像素数据保存的偏移值
- 信息头包含了位图的大小、位面数、位深度、压缩及掩码等信息
- RGB色彩对照表也称调色板,8位以下位图可能包含有调色板信息,16位及以上一般没有调色板
- 位图像素位为实际位图数据保存区
其中,信息表头和RGB调色板合称为位图信息。
2.Windows DIB内存数据结构
我们要把DIB数据读入到内存中,那么就要分配相应的内存,把读入的数据写到对应的内存区中,这里SDK 提供的数据结构是各种结构体,结构体的各个字段对应磁盘文件中各个信息值。我们这里为了逻辑清楚,使用最常使用的DIB结构体。
如图,文件中的数据读到对应的内存结构中完成文件的读入,内存结构中的数据写到对应的文件中完成文件的保存。
其中
- 文件信息头数据读到BITMAPFILEHEADER结构体中
- 位图信息头读到BITMAPINFOHEADER结构体中
- 位图调色板读到RGBQUAD结构体数组中
- 位图数据读到根据位图信息头提供的信息而分配的相应大小的数据区中
把BITMAPINFOHEADER和RGBQUAD[0]作为BITMAPINFO结构体成员,这样一方面是为了和磁盘文件对应,另一方面也是为了访问调色板数据方便。
这里的磁盘文件中各个段在磁盘上保存位置必须是连续的,但是对应的内存中文件信息头、位图信息和位图数据三大块不一定要是连续的。因此,在读入文件中你既可以一次性读入磁盘文件到连续的内存中,也可以分开读入到三个分别连续的内存中,后面会做相关演示。
3.DIB显示
- 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
- );
4.代码演示
- 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);
- }
- }
这里需要补充说明的是,为了保证逻辑清晰,本文没有考虑位图的OS/2兼容格式和自顶向下位图等特殊情况,错误处理可能也不是特别完善(没有考虑超大位图的情况),演示的代码在大部分情况下是适用的,只是为了起抛砖引玉的作用。关于DIB的详细描述当推Petzold的《Windows 程序设计》的“与设备无关的位图”一章,这一章描述非常详细,但是个别地方有些晦涩,结合本文来看可以加深理解。
- Windows DIB文件操作详解-1.DIB的读入、保存和显示
- Windows DIB文件操作详解-1.DIB的读入、保存和显示
- Windows DIB文件操作详解-5.DIB和调色板
- Windows DIB文件操作详解-2.DIB转DDB
- Windows DIB文件操作详解-3.DDB转DIB
- Windows DIB文件操作详解-4.使用DIB Section
- Windows DIB文件操作详解-2.DIB转DDB
- Windows DIB文件操作详解-3.DDB转DIB
- DIB位图文件的格式、读取、保存和显示
- DIB位图文件的格式、读取、保存和显示
- DIB位图文件的格式、读取、保存和显示
- DIB位图文件的格式、读取、保存和显示
- YV12转RGB24的计算转换和bmp(dib)文件的显示保存
- windows下的DDB和DIB
- windows下的DDB和DIB
- windows程序设计之DIB操作
- DIB
- DIB
- 调试:案例学习
- HBase学习笔记
- HDOJ 改革春风吹满地 2036
- 第26课时,实践4,定期存款利息计算器
- Retain Count
- Windows DIB文件操作详解-1.DIB的读入、保存和显示
- Deep Learning by Andrew Ng --- self-taught
- sql优化总结
- eclipse中删除的文件进行恢复
- 源码推荐:无限循环自动图片轮播器,可伸缩式header bar
- poj 3014 Cake Pieces and Plates 整数拆分
- Android性能优化典范
- hdu 2501 Tiling_easy version
- 第37天【健身】