【问题标题】:How to save a GDI+ HDC to bitmap file?如何将 GDI+ HDC 保存为位图文件?
【发布时间】:2021-11-06 00:58:32
【问题描述】:

我正在尝试将hdc 的内容保存到位图文件中,我目前正在使用上面的代码,它确实保存了图像,但我无法打开它。

看起来它已损坏,并且始终具有相同的大小(54 字节)。 我可能在 HDCTofile 函数中做错了。

#include <vector>    // HDCToFile
#include <fstream>
#include <cstring>
#include <windows.h>

HDCToFile("output.bmp", hdc);
    
bool HDCToFile(const char* FilePath, HDC Context, uint16_t BitsPerPixel = 24)
{
    //uint32_t Width = Area.right - Area.left;
    //uint32_t Height = Area.bottom - Area.top;

    BITMAPINFO Info;
    BITMAPFILEHEADER Header;
    memset(&Info, 0, sizeof(Info));
    memset(&Header, 0, sizeof(Header));
    Info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    //Info.bmiHeader.biWidth = Width;
    //Info.bmiHeader.biHeight = Height;
    Info.bmiHeader.biPlanes = 1;
    Info.bmiHeader.biBitCount = BitsPerPixel;
    Info.bmiHeader.biCompression = BI_RGB;
    //Info.bmiHeader.biSizeImage = Width * Height * (BitsPerPixel > 24 ? 4 : 3);
    Header.bfType = 0x4D42;
    Header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);


    char* Pixels = NULL;
    HDC MemDC = CreateCompatibleDC(Context);
    HBITMAP Section = CreateDIBSection(Context, &Info, DIB_RGB_COLORS, (void**)&Pixels, 0, 0);
    DeleteObject(SelectObject(MemDC, Section));
    BitBlt(MemDC, 0, 0, Info.bmiHeader.biWidth, Info.bmiHeader.biHeight, Context, 0, 0, SRCCOPY);
    DeleteDC(MemDC);

    std::fstream hFile(FilePath, std::ios::out | std::ios::binary);
    if (hFile.is_open())
    {
        hFile.write((char*)&Header, sizeof(Header));
        hFile.write((char*)&Info.bmiHeader, sizeof(Info.bmiHeader));
        hFile.write(Pixels, (((BitsPerPixel * Info.bmiHeader.biWidth + 31) & ~31) / 8) * Info.bmiHeader.biHeight);
        hFile.close();
        DeleteObject(Section);
        return true;
    }

    DeleteObject(Section);
    return false;
}

【问题讨论】:

  • 评论Info结构体的heighwidth有一些原因?
  • 如果我取消注释所有内容,您的代码将有效。显示你是如何打电话给HDCToFile

标签: c++ gdi+


【解决方案1】:

你的工作差不多完成了,只需将 DC 大小信息添加到 bitmapfileheader 和 bitmap info 中即可:

BITMAP structBitmapHeader;
memset(&structBitmapHeader, 0, sizeof(BITMAP));

HGDIOBJ hBitmap = GetCurrentObject(Context, OBJ_BITMAP);
GetObject(hBitmap, sizeof(BITMAP), &structBitmapHeader);

uint32_t Width = structBitmapHeader.bmWidth;
uint32_t Height = structBitmapHeader.bmHeight;

BITMAPINFO Info;
BITMAPFILEHEADER Header;
memset(&Info, 0, sizeof(Info));
memset(&Header, 0, sizeof(Header));
Info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

Info.bmiHeader.biWidth = Width;
Info.bmiHeader.biHeight = Height;

Info.bmiHeader.biPlanes = 1;
Info.bmiHeader.biBitCount = BitsPerPixel;
Info.bmiHeader.biCompression = BI_RGB;
Info.bmiHeader.biSizeImage = Width * Height * (BitsPerPixel > 24 ? 4 : 3);

Header.bfType = 0x4D42;
Header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

//--- your code to draw DC into bitmap ----

【讨论】:

  • 您好,当将一张图片保存在另一张图片上方时,图片会调整大小。
  • 是否要将多张图片保存到同一个bmp文件中?
  • 不,我的意思是当它覆盖一个文件时。看一下:i.imgur.com/VcbpQvg.gif,图片大小调整了,有时候还能正确保存,奇怪。
  • 是的,文件大小将根据保存的位图之一调整大小
  • 预览区在绘制新的加载位图之前被重新初始化?或者传递给 HDCToFile 的 DC 不是好的(最好在位图查看器中查看?)
猜你喜欢
  • 2010-11-13
  • 2012-09-02
  • 2013-01-29
  • 2019-02-26
  • 2010-09-14
  • 2010-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多