例如,下面的图片是一个背景照片,中心有一个叫'Iniesta'的角色。但由于颜色不好,这个角色很难阅读。是否有好的算法可以获得颜色,使图像上的字符更加突出?
不要使用矩形背景(看起来实际上不太好看),您可以使用以下技巧:
如果无法使用宽笔描边文本,另一种方法是多次绘制文本并进行微小偏移;例如(Python)
for dy in range(-3, 4):
for dx in range(-3, 4):
draw_text(color1, x+dx, y+dy, message)
draw_text(color2, x, y, message)
纸张背景
使用纸张颜色清除文字后面的空白区域,并使用油墨颜色渲染文本。正如您所提到的,这对于复杂的图像并不好看。
描边、阴影、3D
使用两种颜色渲染文本。内部使用文本颜色,外部使用对比色进行描边。如果您没有此功能,则可以先使用描边颜色以更大的字体/加粗大小渲染字符,然后再使用较小的字体大小使用内部颜色覆盖 +/-
移动位置以使字体居中。移动方法决定了是否可以通过这种方式呈现描边或阴影甚至 3D 文本。
透明度
与其使用恒定颜色渲染文本像素,不如为原始像素颜色添加一些颜色值。您还可以减去颜色或使用 alpha 混合等方法...
XOR
使用另一种颜色或白色 XOR
原始颜色而不是渲染像素。
以下是VCL/C++的源代码:
void TMain::draw()
{
if (!_redraw) return;
// needed variables
AnsiString txt,a;
TColor c0=clBlack,c1=clWhite;
int tx=50,ty=50,tys=30,dty=tys*1.5;
int x,y,x0,x1,y0,y1,i,b;
// clear whole image
bmp->Canvas->Brush->Color=clBlack;
bmp->Canvas->FillRect(TRect(0,0,xs,ys));
// copy photo
bmp->Canvas->Draw(0,0,in);
// render texts ...
txt="Paper area ";
bmp->Canvas->Font ->Size=tys;
bmp->Canvas->Font ->Color=c1;
bmp->Canvas->Brush->Color=c0;
bmp->Canvas->Brush->Style=bsSolid;
bmp->Canvas->TextOutA(tx,ty,txt); ty+=dty;
txt="Stroke";
bmp->Canvas->Brush->Style=bsClear;
for (x=tx,y=ty,i=1;i<=txt.Length();i++)
{
a=txt[i];
// stroked char
bmp->Canvas->Font ->Size=tys+3;
bmp->Canvas->Font ->Color=c0;
bmp->Canvas->Font ->Style=TFontStyles()<<fsBold;
x0=bmp->Canvas->TextWidth(a);
y0=bmp->Canvas->TextHeight(a);
bmp->Canvas->TextOutA(x,y,a);
// inside char
bmp->Canvas->Font ->Size=tys;
bmp->Canvas->Font ->Color=c1;
bmp->Canvas->Font ->Style=TFontStyles();
x1=bmp->Canvas->TextWidth(a);
y1=bmp->Canvas->TextHeight(a);
bmp->Canvas->TextOutA(x+((x0-x1)>>1),y+((y0-y1)>>1),a);
// next char position
x+=x0;
} ty+=dty;
txt="Shadow/3D text";
bmp->Canvas->Brush->Style=bsClear;
bmp->Canvas->Font ->Size=tys;
bmp->Canvas->Font ->Color=c0;
for (i=0;i<5;i++)
bmp->Canvas->TextOutA(tx-i,ty+i,txt);
bmp->Canvas->Font ->Color=c1;
bmp->Canvas->TextOutA(tx,ty,txt); ty+=dty;
Graphics::TBitmap *tmp=new Graphics::TBitmap;
tmp->PixelFormat=pf32bit;
tmp->HandleType=bmDIB;
txt="Transparent";
tmp->Canvas->Brush->Style=bsSolid;
tmp->Canvas->Brush->Color=0x00000000; // max black
tmp->Canvas->Font ->Size=tys;
tmp->Canvas->Font ->Color=0x00808080; // color offset
x=bmp->Canvas->TextWidth(txt);
y=bmp->Canvas->TextHeight(txt);
tmp->SetSize(x,y);
tmp->Canvas->FillRect(TRect(0,0,x,y));
tmp->Canvas->TextOutA(0,0,txt);
union col { DWORD dd; BYTE db[4]; } *p0,*p1;
for (y0=0,y1=ty;y0<y;y0++,y1++)
{
p0=(col*)tmp->ScanLine[y0];
p1=(col*)bmp->ScanLine[y1];
for (x0=0,x1=tx;x0<x;x0++,x1++)
for (i=0;i<4;i++)
{
b=WORD(p0[x0].db[i])+WORD(p1[x1].db[i]);
if (b>255) b=255;
p1[x1].db[i]=b;
}
} ty+=dty;
txt="XOR";
tmp->Canvas->Brush->Style=bsSolid;
tmp->Canvas->Brush->Color=0x00000000; // max black
tmp->Canvas->Font ->Size=tys;
tmp->Canvas->Font ->Color=0x00FFFFFF; // max white
x0=bmp->Canvas->TextWidth(txt);
y0=bmp->Canvas->TextHeight(txt);
tmp->SetSize(x0,y0);
tmp->Canvas->FillRect(TRect(0,0,x0,y0));
tmp->Canvas->TextOutA(0,0,txt);
bmp->Canvas->CopyMode=cmSrcInvert;
bmp->Canvas->Draw(tx,ty,tmp); ty+=dty;
bmp->Canvas->CopyMode=cmSrcCopy;
delete tmp;
// render backbuffer
Main->Canvas->Draw(0,0,bmp);
_redraw=false;
}
现在选择一种与此平均颜色形成良好对比的颜色。例如,您可以使用简单的公式(255-r, 255-g, 255-b)
来获得对比色。但是,如果平均颜色接近于128-gray,则会失败,因此您需要特殊处理。
另一种方法是将平均颜色转换为HSL或HSV颜色空间,然后玩弄色调;例如,只需将其加上180,并/或反转“亮度”(值/亮度)。同样,您需要特殊处理灰度(饱和度接近0)情况。