如何在 WinAPI 中将 TrueType 字体绘制到像素数组中?
Posted
技术标签:
【中文标题】如何在 WinAPI 中将 TrueType 字体绘制到像素数组中?【英文标题】:How to draw TrueType fonts into an array of pixels in WinAPI? 【发布时间】:2019-01-16 03:24:23 【问题描述】:有一些 WinAPI 函数可以将 TrueType 字体绘制到 Windows GDI 上下文中。
我想将这个 TrueType 文本写入我自己的二维像素数组中(我只是用这段代码将它粘贴到一个窗口中:)
int blit_mode = STRETCH_DELETESCANS;
void BlitFrame()
BITMAPINFO bmi = sizeof(BITMAPINFOHEADER), frame_size_x, -frame_size_y,1,32,BI_RGB,0,0,0,0,0, 0,0,0,0 ;
SetStretchBltMode(hdc, blit_mode);
int result = StretchDIBits(hdc,
0, 0, client_x, client_y,
0, 0, frame_size_x, frame_size_y,
frame_bitmap,
&bmi,
DIB_RGB_COLORS,
SRCCOPY);
这段代码在 WinAPI 中非常混乱,我不知道(至少到现在)该怎么做。
我该怎么做?
【问题讨论】:
搜索“内存设备上下文”和“设备无关位图”。 Petzold 的“Programming Windows”解释了位图、设备上下文以及它们之间的关系。了解您正在使用的概念是一种有效且高效的前进策略。 奇怪的是:即使我不会将这个字形渲染到我的位图中(我不知道该怎么做,这很受欢迎,因为我可以用我的 cpu 等对其进行后处理),我只是将我的像素表blit到窗口然后将这些文本也渲染到窗口 - 然后它也不起作用,它闪烁......我不明白为什么......这一切都是在一个绘画程序中完成的,在我看来它不应该是被视为两个单独的重绘,即使这两个绘图之间的时间间隔很小.. 奇怪的结论可能是窗口在绘图例程结束之前不会缓冲它,而是实时显示它 如果那真的很奇怪..那么我需要将那些将其渲染到我的数组中的例程...但是为什么这一切都如此混乱和如此混乱 这对您来说似乎是一团糟,因为您拒绝做基础工作,并拒绝了解您正在使用的系统的解剖结构。阅读WM_PAINT message 文档以了解您的解决方案为何会出现闪烁。更好的是,获取 Petzold 的Programming Windows®。这是学习 Windows 编程的最有效方式。 【参考方案1】:tnx 巴马克谢米拉尼
我得到了你的代码并产生了类似的东西
void BlitFrame2()
BITMAPINFO bmi = sizeof(BITMAPINFOHEADER), frame_size_x, -frame_size_y,1,32,BI_RGB,0,0,0,0,0, 0,0,0,0 ;
HDC memdc = CreateCompatibleDC(hdc);
HBITMAP hbitmap = CreateBitmap(frame_size_x, frame_size_y, 1, 32, frame_bitmap);
HGDIOBJ oldbmp = SelectObject(memdc, hbitmap);
SetBkMode(memdc, TRANSPARENT);
SetTextColor(memdc, 0xffffff);
TextOut(memdc, 0, 0, "123", 3);
SelectObject(memdc, oldbmp);
GetDIBits(memdc, hbitmap, 0, frame_size_y, frame_bitmap, &bmi, 0);
DeleteObject(hbitmap);
DeleteDC(memdc);
// ReleaseDC(0, hdc);
SetStretchBltMode(hdc, blit_mode);
int result = StretchDIBits(hdc,
0, 0, client_x, client_y,
0, 0, frame_size_x, frame_size_y,
frame_bitmap,
&bmi,
DIB_RGB_COLORS,
SRCCOPY);
它为我的 blitted 帧添加了稳定的文本,tnx
悬停我会得到一些问题,因为我不明白它
1) 也许有人可以告诉我更多它是如何工作的以及内存传输在哪里?我对这个用绘制文本更新的像素表有简单的字节访问吗? (例如后处理)
2) 它可以工作,但速度会明显变慢,例如,当我的原始帧为 2 毫秒(绘制一些位图精灵然后 blit)时,使用这个驯服会增长到 8 毫秒
3) 我可以将其中一些调用移到帧循环之外吗?
PS 在考虑这个问题时,我认为它是这样工作的 1)它会在某个时候(在哪里?)将我的像素表复制到 memdc 中 2)它将那些字体吸引到这个memdc 3)GetDIBits 用改变的像素更新我的原始像素表(我不确定这个悬停,但几乎可以肯定) 4)我像以前一样blit它
如果是这样,我得到三个而不是一个 blit(co 它应该慢 3 倍, 测量显示它更像是 4 次,但可能是测量误差(例如 2 和 8 可能是 2.7 和 8.1)
如果这是三个就可以了,但是我认为我并不总是需要从 memdc 重新更新那些表格像素,有没有办法 从 memdc 直接删除它? (那么它只会慢两倍而不是 3 倍,但遗憾的是那些 fount 例程不能直接渲染到我自己的 ram 表中 - 那么它根本不会慢)(真的可能吗?)
【讨论】:
你的目标是什么?您可以使用 memory dc 在位图上绘图。您还可以使用内存 dc 作为绘图缓冲区。BitBlit
或 StretchBlt
跳过 BITMAPINFO
函数。 hdc
的用法似乎是错误的。 hdc
是一个临时句柄,它可以传递,但不应该保留 - 顺便说一句,您可以更新问题,或者删除答案和问题,而是提出一个新问题。
GDI 字体渲染例程可以直接渲染到设备上下文中,由内存中的位图支持。要看到这一点,需要了解device contexts。以上是关于如何在 WinAPI 中将 TrueType 字体绘制到像素数组中?的主要内容,如果未能解决你的问题,请参考以下文章