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),而是指该位 ...
随机推荐
- Java高并发-无锁
一.无锁类的原理 1.1 CAS CAS算法的过程是这样:它包含3个参数CAS(V,E,N).V表示要更新的变量,E表示预期值,N表示新值.仅当V值等于E值时,才会将V的值设为N,如果V值和E值不同, ...
- 【NodeJS】替换模糊查询字符里包含的正则关键字
问题:正则匹配时字符串中包含了一些特殊字符,导致查询失败 例如,下面的字符包含了( 和 ),这在正则中属于特殊字符 (-)-magnocurarine 正则中的特殊字符如下图 思路: 1.映射查询字符 ...
- There appears to be trouble with your network connection. Retrying…
yarn 错误There appears to be trouble with your network connection. Retrying- 原因:yarn超时 解决途径: #查看代理 yar ...
- CoaXPress 是如何只用一条线缆实现双向传输和供电的
这是个很有意思的事情,CoaXPress的全双工双向数据传输.且供电只需要一条同轴线缆,这个原理对其它串行接口的设计是非常有参考价值的,尤其是对线缆长度.数量有严格要求的场合,一条同轴线缆走天下,不要 ...
- 【freertos】010-消息队列概念及其实现细节
目录 前言 10.1 消息队列概念 10.2 消息队列的数据传输机制 10.3 消息队列的阻塞访问机制 10.4 消息队列使用场景 10.5 消息队列控制块 10.5.1 队列控制块源码 10.5.2 ...
- ROS基本程序实现
0.前言 现在介绍ROS基本程序实现的教程有很多,步骤无非就是建工作空间,编译,创建功能包,创建文件和修改CMakeList,之后再编译.运行程序这几步.但是这些教程中很多在文件夹切换的很混乱,导致会 ...
- JavaScript中的??和?.和??=操作符
JS中两种不常使用但挺实用的操作符:??和?. 一起来了解并学会使用它们吧: 空值合并操作符:?? 只有当操作符左侧为null或undefined时才会返回操作符右侧的值,否则返回左侧的值. eg: ...
- 如何实现Springboot+camunda+mysql的集成
本文介绍基于mysql数据库,如何实现camunda与springboot的集成,如何实现基于springboot运行camunda开源流程引擎. 一.创建springboot工程 使用IDEA工具, ...
- C#实现[移除文件名中的非中文字符]
更新记录: 2022年5月28日 从程序中抽出方法复用. 处理财务文件时写的一个小函数.用于移除文件名中的非中文字符. /// <summary> /// 移除文件名中的非中文字符 /// ...
- BUUCTF-RAR
rar 看提示知道爆破压缩包的题,纯数字4位数拿出ARCHPR爆破即可.