如何在 Windows API 中更新用户创建的位图

发布于 2024-10-09 18:10:36 字数 2088 浏览 3 评论 0原文

在我的代码中,我快速动态生成图像,并且我想尽快显示它们。因此,第一次创建图像时,我创建了一个新的位图,但我不想删除旧的位图并为每个后续图像创建新的位图,而是只想将数据复制回现有的图像中。这是我的代码,用于执行初始创建和更新。创建工作正常,但更新工作不起作用。

BITMAPINFO bi;
HBITMAP Frame::CreateBitmap(HWND hwnd, int tol1, int tol2, bool useWhite, bool useBackground)
{
  ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
  bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  bi.bmiHeader.biWidth = width;
  bi.bmiHeader.biHeight = height;
  bi.bmiHeader.biPlanes = 1;
  bi.bmiHeader.biBitCount = 24;
  bi.bmiHeader.biCompression = BI_RGB;
  ZeroMemory(bi.bmiColors, sizeof(RGBQUAD));

  // Allocate memory for bitmap bits
  int size = height * width;
  Pixel* newPixels = new Pixel[size];

  // Recompute the output
  //memcpy(newPixels, pixels, size*3);
  ComputeOutput(newPixels, tol1, tol2, useWhite, useBackground);

  HBITMAP bitmap = CreateDIBitmap(GetDC(hwnd), &bi.bmiHeader, CBM_INIT, newPixels, &bi, DIB_RGB_COLORS);
  delete newPixels;

  return bitmap;
}

为什么

void Frame::UpdateBitmap(HWND hwnd, HBITMAP bitmap, int tol1, int tol2, bool useWhite, bool useBackground)
{
  ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
  bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

  HDC hdc = GetDC(hwnd);
  if(!GetDIBits(hdc, bitmap, 0, bi.bmiHeader.biHeight, NULL, &bi, DIB_RGB_COLORS))
    MessageBox(NULL, "Can't get base image info!", "Error!", MB_ICONEXCLAMATION | MB_OK);

  // Allocate memory for bitmap bits
  int size = height * width;
  Pixel* newPixels = new Pixel[size];

  // Recompute the output
  //memcpy(newPixels, pixels, size*3);
  ComputeOutput(newPixels, tol1, tol2, useWhite, useBackground);

  // Push back to windows
  if(!SetDIBits(hdc, bitmap, 0, bi.bmiHeader.biHeight, newPixels, &bi, DIB_RGB_COLORS))
      MessageBox(NULL, "Can't set pixel data!", "Error!", MB_ICONEXCLAMATION | MB_OK);

  delete newPixels;
}

Pixel 结构就是这样:

struct Pixel { unsigned char b, g, r; };

我的更新功能不起作用。我总是收到“无法设置像素数据!”的消息框。当我从文件加载原始位图,然后编辑数据时,我使用了与此类似的代码,但现在当我手动创建它时,它不起作用。

In my code I quickly generate images on the fly, and I want to display them as quickly as possible. So the first time I create my image, I create a new BITMAP, but instead of deleting the old one and creating a new one for every subsequent image, I just want to copy my data back into the existing one. Here is my code to do both the initial creation and the updating. The creation works just fine, but the updating one doesn't work.

BITMAPINFO bi;
HBITMAP Frame::CreateBitmap(HWND hwnd, int tol1, int tol2, bool useWhite, bool useBackground)
{
  ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
  bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  bi.bmiHeader.biWidth = width;
  bi.bmiHeader.biHeight = height;
  bi.bmiHeader.biPlanes = 1;
  bi.bmiHeader.biBitCount = 24;
  bi.bmiHeader.biCompression = BI_RGB;
  ZeroMemory(bi.bmiColors, sizeof(RGBQUAD));

  // Allocate memory for bitmap bits
  int size = height * width;
  Pixel* newPixels = new Pixel[size];

  // Recompute the output
  //memcpy(newPixels, pixels, size*3);
  ComputeOutput(newPixels, tol1, tol2, useWhite, useBackground);

  HBITMAP bitmap = CreateDIBitmap(GetDC(hwnd), &bi.bmiHeader, CBM_INIT, newPixels, &bi, DIB_RGB_COLORS);
  delete newPixels;

  return bitmap;
}

and

void Frame::UpdateBitmap(HWND hwnd, HBITMAP bitmap, int tol1, int tol2, bool useWhite, bool useBackground)
{
  ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
  bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

  HDC hdc = GetDC(hwnd);
  if(!GetDIBits(hdc, bitmap, 0, bi.bmiHeader.biHeight, NULL, &bi, DIB_RGB_COLORS))
    MessageBox(NULL, "Can't get base image info!", "Error!", MB_ICONEXCLAMATION | MB_OK);

  // Allocate memory for bitmap bits
  int size = height * width;
  Pixel* newPixels = new Pixel[size];

  // Recompute the output
  //memcpy(newPixels, pixels, size*3);
  ComputeOutput(newPixels, tol1, tol2, useWhite, useBackground);

  // Push back to windows
  if(!SetDIBits(hdc, bitmap, 0, bi.bmiHeader.biHeight, newPixels, &bi, DIB_RGB_COLORS))
      MessageBox(NULL, "Can't set pixel data!", "Error!", MB_ICONEXCLAMATION | MB_OK);

  delete newPixels;
}

where the Pixel struct is just this:

struct Pixel { unsigned char b, g, r; };

Why does my update function not work. I always get the MessageBox for "Can't set pixel data!" I used code similar to this when I was loading in the original bitmap from file, then editing the data, but now when I manually create it, it doesn't work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

执手闯天涯 2024-10-16 18:10:37

要写入位图,您必须将其选择到 DeviceContext 中:

hdcMemDC = CreateCompatibleDC(hdc); 
... // adjust hdcMem to right sizes (see MSDN : Capturing an Image)
SelectObject(hdcMemDC,bitmap);
... // your Bitmap drawing
BitBlt( hdcMemDC, ... ) // to copy to hdc.

ReleaseDC(hWnd, hdcMemDC);

另外 CreateDIBitmap( GetDC(hwnd),... ) 需要 ReleaseDC(hWnd ,??? ) ;

您必须将 GetDC(...) 分配给变量,以便可以释放它。

to write to a bitmap you have to Select it into a DeviceContext:

hdcMemDC = CreateCompatibleDC(hdc); 
... // adjust hdcMem to right sizes (see MSDN : Capturing an Image)
SelectObject(hdcMemDC,bitmap);
... // your Bitmap drawing
BitBlt( hdcMemDC, ... ) // to copy to hdc.

ReleaseDC(hWnd, hdcMemDC);

Also CreateDIBitmap( GetDC(hwnd),... ) needs a ReleaseDC(hWnd ,??? );

You must assign GetDC(...) to a variable so you can release it.

温柔戏命师 2024-10-16 18:10:37

请使用 CreateDIBSection 创建位图。

这将创建一个指向位图的 HBITMAP 并返回一个指向用户模式可访问缓冲区的指针。按照您指定的格式。

Please, create your bitmap with CreateDIBSection.

This creates a HBITMAP to a bitmap and returns a pointer to a usermode accessible buffer. In the format you specify.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文