Если изображение не отличается таким, что можно предположить, что вы нарисуете строку в области с довольно сплошным цветом, вы можете использовать следующее решение.
Вы можете сначала использовать алгоритм для расчета наиболее различного цвета от другого цвета следующим образом:
public static byte MostDifferent (byte original) {
if(original < 0x80) {
return 0xff;
} else {
return 0x00;
}
}
public static Color MostDifferent (Color original) {
byte r = MostDifferent(original.R);
byte g = MostDifferent(original.G);
byte b = MostDifferent(original.B);
return Color.FromArgb(r,g,b);
}
Теперь, когда мы сделали это, мы должны рассчитать средний цвет в пределах области, где string
будет нарисован. Вы можете сделать это на Bitmap
уровне:
public static unsafe Color AverageColor (Bitmap bmp, Rectangle r) {
BitmapData bmd = bmp.LockBits (r, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
int s = bmd.Stride;
int cr = 0;
int cg = 0;
int cb = 0;
int* clr = (int*)(void*)bmd.Scan0;
int tmp;
int* row = clr;
for (int i = 0; i < r.Height; i++) {
int* col = row;
for (int j = 0; j < r.Width; j++) {
tmp = *col;
cr += (tmp >> 0x10) & 0xff;
cg += (tmp >> 0x08) & 0xff;
cb += tmp & 0xff;
col++;
}
row += s>>0x02;
}
int div = r.Width * r.Height;
int d2 = div >> 0x01;
cr = (cr + d2)/div;
cg = (cg + d2)/div;
cb = (cb + d2)/div;
bmp.UnlockBits (bmd);
return Color.FromArgb (cr, cg, cb);
}
Наконец алгоритм первым измеряет прямоугольник, в котором будет окрашена строка, рядом она определяет наиболее различный цвет и, наконец, рисует строку с этим цветом:
public static void DrawColorString (this Graphics g, Bitmap bmp, string text, Font font, PointF point) {
SizeF sf = g.MeasureString (text, font);
Rectangle r = new Rectangle (Point.Truncate (point), Size.Ceiling (sf));
r.Intersect (new Rectangle(0,0,bmp.Width,bmp.Height));
Color brsh = MostDifferent (AverageColor (bmp, r));
g.DrawString (text, font, new SolidBrush (brsh), point);
}
Теперь вы можете вызвать метод, например, как:
Bitmap bmp = new Bitmap("Foo.png");
Graphics g = Graphics.FromImage(bmp);
g.DrawColorString (bmp, "Sky", new Font ("Arial", 72.0f), new PointF (600.0f, 150.0f));
g.DrawColorString (bmp, "Sand", new Font ("Arial", 72.0f), new PointF (600.0f, 450.0f));
bmp.Save ("result.jpg");
Этот результат, например, в:
Рисует непрозрачный белый прямоугольник фона за текстом, приемлемым в вашей ситуации? –
Я не помню, где я это слышал, но из того, что я помню, лучший способ убедиться, что текст всегда виден, будет иметь белый текст с черной рамкой. – krillgar
Может ли цвет сильно отличаться в пределах одной строки?Или разумно предположить, что одного цвета на строку будет достаточно? –