0

I'm trying to draw text onto a bitmap, and the image is coming out black.

protected Bitmap DrawTextImage(string text, float fontsize, string fontname = "Helvetica")
{
    string imagePath = @"C:\img.bmp";
    string imagePathTest = @"C:\imgTest.bmp";
    Font textFont = new Font(fontname, fontsize);
    var size = TextRenderer.MeasureText(text, textFont);
    Bitmap bmp = new Bitmap(size.Width, size.Height);

    Graphics graphics = Graphics.FromImage(bmp);
    SolidBrush brush = new SolidBrush(Color.Black);
    graphics.DrawString(text, textFont, brush, size.Width, size.Height);
    if(File.Exists(imagePathTest))
        File.Delete(imagePathTest);
    bmp.Save(imagePathTest, ImageFormat.Bmp);

For what it's worth, the image also needs to be eventually converted into a bitmap format for printing on a thermal printer, but I'm just focused on this part for the moment.

The arguments i'm using here are DrawTextImage(text, 36);

  • I see you save the `bmp` but I dont see anywhere where `bmp` is modified. You only modify `graphics` – maccettura Feb 03 '20 at 21:34
  • 1
    @maccettura `graphics.DrawString()` will modify the underlying image –  Feb 03 '20 at 21:58
  • 1
    @maccettura . The `Graphics` object does not __contain__ any graphics; it is a **tool** that lets you draw onto a related bitmap, including a control's surface. - It should be created in a `using` clause, though. – TaW Feb 03 '20 at 22:21
  • 1
    You are drawing right beside a black bitmap with a black brush. – TaW Feb 03 '20 at 22:24
  • With a Thermal printer as destination, also try with `MeasureCharacterRanges`, as shown [here](https://stackoverflow.com/a/54772134/7444103). – Jimi Feb 03 '20 at 23:25
  • The notes here may come in handy: [Drawing a Long String on to a Bitmap results in Drawing Issues](https://stackoverflow.com/a/49953353/7444103), in reation to the use of `TextRenderer.DrawText()` in place of `Graphics.DrawString()`. Or [here](https://stackoverflow.com/a/53074638/7444103), when opting for `GraphicsPath.AddString()` instead. – Jimi Feb 03 '20 at 23:30
  • @TaW, turns out I actually needed to be drawing white text on a black background, but using a white brush still resutls in the same issue. Main post updated with more details – Brian Schamel Feb 04 '20 at 15:34
  • 2
    You are still drawing to the right of the bitmap. Draw at (0,0)! – TaW Feb 04 '20 at 15:46
  • @TaW that was it, thank you! If you post that as an answer, I'll mark it as Solved. – Brian Schamel Feb 04 '20 at 16:15
  • 2
    It ist already part of the posted answer. I do not post anymore answers here, as long the the language police are on patrol. – TaW Feb 04 '20 at 16:20
  • Sorry for the late replies guys, I only had experience with the .NET Core ImageSharp library and it works sorta opposite of this library. – maccettura Feb 04 '20 at 16:51
  • 1
    Please don't edit your question so as to potentially invalidate existing answers. _[Is it OK to make a clarifying edit to a question if it will invalidate existing answers?](https://meta.stackoverflow.com/questions/266946/is-it-ok-to-make-a-clarifying-edit-to-a-question-if-it-will-invalidate-existing)_. Your original question was already quite clear. Taw has already kindly pointed out the final solution is part of a posted answer –  Feb 04 '20 at 22:06
  • @MickyD the solution was actually to draw at (0,0), which is not part of the existing answer. – Brian Schamel Feb 07 '20 at 15:08
  • Incorrect. As mentioned by everyone you had **many** problems not in any way limited to (0,0) however this is all moot until you set the right background color. And as Taw says, (0,0) was part of the posted answer –  Feb 07 '20 at 16:07

1 Answers1

2

I'm trying to draw text onto a bitmap, and the image is coming out black.

The resulting image is black because you are drawing in black...on a black background. The reason for the black background is that bitmaps default to black.

You just need to call FillRectangle (or Clear() as mentioned in the comments) to a different color just after obtaining graphics prior to any other drawing.

Change:

Graphics graphics = Graphics.FromImage(bmp);
SolidBrush brush = new SolidBrush(Color.Black);
graphics.DrawString(text, textFont, ...);

...to:

Graphics graphics = Graphics.FromImage(bmp);
graphics.FillRectangle (Brushes.White, 0, 0, size.Width, size.Height); // Fill to white
SolidBrush brush = new SolidBrush(Color.Black);
graphics.DrawString(text, textFont, ...);

For a simpler approach, try graphics.Clear(Color.White).

Tips

1. Dispose GDI Objects When Done

Because you're creating an explicit Graphics and Brush that isn't used anywhere else, it's a good idea to Dispose them when you are finished. GDI resources have always been a system-wide limited resource on Windows, irrespective of bitness and installed RAM.

e.g.

using (var graphics = Graphics.FromImage(bmp))
{
...
    graphics.DrawString(text, ...);
    if(File.Exists(imagePathTest))
        File.Delete(imagePathTest);
    bmp.Save(imagePathTest, ImageFormat.Bmp);
...
}

2. Use Pre-defined GDI Brushes/Pens Where Possible

Instead of creating brushes, try to use one of the pre-existing brushes or pens. They're quicker to obtain; don't need disposing because they're system-wide.

Instead of:

var brush = new SolidBrush(Color.Black);

...use:

_blackBrush = Brushes.Black; // optionally save in a field for future use
  • 2
    `graphics.Clear(Color.White);` would work also and `graphics.DrawString` should probably draw at position 0, i.e. `graphics.DrawString(text, textFont, brush, 0, 0);' – J.R. Feb 03 '20 at 22:14
  • He also should avoid leaking resources, like the graphics obeject and the brush.. – TaW Feb 03 '20 at 22:22
  • @MickyD I tried your suggestions, but now I'm getting a solid White image instead of solid black. However, it looks like the printer itself inverts the colors before printing (so this solid white image that I'm sending is actually solid black). I'm updating my post with more info. – Brian Schamel Feb 04 '20 at 15:25
  • @BrianSchamel that sounds like a _new question_. Feel free to post it –  Feb 04 '20 at 22:01