Reputation: 36483
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
Upvotes: 3
Views: 2006
Reputation: 67
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);
}
Upvotes: 0
Reputation: 6360
This could be a number of variations on the answer by reinier.
For some examples of the last option, check out slides 18 and 21 in Advanced OSM Cartography on SlideShare.
Upvotes: 0
Reputation: 5946
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.
Upvotes: 0
Reputation: 310997
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
.
Upvotes: 1
Reputation: 15925
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
Upvotes: 7