水印在现代社会中常用,网上有各种制作水印的办法,而我要说的办法,实际上简单而且好理解,那就是制作半透明的 PNG 图片覆盖到原始项目上就可以了。至于为啥不说 FMX 的实现,是因为 FMX 本身各种颜色设置中就包含了透明度信息,不需要这么折腾了。
第一步:制作水印内容,比如我们创建一个TBitmap对象,在上面随便输出点文字,乐意的话,还可以旋转一下。这段代码咱们省略不提,毕竟没啥需要提及的东西,直接在 TBitmap 的 Canvas 组图就好。注意一点,一定要将背景和前景区分成不同的颜色,因为我们后面要将背景给透掉。
第二步:创建 TPngImage 对象,并利用 Assign 方法复制 TBitmap 实例的内容,我们假设背景是 clWhite,那么我们需要的就是:
1、调用 TPngImage 对象的 CreateAlpha 方法,为 TPngImage 实例创建 Alpha 通道。
2、循环每行,检查每个像素的颜色,如果与背景色相同,则将其对应的Alpha值调整为 0,这样就透过去了。如果不同,则修改为目标 Alpha 值(0-255,一般不要太高),通过 AlphaScanline 属性可以获取一个 Alpha 值数组。当然,如果有兴趣搞的复杂点,还可以对水印加上一些掩码,比如随机而已的空白点啥的。
嗯,总体的设计思路就是这样子。代码就不提供了,顺着思路写起来相信对大家来说并不难。发一个效果图吧:
function CreateWatermark(const AText, AFontName: String;
AFontSize, Alpha: Integer; AFontStyles: TFontStyles): TPngImage; overload;
var
Y: Integer;
ASize: TSize;
ABitmap: TBitmap;
X: Integer;
pAlpha: pByteArray;
AIsHole: Boolean;
begin
Result := TPngImage.Create;
ABitmap := TBitmap.Create;
try
ABitmap.SetSize(1, 1);
ABitmap.PixelFormat := TPixelFormat.pf24bit;
ABitmap.Canvas.Font.Name := AFontName;
ABitmap.Canvas.Font.Size := AFontSize;
ABitmap.Canvas.Font.Style := AFontStyles;
ASize := ABitmap.Canvas.TextExtent(AText);
ABitmap.SetSize(ASize.cx, ASize.cy);
ABitmap.Canvas.TextOut(0, 0, AText);
Result.Assign(ABitmap);
Result.CreateAlpha;
for Y := 0 to Result.Height – 1 do
begin
pAlpha := Result.AlphaScanline[Y];
for X := 0 to Result.Width – 1 do
begin
if Result.Pixels[X, Y] = clWhite then
pAlpha[X] := Byte(0)
else
begin
pAlpha[X] := Alpha;
end;
end;
end;
finally
FreeAndNil(ABitmap);
end;
end;