Is there a better way than examine them pixel by pixel?
Asked
Active
Viewed 4,327 times
9
-
1Please clarify: If they have different pixel formats (for example pf24bit and pf8bit) and therefore different sizes in memory, but contain the exact same pixels, are they the same or not? – mghie Aug 29 '09 at 20:58
3 Answers
17
You can save both Bitmaps to TMemoryStream and compare using 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;
I did not benchmark this code X scanline, if you do, please let us know which one is the fastest.

mghie
- 32,028
- 6
- 87
- 129

Cesar Romero
- 4,027
- 1
- 25
- 44
-
2Some comments: 1) Code isn't exception-safe. 2) I would return False immediately if width or height of the bitmaps differ. Or maybe even if the pixel formats differ, but the question is too vague to tell. – mghie Aug 29 '09 at 21:35
-
Nice comments mghie. Ill change the code to test the height and width. – Cesar Romero Aug 29 '09 at 21:46
-
I dont think I can "allow" others to edit my posts, if I can, please let me know how. If you post here your suggestions I can edit and mention in my post. – Cesar Romero Aug 29 '09 at 21:53
-
I just edited it, but wanted to alert you before. +1 for the answer BTW. – mghie Aug 29 '09 at 21:55
-
-
-
mghie's comment above asks whether matching pixel format is a specification, but it's easy to add as illustrated in RRUZ's answer. – Argalatyr Aug 30 '09 at 01:47
-
1Strictly speaking, such compares can go wrong when one of the bitmaps has a bit garbage in the alignment bytes/bits between lines. Therefore we always compare the pixeldata with comparemem on a per line basis. – Marco van de Voort Aug 30 '09 at 09:25
-
It would also be interesting to benchmark it against loop tiling. See an example for rotate at http://stackoverflow.com/questions/848025/rotating-bitmaps-in-code Back then I was quite surprised by the speedup, but that example also writes to an image. – Marco van de Voort Apr 05 '16 at 07:50
-
Stack Overflow wouldn't have provided an option for users to edit other users' answers if it wasn't allowed. It's actually highly encouraged. – Jerry Dodge May 17 '18 at 06:09
14
Using ScanLine, Without 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;
Bye.

RRUZ
- 134,889
- 20
- 356
- 483
-
+1 very nicely composed. It would be interesting to compare the speed of this versus Cesar's solution. This has more comparisons, but saves time by not allocate memory. The question title did specify **fastest**, after all. – Argalatyr Aug 30 '09 at 01:45
-
1@RRUZ: I agree that this is a good solution if same bitmap means the same memory layout, +1. I'd consider a fast check for equal bitmaps in possibly different formats to be a more interesting problem, though. If a pf24bit or pf32bit bitmap has less than 256 colours it can make sense to save it in pf8bit, but the same bitmap will still be displayed. – mghie Aug 30 '09 at 06:46
-
I usually only use pf8bit, and for this it would be ok. I wonder though if alignment bits are checked if you have pf12bit and an odd width. Same for bpp's below 8, but those are planed afaik. – Marco van de Voort Aug 30 '09 at 09:28
0
If you need an accurate answer, no. If you need an approximation, you probably could check a selection of pixels. But if you want to find out if the two bitmaps are exactly identical you need to compare the entire pixel and pixel format data.

Tommy Andersen
- 7,165
- 1
- 31
- 50