使用 C++ 在内存中编辑位图

Posted

技术标签:

【中文标题】使用 C++ 在内存中编辑位图【英文标题】:Editing bitmap in memory using C++ 【发布时间】:2015-01-12 03:22:10 【问题描述】:

我有一个要显示为图像的二维数据数组。 计划是这样的 - 使用CreateCompatibleBitmap 创建位图(这会生成纯黑色位图,我可以毫无问题地显示它) 编辑此位图的像素以匹配我的数据 BitBlt 位图到窗口

我认为我需要一个指向内存中像素数据开始位置的指针。我已经尝试了许多不同的方法,并在谷歌上搜索了 3 天,但仍然无法编辑单个像素。 使用SetPixel(HDC, x, y, Color) 的循环来设置每个像素工作但非常缓慢。 我已经在 C# 中通过锁定位图和编辑位来实现这一点,但我是 C++ 新手,似乎不知道如何做类似的事情。

我一直在尝试使用memset(p, value, length) 对于“p”,我尝试使用从CreateCompatibleBitmap 返回的句柄、位图的 DC 和窗口的 DC。我已经尝试了各种值和长度的值。 我不确定这是否是正确的使用方法。

我不必使用位图,这只是我知道要做的唯一事情。实际上,找到一种直接更改主窗口 DC 的方法会很棒。 我确实想避免图书馆。我这样做纯粹是为了学习 C++。

【问题讨论】:

您首先准备像素数据,然后使用CreateDIBSection 创建位图。或者完全绕过位图,直接使用SetDIBitsToDevice从数据缓冲区渲染。 但是,如果您出于某种原因坚持要修改现有位图,SetDIBits 这是非常有用的信息,我将开始着手实施它。我仍然很好奇是否有办法逐像素更改内存中的位图,有点像编写我自己的 SetDIBits 函数。或者这会不会有点太难了? 好吧,如果你的意思是“逐像素”字面意思,那就是SetPixel 在我看来,您主要是在学习低级 C Windows API。可能有用,可能很有趣,但肯定不是 c++。至少不是 21 世纪的 c++ 【参考方案1】:

这需要相当多的研究,所以我将准确地发布它是如何为其他可能正在寻找的人完成的。 这会将每个像素都染成红色。

hDC = BeginPaint(hWnd, &Ps);

    const int
        width = 400,
        height = 400,
        size = width * height * 3;
    byte * data;
    data = new byte[size];
    for (int i = 0; i < size; i += 3)
    
        data[i] = 0; 
        data[i + 1] = 0;
        data[i + 2] = 255;
    

    BITMAPINFOHEADER bmih;
    bmih.biBitCount = 24;
    bmih.biClrImportant = 0;
    bmih.biClrUsed = 0;
    bmih.biCompression = BI_RGB;
    bmih.biWidth = width;
    bmih.biHeight = height;
    bmih.biPlanes = 1;
    bmih.biSize = 40;
    bmih.biSizeImage = size;

    BITMAPINFO bmpi;
    bmpi.bmiHeader = bmih;
    SetDIBitsToDevice(hDC, 0, 0, width, height, 0, 0, 0, height, data, &bmpi, DIB_RGB_COLORS);
    delete[] data;

【讨论】:

为什么要硬编码 40 而不是 sizeof(BITMAPINFOHEADER) ?【参考方案2】:

memset 可用于实际的 RGB 信息数组(但您还需要知道位图的格式,如果像素有 32 位或 24 位)。

通过对msdn的一些研究,似乎你想要得到的是BITMAP结构: http://msdn.microsoft.com/en-us/library/k1sf4cx2.aspx

在那里你有你可以memset的bmBits。

如何从你的函数中到达那里?

好吧,CreateCompatibleBitmap 返回一个 HBITMAP 结构,看来您可以使用以下代码从 HBITMAP 获取 BITMAP:

BITMAP bmp;
GetObject(hBmp, sizeof(BITMAP), &bmp); 

然而,这似乎得到了现有位图信息的副本,它只解决了你的 memset 问题(你现在可以使用 memset 设置位图信息,即使我没有看到 memeset 除了制作 bmp 之外的任何其他用途白色或黑色)。

应该有一个函数可以让你将 DC 位设置为位图,所以你应该可以使用新的位图作为参数。

【讨论】:

以上是关于使用 C++ 在内存中编辑位图的主要内容,如果未能解决你的问题,请参考以下文章

内存泄漏,大量位图图像 C++ CLI

win32api:在文本行中合并位图

用于位图管理的 C++ STL 类

将位图写入 MIME 消息

如何将位图添加到电话库?

MFC对话框添加位图背景后编辑框输入文字会重影