2009-08-29 40 views

Respuesta

16

Puede guardar ambos mapas de bits a TMemoryStream y compara usando 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; 

no lo hice referencia este código X línea de escaneo, si lo hace, por favor sepamos cuál es el más rápido.

+2

Algunos comentarios: 1) El código no es a prueba de excepciones. 2) Devolvería False inmediatamente si el ancho o la altura de los mapas de bits difieren. O tal vez incluso si los formatos de píxeles difieren, pero la pregunta es demasiado vaga para contar. – mghie

+0

Nice comentarios mghie. Cambiaré el código para probar la altura y el ancho. –

+0

Tragar excepciones no era lo que quise decir, permitirme editar el código ... – mghie

0

Si necesita una respuesta precisa, no. Si necesita una aproximación, probablemente pueda verificar una selección de píxeles. Pero si quiere saber si los dos mapas de bits son exactamente idénticos, necesita comparar los datos de formato de píxel y píxel completos.

11

Uso de ScanLine, sin 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; 

Adiós.

+0

+1 muy bien compuesto. Sería interesante comparar la velocidad de esta versus la solución de Cesar. Esto tiene más comparaciones, pero ahorra tiempo al no asignar memoria. El título de la pregunta especificó ** más rápido **, después de todo. – Argalatyr

+1

@RRUZ: Estoy de acuerdo en que esta es una buena solución si el mismo mapa de bits significa el mismo diseño de memoria, +1. Sin embargo, consideraría que un control rápido para mapas de bits iguales en formatos posiblemente diferentes sea un problema más interesante. Si un mapa de bits pf24bit o pf32bit tiene menos de 256 colores, puede tener sentido guardarlo en pf8bit, pero seguirá mostrándose el mismo mapa de bits. – mghie

+0

Normalmente solo uso pf8bit, y para esto estaría bien. Sin embargo, me pregunto si los bits de alineación están marcados si tienes pf12bit y un ancho impar. Lo mismo para bpp's por debajo de 8, pero esos están planeados afaik. –

Cuestiones relacionadas