将 bmp 文件加载到 HBITMAP

Posted

技术标签:

【中文标题】将 bmp 文件加载到 HBITMAP【英文标题】:Load bmp file into HBITMAP 【发布时间】:2013-12-31 17:03:17 【问题描述】:

是否可以从包含多个图像的 bmp 文件加载图像? 例如,我有一个 bmp 文件,我想加载一个从 12;12 到 36;36 的图像。 感谢您的回答。

【问题讨论】:

一个 BMP 文件只包含一个图像。 我认为当你只求助于Windows API时,你需要加载完整的BMP,然后将你需要的部分提取到一个新的位图 Roman R. 是和否。当您想将按钮的所有图标保存到一个 bmp 文件中时... user1781290 谢谢 这实际上是个好问题。 MFC 工具栏被保存到一个位图资源中。如果您想使用单个按钮,则使用 LoadImage WINAPI 只会为您提供 x=width 和 y=height 的选项,而不是 x,y(左、上)的偏移量。我想最简单的方法是加载整个图像并获得一个 RECT。 【参考方案1】:

我使用以下操作和加载位图。它非常便携(HBitmap 和绘图函数除外,它们无论如何都是#ifdef'd ..):

Images.hpp:

#ifndef IMAGES_HPP_INCLUDED
#define IMAGES_HPP_INCLUDED

#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
#include <stdexcept>
#include <windows.h>

namespace CG

    typedef union RGBA
    
        std::uint32_t Colour;
        struct
        
            std::uint8_t R, G, B, A;
        ;
     *PRGB;

    class Image
    
        private:
            RGBA* Pixels;
            std::uint32_t width, height;
            std::uint16_t BitsPerPixel;

        protected:

        public:
            ~Image();

            Image(HWND Window, int X, int Y, int Width, int Height);
    ;


#endif // IMAGES_HPP_INCLUDED

Images.cpp:

#include "Images.hpp"

namespace CG

    Image::~Image()
    
        delete[] this->Pixels;
    

    Image::Image(HWND Window, int X, int Y, int Width, int Height)
    
        HDC DC = GetDC(Window);
        BITMAP Bmp = 0;
        HBITMAP hBmp = reinterpret_cast<HBITMAP>(GetCurrentObject(DC, OBJ_BITMAP));

        if (GetObject(hBmp, sizeof(BITMAP), &Bmp) == 0)
            throw std::runtime_error("BITMAP DC NOT FOUND.");

        RECT area = X, Y, X + Width, Y + Height;
        GetClientRect(Window, &area);

        HDC MemDC = GetDC(nullptr);
        HDC SDC = CreateCompatibleDC(MemDC);
        HBITMAP hSBmp = CreateCompatibleBitmap(MemDC, width, height);
        DeleteObject(SelectObject(SDC, hSBmp));

        BitBlt(SDC, 0, 0, width, height, DC, X, Y, SRCCOPY);
        this->Pixels = new RGBA[width * height];

        BITMAPINFO Info = sizeof(BITMAPINFOHEADER), width, height, 1, BitsPerPixel, BI_RGB, Data.size(), 0, 0, 0, 0;
        GetDIBits(SDC, hSBmp, 0, height, this->Pixels, &Info, DIB_RGB_COLORS);

        DeleteDC(SDC);
        DeleteObject(hSBmp);
        ReleaseDC(nullptr, MemDC);
        ReleaseDC(Window, DC);
    

如果您想将上述任何一个转换为 hBitmap,您可以这样做:

HBITMAP Image::ToHBitmap()

    void* Memory = this->Pixels;        
    std::size_t size = ((width * BitsPerPixel + 31) / 32) * 4 * height;
    BITMAPINFO Info = sizeof(BITMAPINFOHEADER), width, height, 1, BitsPerPixel, BI_RGB, size, 0, 0, 0, 0;
    HBITMAP hBmp = CreateDIBSection(nullptr, &Info, DIB_RGB_COLORS, &Memory, nullptr, 0);
    return hBmp;

【讨论】:

可能你忘记在你的 Images.hpp 文件中包含 'cstdint' 标题 cstdint 包含在 gcc 的 iostream 中。不确定 MSVC。

以上是关于将 bmp 文件加载到 HBITMAP的主要内容,如果未能解决你的问题,请参考以下文章

使用 JavaFX 将 BMP 加载到字节数组中

从 Win32 项目中的 *.bmp 文件加载 HBITMAP

用C或C++怎样提取出bmp图像的像素点信息值?用LSB算法做信息隐藏,位图是24位的。

将 BMP 像素数据加载到数组 C 中

将位图图像加载到 WINApi C++ 并显示

生成 BMP 图像的预览