Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Antialiasing (https://www.delphipraxis.net/8744-antialiasing.html)

Sanchez 11. Sep 2003 10:02


Antialiasing
 
hallo erstmal,

Ich habe eine Funktion fürs Antialiasing auf einem Canvas aufgetrieben.

Delphi-Quellcode:
procedure Antialiasing(C: TCanvas; Rect: TRect; Percent: Integer);
var
  l, p: Integer;
  R, G, B: Integer;
  R1, R2, G1, G2, B1, B2: Byte;
begin
  with c do
  begin
    Brush.Style := bsclear;
    for l := Rect.Top to Rect.Bottom do begin
      for p := Rect.Left to Rect.Right do begin
        R1 := GetRValue(Pixels[p, l]);
        G1 := GetGValue(Pixels[p, l]);
        B1 := GetBValue(Pixels[p, l]);

        //Pixel links
        //Pixel left
        R2 := GetRValue(Pixels[p - 1, l]);
        G2 := GetGValue(Pixels[p - 1, l]);
        B2 := GetBValue(Pixels[p - 1, l]);

        if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin
          R := Round(R1 + (R2 - R1) * 50 / (Percent + 50));
          G := Round(G1 + (G2 - G1) * 50 / (Percent + 50));
          B := Round(B1 + (B2 - B1) * 50 / (Percent + 50));
          Pixels[p - 1, l] := RGB(R, G, B);
        end;

        //Pixel rechts
        //Pixel right
        R2 := GetRValue(Pixels[p + 1, l]);
        G2 := GetGValue(Pixels[p + 1, l]);
        B2 := GetBValue(Pixels[p + 1, l]);

        if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin
          R := Round(R1 + (R2 - R1) * 50 / (Percent + 50));
          G := Round(G1 + (G2 - G1) * 50 / (Percent + 50));
          B := Round(B1 + (B2 - B1) * 50 / (Percent + 50));
          Pixels[p + 1, l] := RGB(R, G, B);
        end;

        //Pixel oben
        //Pixel up
        R2 := GetRValue(Pixels[p, l - 1]);
        G2 := GetGValue(Pixels[p, l - 1]);
        B2 := GetBValue(Pixels[p, l - 1]);

        if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin
          R := Round(R1 + (R2 - R1) * 50 / (Percent + 50));
          G := Round(G1 + (G2 - G1) * 50 / (Percent + 50));
          B := Round(B1 + (B2 - B1) * 50 / (Percent + 50));
          Pixels[p, l - 1] := RGB(R, G, B);
        end;

        //Pixel unten
        //Pixel down
        R2 := GetRValue(Pixels[p, l + 1]);
        G2 := GetGValue(Pixels[p, l + 1]);
        B2 := GetBValue(Pixels[p, l + 1]);

        if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin
          R := Round(R1 + (R2 - R1) * 50 / (Percent + 50));
          G := Round(G1 + (G2 - G1) * 50 / (Percent + 50));
          B := Round(B1 + (B2 - B1) * 50 / (Percent + 50));
          Pixels[p, l + 1] := RGB(R, G, B);
        end;
      end;
    end;
  end;
end;
Allerdings ist der Code ziemlich langsam. Hat jemand eine Idee wie ich ihn perfomanter machen kann?

grüße, daniel

Blechwolf 11. Sep 2003 10:38

Re: Antialiasing
 
Salut,

auf den ersten Blick würde ich schauen, ob Du die Round-Funktion evtl durch was selber geschriebens ersetzen kannst. Das ist nämlich (afaik) ein ziemlicher Performance Killer.
Habe aber im Augenblick keine wirklich sinnvolle Idee, das Ding zu umgehen.

Grüße

Blechwolf

sakura 11. Sep 2003 10:45

Re: Antialiasing
 
Und Nummer zwei ist der Zugriff auf Pixels. Der ist zwar unabhängig vom aktuellen PixelFormat aber sehr, sehr langsam. Besser ist es mit ScanLine zu arbeiten.

...:cat:...

Sanchez 11. Sep 2003 12:05

Re: Antialiasing
 
Wahnsinn was das gebracht hat.
Danke Leute

Hier der neue Algo

Delphi-Quellcode:
procedure Antialiasing(Bitmap: TBitmap; Rect: TRect; Percent: Integer);
var
  pix, prevscan, nextscan, hpix: ^PixArray;
  l, p: Integer;
  R, G, B: Integer;
  R1, R2, G1, G2, B1, B2: Byte;
begin
  Bitmap.PixelFormat := pf24bit;
  with Bitmap.Canvas do begin
    Brush.Style := bsclear;
    for l := Rect.Top to Rect.Bottom - 1 do begin
      pix:= Bitmap.ScanLine[l];
      if l <> Rect.Top then prevscan := Bitmap.ScanLine[l-1]
      else prevscan := nil;
      if l <> Rect.Bottom - 1 then nextscan := Bitmap.ScanLine[l+1]
      else nextscan := nil;

      for p := Rect.Left to Rect.Right - 1 do begin
        R1 := pix^[3];
        G1 := pix^[2];
        B1 := pix^[1];

        if p <> Rect.Left then begin
          //Pixel links
          //Pixel left

          hpix := pix;
          dec(hpix);
          R2 := hpix^[3];
          G2 := hpix^[2];
          B2 := hpix^[1];

          if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin
            R := R1 + (R2 - R1) * 50 div (Percent + 50);
            G := G1 + (G2 - G1) * 50 div (Percent + 50);
            B := B1 + (B2 - B1) * 50 div (Percent + 50);
            hpix^[3] := R;
            hpix^[2] := G;
            hpix^[1] := B;
          end;
        end;

        if p <> Rect.Right - 1 then begin
          //Pixel rechts
          //Pixel right
          hpix := pix;
          inc(hpix);
          R2 := hpix^[3];
          G2 := hpix^[2];
          B2 := hpix^[1];

          if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin
            R := R1 + (R2 - R1) * 50 div (Percent + 50);
            G := G1 + (G2 - G1) * 50 div (Percent + 50);
            B := B1 + (B2 - B1) * 50 div (Percent + 50);
            hpix^[3] := R;
            hpix^[2] := G;
            hpix^[1] := B;
          end;
        end;

        if prevscan <> nil then begin
          //Pixel oben
          //Pixel up
          R2 := prevscan^[3];
          G2 := prevscan^[2];
          B2 := prevscan^[1];

          if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin
            R := R1 + (R2 - R1) * 50 div (Percent + 50);
            G := G1 + (G2 - G1) * 50 div (Percent + 50);
            B := B1 + (B2 - B1) * 50 div (Percent + 50);
            prevscan^[3] := R;
            prevscan^[2] := G;
            prevscan^[1] := B;
          end;
          Inc(prevscan);
        end;

        if nextscan <> nil then begin
          //Pixel unten
          //Pixel down
          R2 := nextscan^[3];
          G2 := nextscan^[2];
          B2 := nextscan^[1];

          if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin
            R := R1 + (R2 - R1) * 50 div (Percent + 50);
            G := G1 + (G2 - G1) * 50 div (Percent + 50);
            B := B1 + (B2 - B1) * 50 div (Percent + 50);
            nextscan^[3] := R;
            nextscan^[2] := G;
            nextscan^[1] := B;
          end;
          Inc(nextscan);
        end;
        Inc(pix);
      end;
    end;
  end;
end;
Noch kurz eine Frage zu den Scanlines:
scanline^[3] ist Rot
scanline^[2] ist Grün
scanline^[1] ist Blau

Sehe ich das richtig?

sakura 11. Sep 2003 12:21

Re: Antialiasing
 
Es sollte nicht 1-3 sondern 0-2 sein ;-)
Pix[0]-blau
Pix[1]-grün
Pix[2]-rot

