2009-07-28 4 views
3

Итак, у меня есть моментальный снимок источника видео, который я получаю в изображение, захватить для него объект Graphics и затем нарисовать временную метку в правом нижнем углу изображения. Пока нет проблем. Тем не менее, я не могу гарантировать, какой цвет будет за текстом, поэтому независимо от того, какую кисть я использую, он почти наверняка столкнется с некоторыми изображениями, на которых он нарисован, делая текст нечитаемым.Рисование контрастной строки на изображении

Мне интересно, знает ли кто-нибудь способ (либо метод в .net, либо хороший алгоритм), для определения наилучшего цвета для строки, основанной на изображении за ней.

Приветствия

ответ

7
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 
+0

Отличное решение и прост, красиво сделано. – Kazar

+0

Это похоже на набросок текста –

+0

Кажется, так. Мое предложение тоже. :) –

1

Назад в дни Commodore 64 спрайтов графика, если вы хотите что-то выделиться на любом фоне, вы использовали XOR блиттинг. Некоторые люди называли это «обратным видео».

Вы можете нарисовать линии таким образом, используя ControlPaint.DrawReversibleLine, но это не будет работать для текста.

Это CodeProject article показывает, как вы можете создать кисть XOR, используя interop to gdi32.dll.

+0

Не выглядит ли это ужасно? – peSHIr

+0

Он хорошо работает на относительно мягком фоне, но даст вам очень уродливые цвета. –

2

Единственный надежный способ - использовать контрастный контур.

0

Или, если это разрешено, вы можете использовать цвет фона (ваш выбор) для текста (например, белый текст на черном фоне).

В противном случае вам нужно будет захватить прямоугольник, где будет записан текст (для каждого кадра), create the negative image of it, а затем получить цвет median в прямоугольнике и использовать его для записи текста.

Более сложное решение позволит вам использовать два слоя (начальное изображение - L1 и текст (прозрачный фон, черный текст) - L2), и перед их объединением взять все пиксели из L2, содержащие текст и изменить цвет для каждого пикселя текста для «отрицательного» базового значения цвета пикселя L1, но вы не получите того, что слишком полезно для использования с точки зрения «зрителя».

0

Это может быть ряд вариаций на the answer by reinier.

  1. Нарисуйте основной текст (четыре смещения, упомянутые повторно), не в черном, но на самом деле контрастирующим цветом переднего плана фактического текста.
  2. Нарисуйте текст дважды: один раз контрастным цветом, но полужирным и/или немного большим размером, а затем в тексте переднего плана над этим. Возможно, придется немного поиграть с координатами и даже нужно сделать рисунок на слово или даже персонаж, чтобы получить оба прохода, чтобы хорошо совместить и не дать уродливый конечный результат.
  3. Do what reinier suggested, но, возможно, не четыре раза (все четыре направления), но, возможно, три или даже два раза, чтобы получить своего рода «затененный» вид.
  4. Отпустите весь подход «нарисовать пиксельный пиксель с использованием API-вызовов» и используйте передовые технологии многослойного компоновки, такие как те, которые доступны в дизайне WPF.

Для некоторых примеров последнего варианта ознакомьтесь с слайдами 18 и 21 в Advanced OSM Cartography на SlideShare.

+0

предложение номер 2 не работает. Принимая больший текст, все предложение становится шире. По сути, это означает, что только средний характер предложения имеет контур, все символы слева и справа от него становятся все более и более неразборчивыми. Чтобы сделать этот трюк, нужно построить каждую букву индивидуально. (но это довольно сложно сделать добро). – Toad

+0

также предложение номер 2 не очень хорошо. Если вы постоянно меняете цвет на основное изображение, это даст очень раздражающий мерцающий текст. Мое предложение с черным контуром работает на любом фоне. Даже на чистом белом, где вы только видите черный контур. – Toad

+0

@reinier 1: Отсюда мой комментарий о том, что, вероятно, нужно сделать рендеринг текста для каждого персонажа и нужно много координировать, чтобы избежать уродливых результатов. Надеюсь, вы прочитали весь текст? @reinier 2: я не предлагаю изменить цвет основного изображения, но изменяя контрастный цвет на цвет переднего плана текста. Итак: нарисуйте белый контур для черного текста и черный контур для белого текста, независимо от того, что вы рисуете. – peSHIr

0

Следующий фрагмент показывает, как инвертировать цвет (фон), а затем применяет предложение Дины для создания фона с использованием 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); 
} 
Смежные вопросы