简体   繁体   English

如何使用GDI渲染8位索引位图?

[英]How to render 8bit indexed bitmap using GDI?

I'm trying to render a freetype's glyph to a window using windows GDI. 我正在尝试使用Windows GDI将freetype的字形呈现给窗口。 It seems the bitmap generated by freetype is 8bit index bitmap or something, because in its official tutorial example4.cpp, it use Qt to render the glyph as follows: 看来freetype生成的位图是8bit索引位图之类的东西,因为在其官方教程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);

So I try to render it using gdi as follows: 因此,我尝试使用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);

Then I try to use GDI+ to render, but failed too. 然后,我尝试使用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);

Could you please tell me, how to render 8bit per pixel indexed bitmap in Windows using GDI/GDI+. 您能否告诉我,如何在Windows中使用GDI / GDI +渲染8bit每像素的索引位图。 Thanks. 谢谢。

Just as a note here: 就像这里的注释:

        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);

Two points: 两点:
1) as Mark Randsom and paulsm4 said color palette is mandantory. 1)正如Mark Randsom和paulsm4所说,调色板是强制性的。
2) align by 4. 2)对齐4。

The Qt example you give creates a color palette that's all black, with the transparency varying with the intensity. 您提供的Qt示例创建了一个全黑色的调色板,其透明度随强度而变化。 The palette you're using with GDI is all black, period. 您与GDI一起使用的调色板全为黑色。 You need to vary the color. 您需要改变颜色。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM