有没有更好的方法,而不是逐个像素地检查它们?检查两个Tbitmap是否相同的最快方法是什么?
回答
可以节省位图到内存流和使用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扫描线,如果你这样做,请让我们知道哪一个是最快的。
如果你需要一个准确的答案,没有。如果你需要一个近似值,你可能会检查一个像素的选择。但是如果你想知道两个位图是否完全相同,你需要比较整个像素和像素格式的数据。
使用ScanLine,无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;
再见。
+1非常好地组成。比较这个与Cesar的解决方案的速度会很有趣。这有更多的比较,但通过不分配内存节省时间。问题标题确实指定了**最快的**,毕竟。 – Argalatyr 2009-08-30 01:45:00
@RRUZ:我同意这是一个很好的解决方案,如果相同的位图意味着相同的内存布局+1。尽管如此,我认为尽快检查可能不同格式的相同位图是一个更有趣的问题。如果pf24bit或pf32bit位图的颜色少于256色,则将其保存为pf8bit是合理的,但仍会显示相同的位图。 – mghie 2009-08-30 06:46:26
我通常只使用pf8bit,为此可以。我想知道如果对齐位被检查,如果你有pf12bit和一个奇数的宽度。 bpp的8以下同样,但是这些都是计划的afaik。 – 2009-08-30 09:28:58
请说明:如果它们具有不同的像素格式(例如pf24bit和pf8bit),因此内存大小不同,但包含完全相同的像素,它们是否相同? – mghie 2009-08-29 20:58:34