ame1011 Posted June 24, 2011 Posted June 24, 2011 Hi, I'm looking for a fast way to compare 2 hbitmap objects that are being returned by _ScreenCapture_Capture. All I need is a function with 2 input variables (the 2 hbitmaps) that returns a number that indictates the difference in the images. I've seen some examples of bitblt and prospeed but most is either image search or the input is vastly different than what I'm looking for. To be honest dll calls are a bit over my head. Can anyone point me in the right direction to either find/create a function like the one stated above? Thanks in advance [font="Impact"] I always thought dogs laid eggs, and I learned something today. [/font]
monoscout999 Posted June 25, 2011 Posted June 25, 2011 what return type do you want...? the number of different pixels?
junkew Posted June 25, 2011 Posted June 25, 2011 FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets
ame1011 Posted June 26, 2011 Author Posted June 26, 2011 As for the return type: I'm happy with any numeric value. I would determine a 'threshold' by trial and error and I would compare future images to ensure that they are over the threshold. [font="Impact"] I always thought dogs laid eggs, and I learned something today. [/font]
ame1011 Posted June 27, 2011 Author Posted June 27, 2011 Using modified code from the page linked by junkew, I have the following code: expandcollapse popup#include <GDIPlus.au3> #include <GDIPlusConstants.au3> #include <StructureConstants.au3> #include <WinAPI.au3> #include <ScreenCapture.au3> ; quick and dirty.... Global $stride, $ptr, $pixeldata global $bitmapfile1, $width1, $height1, $stride1, $pbitmap1 global $bitmapfile2, $width2, $height2, $stride2, $pbitmap2 local $numberdiff = 0 _ScreenCapture_SetJPGQuality(20) $pic1 = _ScreenCapture_Capture() Sleep(1000) $pic2 =_ScreenCapture_Capture() $timer = TimerInit() _GDIPlus_Startup() $pixelstruct1 = getbmpdata($pic1, $width1, $height1, $stride1, $pbitmap1) $pixelstruct2 = getbmpdata($pic2, $width2, $height2, $stride2, $pbitmap2) $length = DllStructGetSize($pixelstruct1) for $i=1 to $length $diff=dllstructgetdata($pixelstruct1,1,$i)-dllstructgetdata($pixelstruct2,1,$i) if $diff<>0 Then $numberdiff+=1 next ConsoleWrite(@CRLF & "Timer Diff: " & TimerDiff($timer)/1000 & " seconds." & @CRLF & "Difference: " & $numberdiff & @CRLF) _GDIPlus_Shutdown() Func getbmpdata($bmpfile, ByRef $width, ByRef $height, ByRef $stride, Byref $pbitmap) ;returns a struct with the data of the pixel $pbitmap = _GDIPlus_BitmapCreateFromHBITMAP($bmpfile) $BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF24RGB) If @error Then MsgBox(0, "", "Error locking region " & @error) $stride = DllStructGetData($BitmapData, "Stride");Stride - Offset, in bytes, between consecutive scan lines of the bitmap. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up. $width = DllStructGetData($BitmapData, "Width");Image width - Number of pixels in one scan line of the bitmap. $height = DllStructGetData($BitmapData, "Height");Image height - Number of scan lines in the bitmap. $Scan0 = DllStructGetData($BitmapData, "Scan0");Scan0 - Pointer to the first (index 0) scan line of the bitmap. $pixeldata = DllStructCreate("ubyte[" & (Abs($stride) * ($height)) & "]", $Scan0) $BMPData = DllStructGetData($pixeldata, 1) _WinAPI_DeleteObject($pbitmap) _GDIPlus_BitmapUnlockBits($pBitmap, $BmpData) return $pixeldata EndFunc ;==>getbmpdata Unfortunately this takes 14 seconds for a full-screen screenshot. I know I can reduce this by adding a 'Step' in the for loop, however I'd like to exhaust all other options before I do this. Basically, I'm looking to only save a screenshot if it is different from the last. Perhaps I'm looking at this the wrong way? Rather than comparing images maybe ignore images taken when windows is not doing any kind of window redraws? Anyone have any ideas? [font="Impact"] I always thought dogs laid eggs, and I learned something today. [/font]
monoscout999 Posted June 27, 2011 Posted June 27, 2011 (edited) I edited only a few adding some time checks... Theres no takes 14 seconds to take the screenshot it takes 14 seconds in compare the info data... also you forget_WinAPI_DeleteObject() to delete the HBITMAP Objects from the screenshots(i read that from the screenshot help)expandcollapse popup#include <GDIPlus.au3> #include <GDIPlusConstants.au3> #include <StructureConstants.au3> #include <WinAPI.au3> #include <ScreenCapture.au3> ; quick and dirty.... Global $stride, $ptr, $pixeldata global $bitmapfile1, $width1, $height1, $stride1, $pbitmap1 global $bitmapfile2, $width2, $height2, $stride2, $pbitmap2 local $numberdiff = 0 $timer = TimerInit() _ScreenCapture_SetJPGQuality(20) $pic1 = _ScreenCapture_Capture() Sleep(1000) $pic2 =_ScreenCapture_Capture() ConsoleWrite(@CRLF & "Timer Diff: " & TimerDiff($timer)/1000 & " seconds." & @CRLF) _GDIPlus_Startup() $pixelstruct1 = getbmpdata($pic1, $width1, $height1, $stride1, $pbitmap1) ConsoleWrite(@CRLF & "Timer Diff: " & TimerDiff($timer)/1000 & " seconds." & @CRLF) $pixelstruct2 = getbmpdata($pic2, $width2, $height2, $stride2, $pbitmap2) ConsoleWrite(@CRLF & "Timer Diff: " & TimerDiff($timer)/1000 & " seconds." & @CRLF) $length = DllStructGetSize($pixelstruct1) for $i=1 to $length $diff=dllstructgetdata($pixelstruct1,1,$i)-dllstructgetdata($pixelstruct2,1,$i) if $diff<>0 Then $numberdiff+=1 next ConsoleWrite(@CRLF & "Timer Diff: " & TimerDiff($timer)/1000 & " seconds." & @CRLF & "Difference: " & $numberdiff & @CRLF) _WinAPI_DeleteObject($pic1) _WinAPI_DeleteObject($pic2) _GDIPlus_Shutdown() Func getbmpdata($bmpfile, ByRef $width, ByRef $height, ByRef $stride, Byref $pbitmap) ;returns a struct with the data of the pixel $pbitmap = _GDIPlus_BitmapCreateFromHBITMAP($bmpfile) $BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF24RGB) If @error Then MsgBox(0, "", "Error locking region " & @error) $stride = DllStructGetData($BitmapData, "Stride");Stride - Offset, in bytes, between consecutive scan lines of the bitmap. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up. $width = DllStructGetData($BitmapData, "Width");Image width - Number of pixels in one scan line of the bitmap. $height = DllStructGetData($BitmapData, "Height");Image height - Number of scan lines in the bitmap. $Scan0 = DllStructGetData($BitmapData, "Scan0");Scan0 - Pointer to the first (index 0) scan line of the bitmap. $pixeldata = DllStructCreate("ubyte[" & (Abs($stride) * ($height)) & "]", $Scan0) $BMPData = DllStructGetData($pixeldata, 1) _WinAPI_DeleteObject($pbitmap) _GDIPlus_BitmapUnlockBits($pBitmap, $BmpData) return $pixeldata EndFunc ;==>getbmpdataPD: If You anyway want more speed in pixel function, maybe you would try this UDF Edited June 27, 2011 by monoscout999
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now