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