C++保存HBITMAP为位图文件的实现方法
- 作者: 不知道哪个名字好
- 来源: 51数据库
- 2021-08-01
本文使用c++将位图句柄hbitmap保存为位图文件,配合c++抓图代码可以实现抓图保存文件(.bmp)。
其步骤如下:
1、创建位图文件;
2、计算位图中每个像素所占字节数;
3. 获取位图结构bitmap;
4、构造位图信息头bitmapinfoheader;
5、构造位图文件头bitmapfileheader;
6、为位图内容分配内存;
7、处理调色板;
8、写入文件;
9、清除资源。
下面是c++源代码:
imagehelper.h
#pragma once
#include <windows.h>
#include <string>
using namespace std;
class imagehelper
{
public:
static bool savebitmaptofile(hbitmap bitmap, const string& filename); //保存位图到文件
private:
static word getbitmapbitcount(); //计算位图文件每个像素所占字节数
static void processpalette(hbitmap hbitmap, const bitmap& bitmap,
dword palettesize, lpbitmapinfoheader lpbmpinfoheader); //处理调色板
};
imagehelper.cpp
#include "imagehelper.h"
#include <shlwapi.h>
bool imagehelper::savebitmaptofile(hbitmap hbitmap, const string& filename)
{
//1. 创建位图文件
const auto file = createfilea(filename.c_str(), generic_write,
0, nullptr, create_always,
file_attribute_normal | file_flag_sequential_scan,
nullptr);
if (file == invalid_handle_value)
{
return false;
}
//2. 计算位图文件每个像素所占字节数
const auto bitcount = getbitmapbitcount();
//3. 获取位图结构
bitmap bitmap;
::getobject(hbitmap, sizeof(bitmap), reinterpret_cast<lpstr>(&bitmap));
//位图中像素字节大小(32字节对齐)
const dword bmbitssize = ((bitmap.bmwidth * bitcount + 31) / 32) * 4 * bitmap.bmheight;
//调色板大小
const dword palettesize = 0;
//4. 构造位图信息头
bitmapinfoheader bmpinfoheader; //位图信息头结构
bmpinfoheader.bisize = sizeof(bitmapinfoheader);
bmpinfoheader.biwidth = bitmap.bmwidth;
bmpinfoheader.biheight = bitmap.bmheight;
bmpinfoheader.biplanes = 1;
bmpinfoheader.bibitcount = bitcount;
bmpinfoheader.bicompression = bi_rgb;
bmpinfoheader.bisizeimage = 0;
bmpinfoheader.bixpelspermeter = 0;
bmpinfoheader.biypelspermeter = 0;
bmpinfoheader.biclrimportant = 0;
bmpinfoheader.biclrused = 0;
//5. 构造位图文件头
bitmapfileheader bmpfileheader;
bmpfileheader.bftype = 0x4d42; //"bm"
//位图文件大小
const dword dibsize = sizeof(bitmapfileheader) + sizeof(bitmapinfoheader) + palettesize + bmbitssize;
bmpfileheader.bfsize = dibsize;
bmpfileheader.bfreserved1 = 0;
bmpfileheader.bfreserved2 = 0;
bmpfileheader.bfoffbits = static_cast<dword>(sizeof(bitmapfileheader))
+ static_cast<dword>(sizeof(bitmapinfoheader)) + palettesize;
//6. 为位图内容分配内存
const auto dib = globalalloc(ghnd, bmbitssize + palettesize + sizeof(bitmapinfoheader)); //内存句柄
const auto lpbmpinfoheader = static_cast<lpbitmapinfoheader>(globallock(dib)); //指向位图信息头结构
*lpbmpinfoheader = bmpinfoheader;
//7. 处理调色板
processpalette(hbitmap, bitmap, palettesize, lpbmpinfoheader);
//8. 写入文件
dword written = 0; //写入文件字节数
writefile(file, reinterpret_cast<lpstr>(&bmpfileheader), sizeof(bitmapfileheader),
&written, nullptr); //写入位图文件头
writefile(file, reinterpret_cast<lpstr>(lpbmpinfoheader), dibsize,
&written, nullptr); //写入位图文件其余内容
//9. 清理资源
globalunlock(dib);
globalfree(dib);
closehandle(file);
return true;
}
//计算位图文件每个像素所占字节数
word imagehelper::getbitmapbitcount()
{
const auto dc = ::createdca("display", nullptr, nullptr, nullptr);
//当前分辨率下每像素所占字节数
const auto bits = ::getdevicecaps(dc, bitspixel) * getdevicecaps(dc, planes);
::deletedc(dc);
//位图中每像素所占字节数
word bitcount;
if (bits <= 1)
bitcount = 1;
else if (bits <= 4)
bitcount = 4;
else if (bits <= 8)
bitcount = 8;
else
bitcount = 24;
return bitcount;
}
//处理调色板
void imagehelper::processpalette(hbitmap hbitmap, const bitmap& bitmap,
dword palettesize, lpbitmapinfoheader lpbmpinfoheader)
{
handle oldpalette = nullptr;
hdc dc = nullptr;
const auto palette = getstockobject(default_palette);
if (palette != nullptr)
{
dc = ::getdc(nullptr);
oldpalette = ::selectpalette(dc, static_cast<hpalette>(palette), false);
::realizepalette(dc); //实现设备调色板
}
//获取该调色板下新的像素值
getdibits(dc, hbitmap, 0, static_cast<uint>(bitmap.bmheight),
reinterpret_cast<lpstr>(lpbmpinfoheader) + sizeof(bitmapinfoheader) + palettesize,
reinterpret_cast<bitmapinfo*>(lpbmpinfoheader), dib_rgb_colors);
//恢复调色板
if (oldpalette != nullptr)
{
::selectpalette(dc, static_cast<hpalette>(oldpalette), true);
::realizepalette(dc);
::releasedc(nullptr, dc);
}
}
以上就是c++保存hbitmap为位图文件的实现方法的详细内容,更多关于c++保存hbitmap的资料请关注其它相关文章!
推荐阅读
