【问题标题】:What is the fastest way to check if two Tbitmaps are the same?检查两个 Tbitmap 是否相同的最快方法是什么?
【发布时间】:2010-11-24 01:13:19
【问题描述】:

有没有比逐像素检查更好的方法?

【问题讨论】:

  • 请澄清:如果它们具有不同的像素格式(例如 pf24bit 和 pf8bit),因此在内存中的大小不同,但包含完全相同的像素,它们是否相同?

标签: delphi delphi-2009


【解决方案1】:

如果您需要准确的答案,请不要。如果您需要近似值,您可能可以检查选择的像素。但是如果你想知道这两个位图是否完全相同,你需要比较整个像素和像素格式数据。

【讨论】:

    【解决方案2】:

    您可以将两个位图保存到 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 扫描线进行基准测试,如果你这样做了,请告诉我们哪一个是最快的。

    【讨论】:

    • 一些 cmets:1) 代码不是异常安全的。 2) 如果位图的宽度或高度不同,我会立即返回 False。或者即使像素格式不同,但问题太模糊,无法分辨。
    • 不错的 cmets mghie。我将更改代码以测试高度和宽度。
    • 我不认为我可以“允许”其他人编辑我的帖子,如果可以,请告诉我如何。如果您在此处发布您的建议,我可以在帖子中进行编辑和提及。
    • 我刚刚编辑了它,但之前想提醒你一下。顺便说一句,+1 答案。
    • 严格来说,当其中一个位图在行之间的对齐字节/位中有位垃圾时,此类比较可能会出错。因此,我们总是逐行比较像素数据和 comparemem。
    【解决方案3】:

    使用 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 的解决方案进行比较会很有趣。这有更多的比较,但通过不分配内存来节省时间。毕竟,问题标题确实指定了最快
    • @RRUZ:我同意这是一个很好的解决方案,如果相同的位图意味着相同的内存布局,+1。不过,我认为快速检查可能不同格式的相同位图是一个更有趣的问题。如果 pf24bit 或 pf32bit 位图的颜色少于 256 种,则可以将其保存在 pf8bit 中,但仍会显示相同的位图。
    • 我一般只用pf8bit,这样就可以了。我想知道如果您有 pf12bit 和奇数宽度,是否会检查对齐位。低于 8 的 bpp 也是如此,但这些都是计划好的。
    猜你喜欢
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    • 2010-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多