...:cat:...

Sanchez 11. Sep 2003 12:56

Re: Antialiasing
 
Noch was hinten nach (vor allem für mich, sollte ich das hier in Zukunft wieder lesen)

Nie das PixelFormat dem Zufall überlassen

Ich glaube jetzt hab ichs kapiert :firejump:

Stanlay Hanks 18. Okt 2003 20:25

Re: Antialiasing
 
Hallo! Ich wollte gerade diese Prozedur mal so Copy&Paste mäßig ausprobieren, weil mich das interessiert hat. Allerdings kriege ich in der 3. Zeile bei pix, prevscan, nextscan, hpix: ^PixArray; einen Fehler, dass ^PixArray undefiniert ist. In der Tat hab ich da keinerlei deklaration gefunden. Kann mir da wer mal auf die Schnelle helfen?

Danke, man liest sich, Stanlay :hi:

Sanchez 18. Okt 2003 20:29

Re: Antialiasing
 
Sorry, hier hab ichs vergessen. Bei der Version in der Code Lib ists dabei. Guckst du hier

grüße, daniel

Stanlay Hanks 18. Okt 2003 20:32

Re: Antialiasing
 
Oh. :oops: Ich hab nicht gewusst, dass das auch in der Code Lib steht. Auf jeden Fall vielen Dank für die schnelle Antwort! :hello:

Man liest sich, Stanlay :hi:


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:25 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz