Jump to content

CompareBitmaps get nbr of different pixel


lJoel
 Share

Recommended Posts

Hi

Is there a fast way to get the number of different pixel / colors from this code:

Func CompareBitmaps($bm1, $bm2)
    
    $Bm1W = _GDIPlus_ImageGetWidth($bm1)
    $Bm1H = _GDIPlus_ImageGetHeight($bm1)
    $BitmapData1 = _GDIPlus_BitmapLockBits($bm1, 0, 0, $Bm1W, $Bm1H, $GDIP_ILMREAD, $GDIP_PXF32RGB)
    $Stride = DllStructGetData($BitmapData1, "Stride")
    $Scan0 = DllStructGetData($BitmapData1, "Scan0")
    
    $ptr1 = $Scan0
    $size1 = ($Bm1H - 1) * $Stride + ($Bm1W - 1) * 4
    
    $Bm2W = _GDIPlus_ImageGetWidth($bm2)
    $Bm2H = _GDIPlus_ImageGetHeight($bm2)
    $BitmapData2 = _GDIPlus_BitmapLockBits($bm2, 0, 0, $Bm2W, $Bm2H, $GDIP_ILMREAD, $GDIP_PXF32RGB)
    $Stride = DllStructGetData($BitmapData2, "Stride")
    $Scan0 = DllStructGetData($BitmapData2, "Scan0")
    
    $ptr2 = $Scan0
    $size2 = ($Bm2H - 1) * $Stride + ($Bm2W - 1) * 4
    
    $smallest = $size1
    If $size2 < $smallest Then $smallest = $size2
        
    $call = DllCall("msvcrt.dll", "int:cdecl", "memcmp", "ptr", $ptr1, "ptr", $ptr2, "int", $smallest)
    
    _GDIPlus_BitmapUnlockBits($bm1, $BitmapData1)
    _GDIPlus_BitmapUnlockBits($bm2, $BitmapData2)
    
    Return ($call[0]=0)
    
    
EndFunc  ;==>CompareBitmaps

Cheers

Joe

Link to comment
Share on other sites

Whats the end goal of your comparison?

The answers can be different based on your end goal

Just checking if they are equal or do you want to now the locations of the differences.?

Search for BITBLT in the forum or on GOOGLE for general solutions in other languages with SRCINVERT which should give you some directions.

http://www.codeproject.com/KB/graphics/BitmapCompare.aspx

http://www.codeproject.com/KB/GDI-plus/comparingimages.aspx

http://www.allegro.cc/forums/thread/587792/616685#target

Be prepared for padding issues on line(s) if you do have bitmaps of different sources. This could be especially the case as you are using memcmp to do the comparison.

http://www.autoitscript.com/forum/index.php?showtopic=66545&hl=findbmp&st=0 will give you some directions including other links manipulating with bitmaps

Link to comment
Share on other sites

This example returns the number of pixels that do not have the same pixel value at corresponding coordinates of two images.

Playing around with your function, CompareBitmaps(), using my script, CompareBitmaps() returned False when there was only one pixel different, and, returned True when the same image was compared in a .bmp file format and a .png file format. This means that CompareBitmaps() worked well.

#include <GDIPlus.au3>
#include <Array.au3>
;Opt("MustDeclareVars", 1) ;0=no, 1=require pre-declare

Local $hImage1, $iX, $iY, $hImage2, $iIW, $iIH, $bm1, $bm2

_GDIPlus_Startup()
$hImage1 = _GDIPlus_ImageLoadFromFile("testplus2.bmp")
$iX = _GDIPlus_ImageGetWidth($hImage1)
$iY = _GDIPlus_ImageGetHeight($hImage1)

$hImage2 = _GDIPlus_ImageLoadFromFile("test.bmp")
$iIW = _GDIPlus_ImageGetWidth($hImage2)
$iIH = _GDIPlus_ImageGetHeight($hImage2)

$bm1 = _GDIPlus_BitmapCloneArea($hImage1, 0, 0, $iX, $iY, $GDIP_PXF32ARGB)
$bm2 = _GDIPlus_BitmapCloneArea($hImage2, 0, 0, $iIW, $iIH, $GDIP_PXF32ARGB)

MsgBox(0, "Results", "Number of different pixels is " & CompareBitmapPixels($bm1, $bm2) & @CRLF)

_GDIPlus_BitmapDispose($bm1)
_GDIPlus_BitmapDispose($bm2)
_GDIPlus_ImageDispose($hImage1)
_GDIPlus_ImageDispose($hImage2)
_GDIPlus_Shutdown()

