【发布时间】:2014-04-02 13:45:18
【问题描述】:
我正在从 VCL 转换为 FMX。在 VCL 中,TBitmap 的 TCanvas 中有一个名为 FloodFill 的函数,它允许 TBitmap 的画布被特定颜色填充,直到在位图的画布上达到另一种特定颜色。
在 FMX 中是否有与此功能等效的功能?
【问题讨论】:
标签: delphi c++builder firemonkey vcl
我正在从 VCL 转换为 FMX。在 VCL 中,TBitmap 的 TCanvas 中有一个名为 FloodFill 的函数,它允许 TBitmap 的画布被特定颜色填充,直到在位图的画布上达到另一种特定颜色。
在 FMX 中是否有与此功能等效的功能?
【问题讨论】:
标签: delphi c++builder firemonkey vcl
根据 RRUZ 的回答和 Anthony 的回答,我做了这个代码:
Procedure TForm1.FloodFill(BitmapData:TBitmapData; X, Y:Integer; OldColor, NewColor: TAlphaColor);
var
Current: TAlphaColor;
begin
Current := BitmapData.GetPixel(X, Y);
if Current = OldColor then begin
BitmapData.SetPixel(X,Y,NewColor);
FloodFill(BitmapData, X+1, Y, OldColor, NewColor);
FloodFill(BitmapData, X-1, Y, OldColor, NewColor);
FloodFill(BitmapData, X, Y+1, OldColor, NewColor);
FloodFill(BitmapData, X, Y-1, OldColor, NewColor);
end;
end;
还有一个使用示例:
procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Single);
var
MyBmpData: TBitmapData;
OldColor, NewColor: TAlphaColor;
ix, iy: integer;
begin
Image1.Bitmap.Canvas.Bitmap.Map(TMapAccess.ReadWrite, MyBmpData);
ix := round(X); iy := Round(Y);
OldColor := MyBmpData.GetPixel(ix, iy);
NewColor := ColorComboBox1.Color; // or use some other source for a new color
FloodFill(MyBmpData, ix, iy, OldColor, NewColor) ;
Image1.Bitmap.Canvas.Bitmap.Unmap(MyBmpData);
end;
【讨论】:
FireMonkey 中没有等效的FloodFill 函数,但您可以使用可以填充的路径(TPathData)。所以你可以用要填充的形状定义一个路径,然后
用FMX.Graphics.TCanvas.FillPath做室内画。
【讨论】:
我转换了这个旧的填充代码(由 Jon Lennart Berg 发布)以支持 Firemonkey 位图:
https://groups.google.com/forum/#!topic/borland.public.delphi.graphics/84pyiclLTvg
procedure Bitmap_FloodFill(fBitmap: TBitmap; StartX,StartY : Integer; FillColor: TAlphaColor);
var
fBitmapData : TBitmapData;
X, Y : Integer;
ReplaceColor : TAlphaColor;
Stack : Array of TPoint;
fHeight : Integer;
fWidth : Integer;
procedure PutInStack(X, Y: Integer);
begin
SetLength(Stack, Length(Stack)+1);
Stack[Length(Stack)-1] := Point(X, Y);
end;
procedure GetFromStack(var X, Y: Integer);
begin
X := Stack[Length(Stack)-1].X;
Y := Stack[Length(Stack)-1].Y;
SetLength(Stack, Length(Stack)-1);
end;
begin
X := StartX;
Y := StartY;
fHeight := fBitmap.Height;
fWidth := fBitmap.Width;
if (X >= fWidth) or (Y >= fHeight) then Exit;
If fBitmap.Map(TMapAccess.ReadWrite,fBitmapData) then
Try
ReplaceColor := fBitmapData.GetPixel(X,Y);
If ReplaceColor <> FillColor then
Begin
PutInStack(X,Y);
While Length(Stack) > 0 do
Begin
GetFromStack(X,Y);
While (X > 0) and (fBitmapData.GetPixel(X-1, Y) = ReplaceColor) do Dec(X);
While (X < fWidth) and (fBitmapData.GetPixel(X , Y) = ReplaceColor) do
Begin
if Y > 0 then If fBitmapData.GetPixel(X, Y-1) = ReplaceColor then PutInStack(X, Y-1);
if Y+1 < fHeight then If fBitmapData.GetPixel(X, Y+1) = ReplaceColor then PutInStack(X, Y+1);
fBitmapData.SetPixel(X,Y,FillColor);
Inc(X);
End;
End;
End;
Finally
fBitmap.Canvas.Bitmap.Unmap(fBitmapData);
End;
end;
可以通过将 GetPixel/SetPixel 函数替换为扫描线和直接内存访问来优化此代码,但即使按原样,它对于大多数操作来说也足够快。
【讨论】: