AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi [Erledigt] BitmapCompare nicht zuverlässig / Scanline Problem?
Thema durchsuchen
Ansicht
Themen-Optionen

[Erledigt] BitmapCompare nicht zuverlässig / Scanline Problem?

Ein Thema von berens · begonnen am 24. Jan 2019 · letzter Beitrag vom 24. Jan 2019
 
berens

Registriert seit: 3. Sep 2004
441 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: BitmapCompare nicht zuverlässig / Scanline Problem?

  Alt 24. Jan 2019, 19:17
Danke für die Antworten.

Das ScanLine-Beispiel habe ich auch zur Verifizierung meines Codes verwendet; ich kann nichts erkennen, was ich falsch gemacht hätte.

Zitat:
Na ja Du vergleichst Äpfel mit Birnen......
Nunja, hier muss ich doch Einspruch erheben. Trotzdem erstmal danke, dass Du Dich mit dem Thema auseinandersetzt.
Man muss natürlich berücksichtigen, dass der Code aus dem Anhang zur Verdeutlichung angepasst und erweitert wurde, was in der fertigen Version natürlich so nicht sein soll. Doch zum eigentlichen Thema:

Delphi-Quellcode:
// Hier vergleichst Du Byte......
    if Pix1[x] <> Pix2[x] then begin
Das hier ist der Code, der in der fertigen Version verwendet werden soll. Beide Bitmaps sind im Pixelformat 32-Bit, entsprechend sollte Pix1[x] ein 4 Byte langer Wert sein (jede Farbe R G B und der Alphakanal; jeweils ein Byte). Somit kann ich imo durchaus sagen: Wenn Bild1[x] = Bild2[x], dann sind die Farben Rot, Grün, Blau und der Alpha Wert auf beiden Seiten identisch. Halten wir das erstmal so fest: Ich vergleiche vergleichbare Werte, und erhalte das Ergebnis: Die Farben auf beiden Bildern sind 1:1 identisch.

Delphi-Quellcode:
        end else begin // bedeutet Pix1[x] = Pix2[x]
          c1 := pic1.Canvas.Pixels[x,y];
          c2 := pic2.Canvas.Pixels[x,y];
// und hier Integer
          if c1 <> c2 then begin
An dieser Stelle muss man betonen, dass es nur die detaillierte Fehlersuche darstellt. Das Else bedeutet ja automatisch in diesem Zusammenhang "Pix1[x] = Pix2[x]". Das bedeutet wiederum: der Pixel in Bild1 ist 1:1 identisch mit dem Pixel in Bild2.
Nun lese ich mit (der exorbitant langsamen) Funktion "Pixels" die Farbe (TColor) genau der selben Pixel aus, die ich eben schon mit Scanline geprüft habe. ScanLine sagte ja, dass genau dieser Pixel in Bild 1 und 2 jeweils für R, G, B und A den Wert "0" hat, und somit auf beiden Bildern identisch ist (in beiden Bildern "Schwarz", obwohl eigentlich in Bild 2 "grün"). c1 besagt nun: in Bild 1 ist der Pixel Schwarz (korrekt) und: in Bild 2 ist dieser Pixel grün (korrekt).

Durch die Verschachtelung der Anweisungen habe ich im Endeffekt die Abfrage "Sind die Pixel auf beiden Bildern identisch? (Scanline-Verfahren)" und "Sind die Pixel auf beiden Bildern identisch? (Pixel-Verfahren)". Beide Abfragen müssen korrekterweise das gleiche ausgeben, tun sie aber nicht - ScanLine liefert eine falsche Antwort.

Das Vergleichsverfahren kann ich nicht komplett auf die "Pixels"-Prüfung umstellen, da diese viel zu langsam ist; ich muss mit ScanLine Arbeiten. Das Pixelsverfahren ist hier nur einprogrammiert, um den Fehler von Scanline "nachweisen" zu können.

Also: Was mache ich an ScanLine falsch?

Zwecks lesbarkeit, hier nochmal die aktuelle Version:
Delphi-Quellcode:
function BitmapCompare(pic1, pic2: Graphics.Tbitmap): Boolean;
var
  Pix1, Pix2 : PByte;
  y, k, x : Integer;
  c1, c2: TColor;
const
  PixelFormatBytes: Array[TPixelFormat] of Byte = ( 0, 0, 0, 1, 0, 2, 3, 4, 0 );
begin
  result:=false;
  try
    if PixelFormatBytes[pic1.PixelFormat] <> PixelFormatBytes[pic2.PixelFormat] then Exit;
    if PixelFormatBytes[pic1.PixelFormat] = 0 then Exit; // PixelFormat wird nicht unterstützt
    if (pic1.Width <> pic2.Width) or (pic1.Height <> pic2.Height) then Exit;

    for y := 0 to pic2.Height - 1 do
    begin
      Pix1 := pic1.Scanline[y];
      Pix2 := pic2.Scanline[y];
      for x := 0 to pic2.Width - 1 do begin

        if (x = 4) and (y = 0) then begin
          c1 := pic1.Canvas.Pixels[4,0];
          c2 := pic2.Canvas.Pixels[4,0];
          sleep(0);
        end;

        if Pix1[x] <> Pix2[x] then begin
          Exit; // ungleich, verlasse deshalb routine. Result ist in diesem Falle = False ...
        end else begin // bedeutet Pix1[x] = Pix2[x]
          c1 := pic1.Canvas.Pixels[x,y];
          c2 := pic2.Canvas.Pixels[x,y];
          if c1 <> c2 then begin
            ShowMessage('ACHTUNG: Farbe unterschiedlich, obwohl Scanline angeblich identisch???'
                        + #13#10#13#10 + IntToStr(c1) + ' // ' + IntToStr(c2));
          end;
        end;

      end;
    end;
    Result := true;
  except
    on E: SysUtils.Exception do begin
    end;
  end;
end;
Delphi 10.4 32-Bit auf Windows 10 Pro 64-Bit, ehem. Delphi 2010 32-Bit auf Windows 10 Pro 64-Bit
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:49 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz