![]() // Ein
TPngImage wird partiell eingefärbt, wobei eine bestimmte Toleranz
uses System.Generics.Collections, System.Types; procedure PngFloodFill(Bild: TPngImage; X, Y: Integer; oldCol, newCol: TColor; Toleranz: Byte); const s = 100 / 255; var Queue: TQueue<TPoint>; Entn, Ent, CrtPt: TPoint; Line: Pointer; r, g, b, rn, gn, bn: Byte; function prozent(p: Pointer; X: Integer): Boolean; begin result := (abs(b - PRGBLine(Line)^[X].rgbtBlue) * s <= Toleranz) and (abs(g - PRGBLine(Line)^[X].rgbtGreen) * s <= Toleranz) and (abs(r - PRGBLine(Line)^[X].rgbtRed) * s <= Toleranz); end; function gleich(X, Y: Integer): Boolean; begin Line := Bild.Scanline[Y]; result := (PRGBLine(Line)^[X].rgbtBlue = bn) and (PRGBLine(Line)^[X].rgbtGreen = gn) and (PRGBLine(Line)^[X].rgbtRed = rn); end; function drin(X, Y: Integer): Boolean; begin Line := Bild.Scanline[Y]; result := prozent(Line, X); end; procedure doit(X, Y: Integer); begin Line := Bild.Scanline[Y]; PRGBLine(Line)^[X].rgbtBlue := bn; PRGBLine(Line)^[X].rgbtGreen := gn; PRGBLine(Line)^[X].rgbtRed := rn; end; begin oldCol := ColorToRGB(oldCol); newCol := ColorToRGB(newCol); r := GetRValue(oldCol); g := GetGValue(oldCol); b := GetBValue(oldCol); rn := GetRValue(newCol); gn := GetGValue(newCol); bn := GetBValue(newCol); Queue := TQueue<TPoint>.Create; Queue.Enqueue(Point(X, Y)); while (Queue.Count > 0) do begin Ent := Queue.Dequeue; if not drin(Ent.X, Ent.Y) or gleich(Ent.X, Ent.Y) then continue; Entn := Ent; CrtPt := TPoint.Create(Ent.X + 1, Ent.Y); while (Entn.X >= 0) and drin(Entn.X, Entn.Y) do begin doit(Entn.X, Entn.Y); if ((Entn.Y > 0) and drin(Entn.X, Entn.Y - 1)) then Queue.Enqueue(TPoint.Create(Entn.X, Entn.Y - 1)); if (Entn.Y < Bild.Height - 1) and drin(Entn.X, Entn.Y + 1) then Queue.Enqueue(TPoint.Create(Entn.X, Entn.Y + 1)); dec(Entn.X); end; while (CrtPt.X <= Bild.Width - 1) and drin(CrtPt.X, CrtPt.Y) do begin doit(CrtPt.X, CrtPt.Y); if (CrtPt.Y > 0) and drin(CrtPt.X, CrtPt.Y - 1) then Queue.Enqueue(TPoint.Create(CrtPt.X, CrtPt.Y - 1)); if (CrtPt.Y < Bild.Height - 1) and drin(CrtPt.X, CrtPt.Y + 1) then Queue.Enqueue(TPoint.Create(CrtPt.X, CrtPt.Y + 1)); inc(CrtPt.X); end; end; Queue.free; end; // Beispielaufruf für PngFloodFill procedure TForm1.Button1Click(Sender: TObject); var png: TPngImage; p1, p2: TPoint; begin p1 := Point(90, 225); p2 := Point(70, 205); png := TPngImage.CreateBlank(COLOR_RGB, 8, Image1.Picture.Width, Image1.Picture.Height); png.Canvas.Draw(0, 0, Image1.Picture.Graphic); PngFloodFill(png, p1.X, p1.Y, png.Canvas.Pixels[p1.X, p1.Y], clAqua, 35); PngFloodFill(png, p2.X, p2.Y, png.Canvas.Pixels[p2.X, p2.Y], clLime, 40); Image1.Picture.Assign(png); FreeAndNil(png); end; // Vergleich mit FloodFill procedure TForm1.Button2Click(Sender: TObject); var png: TPngImage; p1, p2: TPoint; begin p1 := Point(90, 225); p2 := Point(70, 205); png := TPngImage.CreateBlank(COLOR_RGB, 8, Image2.Picture.Width, Image2.Picture.Height); png.Canvas.Draw(0, 0, Image2.Picture.Graphic); png.Canvas.Brush.Color := clAqua; png.Canvas.FloodFill(p1.X, p1.Y, png.Canvas.Pixels[p1.X, p1.Y], fsSurface); png.Canvas.Brush.Color := clLime; png.Canvas.FloodFill(p2.X, p2.Y, png.Canvas.Pixels[p2.X, p2.Y], fsSurface); Image2.Picture.Assign(png); FreeAndNil(png); end;
|
|||||
![]()
Zugriffe seit
6.9.2001 auf Delphi-Ecke |