Draw text in a bitmap using TextRenderer

I am trying to draw text using TextRenderer (since it is beneficial to use Graphics.DrawString ) for Bitmap , however it has some very undesirable effects.

Code example

 using (Bitmap buffer = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { using (Graphics graphics = Graphics.FromImage(buffer)) { // Produces the result below graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; // Produces clean text, but I'd really like ClearType! graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; TextRenderer.DrawText(graphics, "Hello World", this.Font, this.ClientRectangle, Color.Black); } e.Graphics.DrawImageUnscaled(buffer, this.ClientRectangle); } 

Result

enter image description here

I'm not sure how to fix this ... help!

I DO NOT want to use Graphics.DrawString since I want GDI to render correctly (unlike GDI +).

NOTE: I just realized I left a gap in this question. Some people have indicated that ClearType text rendering works fine on their machines ...

I am trying to make the text transparent (Color.Transparent) bitmap. If I do this with a solid color, everything will be fine! (but it is necessary that I visualize a transparent bitmap).

+4
source share
3 answers

You can try installing TextRenderingHint for your Image Graphics :

 using (Graphics graphics = Graphics.FromImage(buffer)) { graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; TextRenderer.DrawText(graphics, "Hello World", this.Font, this.ClientRectangle, Color.Black); } 
+4
source

The problem is that TextRenderer uses GDI rendering, which uses ClearType to render text, clear-type uses a special anti-aliasing algorithm to smooth text, unfortunately, it does not work when you try to draw a raster device.

To make it work, you have to use a trick, paste into memory and then copy to bitmap:

  • Create in memory a raster buffer compatible with the display device context (IntPtr.Zero descriptor)
  • Fill the buffer background with a solid color or image.
  • Extract text to memory bitmap
  • Copying from a bitmap in memory to the image device context (BitBlt)

See this blog post for more: rendering GDI text for an image .

Sample code, excuse it a little long:

 public static class Test { public static Image Render() { // create the final image to render into var image = new Bitmap(190, 30, PixelFormat.Format32bppArgb); // create memory buffer from desktop handle that supports alpha channel IntPtr dib; var memoryHdc = CreateMemoryHdc(IntPtr.Zero, image.Width, image.Height, out dib); try { // create memory buffer graphics to use for HTML rendering using (var memoryGraphics = Graphics.FromHdc(memoryHdc)) { // must not be transparent background memoryGraphics.Clear(Color.White); // execute GDI text rendering TextRenderer.DrawText(memoryGraphics, "Test string 1", new Font("Arial", 12), new Point(5, 5), Color.Red, Color.Wheat); TextRenderer.DrawText(memoryGraphics, "Test string 2", new Font("Arial", 12), new Point(100, 5), Color.Red); } // copy from memory buffer to image using (var imageGraphics = Graphics.FromImage(image)) { var imgHdc = imageGraphics.GetHdc(); BitBlt(imgHdc, 0, 0, image.Width, image.Height, memoryHdc, 0, 0, 0x00CC0020); imageGraphics.ReleaseHdc(imgHdc); } } finally { // release memory buffer DeleteObject(dib); DeleteDC(memoryHdc); } return image; } private static IntPtr CreateMemoryHdc(IntPtr hdc, int width, int height, out IntPtr dib) { // Create a memory DC so we can work off-screen IntPtr memoryHdc = CreateCompatibleDC(hdc); SetBkMode(memoryHdc, 1); // Create a device-independent bitmap and select it into our DC var info = new BitMapInfo(); info.biSize = Marshal.SizeOf(info); info.biWidth = width; info.biHeight = -height; info.biPlanes = 1; info.biBitCount = 32; info.biCompression = 0; // BI_RGB IntPtr ppvBits; dib = CreateDIBSection(hdc, ref info, 0, out ppvBits, IntPtr.Zero, 0); SelectObject(memoryHdc, dib); return memoryHdc; } [DllImport("gdi32.dll")] public static extern int SetBkMode(IntPtr hdc, int mode); [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)] private static extern IntPtr CreateCompatibleDC(IntPtr hdc); [DllImport("gdi32.dll")] private static extern IntPtr CreateDIBSection(IntPtr hdc, [In] ref BitMapInfo pbmi, uint iUsage, out IntPtr ppvBits, IntPtr hSection, uint dwOffset); [DllImport("gdi32.dll")] public static extern int SelectObject(IntPtr hdc, IntPtr hgdiObj); [DllImport("gdi32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop); [DllImport("gdi32.dll")] public static extern bool DeleteObject(IntPtr hObject); [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)] public static extern bool DeleteDC(IntPtr hdc); [StructLayout(LayoutKind.Sequential)] internal struct BitMapInfo { public int biSize; public int biWidth; public int biHeight; public short biPlanes; public short biBitCount; public int biCompression; public int biSizeImage; public int biXPelsPerMeter; public int biYPelsPerMeter; public int biClrUsed; public int biClrImportant; public byte bmiColors_rgbBlue; public byte bmiColors_rgbGreen; public byte bmiColors_rgbRed; public byte bmiColors_rgbReserved; } } 
+3
source

Specify the inverse color in your DrawText () call:

 TextRenderer.DrawText(graphics, "Hello World", this.Font, this.ClientRectangle, Color.Black, this.BackColor); 
+2
source

Source: https://habr.com/ru/post/1502504/


All Articles