【发布时间】:2018-02-22 13:17:16
【问题描述】:
我正在尝试使用代码创建具有 alpha 透明度的 TImage。 在这个例子中,一个消除锯齿的圆圈。
我为圆创建了一个 8 位不透明度贴图,然后使用这段代码将其应用到 TImage 的 TBitmap:
type
TOpacityMap = Array[0..4095] of PByteArray;
procedure DrawAntiAliasedCircle(srcBitmap: TBitmap; FillColor : TAlphaColor; CenterX, CenterY, Radius, LineWidth, Feather: single);
var
FillR : Integer;
FillG : Integer;
FillB : Integer;
FillRGB : Integer;
OpacityMap : TOpacityMap;
AlphaScanLine : Array[0..4095] of TAlphaColor;
bitmapData : FMX.Graphics.TBitmapData;
tmpScanLine : Pointer;
X,Y : Integer;
tmpMS : TMemoryStream;
begin
{Initialization}
FillR := TAlphaColorRec(FillColor).R;
FillG := TAlphaColorRec(FillColor).G;
FillB := TAlphaColorRec(FillColor).B;
CreateAntiAliasedCircleOpacityMap(OpacityMap, srcBitmap.Width, srcBitmap.Height, CenterX, CenterY, Radius, LineWidth, Feather);
{create image based on opacity map and free memory}
If srcBitmap.Map(TMapAccess.Write, bitmapData) then
try
FillRGB := (FillR shl 16)+(FillG shl 8)+FillB;
for Y := 0 to srcBitmap.Height-1 do
begin
for X := 0 to srcBitmap.Width-1 do
AlphaScanLine[X] := (OpacityMap[Y][X] shl 24)+FillRGB; // Opacity
tmpScanLine := bitmapData.GetScanline(Y);
AlphaColorToScanLine(@AlphaScanLine,tmpScanLine,srcBitmap.Width,srcBitmap.PixelFormat);
FreeMem(OpacityMap[Y]);
end;
finally
srcBitmap.Unmap(bitmapData);
end;
// Work-around fix
{tmpMS := TMemoryStream.Create;
srcBitmap.SaveToStream(tmpMS);
srcBitmap.LoadFromStream(tmpMS);
tmpMS.Free;}
end;
结果是左边的图像。 实际的 TBitmap 似乎不错,调用“srcBitmap.SaveToFile('circle.png')”会生成一个带有有效 alpha 通道的 PNG 文件。
我可以通过简单地使用 TMemoryStream 保存/加载位图来解决这个问题。
如何在右侧获得所需的图像,而不会因通过 TMemoryStream 传递图像而造成性能损失?
这些屏幕截图来自演示此问题的最小示例项目:
https://github.com/bLightZP/AntiAliasedCircle
编辑#1:
上面链接的 github 代码已更新为 Tom Brunberg 建议修复的优化(大约快 25%)版本。
【问题讨论】:
标签: delphi firemonkey alphablending alpha-transparency