BMP位图之代码实现
从16位开始,不存在调色板,顶多存在一个RGBQUAD的掩码。
16位位图,我没有拿到对应的素材,但是根据官方文档的描述和代码验证后,我总结为下:
当biCompression为BI_RGB时,此时是RGB555格式,不存在调色板。
当biCompression为BI_BITFIELDS时,16位位图时RGB565格式,对应的32位是带掩码的格式,两种都有一个RGBQUAD的数据存在于调色板。
24位位图,只有BI_RGB存储方式。
代码实现如下
enum { bitmap_undefined, bitmap_unknown, bitmap1, bitmap4, bitmap4_RLE4,
bitmap8, bitmap8_RLE8, bitmap16_RGB555, bitmap16_RGB565, bitmap24, bitmap32, bitmap32_mask};//所有bmp类型 class Bitmap {
public:
Bitmap();
virtual ~Bitmap();
HBITMAP BitCreate(HDC hDC, LPTSTR szFilename);//从文件载入
HBITMAP BitCreate(HDC hDC, HINSTANCE hInstance, UINT rscID);//从资源载入
PBITMAPFILEHEADER GetBitFileheader(PBYTE pBitmap = NULL);//位图头
PBITMAPINFOHEADER GetBitInfoheader(PBYTE pBitmap = NULL);//位图INFO结构
LPRGBQUAD GetBitPalette(PBYTE pBitmap = NULL);//位图画板,不存在返回NULL
PVOID GetBitData(PBYTE pBitmap = NULL);//位图数据
void BitDraw(HDC hDC, int x, int y, HBITMAP hBitmap);//将位图画到自己的窗口
protected:
void BitErrorshow(DWORD errorID);//错误提示
void BitTypedefined();//类型定义
void BitFree();//资源释放
HBITMAP BitLoad(HDC hDC, PBYTE pBitmap = NULL);//载入的数据,转换为HBITMAP句柄,方便操作
private:
HGLOBAL m_hGlablebitmap;
HANDLE m_hFilemapping;
PBYTE m_pBitmap;
int m_iWidth, m_iHeight, m_iFilesize;
int m_iType;
};
对应的实现代码
Bitmap::Bitmap() {
m_hFilemapping = m_hGlablebitmap = NULL;
m_pBitmap = NULL;
m_iFilesize = m_iWidth = m_iHeight = 0;
m_iType = bitmap_undefined;
} Bitmap::~Bitmap() {
BitFree();
} void Bitmap::BitTypedefined() {
PBITMAPINFOHEADER bInfoheader;
bInfoheader = GetBitInfoheader();
m_iWidth = bInfoheader->biWidth;
m_iHeight = bInfoheader->biHeight;
WORD bitCount = bInfoheader->biBitCount;
DWORD bitCompression = bInfoheader->biCompression;
if (bitCompression == BI_RGB) {
switch (bitCount) {
case 1:
m_iType = bitmap1; break;
case 4:
m_iType = bitmap4; break;
case 8:
m_iType = bitmap8; break;
case 16:
m_iType = bitmap16_RGB555; break;
case 24:
m_iType = bitmap24; break;
case 32:
m_iType = bitmap32; break;
default:
m_iType = bitmap_unknown;
}
}
else if (bitCompression == BI_BITFIELDS) {
switch (bitCount) {
case 16:
m_iType = bitmap16_RGB565; break;
case 32:
m_iType = bitmap32_mask; break;
default:
m_iType = bitmap_unknown;
}
}
else if (bitCompression == BI_RLE4)
m_iType = bitmap4_RLE4;
else if (bitCompression == BI_RLE8)
m_iType = bitmap8_RLE8;
else
m_iType = bitmap_unknown;
} HBITMAP Bitmap::BitLoad(HDC hDC, PBYTE pBitmap) {
PBITMAPINFOHEADER pBitmapinfo = GetBitInfoheader(pBitmap);
PBYTE pBitmapdata = (PBYTE)GetBitData(pBitmap), pDIBData = NULL;
HBITMAP hBitmap = CreateDIBSection(hDC, (PBITMAPINFO)pBitmapinfo, DIB_RGB_COLORS, (void **)&pDIBData,
NULL, 0);
DWORD sizeImage = m_iFilesize - (DWORD)(pBitmapdata - pBitmap);//永远自己计算数据大小,因为位图INFO头中的biSizeImage字段可能为0.
CopyMemory(pDIBData, pBitmapdata, sizeImage);
return hBitmap;
} void Bitmap::BitErrorshow(DWORD errorID) {
TCHAR szCaption[64];
LPVOID lpMsgBuf;
wsprintf(szCaption, L"错误代码:0x%08x", errorID);
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
errorID,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
MessageBox(NULL, (LPTSTR)lpMsgBuf, szCaption, MB_OK | MB_ICONSTOP);
LocalFree(lpMsgBuf);
} HBITMAP Bitmap::BitCreate(HDC hDC, LPTSTR szFilename) {
HANDLE hFile = NULL;
BitFree();//释放之前数据
__try {
hFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
m_hFilemapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
m_pBitmap = (PBYTE)MapViewOfFile(m_hFilemapping, FILE_MAP_READ, 0, 0, 0);
m_iFilesize = GetFileSize(hFile, 0);
BitTypedefined();
}__except (EXCEPTION_EXECUTE_HANDLER) {
BitErrorshow(GetLastError());
CloseHandle(hFile);
BitFree();
return NULL;
}
CloseHandle(hFile);
return BitLoad(hDC, m_pBitmap);
} HBITMAP Bitmap::BitCreate(HDC hDC, HINSTANCE hInstance, UINT rscID) {
HRSRC hResInfo = NULL;
BitFree();//释放之前数据
__try {
hResInfo = FindResource(hInstance, MAKEINTRESOURCE(rscID), RT_BITMAP);
m_hGlablebitmap = LoadResource(hInstance, hResInfo);
m_pBitmap = (PBYTE)LockResource(m_hGlablebitmap);
m_iFilesize = SizeofResource(hInstance, hResInfo);
BitTypedefined();
}__except (EXCEPTION_EXECUTE_HANDLER) {
BitErrorshow(GetLastError());
BitFree();
return NULL;
}
return BitLoad(hDC, m_pBitmap);
} void Bitmap::BitFree() {
if (m_hFilemapping != NULL) {
UnmapViewOfFile(m_pBitmap);
CloseHandle(m_hFilemapping);
m_hFilemapping = NULL;
}
else if (m_hGlablebitmap != NULL) {
UnlockResource(m_hGlablebitmap);
FreeResource(m_hGlablebitmap);
m_hGlablebitmap = NULL;
}
m_pBitmap = NULL;
m_iType = bitmap_undefined;
m_iFilesize = m_iHeight = m_iWidth = 0;
} PBITMAPFILEHEADER Bitmap::GetBitFileheader(PBYTE pBitmap) {
if (m_hFilemapping != NULL)
return pBitmap ? (PBITMAPFILEHEADER)pBitmap : (PBITMAPFILEHEADER)m_pBitmap;
return NULL;
} PBITMAPINFOHEADER Bitmap::GetBitInfoheader(PBYTE pBitmap) {
DWORD offset = 0;
if (m_hFilemapping != NULL)
offset = sizeof(BITMAPFILEHEADER);
return pBitmap ? (PBITMAPINFOHEADER)(pBitmap + offset) : (PBITMAPINFOHEADER)(m_pBitmap + offset);
} LPRGBQUAD Bitmap::GetBitPalette(PBYTE pBitmap) {
PBITMAPINFOHEADER pBitmapinfo = GetBitInfoheader(pBitmap);
PBYTE pPalette = (PBYTE)pBitmapinfo + sizeof(PBITMAPINFOHEADER), pData = (PBYTE)GetBitData(pBitmap);
if (pPalette == pData)//不存在调色板
return NULL;
return (LPRGBQUAD)pPalette;
} PVOID Bitmap::GetBitData(PBYTE pBitmap) {
DWORD offset = 0, n;
PBITMAPINFOHEADER pBitmapinfo = GetBitInfoheader(pBitmap);
n = pBitmapinfo->biClrUsed ? pBitmapinfo->biClrUsed : pBitmapinfo->biBitCount;
switch (m_iType) {
case bitmap1:
case bitmap4:
case bitmap4_RLE4:
case bitmap8:
case bitmap8_RLE8:
offset = (DWORD)pow(2, n); break;
case bitmap16_RGB565:
case bitmap32_mask:
offset = 1; break;
}
return (PBYTE)pBitmapinfo + offset * sizeof(RGBQUAD)+sizeof (BITMAPINFOHEADER);
} void Bitmap::BitDraw(HDC hDC, int x, int y, HBITMAP hBitmap){
if (hBitmap != NULL) {
HDC hMemDC = CreateCompatibleDC(hDC);
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);//载入位图
BitBlt(hDC, x, y, m_iWidth, m_iHeight, hMemDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hOldBitmap);//还原位图
DeleteDC(hMemDC);
}
}
代码测试图
1位位图:
4位位图
8位位图
24位位图
其他位图可以随意测试,均无问题。图片是我随意弄的,哈哈哈,自己用windows自带的画图工具就可以做出不同类型的位图,这里就不上传位图资源文件了。
BMP位图之代码实现的更多相关文章
- vc 加载bmp位图并显示的方法
方法一.显示位图文件 HBITMAP hBitmap=(HBITMAP)LoadImage(NULL,_T(“xxx.bmp”),Image_Bitmap,0,0,Lr_CreateDibSectio ...
- 将文件内容隐藏在bmp位图中
首先要实现这个功能,你必须知道bmp位图文件的格式,这里我就不多说了,请看:http://www.cnblogs.com/xiehy/archive/2011/06/07/2074405.html 接 ...
- C语言实现将彩色BMP位图转化为二值图
CTF做了图片的隐写题,还没有形成系统的认识,先来总结一下BMP图的组成,并通过将彩色图转为二值图的例子加深下理解. 只写了位图二进制文件的格式和代码实现,至于诸如RGB色彩和调色板是什么的一些概念就 ...
- 浅析BMP位图文件结构(含Demo)
浅析BMP位图文件结构(含Demo) 作者:一点一滴的Beer http://beer.cnblogs.com/ 关于BMP位图格式在网上可以找到比较详细的相关文档,有兴趣的可以搜索标题为“BMP ...
- (学习笔记3)BMP位图的读取与显示
在(学习笔记2)中.我们已经具体说明怎样去创建MFC.在这节中.主要解决BMP位图照片的读取和显示问题. 我们新建一个projectdemo1.创建步骤请看(学习笔记2)中具体说明. 创建成功后,例如 ...
- gnu-ucos 增加 bmp 位图显示
昨天又下了点功夫弄了个在tft屏幕上显示bmp位图的. 我选择的是24位tft真彩測显示方式所以也要选择真彩色位图.网上给出的16位位图数组无法使用.在csdn上下载了2个制作工具,一个是c代码的,一 ...
- 如何将打印内容转换为bmp位图文件
bmp是一种与硬件设备无关的图像文件格式,使用非常广.它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BblP文件所占用的空间很大.BMP文件的图像深度可选lbit.4bit.8 ...
- BMP位图图像格式简介
1. 文件结构 位图文件可看成由4个部分组成:位图文件头(bitmap-fileheader).位图信息头(bitmap-informationheader).彩色表(colortable)和定义位图 ...
- BMP位图调色板说明
网上一搜,可以看到BMP位图结构的详细说明,这篇文章专门谈一下其中的调色板. 多少位位图并不是指每一个颜色该用多少位表示,对于颜色来说,它始终都是24位(RGB),或者是32位(RGBA),而是指该位 ...
随机推荐
- 520表白小程序设计Python代码详解(PyQt5界面,B站动漫风)
摘要:介绍一个动漫风的表白小程序,界面使用Python以及PyQt实现,界面样式经过多次美化调整,使得整体清新美观.本文详细介绍代码设计和实现过程,不仅是居家表白必备,而且适合新入门的朋友学习界面设计 ...
- 爷青回,canal 1.1.6来了,几个重要特性和bug修复
刚刚在群里看到消息说,时隔一年,canal 1.1.6正式release了,赶紧上去看看有什么新特性. (居然才发布了6个小时,前排围观) 1.什么是canal canal [kə'næl],译意为水 ...
- 前端 关于请求地址时出现乱码, 出现%E2%80%8B的问题
做项目时,添加了新的一个接口,习惯性地复制了接口下来.然后测试发现 请求时自动添加 了几个%E2%80%8B这种乱码. 问题原因: 我输出请求地址时也是正确的,是因为复制过来的接口地址会有零宽空格 解 ...
- “极简”创建 github page 并设置域名
最简单最详细的,创建 github page 并设置域名,没有多余的步骤,并且多图,对新手特别友好 尝试用 github page 创建博客,并设置独立域名.网上找了许多教程,都太复杂.自己的创建过程 ...
- php判断客户端浏览器类型
/** * 判断浏览器名称和版本 */ function get_user_browser() { if (empty($_SERVER['HTTP_USER_AGENT'])) { return ' ...
- 龙芯发布 .NET 6 SDK 6.0.105-ea1 LoongArch64 版本
龙芯平台.NET,是龙芯公司基于开源社区.NET独立研发适配的龙芯版本,我们会长期进行安全更新和错误修复,并持续进行性能优化.社区.NET7版本开始已经原生支持LoongArch64架构源码.具备如下 ...
- 关于kali安装输入法
之前老是被kali大小写输入恶心坏了,正好看到一篇文章写kali安装搜狗输入法的,虽然不需要输入中文,但是英文输入就很方便了. 一.切换root用户登录 1.sodu su切换为root权限 2.pa ...
- jetbrains 系列产品无限试用
无限试用插件 在线安装 需要添加第三方插件仓库地址 设置 -- Manage Plugins Reposition... -- + https://plugins.zhile.io plugins 中 ...
- W10修改被改的默认打开文本方式
今天不小心给默认方式打开点错了,身为处女座的我有洁癖非要非恢复过来,这是找到的 原文操作出处:win10系统如何还原文件默认打开方式?win10设置文件默认打开方式的方法 -Win7系统之家 (win ...
- NC204382 中序序列
NC204382 中序序列 题目 题目描述 给定一棵有 \(n\) 个结点的二叉树的先序遍历与后序遍历序列,求其中序遍历序列. 若某节点只有一个子结点,则此处将其看作左儿子结点 示例1 输入 5,[3 ...