Windows DIB文件操作详解-4.使用DIB Section
前面讲了为了提高DIB的显示性能和效率,我们将DIB转换成DDB,但是这又遇到一个问题,如果我想操作DIB的数据的话,显然是不能使用DDB:一是因为DIB转DDB时发生了颜色转换,再就是DDB无法直接提取指定像素点的数据。那么我们怎么办呢,Windows使用一种折中的方式来达到这一目标(既提高了显示效率和性能,又可以直接操作像素点)。
1.DIB Section存储和显示
Windows使用DIB块(DIB Section)来存储DIB数据,其内存结构示意图如下
其实,和我们自己读入DIB数据到自己分配的各个数据区感觉是一样的,只是现在这些DIB的各个数据区是由Windows自己分配维护的,值得注意的是这些Windows自己维护的DIB数据区是通过HBITMAP句柄来组织的,这个HBITMAP句柄和BITMAP的HBITMAP句柄是不一样的,至于为什么同一种句柄可表示不同的对象可以查看笔者的博文“深入了解Windows句柄到底是什么”。
继续说现在的问题,这里存储的是DIB的数据,只有在使用BitBlt和StretchBlt显示的时候,才会发生DIB->DDB的转换,显然这里BitBlt和StretchBlt会对句柄属性做一个判断来确认指向BITMAP的HBITMAP及指向DIB Section的HBITMAP的不同操作。当然,这里的DIB Section各个区不一定是连续的,这是一定要注意的。
这里Windows自己维护DIB各个数据区,做了一定优化,所以比我们自己分配和存储DIB各个数据区的显示效率和性能要高。
2.DIB Section的相关函数使用
明白了Windows对于DIB Section的存储原理和转换规则以后,我们说一下DIB Section的相关函数使用。
1.CreateDIBSection
HBITMAP CreateDIBSection(HDC hdc, // 设备描述表句柄CONST BITMAPINFO *pbmi, // 包含Info Header、Mask、Color Table数据的BITMAPINFO指针UINT iUsage, // DIB_PAL_COLORS或DIB_RGB_COLORSVOID *ppvBits, // 指向存储位图数据的地址的指针HANDLE hSection, DWORD dwOffset
);
使用如下:
1.一般不考虑后两个参数
2.传入包含DIB位图信息头(Info Header)、压缩掩码(Mask)及调色板信息(Color Table,主要针对位图深度<=8)的BITMAPINFO* pbmi指针,这三者必须是连续存储的,一般指明DIB_RGB_COLORS参数,这样Windows会自动按照pbmi提供的信息分配对应的DIB Section,包括Info Header、Mask、Color Table及Bits四个区,其中分配的Bits区的地址被写到ppvBits指向的指针中。
即常用调用步骤如下:
a.读入DIB的位图信息头(Info Header)、压缩掩码(Mask)及调色板信息(Color Table)到pbmi指向内存中
b.hBitmap = CreateDIBSection(NULL, pbmi, DIB_RGB_COLORS, &pBits, NULL, 0);
c.读入DIB的Bits数据到pBits指向的内存中
d.BitBlt或StretchBlt显示hBitmap
3.只有使用DIB_PAL_COLORS参数时才需要hdc参数。只有DIB的调色板使用索引存储方式才需要使用这两个参数。实际上,这里的hdc和DIB_PAL_COLORS实际上最终被SetDIBitsToDevice和StretchDIBits函数调用,可以查看他们两个的参数。
4.pBits指向的内存由Windows操作系统托管,但是用户可以操作pBits数据,删除hBitmap时pBits内存区同时也会释放掉。
2.GetDIBColorTable和SetDIBColorTable
UINT GetDIBColorTable(HDC hdc, // 设备描述表句柄UINT uStartIndex, // 调色板起始索引UINT cEntries, // 要获取的调色板项个数RGBQUAD *pColors // 存储调色板项的地址
);UINT SetDIBColorTable(HDC hdc, // 设备描述表句柄UINT uStartIndex, // 调色板起始索引UINT cEntries, // 要设置的调色板项个数RGBQUAD *pColors // 存储调色板项的地址
);
hdcMem = CreateCompatibleDC(NULL);
SelectObject(hdcMem, hBitmap);
GetDIBColorTable(hdcMem, uFirstIndex, uNumEntries, &prgb);
DeleteDC(hdcMem);
hdcMem = CreateCompatibleDC(NULL);
SelectObject(hdcMem, hBitmap);
SetDIBColorTable(hdcMem, uFirstIndex, uNumEntries, &prgb);
DeleteDC(hdcMem);
通过DIB Section来获取和设置调色板,可以屏蔽OS/2兼容位图带来的差异(BITMAPCOREINFO调色板项采用RGBTRIPLE结构体而不是BITMAPINFOHEADER采用的RGBQUAD)。
3.获取DIBSECTION
typedef struct tagDIBSECTION { BITMAP dsBm; BITMAPINFOHEADER dsBmih; DWORD dsBitfields[3]; HANDLE dshSection; DWORD dsOffset;
} DIBSECTION;
使用
GetObject(hBitmap, sizeof(DIBSECTION), &dibsection);
不同于BITMAP,DIB Section使用GetObject获取的是DIB Section,可以看到DIBSECTION将BITMAP设为第一个属性,这是为了保证和BITMAP的兼容,万一你不知道hBitmap的属性是指向DIB Section的,那么GetObject(hBitmap, sizeof(BITMAP), &bitmap)也不至于发生错误。
3.代码演示
//读入DIB文件并转换成DIB Section
HBITMAP CreateDibSectionFromDibFile(PTSTR szFileName)
{BITMAPFILEHEADER bmfh;BITMAPINFO *pbmi;BYTE *pBits;BOOL bSuccess;DWORD dwInfoSize, dwBytesRead;HANDLE hFile;HBITMAP hBitmap;//打开文件hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);if (INVALID_HANDLE_VALUE == hFile){return NULL;}//读入DIB文件头bSuccess = ReadFile(hFile, &bmfh, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL);if (!bSuccess || (dwBytesRead != sizeof(BITMAPFILEHEADER)) || (bmfh.bfType != *(WORD *)"BM")){CloseHandle(hFile);return NULL;}//为DIB BITMAPINFO分配内存,并读入DIB数据dwInfoSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);pbmi = malloc(dwInfoSize);if (NULL == pbmi){CloseHandle(hFile);return NULL;}bSuccess = ReadFile(hFile, pbmi, dwInfoSize, &dwBytesRead, NULL);if (!bSuccess || (dwBytesRead != dwInfoSize)){free(pbmi);CloseHandle(hFile);return NULL;}//创建DIB SectionhBitmap = CreateDIBSection(NULL, pbmi, DIB_RGB_COLORS, &pBits, NULL, 0);free(pbmi);if (NULL == hBitmap){CloseHandle(hFile);return NULL;}//读入位图数据到分配的DIB Section的Bits区(pBits指向)bSuccess = ReadFile(hFile, pBits, bmfh.bfSize-bmfh.bfOffBits, &dwBytesRead, NULL);CloseHandle(hFile);if (!bSuccess || (dwBytesRead != (bmfh.bfSize-bmfh.bfOffBits))){return NULL;}return hBitmap;
}//如果有调色板则获得第一个调色板项
BOOL GetFirstColorTableItem(HBITMAP hBitmap, RGBQUAD *prgb)
{HDC hdcMem;int iNum;hdcMem = CreateCompatibleDC(NULL);SelectObject(hdcMem, hBitmap);iNum = GetDIBColorTable(hdcMem, 0, 1, prgb);DeleteDC(hdcMem);return 0==iNum ? FALSE : TRUE;
}//获得第一个调色板项
DWORD GetFirstMaskItem(HBITMAP hBitmap)
{DIBSECTION ds;GetObject(hBitmap, sizeof(DIBSECTION), &ds);return ds.dsBitfields[0];
}
在后续我会讲解使用DIB Section来完成图像指定像素点的读写,实际上,一旦能够操作pBits,那么完成指定像素点的读写也不是什么难事。
完整演示代码下载链接
Windows DIB文件操作详解-4.使用DIB Section相关推荐
- Windows DIB文件操作详解-1.DIB的读入、保存和显示
DIB(设备无关位图)是存储在磁盘上的位图文件,可以从磁盘读到内存中或从内存保存到磁盘上,它的磁盘文件结构是标准化的,在Linux.Unix及Windows上都可以以同样效果显示.位图是最接近硬件的图 ...
- Windows DIB文件操作详解-3.DDB转DIB
上一节讲到DIB转换成DDB以提高位图显示性能,那么这里自然想到DDB转DIB.DDB转DIB有什么用呢?最常见的应用场合就是你得到了一个屏幕截图的DDB,现在想把它保存到磁盘上,这时候就要用到DDB ...
- Windows DIB文件操作详解-2.DIB转DDB
上一节讲到显示DIB的显示时需要将文件内容读到内存中(如下图),当使用SetDIBitsToDevice和StretchDIBits函数显示时中间涉及到一系列的转换,这样大大增加了性能消耗,特别是在重 ...
- C 和 C++ 文件操作详解
来源:http://www.cnblogs.com/likebeta/archive/2012/06/16/2551662.html 来源:http://www.cnblogs.com/likebet ...
- Qt QFile文件操作详解
Qt QFile文件操作详解 很多应用程序都需要具备操作文件的能力,包括对文件内容进行读/写.创建和删除文件等,甚至某些应用程序的诞生纯粹是为了操作文件,比如 WPS Office.PDFedit 等 ...
- Python文件操作详解(一)
今天继续给大家介绍Python相关知识,本文主要内容是Python文件操作详解. 一.Python文件处理简介 使用Python可以编写程序处理文件,Python可以处理的文件值得是任何存储在辅助存储 ...
- C++文件操作详解(ifstream、ofstream、fstream)【笔记本】
C++文件操作详解(ifstream.ofstream.fstream) C++ 通过以下几个类支持文件的输入输出: ofstream: 写操作(输出)的文件类 (由ostream引申而来) ifst ...
- 简述python文件操作的流程_Python文件操作详解
这篇文章主要介绍了Python 文件操作的详解及实例的相关资料,希望通过本文大家能够理解掌握Python 文件操作的知识,需要的朋友可以参考下 Python 文件操作的详解及实例 一.文件操作 1.对 ...
- 【Kubernetes 018】cfssl创建证书并结合RBAC的RoleBinding配置新用户config文件操作详解
安全性是企业生产环境中的头等大事,对于访问同一集群的不同用户或者用户组来说,将权限分级是很有必要的.和很多云厂商一样,k8s也是采用按照角色和用户绑定的方式来分配权限的,这一节我们就来实际操作下,新建 ...
最新文章
- ArcSDE、ArcGis Engine、ArcGis Desktop的授权配置
- android截取字符串工具类,StringsUtil字符串工具类---灵活截取
- Android开发基本概念
- linux命令在线查
- htcvr设备计算机配置,准备买HTC VIVE了?来测试一下你的电脑配置够不够
- 第六十期:华为:希望把VR/AR打造成下个智能手机产业
- 排烟管道过长怎么处理_厨房装修失误导致烟道过长该怎么办?
- 陈天石吴翰清顾嘉唯光速对话(汤晓鸥今天没有晒娃)
- matlab 简单的图像填充例子
- VRay高级材质素材分享,精选,热门
- 利用JavaScript实现京东自动叠蛋糕+淘宝自动领喵币,叠列车+618全民购物
- 计算机设计大赛南京邮电大学,喜讯:我校信息学子在中国大学生计算机设计大赛中再创佳绩...
- 串级控制系统matlab仿真,锅炉串级三冲量给水控制系统的MATLAB 仿真
- MatLab 计算开根号
- 用R进行文本分析初探——包含导入词库和和导入李白语句
- 计算机里不显示u盘盘符,U盘不显示盘符怎么办 U盘没了盘符解决方法【详解】...
- 【计算机组成与结构】中央处理器
- TApplicaiton.ProcessMessages不能在非主线程使用
- U281819 糟心的语文课
- 你来讲讲AQS是什么吧?都是怎么用的?