Drawing a contrasted string on an image

前提是你 提交于 2019-12-30 07:18:11

问题


So, I have a snapshot of a video source, which I get into an Image, grab a Graphics object for it, and then draw a timestamp in the bottom right of the image. No problem thus far. However, I cannot guarantee what colour is going to be behind the text, so no matter what brush I use, it will almost certainly clash with some of the images that it is drawn on, making the text unreadable.

I am wondering if anyone knows of a way (either a method in .net, or a nice algorithm), for determining the best colour for a string based on the image behind it.

Cheers


回答1:


 just draw the string 5 times.
 One time 1(or2) pixels to the left in black
 One time 1(or2) pixels to the right in black
 One time 1(or2) pixels above it in black
 One time 1(or2) pixels below it in black
 and the final time in white on the place where you want it



回答2:


The only reliable way is to use a contrasting outline.




回答3:


Back in the days of Commodore 64 sprite graphics, if you wanted something to stand out against any background, you used XOR blitting. Some people referred to this as 'reverse video'.

You can draw lines this way using ControlPaint.DrawReversibleLine, but that won't work for text.

This CodeProject article shows how you can create an XOR brush using interop to gdi32.dll.




回答4:


Or, if it is allowed, you could use a background color (your choice) for the text (for example white text on black background).

Otherwise, you would need to capture the rectangle where the text is written (for every frame), create the negative image of it, and then get the median color in the rectangle and use it to write the text.

A more complex solution would get you to use two layers (initial picture - L1 and Text (transparent background, black text) - L2), and before combining them, take all the pixels from L2 that contain text and change the color for the each pixel of the text to the "negative" underlying pixel color value of the L1, but you won't get something that's too usable from a "viewer's" point of view.




回答5:


This could be a number of variations on the answer by reinier.

  1. Draw underlying text (the four offset ones mentioned by reinier) not in black, but actually in a contrasting color to the foreground color of the actualy text.
  2. Draw the text twice: once in a contrasting color but in bold and/or a slightly larger size, then in the text foreground color over that. Might have to fiddle a bit with coordinates and even need to do the drawing per word or even character to get both passes to nicely align and not give an ugly end result.
  3. Do what reinier suggested, but perhaps not four times (all four directions), but maybe three or even two times to get a kind of "shaded" look.
  4. Let go of the whole "draw text pixel by pixel using API calls" approach and use advanced multilayer compositing techniques like the ones available in WPF design.

For some examples of the last option, check out slides 18 and 21 in Advanced OSM Cartography on SlideShare.




回答6:


The following snippet shows how to invert a color (background) and then applies Dinah's suggestion to create the background using Graphics.DrawString().

private static Color InvertColor(Color c)
{
  return Color.FromArgb(255 - c.R, 255 - c.G, 255 - c.B);
}
// In the following, constants and inplace vars can be parameters in your code
const byte ALPHA = 192;
var textColor = Color.Orange;
var textBrush = new SolidBrush(Color.FromArgb(ALPHA, textColor));
var textBrushBkg = new SolidBrush(Color.FromArgb(ALPHA, InvertColor(textColor)));
var font = new Font("Tahoma", 7);
var info = "whatever you wanna write";
var r = new Rectangle(10, 10, 10, 10);

// write the text
using (var g = Graphics.FromImage(yourBitmap))
{
  g.Clear(Color.Transparent);
  // to avoid bleeding of transparent color, must use SingleBitPerPixelGridFit
  g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
  // Draw background for text
  g.DrawString(info, font, textBrushBkg, r.Left - 1, r.Top - 1);
  g.DrawString(info, font, textBrushBkg, r.Left + 1, r.Top + 1);
  g.DrawString(info, font, textBrushBkg, r.Left + 1, r.Top - 1);
  g.DrawString(info, font, textBrushBkg, r.Left - 1, r.Top + 1);
  // Draw text
  g.DrawString(info, font, textBrush, r.Left, r.Top);
}


来源:https://stackoverflow.com/questions/1192543/drawing-a-contrasted-string-on-an-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!