【问题标题】:How to render 8bit indexed bitmap using GDI?如何使用 GDI 渲染 8 位索引位图?
【发布时间】:2013-01-01 18:01:32
【问题描述】:

我正在尝试使用 Windows GDI 将 freetype 的字形渲染到窗口。 freetype生成的bitmap好像是8bit index bitmap什么的,因为在它的官方教程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);

您能否告诉我,如何在 Windows 中使用 GDI/GDI+ 渲染每像素 8 位的索引位图。 谢谢。

【问题讨论】:

标签: windows qt gdi+ gdi freetype


【解决方案1】:

就像这里的注释:

        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 对齐。

【讨论】:

  • 大多数情况下步幅对齐 4 只是因为宽度是 4 的倍数。不过最好强制执行。
  • @MarkRansom:如果这里我不强制执行,结果会不正确。
【解决方案2】:

您给出的 Qt 示例创建了一个全黑的调色板,透明度随强度而变化。您与 GDI 一起使用的调色板是全黑的,句号。你需要改变颜色。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-02
    • 1970-01-01
    • 1970-01-01
    • 2012-03-25
    • 2010-10-29
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    相关资源
    最近更新 更多