我正在尝试使用Windows GDI将freetype的字形渲染到窗口。似乎freetype生成的位图是8位索引位图或其他东西,因为在其官方教程example4.cpp中,它使用Qt渲染字形如下:
error = FT_Render_Glyph(m_face->glyph,
FT_RENDER_MODE_NORMAL);
QImage glyphImage(m_face->glyph->bitmap.buffer,
m_face->glyph->bitmap.width,
m_face->glyph->bitmap.rows,
m_face->glyph->bitmap.pitch,
QImage::Format_Indexed8);
/*painter.translate(m_glyphRect.x(),
m_glyphRect.y());*/
QVector<QRgb> colorTable;
for (int i = 0; i < 256; ++i)
colorTable << qRgba(0, 0, 0, i);
glyphImage.setColorTable(colorTable);
painter.drawImage(QPoint(0, 0),
glyphImage);
所以我尝试使用gdi渲染它,如下所示:
BITMAPINFO* pBmi = (BITMAPINFO*)malloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255);
BITMAPINFOHEADER &bmh = pBmi->bmiHeader;
bmh.biSize = sizeof(BITMAPINFOHEADER);
bmh.biBitCount = 8;
bmh.biCompression = BI_RGB;
bmh.biPlanes = 1;
RGBQUAD* palette = &pBmi->bmiColors[0];
for (int i = 0; i < 256; ++i) {
RGBQUAD rgb = {0};
palette[i] = rgb;
}
//assert(pBm->bitmap);
bmh.biWidth = pBm->bitmap.width;
bmh.biHeight = - pBm->bitmap.rows;
StretchDIBits(hdc, 200, 200, pBm->bitmap.width, pBm->bitmap.rows, 0, 0, pBm->bitmap.width, pBm->bitmap.rows, pBm->bitmap.buffer,
pBmi, DIB_PAL_COLORS, SRCCOPY);
然后我尝试使用GDI +进行渲染,但也失败了。
error = FT_Render_Glyph(m_face->glyph, FT_RENDER_MODE_NORMAL);
Bitmap bitmap(pBm->bitmap.width, pBm->bitmap.rows, pBm->bitmap.pitch, PixelFormat8bppIndexed, pBm->bitmap.buffer);
//Bitmap bitmap(pBm->bitmap.width, pBm->bitmap.rows, 64, PixelFormat8bppIndexed, pBm->bitmap.buffer);
ColorPalette* pal = (ColorPalette*)malloc(sizeof(ColorPalette) + 255 * sizeof(ARGB));
pal->Flags = PaletteFlagsGrayScale;
pal->Count = 256;
for (int i = 0; i <= 255; i++) {
pal->Entries[i] = Color::MakeARGB(i, 0, 0, 0);
}
bitmap.SetPalette(pal);
Graphics graphics(hdc);
graphics.DrawImage(&bitmap, 100, 100);
请告诉我,如何使用GDI / GDI +在Windows中呈现每像素8位索引位图。 感谢。
答案 0 :(得分:2)
就像这里的说明一样:
hdc = BeginPaint(hWnd, &ps);
assert(Draw());
FT_GlyphSlot &pBm = m_face->glyph;
//output by console
{
printf("\n");
for (int j = 0; j < pBm->bitmap.rows; j++) {
printf("\n");
for (int i = 0; i < pBm->bitmap.width; i++)
printf("%2x", pBm->bitmap.buffer[j * pBm->bitmap.width + i]);
}
}
//output by gdi+
{
Bitmap *pBitmap = NULL;
LPBYTE pBuffer = NULL;
int stride = (pBm->bitmap.pitch + 3) / 4 * 4;
if (stride != pBm->bitmap.pitch)
{
pBuffer = new BYTE[stride * pBm->bitmap.rows];
memset(pBuffer, 0, stride * pBm->bitmap.rows);
for (int i = 0; i < pBm->bitmap.rows; i++)
for (int j = 0; j < pBm->bitmap.width; j++)
pBuffer[i * stride + j] = pBm->bitmap.buffer[i * pBm->bitmap.width + j];
} else
{
pBuffer = pBm->bitmap.buffer;
}
pBitmap = new Bitmap(pBm->bitmap.width, pBm->bitmap.rows, stride, PixelFormat8bppIndexed, pBuffer);
ColorPalette *pPalette = (ColorPalette*)malloc(sizeof(ColorPalette) + 255 * sizeof(ARGB));
pPalette->Count = 256;
pPalette->Flags = PaletteFlagsGrayScale;
ARGB* pColor = &pPalette->Entries[0];
for (int i = 0; i < 256; i++)
pColor[i] = Color::MakeARGB(i, 0x00, 0x00, 0x00);
assert(pBitmap->GetLastStatus() == Ok);
pBitmap->SetPalette(pPalette);
assert(pBitmap->GetLastStatus() == Ok);
Graphics graphics(hdc);
graphics.DrawImage(pBitmap, 300, 300);
free(pPalette);
delete pBitmap;
//draw with gdi
{
BITMAPINFO* pBmi = (BITMAPINFO*)malloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255);
memset(pBmi, 0, sizeof(BITMAPINFO));
BITMAPINFOHEADER &bmh = pBmi->bmiHeader;
bmh.biSize = sizeof(BITMAPINFOHEADER);
bmh.biBitCount = 8;
bmh.biCompression = BI_RGB;
bmh.biPlanes = 1;
RGBQUAD* palette = &pBmi->bmiColors[0];
for (int i = 0; i < 256; ++i)
{
RGBQUAD rgb = {0};
rgb.rgbRed = ~i;
rgb.rgbGreen = ~i;
rgb.rgbBlue = ~i;
palette[i] = rgb;
}
bmh.biWidth = stride;
bmh.biHeight = - pBm->bitmap.rows;
StretchDIBits(hdc, 200, 200, stride, pBm->bitmap.rows, 0, 0, stride, pBm->bitmap.rows, pBuffer,
pBmi, DIB_RGB_COLORS, SRCCOPY);
if (pBmi)
free(pBmi);
if (pBuffer != pBm->bitmap.buffer)
delete [] pBuffer;
/*bmh.biWidth = pBm->bitmap.width;
bmh.biHeight = - pBm->bitmap.rows;
StretchDIBits(hdc, 200, 200, pBm->bitmap.width, pBm->bitmap.rows, 0, 0, pBm->bitmap.width, pBm->bitmap.rows, pBm->bitmap.buffer,
pBmi, DIB_PAL_COLORS, SRCCOPY);*/
}
}
EndPaint(hWnd, &ps);
两点:
1)正如Mark Randsom和paulsm4所说,调色板是强制性的
2)对齐4。
答案 1 :(得分:0)
您给出的Qt示例会创建一个全黑的调色板,透明度随强度而变化。您与GDI一起使用的调色板全部为黑色,周期。你需要改变颜色。