比较屏幕截图并获得第一个像素变化的屏幕坐标

时间:2013-03-06 14:56:52

标签: delphi

我有一个接一个的截屏,几秒钟的差距。我正在比较两个图像,并试图找出它们之间是否存在任何差异。如果存在任何差异,我需要更改该像素的屏幕坐标。

我可以使用Delphi实现这一目标吗?

1 个答案:

答案 0 :(得分:8)

如果要比较两个位图,并且需要找到第一个不同像素的位置,则可以迭代位图行,为两个位图的每一行获取位图像素数组,比较它们,如果不是匹配,找到不同像素的水平位置。在代码中它可能如下所示:

function CompareBitmaps(ABitmap1, ABitmap2: TBitmap;
  var ADiffPixel: TPoint): Boolean;
var
  X, Y: Integer;
  Size: Integer;
  Pixels1, Pixels2: PByteArray;
begin
  // first check if both bitmaps match in size and pixel format
  Result := (ABitmap1.PixelFormat = ABitmap2.PixelFormat) and
    (ABitmap1.Width = ABitmap2.Width) and (ABitmap1.Height = ABitmap2.Height);
  // if so, then...
  if Result then
  begin
    // assign the size of one pixel
    case ABitmap1.PixelFormat of
      pf24bit: Size := SizeOf(TRGBTriple);
      pf32bit: Size := SizeOf(TRGBQuad);
    else
      raise Exception.Create('Bitmap must be 24-bit or 32-bit format!');
    end;
    // iterate all the bitmap rows    
    for Y := 0 to ABitmap1.Height - 1 do
    begin
      // get pointer to pixel data array of the same row for both bitmaps
      Pixels1 := ABitmap1.ScanLine[Y];
      Pixels2 := ABitmap2.ScanLine[Y];
      // compare those pixel data arrays; if they differ, then...
      if not CompareMem(Pixels1, Pixels2, ABitmap1.Width * Size) then
      begin
        // return negative result
        Result := False;
        // assign vertical pixel position to the output ADiffPixel parameter
        ADiffPixel.Y := Y;
        // iterate the current row to find a different pixel; after it's found
        // the pixel's horizontal position is stored to the output ADiffPixel
        // parameter; the pixel array is treated as a byte array, so there's
        // need to be a division by the pixel size
        for X := 0 to ABitmap1.Width * Size - 1 do
          if (Pixels1[X] <> Pixels2[X]) then
          begin
            ADiffPixel.X := X div Size;
            Exit;
          end;
      end;
    end;
  end
  else
    raise Exception.Create('Bitmaps must match in size and pixel format!');
end;

示例用法:

procedure TForm1.Button1Click(Sender: TObject);
var
  PixelPos: TPoint;
begin
  if CompareBitmaps(Image1.Picture.Bitmap, Image2.Picture.Bitmap, PixelPos) then
    ShowMessage('Bitmaps are the same!')
  else
    ShowMessage('Bitmaps are different! The first different pixel was found ' +
      'at [' + IntToStr(PixelPos.X) + '; ' + IntToStr(PixelPos.Y) + '].');
end;