Func CompareBitmapPixels($bm1, $bm2)
    Local $Bm1W, $Bm1H, $BitmapData1, $Scan0, $Bm2W, $BitmapData2, $Bm2H
    Local $Scan01, $iNum = 0, $iDiff = 0, $v_BufferA, $AllPixels
    Local $sREResult1, $aArray, $v_BufferB, $AllPixelsB, $sREResult2, $aArray2
    $Bm1W = _GDIPlus_ImageGetWidth($bm1)
    $Bm1H = _GDIPlus_ImageGetHeight($bm1)
    $BitmapData1 = _GDIPlus_BitmapLockBits($bm1, 0, 0, $Bm1W, $Bm1H, $GDIP_ILMREAD, $GDIP_PXF32RGB)
    $Scan0 = DllStructGetData($BitmapData1, "Scan0")

    $Bm2W = _GDIPlus_ImageGetWidth($bm2)
    $Bm2H = _GDIPlus_ImageGetHeight($bm2)
    $BitmapData2 = _GDIPlus_BitmapLockBits($bm2, 0, 0, $Bm2W, $Bm2H, $GDIP_ILMREAD, $GDIP_PXF32RGB)
    $Scan01 = DllStructGetData($BitmapData2, "Scan0")

    ; =============
    $v_BufferA = DllStructCreate("byte[" & $Bm1H * $Bm1W * 4 & "]", $Scan0) ; Create DLL structure for all pixels
    $AllPixels = DllStructGetData($v_BufferA, 1)
    $sREResult1 = StringRegExpReplace(StringTrimLeft($AllPixels, 2), "(.{8})", "\1 ")
    $aArray = StringSplit(StringStripWS($sREResult1, 3), " ")

    $v_BufferB = DllStructCreate("byte[" & $Bm2H * $Bm2W * 4 & "]", $Scan01) ; Create DLL structure for all pixels
    $AllPixelsB = DllStructGetData($v_BufferB, 1)
    $sREResult2 = StringRegExpReplace(StringTrimLeft($AllPixelsB, 2), "(.{8})", "\1 ")
    $aArray2 = StringSplit(StringStripWS($sREResult2, 3), " ")
    $iDiff = Abs($aArray2[0] - $aArray[0])
    For $i = 1 To UBound($aArray) - 1 - $iDiff
        If $aArray2[$i] <> $aArray[$i] Then $iNum += 1
    Next
    ; =============

    _GDIPlus_BitmapUnlockBits($bm1, $BitmapData1)
    _GDIPlus_BitmapUnlockBits($bm2, $BitmapData2)

    Return $iNum + $iDiff
EndFunc ;==>CompareBitmapPixels

The help with finding images to compare, I ran this script a couple of times to create slightly different image files.

#include <GDIPlus.au3>
; http://www.autoitscript.com/forum/index.php?s=&showtopic=78645&view=findpost&p=567998
_GDIPlus_Startup()

$h_bitmap = _WinAPI_CreateBitmap(150, 150, 1, 32)
$h_image = _GDIPlus_BitmapCreateFromHBITMAP($h_bitmap)
$h_graphic = _GDIPlus_ImageGetGraphicsContext($h_image)
_GDIPlus_GraphicsClear($h_graphic, 0xFF808080)

For $line = 20 To 40
    For $col = 10 To 110
        _GDIPlus_BitmapSetPixel($h_image, $col, $line, 0xFFFF0000)
    Next
Next

For $line = 60 To 80
    For $col = 10 To 110
        _GDIPlus_BitmapSetPixel($h_image, $col, $line, 0x00FF0000)
    Next
Next

_GDIPlus_BitmapSetPixel($h_image, 1, 1, 0xFF0000FF); 
_GDIPlus_BitmapSetPixel($h_image, 3, 1, 0xFFFFFFFF)

_GDIPlus_ImageSaveToFile($h_image, "testPlus2.bmp")
ShellExecute("testPlus2.bmp")

_GDIPlus_ImageDispose($h_image)
_WinAPI_DeleteObject($h_bitmap)
_GDIPlus_Shutdown()

Func _GDIPlus_BitmapSetPixel($hBitmap, $iX, $iY, $iArgb)
    Local $aRet
    $aRet = DllCall($ghGDIPDll, "dword", "GdipBitmapSetPixel", "hwnd", $hBitmap, "int", $iX, "int", $iY, "dword", $iArgb)
    Return
EndFunc ;==>_GDIPlus_BitmapSetPixel
Edited by Malkey
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...