【问题标题】:How to draw into device context如何绘制到设备上下文中
【发布时间】:2017-07-08 00:22:15
【问题描述】:

我有一个 32 位整数数组形式的位图图像(ARGB 像素:uint32 *mypixels)和int widthint height。我需要将它们输出到打印机。

我有打印机上下文:HDC hdcPrinter;

据我所知,我首先需要创建一个兼容的上下文:

HDC hdcMem = CreateCompatibleDC(hdcPrinter);

然后我需要创建一个HBITMAP 对象,将其选择到兼容的上下文中,然后渲染:

HBITMAP hBitmap = ...?
SelectObject(hdcMem, hBitmap);
BitBlt(printerContext, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY);

最后清理一下:

DeleteObject(hBitmap);
DeleteDC(hdcMem);

我的问题是如何创建一个HBITMAP 对象并将mypixels 放入其中?

我找到了两个选择:

  1. HBITMAP hBitmap = CreateCompatibleBitmap(hdcPrinter, width, height);

    看起来不错,但是mypixels 怎么进入这个位图呢?

  2. HBITMAP hBitmap = CreateDIBSection(hdcPrinter /*or hdcMem?*/, ...);

    它会起作用吗?它比选项 1 更好吗?

【问题讨论】:

  • 您可以在CreateCompatibleBitmap 之后使用或SetDIBits - 或者更好地在单个调用CreateDIBitmap 中执行此操作 - creates a compatible bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
  • 很多方法,重要的是它来自哪里。基本上来自文件、资源、内存位置。您必须关注位图的来源,代码 sn-p 会自动从任何基本的 Google 查询中弹出。请注意代码中的错误,您永远不能忽略 SelectObject() 的返回值。必须恢复设备上下文,否则会导致内存泄漏。强烈建议使用库来执行此操作,这也有助于避免使用谷歌搜索。

标签: winapi gdi


【解决方案1】:

此函数创建一个位图并将其设置为初始图像。 直接访问位有点繁琐,但是可以做到。

HBITMAP MakeBitmap(unsigned char *rgba, int width, int height, VOID **buff)
{
    VOID *pvBits;          // pointer to DIB section 
    HBITMAP answer;
    BITMAPINFO bmi;
    HDC hdc;
    int x, y;
    int red, green, blue, alpha;

    // setup bitmap info   
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = width;
    bmi.bmiHeader.biHeight = height;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;         // four 8-bit components 
    bmi.bmiHeader.biCompression = BI_RGB;
    bmi.bmiHeader.biSizeImage = width * height * 4;

    hdc = CreateCompatibleDC(GetDC(0));
    answer = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0x0);
    for (y = 0; y < height; y++)
    {
        for (x = 0; x < width; x++)
        {
            red = rgba[(y*width + x) * 4];
            green = rgba[(y*width + x) * 4 + 1];
            blue = rgba[(y*width + x) * 4 + 2];
            alpha = rgba[(y*width + x) * 4 + 3];
            red = (red * alpha) >> 8;
            green = (green * alpha) >> 8;
            blue = (blue * alpha) >> 8;
            ((UINT32 *)pvBits)[(height - y - 1) * width + x] = (alpha << 24) | (red << 16) | (green << 8) | blue;
        }
    }
    DeleteDC(hdc);

    *buff = pvBits;

    return answer;
}

【讨论】:

  • 谁负责清理*buff?需要哪个分配器来处理*buff?使用Get{R|G|B}Valuecolor macrosRGB macro 可能也是一个好主意。通常不需要评估和设置 Alpha 通道,因为 GDI 不支持 Alpha 透明度。
  • @IInspectable - GDI doesn't support alpha transparency - 是吗?奇怪为什么这对我有用。
  • 我相信当你在 hBitmap 上调用 DeleteObject 时 *buff 会死掉。您不应该尝试释放它或使用您自己的分配器或 malloc() 分配它。
  • @RbMm: “奇怪为什么这对我有用。” - 我不知道,“this” 是什么。如果您指的是在内存中复制字节,那么这是可行的,因为它既不涉及 GDI,也不实现 alpha 透明度。
  • @RbMm: AlphaBlend 不支持真正的每像素 Alpha 透明度(这是您想要拥有专用 Alpha 通道的唯一原因)。无论如何,AlphaBlend 是唯一值得注意的例外。 GDI 中的其他所有内容都不支持 Alpha 透明度。
猜你喜欢
  • 1970-01-01
  • 2013-05-04
  • 1970-01-01
  • 2011-06-05
  • 2011-01-12
  • 1970-01-01
  • 1970-01-01
  • 2015-04-04
  • 1970-01-01
相关资源
最近更新 更多