如何在图像(Jpg,Bmp)或透明文本(颜色与背景图像相同)上书写半透明文本,但带阴影,我想用水印图像。
我想用Delphi win32来实现这个目标。
答案 0 :(得分:6)
一种选择是在Windows.pas单元中使用AlphaBlend函数。像这样的东西会产生半透明的文字(带有投影 - 建立在Jim McKeeth的回应上)覆盖在图像上:
uses Windows, Graphics;
.
.
.
var
BackgroundImage: Graphics.TBitmap; { need to call out specifically for Graphics.TBitmap
because the Windows unit also has a TBitmap
declaration }
TextImage: Graphics.TBitmap;
BlendFunc: BLENDFUNCTION;
begin
BlendFunc.BlendOp := AC_SRC_OVER;
BlendFunc.BlendFlags := 0;
BlendFunc.SourceConstantAlpha := $C0; { a hex value from $00-$FF (0-255).
Represents the percent of opaqueness:
$00 is completely transparent,
$FF is completely opaque.
$C0 is 75% opaque }
BlendFunc.AlphaFormat := AC_SRC_ALPHA;
{ BackgroundImage is for holding the image you want to overlay text onto }
BackgroundImage := Graphics.TBitmap.Create;
try
BackgroundImage.LoadFromFile('yourimagehere.bmp');
{ Create another TBitmap to hold the text you want to overlay }
TextImage := Graphics.TBitmap.Create;
try
{ Set this bitmap to have the same dimensions as the
background image you want the text to appear on. }
TextImage.Height := BackgroundImage.Height;
TextImage.Width := BackgroundImage.Width;
{ In my limited experience with AlphaBlend, Black is always 100%
transparent. So, paint TextImage completely Black. Play around
with this to see the effect it has on the final outcome. }
TextImage.Canvas.Brush.Color := clBlack;
TextImage.Canvas.FloodFill(0, 0, clNone, fsBorder);
TextImage.Canvas.Font.Style := [fsBold];
{ Write the shadow first }
TextImage.Canvas.Brush.Style := bsClear;
TextImage.Canvas.Font.Color := clDkGray;
TextImage.Canvas.TextOut(11, 11, 'Test');
{ Then put the text on top (slightly offset) }
TextImage.Canvas.Brush.Style := bsClear;
TextImage.Canvas.Font.Color := clMaroon;
TextImage.Canvas.TextOut(10, 10, 'Test');
{ Use the AlphaBlend function to overlay the bitmap holding the text
on top of the bitmap holding the original image. }
Windows.AlphaBlend(BackgroundImage.Canvas.Handle, 0, 0,
TextImage.Width, TextImage.Height,
TextImage.Canvas.Handle, 0, 0, TextImage.Width,
TextImage.Height, BlendFunc);
{ Assign the now updated BackgroundImage to a TImage control for display }
Image1.Picture.Bitmap.Assign(BackgroundImage);
finally
TextImage.Free;
end;
finally
BackgroundImage.Free;
end;
end;
答案 1 :(得分:3)
阴影很容易:
// Bold shows up better when over an image
image1.Canvas.Font.Style := [fsBold];
// Write the shadow first
image1.Canvas.Brush.Style:=bsClear;
image1.Canvas.Font.Color := clGrayText;
image1.Canvas.TextOut(1, 1, 'hi there');
// Then put the text on top (slightly offset)
image1.Canvas.Brush.Style:=bsClear;
image1.Canvas.Font.Color :=clBlack;
image1.Canvas.TextOut(0, 0, 'hi there');
这是具有透明背景的文字。或者您是否希望文本本身是透明的?这有点棘手。您需要手动绘制它。一种简单的方法是采样您在图像上书写的区域的平均颜色。然后将字体颜色设置得稍微亮一点,让阴影变暗一点。然后它融入了。
答案 2 :(得分:3)
我认为你想要完成的事情比简单地用透明背景写文字要复杂一些;即你试图在图像上写下某种形式的阿尔法混合文本 最简单的方法是使用GDI +例程。它们封装为delphi,可从http://www.progdigy.com/下载。有很多例子可以作为例子使用。
答案 3 :(得分:2)
我没有测试过,但它会让你知道该去哪里。关键是画笔风格。
类似的东西:
img.Canvas.Brush.Style:=bsClear;
img.Canvas.Font.Color:=clBlack;
img.Canvas.TextOut(0, 0, 'hi there');
答案 4 :(得分:2)
此功能基于Dave Elsberry的想法。
有什么不同:
procedure DrawShadowText(aCanvas: TCanvas; CONST Text: string; CONST X, Y, Opacity: Integer; TextColor, ShadowColor: TColor);
{ Opacity a value from 0-255:
$00 is completely transparent,
$FF is completely opaque.
$C0 is 75% opaque }
CONST ShadowSize= 1;
VAR
TempBMP: TBitmap;
BlendFunc: BLENDFUNCTION;
H, W: Integer;
begin
BlendFunc.BlendOp := AC_SRC_OVER;
BlendFunc.BlendFlags := 0;
BlendFunc.SourceConstantAlpha := Opacity;
BlendFunc.AlphaFormat := AC_SRC_ALPHA;
{ Create another TBitmap to hold the text you want to overlay }
TempBMP := Graphics.TBitmap.Create;
TRY
TempBMP.Canvas.Font.Style := [fsBold];
TempBMP.Canvas.Brush.Style := bsClear;
W:= TempBMP.Canvas.TextWidth(Text);
H:= TempBMP.Canvas.TextHeight(Text);
TempBMP.SetSize(W+ShadowSize, H+ShadowSize);
{ In AlphaBlend, Black is always 100% transparent. So, paint TempBMP completely Black. }
TempBMP.Canvas.Brush.Color := clBlack;
TempBMP.Canvas.FloodFill(0, 0, clNone, fsBorder);
{ Write the shadow first }
TempBMP.Canvas.Font.Color := ShadowColor;
TempBMP.Canvas.TextOut(ShadowSize, ShadowSize, Text); { Diagonal left shadow }
TempBMP.Canvas.TextOut(ShadowSize, 0, Text); { Left shadow }
{ Draw the text with transparency:
TempBMP.Canvas.Brush.Style := bsClear;
TempBMP.Canvas.Font.Color := TextColor;
TempBMP.Canvas.TextOut(0, 0, Text); }
{ Use the AlphaBlend function to overlay the bitmap holding the text on top of the bitmap holding the original image. }
Windows.AlphaBlend(aCanvas.Handle,
x, y, TempBMP.Width, TempBMP.Height,
TempBMP.Canvas.Handle, 0, 0, TempBMP.Width, TempBMP.Height,
BlendFunc);
{ Draw the text at 100% opacity }
aCanvas.Font.Style := [fsBold];
aCanvas.Brush.Style := bsClear;
aCanvas.Font.Color := TextColor;
aCanvas.TextOut(x, y-1, Text);
FINALLY
FreeAndNil(TempBMP);
END;
end;
procedure TfrmTest.UseIt;
VAR BackgroundImage: tbitmap;
begin
BackgroundImage := Graphics.TBitmap.Create;
try
BackgroundImage.LoadFromFile('c:\test.bmp');
DrawShadowText (BackgroundImage.Canvas, 'This is some demo text', 20, 40, 140, clRed, clSilver);
Image1.Picture.Bitmap.Assign(BackgroundImage);
FINALLY
BackgroundImage.Free;
end;
end;
答案 5 :(得分:1)
您可以使用bitblt例程将图像合并到公共画布,然后再次保存图像。
答案 6 :(得分:0)
改进的版本。可能比上一个慢一些,但看起来好多了:
{-------------------------------------------------------------------------------------------------------------
Text shadows
-------------------------------------------------------------------------------------------------------------}
{ Draws text in a semi-transparent rectangle with shadow text.
The shadow text is blended to the background and then blurred.
Parameters:
Opacity a value from 0-255. 0 => Shadow is completelly transparent
To set the Font color/size, the caller should do: aCanvas.Font.Size:= x
Issues:
The blurring function cuts to suddenly. The rectangle that was blurred is too visible. Do a blur that slowly fades at the edges.
Might be slow becuase of the alpha blending and because of the blur.}
procedure DrawTextShadowRect(aCanvas: TCanvas; CONST Text: string; X, Y: Integer; ShadowColor: TColor; ShadowOpacity: Byte);
{ Important! When the AlphaFormat member is AC_SRC_ALPHA, the source bitmap must be 32 bpp. If it is not, the AlphaBlend function will fail. }
VAR
Shadow: Vcl.Graphics.TBitmap;
BlendFunc: BLENDFUNCTION;
H, W: Integer;
OriginalColor: TColor;
R, R2: TRect;
CONST Edge= 5;
begin
OriginalColor:= aCanvas.Font.Color;
{ Write the shadow on a separate bitmap (overlay) }
Shadow := TBitmap.Create;
TRY
{ Assign font }
Shadow.Canvas.Font.Assign(aCanvas.Font);
Shadow.PixelFormat:= pf24bit;
{ Compute overlay size }
W:= Shadow.Canvas.TextWidth (Text);
H:= Shadow.Canvas.TextHeight(Text);
Shadow.SetSize(W, H);
{ Fill shadow rectangle }
R:= Rect(0, 0, Shadow.Width, Shadow.Height);
Shadow.Canvas.Brush.Color := clBlack; { In AlphaBlend, Black is always 100% transparent. So, paint Shadow completely Black. }
Shadow.Canvas.FillRect(R);
{ Blend rectangle with orig image } { Use the AlphaBlend function to overlay the bitmap holding the text on top of the bitmap holding the original image. }
BlendFunc.BlendOp := AC_SRC_OVER;
BlendFunc.BlendFlags := 0;
BlendFunc.SourceConstantAlpha := ShadowOpacity;
BlendFunc.AlphaFormat := 0; //AC_SRC_ALPHA;
WinApi.Windows.AlphaBlend(aCanvas.Handle, x, y, Shadow.Width, Shadow.Height, Shadow.Canvas.Handle, 0, 0, Shadow.Width, Shadow.Height, BlendFunc);
{ Copy the blended area back to the Shadow bmp }
R2:= rect(x, y, x+Shadow.Width, y+Shadow.Height);
Shadow.Canvas.CopyRect(R, aCanvas, R2);
{ Diagonal shadow }
Shadow.Canvas.Brush.Style:= bsClear;
Shadow.Canvas.Font.Color := ShadowColor;
Shadow.Canvas.TextOut(0, 0, Text);
{ Blur the shadow }
janFX.SplitBlur(Shadow, 1);
janFX.SplitBlur(Shadow, 1);
{ Paste it back }
aCanvas.CopyRect(R2, Shadow.Canvas, R);
FINALLY
FreeAndNil(Shadow);
END;
{ Draw actual text at 100% opacity }
aCanvas.Brush.Style:= bsClear;
aCanvas.Font.Color := OriginalColor;
aCanvas.TextOut(x, y, Text);
end;