Sign in to follow this  
Followers 0
ender02

Find differences between 2 pics

2 posts in this topic

Hi all!

I wanted to improve a formal script, but i got some problems with it.

My purpose is, that i have 2 jpeg pictures in the buffer --> (of course without saves, it was just for checking the process)

#include <array.au3>
#Include <WinAPI.au3>
#include <constants.au3>
#include <windowsconstants.au3>
#include <guiconstantsEx.au3>
#include <GDIPlus.au3>
#include <misc.au3>
#include <ScreenCapture.au3>

HotKeySet("{PAUSE}", "TogglePause")
HotKeySet("{ESC}", "Terminate")
Global $Paused

Opt('MustDeclareVars', 1)

_Main()

Func _Main()
    Local $hBitmap1, $hBitmap2, $hImage1, $hImage2

    ; Initialize GDI+ library
    _GDIPlus_Startup ()

    ; Capture full screen
    $hBitmap1 = _ScreenCapture_Capture ("" ,0,0,1024,768,False)
    $hImage1 = _GDIPlus_BitmapCreateFromHBITMAP ($hBitmap1)

    ; Capture screen region
    $hBitmap2 = _ScreenCapture_Capture ("" ,0,0,1024,768,False)
    $hImage2 = _GDIPlus_BitmapCreateFromHBITMAP ($hBitmap2)

    ; Save resultant image
    _GDIPlus_ImageSaveToFile ($hImage1, @MyDocumentsDir & "\SS_1.jpg")
    _GDIPlus_ImageSaveToFile ($hImage2, @MyDocumentsDir & "\SS_2.jpg")

    ; Clean up resources
    _GDIPlus_ImageDispose ($hImage1)
    _GDIPlus_ImageDispose ($hImage2)
    _WinAPI_DeleteObject ($hBitmap1)
    _WinAPI_DeleteObject ($hBitmap2)

    ; Shut down GDI+ library
    _GDIPlus_ShutDown ()

EndFunc   ;==>_Main


;;;;;;;;;;;;;;;;;;;;;
Func Terminate()
    Exit 0
EndFunc

Func TogglePause()
    $Paused = NOT $Paused
    While $Paused
        sleep(0)
        ToolTip('Script is "Paused"',0,0)
    WEnd
    ToolTip("")
EndFunc

So, i want to search for the first difference between these 2 pictures. I don't need all of them, it's slow...

I found this script to improve to that what i need. The problem is, that this one is REALLY slow... and i don't know where to start with.

#include <GDIPlus.au3>
#include <GDIPlusConstants.au3>
#include <StructureConstants.au3>
#include <WinAPI.au3>
; quick and dirty....
Global $stride, $ptr, $pixeldata
global $bitmapfile1, $width1, $height1, $stride1, $pbitmap1
global $bitmapfile2, $width2, $height2, $stride2, $pbitmap2
local  $numberdiff  = 0  ;number of differences between the 2 pics


$pic1 = "earth1.jpg" ;the image....24bit per pixel, could be a JPG
$pic2 = "earth2.jpg"
$pic3 = "difference.bmp"  ;a bitmapfile with the differences

_GDIPlus_Startup()
$pixelstruct1   = getbmpdata($pic1, $width1, $height1, $stride1, $pbitmap1)  ;get all data from the 2 files
$pixelstruct2   = getbmpdata($pic2, $width2, $height2, $stride2, $pbitmap2)

$lenght         = DllStructGetSize($pixelstruct1) ;get lenght of bitmapdata
$pixelstruct3   = dllstructcreate("ubyte["&$lenght&"]")
;compare
 for $i=1 to $lenght
    ; consolewrite (dllstructgetdata($pixelstruct1,1,$i)&"   "&dllstructgetdata($pixelstruct1,1,$i)&@crlf)
    $diff=dllstructgetdata($pixelstruct1,1,$i)-dllstructgetdata($pixelstruct2,1,$i)  ;difference"colour" between the bytes
    if $diff<>0 Then        ;bytes are different
        $numberdiff+=1      ;count
        dllstructsetdata($pixelstruct3,1,$diff,$i)  ;write the difference into the difference-file, bottom-up isnt funny but we´ll mirror it later :o)
    endif
