2009-08-29 13 views

risposta

16

È possibile salvare entrambe le bitmap a TMemoryStream e confrontarlo con CompareMem:

function IsSameBitmap(Bitmap1, Bitmap2: TBitmap): Boolean; 
var 
Stream1, Stream2: TMemoryStream; 
begin 
    Assert((Bitmap1 <> nil) and (Bitmap2 <> nil), 'Params can''t be nil'); 
    Result:= False; 
    if (Bitmap1.Height <> Bitmap2.Height) or (Bitmap1.Width <> Bitmap2.Width) then 
    Exit; 
    Stream1:= TMemoryStream.Create; 
    try 
    Bitmap1.SaveToStream(Stream1); 
    Stream2:= TMemoryStream.Create; 
    try 
     Bitmap2.SaveToStream(Stream2); 
     if Stream1.Size = Stream2.Size Then 
     Result:= CompareMem(Stream1.Memory, Stream2.Memory, Stream1.Size); 
    finally 
     Stream2.Free; 
    end; 
    finally 
    Stream1.Free; 
    end; 
end; 

begin 
    if IsSameBitmap(MyImage1.Picture.Bitmap, MyImage2.Picture.Bitmap) then 
    begin 
    // your code for same bitmap 
    end; 
end; 

non l'ho fatto riferimento questo codice X scanline, se lo fai, fatecelo sapere quale è il più veloce.

+2

Alcuni commenti: 1) Il codice non è sicuro per le eccezioni. 2) Vorrei restituire False immediatamente se la larghezza o l'altezza delle bitmap differiscono. O forse anche se i formati dei pixel differiscono, ma la domanda è troppo vaga da dire. – mghie

+0

commenti piacevoli mghie. Ill cambiare il codice per testare l'altezza e la larghezza. –

+0

Ingerire le eccezioni non era quello che intendevo, permettimi di modificare il codice ... – mghie

0

Se è necessaria una risposta precisa, no. Se hai bisogno di un'approssimazione, probabilmente potresti controllare una selezione di pixel. Ma se vuoi scoprire se i due bitmap sono esattamente identici devi confrontare l'intero pixel e i dati in formato pixel.

11

Utilizzo di ScanLine, senza TMemoryStream.

function IsSameBitmapUsingScanLine(Bitmap1, Bitmap2: TBitmap): Boolean; 
var 
i   : Integer; 
ScanBytes : Integer; 
begin 
    Result:= (Bitmap1<>nil) and (Bitmap2<>nil); 
    if not Result then exit; 
    Result:=(bitmap1.Width=bitmap2.Width) and (bitmap1.Height=bitmap2.Height) and (bitmap1.PixelFormat=bitmap2.PixelFormat) ; 

    if not Result then exit; 

    ScanBytes := Abs(Integer(Bitmap1.Scanline[1]) - Integer(Bitmap1.Scanline[0])); 
    for i:=0 to Bitmap1.Height-1 do 
    Begin 
    Result:=CompareMem(Bitmap1.ScanLine[i],Bitmap2.ScanLine[i],ScanBytes); 
    if not Result then exit; 
    End; 

end; 

Ciao.

+0

+1 molto ben composto. Sarebbe interessante confrontare la velocità di questa contro la soluzione di Cesar. Questo ha più confronti, ma consente di risparmiare tempo non allocare memoria. Il titolo della domanda ha specificato ** il più veloce **, dopo tutto. – Argalatyr

+1

@RRUZ: Sono d'accordo che questa è una buona soluzione se la stessa bitmap indica lo stesso layout di memoria, +1. Considererei un rapido controllo per bitmap uguali in formati possibilmente diversi per essere un problema più interessante, però. Se una bitmap pf24bit o pf32bit ha meno di 256 colori, può avere senso salvarla in pf8bit, ma la stessa bitmap verrà comunque visualizzata. – mghie

+0

Di solito uso solo pf8bit, e per questo sarebbe ok. Mi chiedo però se i bit di allineamento sono controllati se hai pf12bit e una larghezza dispari. Lo stesso per bpp è sotto l'8, ma quelli sono programmati afaik. –

Problemi correlati