2009-08-29 7 views

답변

16

당신은 TMemoryStream이에게 모두 비트 맵을 저장하고 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; 

이 코드의 X의 주사선 벤치 마크하지 않았다, 당신이 경우에, 우리가 가장 빠른 어느 알려 주시기 바랍니다.

+2

일부 의견 : 1) 코드는 예외로부터 안전하지 않습니다. 2) 비트 맵의 ​​너비 또는 높이가 다른 경우 즉시 False를 반환합니다. 또는 픽셀 형식이 다를지라도 질문이 너무 모호해서 말할 필요가 없습니다. – mghie

+0

좋은 댓글 mghie. 코드를 변경하여 높이와 너비를 테스트하십시오. –

+0

예외를 삼키는 것은 내가 의미했던 것이 아니었다. 코드를 편집하도록 허용했다 ... – mghie

0

정확한 답이 필요하면 아니오. 근사값이 필요한 경우 픽셀 선택을 확인할 수 있습니다. 그러나 두 비트 맵이 정확히 일치하는지 알아 보려면 전체 픽셀 및 픽셀 형식 데이터를 비교해야합니다.

11

TMemoryStream없이 ScanLine을 사용하십시오.

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; 

안녕히 계십시오.

+0

+1 매우 멋지게 작곡. 이 속도와 Cesar의 해를 비교하는 것은 흥미로울 것입니다. 이것은 더 많은 비교를하지만, 메모리를 할당하지 않음으로써 시간을 절약합니다. 질문 제목은 ** 가장 빠른 **를 지정했습니다. – Argalatyr

+1

@RRUZ : 동일한 비트 맵이 동일한 메모리 레이아웃 +1을 의미하는 경우 좋은 해결책이라는 데 동의합니다. 하지만 좀 더 흥미로운 문제가 될 수있는 서로 다른 형식의 동일한 비트 맵에 대한 빠른 검사를 고려해 볼 수 있습니다. pf24bit 또는 pf32bit 비트 맵의 ​​색상이 256보다 작 으면 pf8bit로 저장하는 것이 좋지만 동일한 비트 맵이 계속 표시됩니다. – mghie

+0

필자는 보통 pf8bit 만 사용하며이 경우에는 괜찮습니다. 만약 pf12bit와 홀수 너비가 있다면 정렬 비트가 검사되는지 궁금합니다. bpp가 8 세 미만인 경우와 동일하지만 afaik가 계획되어 있습니다. –

관련 문제