next


$head=DllStructcreate("ubyte[54]")
;lets create a bitmapfile with the given data
$Bmpheader = DllStructCreate("align 1;char BM[2];uint Size;uint res;uint Offset;uint BMHI;uint Width;uint Height;short Planes;short BPP;uint BIcomp;int SizeImg;uint reshor;uint resver;uint col;uint colused", dllstructgetptr($head)) ;struct of bytes = header of bitmap #1
;fill struct(bitmapheader) with data
DllStructSetData($bmpheader,"BM","BM")
DllStructSetData($bmpheader,"Size",54+$lenght)
DllStructSetData($bmpheader,"Offset",54)
DllStructSetData($bmpheader,"BMHI",40)
DllStructSetData($bmpheader,"Width",$width1)
DllStructSetData($bmpheader,"Height",-$height1)  ;negativ because "bottom up"
DllStructSetData($bmpheader,"Planes",1)
DllStructSetData($bmpheader,"BPP",24)
DllStructSetData($bmpheader,"BIcomp",0)
DllStructSetData($bmpheader,"SizeImg",$lenght)

$header     = dllstructgetdata($head,1) ;headerdata
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $header = ' & $header & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
$pixeldata  = stringtrimleft(DllStructGetData($pixelstruct3, 1),2) ;pixeldata
$bitmap     = $header&$pixeldata  ;all together is the bitmap-file

$filehandle = FileOpen($pic3, 18) ;write file
FileWrite($filehandle,BinaryToString($bitmap))
FileClose($filehandle)

_GDIPlus_ImageDispose($pBitmap1)  ;not in the function, because ImageDispose destroys the struct
_GDIPlus_ImageDispose($pBitmap2)


;lets have a look what we have done...
GUICreate("Difference pixel",800,500)
GUICtrlCreatePic($pic1, 10, 10, 170, 170 / $width1 * $height1)
GUICtrlCreatePic($pic2, 200, 10, 170, 170 / $width2* $height2)
GUICtrlCreatePic($pic3, 400, 10, 170, 170 / $width2* $height2)
GUISetState()

Do
Until GUIGetMsg() = -3

Func getbmpdata($bmpfile, ByRef $width, ByRef $height, ByRef $stride, Byref $pbitmap) ;returns a struct with the data of the pixel
    $pbitmap = _GDIPlus_BitmapCreateFromFile($bmpfile)
    ;_GDIPlus_BitmapLockBits gibt $tagGDIPBITMAPDATA-Struktur zurück
    $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.
    ;$pixelFormat = DllStructGetData($BitmapData, "PixelFormat");Pixel format - Integer that specifies the pixel format of 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)
    ;_GDIPlus_ImageDispose($pBitmap) ;destroys the pixeldatastruct, have to be done at end of the script!
    return $pixeldata
EndFunc   ;==>getbmpdata

Any help is appreciated!

Of course i already searched for many scripts, also read almost all of the manuals, just tell me plz, where should i edit the getbmpdata function. Cause i think i have all of the data i need of the 2 jpeg pictures, i need to make then struct for it? or the _BitMapCreateFromHBITMAP is also enough for it, now i just have to search for the differences? And do i need this ddlstruct thing? :S

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

http://www.autoitscript.com/forum/index.php?showtopic=117579&st=0&p=819259&hl=bitblt&fromsearch=1&#entry819259

http://www-igm.univ-mlv.fr/~lecroq/string/index.html

Approach 1.search for bitblt functions to merge the 2 pics together. Everything equal will be black

Approach 2. Based on what you already have do either

a. compare line by line

b. compare first byte1 to byte1 then double length compare and compare byte2-4 with byte2-4 so you minimize comparisons and balance on speed

c. first compare all bytes. If not equal split the string in 2 and do the same for the first half and so on till you are in the right spot

Edited by junkew

Share this post


Link to post
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
Sign in to follow this  
Followers 0