gpt4 book ai didi

c - 是否可以使用纯 GDI 将抗锯齿文本渲染到透明背景上?

转载 作者:太空宇宙 更新时间:2023-11-04 01:29:08 25 4
gpt4 key购买 nike

最近我一直在问很多关于文本别名、行别名和透明度的问题,因为我想为 Go 编写一个平台无关的 vector 图形系统; Windows 代码是用 C 语言编写的。预乘恶作剧让我将注意力转移到只渲染文本(这样我就可以访问系统字体)。

现在我有一些东西可以将文本绘制到屏幕外位图上。这有效,除了抗锯齿位。在我的代码中,当我用 0xFF 填充内存缓冲区以翻转 alpha 字节(对于绘制的像素,GDI 将其设置为 0x00)时,抗锯齿为白色。 Other people have seen antialiasing to black. ANTIALIASED_QUALITYCLEARTYPE_QUALITY 都会发生这种情况。

在这种情况下,我正在使用 TextOut() 绘制到 DIB 中。 DIB 由屏幕 DC 的副本 (GetDC(NULL)) 支持。

有什么办法可以让文本透明吗?我能以某种方式检测到白色像素,将它们分解并将其转换为 alpha 吗?对于与白色太相似的颜色,我该怎么做?

最佳答案

我写了一些代码来做到这一点。

AntialiasedText 函数将消除锯齿的文本绘制到离屏位图上。它计算透明度,以便可以使用 AlphaBlend API 函数将文本与任何背景混合。

该函数后跟一个 WM_PAINT 处理程序,说明其用法。

// Yeah, I'm lazy...
const int BitmapWidth = 500;
const int BitmapHeight = 128;

// Draw "text" using the specified font and colour and return an anti-aliased bitmap
HBITMAP AntialiasedText(LOGFONT* plf, COLORREF colour, LPCWSTR text)
{
BITMAPINFO bmi = {0};
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = BitmapWidth;
bmi.bmiHeader.biHeight = BitmapHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;

LPBYTE pBits;

HBITMAP hDIB = CreateDIBSection(0, &bmi, DIB_RGB_COLORS, (LPVOID*)&pBits, 0, 0);

// Don't want ClearType
LOGFONT lf = *plf;
lf.lfQuality = ANTIALIASED_QUALITY;
HFONT hFont = CreateFontIndirect(&lf);

HDC hScreenDC = GetDC(0);
HDC hDC = CreateCompatibleDC(hScreenDC);
ReleaseDC(0, hScreenDC);

HBITMAP hOldBMP = (HBITMAP)SelectObject(hDC, hDIB);
HFONT hOldFont = (HFONT)SelectObject(hDC, hFont);

RECT rect = {0, 0, BitmapWidth, BitmapHeight};
FillRect(hDC, &rect, WHITE_BRUSH);

TextOut(hDC, 2, 2, text, wcslen(text));

// Flush drawing
GdiFlush();

// Calculate alpha
LPBYTE pixel = pBits;
int pixelCount = BitmapWidth * BitmapHeight;
BYTE r = GetRValue(colour);
BYTE g = GetGValue(colour);
BYTE b = GetBValue(colour);
for (int c = 0; c != pixelCount; ++c)
{
// Set alpha
BYTE alpha = 255 - pixel[0];
pixel[3] = alpha;
// Set colour
pixel[0] = b * alpha / 255;
pixel[1] = g * alpha / 255;
pixel[2] = r * alpha / 255;
pixel += 4;
}

SelectObject(hDC, hOldFont);
SelectObject(hDC, hOldBMP);

DeleteDC(hDC);

DeleteObject(hFont);

return hDIB;
}

这里有一个 WM_PAINT 处理函数来执行该函数。它两次绘制相同的文本,首先使用 TextOut,然后使用抗锯齿位图。它们看起来很相似,尽管不如 ClearType。

case WM_PAINT:
{
LPCWSTR someText = L"Some text";

hdc = BeginPaint(hWnd, &ps);

LOGFONT font = {0};
font.lfHeight = 40;
font.lfWeight = FW_NORMAL;
wcscpy_s(font.lfFaceName, L"Comic Sans MS");

// Draw the text directly to compare to the bitmap
font.lfQuality = ANTIALIASED_QUALITY;
HFONT hFont = CreateFontIndirect(&font);
font.lfQuality = 0;
HFONT hOldFont = (HFONT)SelectObject(hdc, hFont);
TextOut(hdc, 2, 10, someText, wcslen(someText));
SelectObject(hdc, hOldFont);
DeleteObject(hFont);

// Get an antialiased bitmap and draw it to the screen
HBITMAP hBmp = AntialiasedText(&font, RGB(0, 0, 0), someText);
HDC hScreenDC = GetDC(0);
HDC hBmpDC = CreateCompatibleDC(hScreenDC);
ReleaseDC(0, hScreenDC);

HBITMAP hOldBMP = (HBITMAP)SelectObject(hBmpDC, hBmp);

BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 255;
bf.AlphaFormat = AC_SRC_ALPHA;

int x = 0;
int y = 40;

AlphaBlend(hdc, x, y, BitmapWidth, BitmapHeight, hBmpDC, 0, 0, BitmapWidth, BitmapHeight, bf);

SelectObject(hBmpDC, hOldBMP);
DeleteDC(hBmpDC);

DeleteObject(hBmp);

EndPaint(hWnd, &ps);
}
break;

关于c - 是否可以使用纯 GDI 将抗锯齿文本渲染到透明背景上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26023798/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com