MasonMill Posted July 23, 2010 Posted July 23, 2010 Hey guys, Whats he best and most quickly computed way of creating an array of a bitmap image? like a 2D matrix. How would i set it up? Just need pointedin the right direction, thanks for the help! -Mason
Yoriz Posted July 23, 2010 Posted July 23, 2010 Link: is there a function for reading images into 2d arrays? GDIPlusDispose - A modified version of GDIPlus that auto disposes of its own objects before shutdown of the Dll using the same function Syntax as the original.EzMySql UDF - Use MySql Databases with autoit with syntax similar to SQLite UDF.
MasonMill Posted July 23, 2010 Author Posted July 23, 2010 Awesome, how can i display the matrices so i can compare different ones? Everyone keeps telling me consolewrite but i cant ever figure out how to view it.
JohnOne Posted July 23, 2010 Posted July 23, 2010 #include <Array.au3> _ArrayDisplay($aArray) AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans.
AndyG Posted July 24, 2010 Posted July 24, 2010 (edited) i dont know what you want to do, but writing "pixel" into an array to compare 2 Pic´s to get the difference is one of the slowest things ever....A much faster way to compare two Bitmaps is shown here (Pictures needed are in the first post of the thread)A very fast way to compare is using _WinApi_BitBlt(). The Example shows the result of blitting two pics with the several $iROP-Parameterexpandcollapse popup#include <GDIPlus.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> #include <StructureConstants.au3> #include <GDIConstants.au3> ;#include <Misc.au3> _GDIPlus_Startup() ;no manipulating with gdi+ in this script, but it´s easy to load files other than bmp... $picfile1 = "earth1.jpg" ;get them from here http://www.autoitscript.com/forum/index.php?showtopic=106815&view=findpost&p=753759 $picfile2 = "earth2.jpg" $hgui = GUICreate("Example for comparing 2 pic´s with _winapi_bitblt()", 500, 200) ;create a gui $lsource1 = GUICtrlCreateLabel($picfile1, 10, 35, 100, 30) ; some labels and a button... $lsource2 = GUICtrlCreateLabel($picfile2, 150, 35, 100, 30) $lresult = GUICtrlCreateLabel("Result", 350, 35, 200, 30) $lblittingtime = GUICtrlCreateLabel("Blitting", 10, 165, 300, 30) $lmethod = GUICtrlCreateLabel("Combine the two pics with iROP-Method #", 10, 10, 250, 20) $button = GUICtrlCreateButton("Next iROP", 350, 5, 100) ;button to choose the next method to combine 2 pics ;$hGUI1 = GUICreate("DESTINATION", 100, 100, 0, 0) ;we could save the destination into an other window or into a file ;$pic1=GUICtrlCreatePic($picfile1,10,60,200,200) ;we dont need that, we could "blit" the pics into the window.... ;$pic2=GUICtrlCreatePic($picfile2,250,60,200,200) $hdc_gui = _WinAPI_GetDC($hgui) ;device context of the window GUISetState(@SW_SHOW, $hgui) ;get a DeviceContext from the bitmap-file, if alphachannel is not needed, 24Bit saves 25% ram and is faster when searching or manipulating pixels^^ Local $pointer1, $pointer2 ;no need for them in this script, but the variables are used ByRef $hdc_pic1 = _getdcfromfile32($picfile1, $pointer1) ;pointer is the pointer to the bitmapdata, if you want to manipulate pixels $hdc_pic2 = _getdcfromfile32($picfile2, $pointer2) ;pointer is the pointer to the bitmapdata, if you want to manipulate pixels _WinAPI_BitBlt($hdc_gui, 10, 60, 100, 100, $hdc_pic1, 0, 0, $SRCCOPY) ;"copy" the pic into the gui, remember, we don´t need the gui to manipulate the pics _WinAPI_BitBlt($hdc_gui, 150, 60, 100, 100, $hdc_pic2, 0, 0, $SRCCOPY) ;because we don´t want to destroy the pics (overwrite), we "paint" into a Buffer, so we have to create a new bitmap Local $pointer_buffer ;we dont need this variable in this script, pointer to the pixeldata ;this variable is used ByRef Local $hbmp_buffer ;no need to do something with gdi+ , but this variable is used ByRef Local $iwidth_buffer = 100 ;size of the buffer, we need width and height of the pics, but i am lazy... Local $iheight_buffer = 100 ;...could get them with _GDIPlus_ImageGetWidth()....but lazyness^^ $hdc_buffer = _CreateNewBmp32($iwidth_buffer, $iheight_buffer, $pointer_buffer, $hbmp_buffer) ;returns all what you need, a DC, a pointer to the 32Bit-"pixels", and a handle to use with gdi+ Dim $iRop[20] ;see the helpfile for _winapi_bitblt $iRop[0] = $BLACKNESS ;- Füllt das Ziel-Rechteck mit der Farbe, die mit dem Paletten-Index 0 verknüpft ist $iRop[1] = $CAPTUREBLT ;- Inkludiert jegliche Fenster, die das eigene Fenster überlagern in das resultierende Bild $iRop[2] = $DSTINVERT ;- Invertiert die Farben des Ziel-Rechtecks (umkehren) $iRop[3] = $MERGECOPY ;- Mischt die Farben des Quell-Rechtecks mit dem in hDest aktuell gewähltem Füllmuster (Brush), unterVerwendung des AND Operators. $iRop[4] = $MERGEPAINT ;- Mischt die invertierten Farben des Quell-Rechtecks mit den Farben des Ziel-Rechtecks unter Verwendung des OR Operators. $iRop[5] = $NOMIRRORBITMAP ;- Verhindert das spiegeln der Bitmap $iRop[6] = $NOTSRCCOPY ;- Kopiert das invertierte Quell-Rechteck ins Ziel-Rechteck $iRop[7] = $NOTSRCERASE ;- Kombiniert die Farben des Quell- und Ziel-Rechtecks unter Verwendung des OR Operators undinvertiert dann die daraus resultierenden Farben. $iRop[8] = $PATCOPY ;- Kopiert das in hdcDest gewählte Füllmuster in die Ziel-Bitmap $iRop[9] = $PATINVERT ;- Kombiniert die Farben des Quell-Rechtecks mit dem in hDest aktuell gewähltem Füllmuster, mit den Farben desZiel-Rechtecks unter Verwendung des XOR Operators. $iRop[10] = $PATPAINT ;- Kombiniert die Farben des in hDest aktuell gewähltem Füllmusters, mit den Farben desinvertiertem Quell-Rechtecks unter Verwendung des OR Operators. Das Resultat dieser Operation wird wiederum mit den Farbendes Ziel-Rechtecks kombiniert, unter Verwendung des OR Operators. $iRop[11] = $SRCAND ;- Kombiniert die Farben des Quell- und Ziel-Rechtecks unter Verwendung des AND Operators $iRop[12] = $SRCCOPY ;- Kopiert das Quell-Rechteck direkt ins Ziel-Rechteck $iRop[13] = $SRCERASE ;- Kombiniert die invertierten Farben des Ziel-Rechtecks mit den Farben des Quell-Rechtecks unter Verwendung des AND Operators. $iRop[14] = $SRCINVERT ;- Kombiniert die Farben des Quell- und Ziel-Rechtecks unter Verwendung des XOR Operators $iRop[15] = $SRCPAINT ;- Kombiniert die Farben des Quell- und Ziel-Rechtecks unter Verwendung des OR Operators $iRop[16] = $WHITENESS ;- Füllt das Ziel-Rechteck mit der Farbe, die mit dem Index 1 in der PhysikalischenPalette verknüpft ist. While 1 For $i = 0 To 16 ;from the first iROP to the last _WinAPI_BitBlt($hdc_gui, 10, 60, 100, 100, $hdc_pic1, 0, 0, $SRCCOPY) ;"copy" the pic into the gui, _WinAPI_BitBlt($hdc_gui, 150, 60, 100, 100, $hdc_pic2, 0, 0, $SRCCOPY) ;someone could move the window or minimize it GUICtrlSetData($lmethod, "Combine the two pics with iROP-Method #" & $i) ;set label $t = TimerInit() ;save timestamp ;we want to combine the two pics with each of the $iROP-methods _WinAPI_BitBlt($hdc_buffer, 0, 0, 200, 200, $hdc_pic1, 0, 0, $SRCCOPY) ;copy the pic1 into the buffer _WinAPI_BitBlt($hdc_buffer, 0, 0, 200, 200, $hdc_pic2, 0, 0, $iRop[$i]) ;use a method to combine pic1 with pic2 ;at this time, "comparing" is done! Because we have all the data, i.e. pointer to the "pixeldata" we could count different pixels (because they are not black) or something else ;blitting is done awsome fast(depending on CPU and bus), lets see how fast it is.. $m = TimerDiff($t) GUICtrlSetData($lblittingtime, StringFormat("Time to blt the two pics: %.4f milliseconds", $m)) ;set label _WinAPI_BitBlt($hdc_gui, 350, 60, 100, 100, $hdc_buffer, 0, 0, $SRCCOPY) ;copies the buffer into the window to show what we have done Do ;exit or button pressed? $msg = GUIGetMsg() If $msg = -3 Then _Exit() ;end of program Until $msg = $button ;if button pressed, move on... Next WEnd Func _exit() _DeleteBitmap32($hdc_pic1, $pointer1, 0) _DeleteBitmap32($hdc_pic2, $pointer2, 0) _DeleteBitmap32($hdc_buffer, $pointer_buffer, $hbmp_buffer) _GDIPlus_Shutdown() Exit EndFunc ;==>_exit ;~ filedelete("ergebnis.jpg") ;~ $t=timerinit() ;~ Local $hCDC = _WinAPI_CreateCompatibleDC($hpic1dc) ;~ Local $hBMP = _WinAPI_CreateCompatibleBitmap($hpic1dc, 100, 100) ;~ ;ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hpic1dc = ' & $hpic1dc & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console ;~ _WinAPI_SelectObject($hCDC, $hBMP) ;~ _WinAPI_BitBlt($hCDC, 0, 0, 100,100, $hpic1dc, 0,0, $SRCCOPY) ;~ _WinAPI_ReleaseDC($hgui1, $hpic1dc) ;~ _WinAPI_DeleteDC($hCDC) ;~ _ScreenCapture_SaveImage("ergebnis.jpg", $hBMP) ;~ $m=timerdiff($t) ;~ ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $m = ' & $m & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console ;~ shellexecute("ergebnis.jpg") ;~ _GDIPlus_GraphicsDispose($hGraphic1) ;~ _GDIPlus_GraphicsDispose($hGraphic2) ;~ _GDIPlus_ImageDispose($himg1) ;~ _GDIPlus_ImageDispose($hBild) ;~ _GDIPlus_GraphicsReleaseDC($hGraphic1,$hpic1dc) ;~ _GDIPlus_GraphicsReleaseDC($hGraphic2,$hSrcDC) ;~ _GDIPlus_Shutdown() Func _getDCfromfile32($bmpfile, ByRef $ptr) ;ptr to bitmapdata, it is possible to manipulate one pixel if needed Local $hbitmap = _GDIPlus_BitmapCreateFromFile($bmpfile) Local $hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hbitmap) Local $iwidth = _GDIPlus_ImageGetWidth($hbitmap) Local $iheight = _GDIPlus_ImageGetHeight($hbitmap) Local $ibitcount = 32 ;if alpha is not needed, 24Bit saves 25% of space Local $tBMI = DllStructCreate($tagBITMAPINFO) DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4) DllStructSetData($tBMI, "Width", $iwidth) DllStructSetData($tBMI, "Height", -$iheight) DllStructSetData($tBMI, "Planes", 1) DllStructSetData($tBMI, "BitCount", $ibitcount) Local $hdc = _WinAPI_GetDC(0) Local $hcdc = _WinAPI_CreateCompatibleDC($hdc) Local $adib = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'ptr', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', $DIB_RGB_COLORS, 'ptr*', 0, 'ptr', 0, 'uint', 0) ; select object _WinAPI_SelectObject($hcdc, $adib[0]) ; copy the content of the bitmap into the buffer ... _WinAPI_GetDIBits($hdc, $hbmp, 0, $iheight, $adib[4], DllStructGetPtr($tBMI), $DIB_RGB_COLORS) ; create the a dllstruct with the pointer $aDIB[4] Local $stride = 3 * $iwidth + Mod($iwidth, 4) ;number of bytes in one line (filled with some bytes, because it must be a multiple of four!) Local $tBits = DllStructCreate('byte[' & $stride * $iheight & ']', $adib[4]) $ptr = DllStructGetPtr($tBits) _GDIPlus_BitmapDispose($hbitmap) _WinAPI_DeleteObject($adib[0]) Return $hcdc ;MemoryDC of bitmap EndFunc ;==>_getDCfromfile32 Func _CreateNewBmp32($iwidth, $iheight, ByRef $ptr, ByRef $hbmp) ;erstellt leere 32-bit-Bitmap; Rückgabe $HDC und $ptr und handle auf die Bitmapdaten Local $hcdc = _WinAPI_CreateCompatibleDC(0) ;Desktop-Kompatiblen DeviceContext erstellen lassen Local $tBMI = DllStructCreate($tagBITMAPINFO) ;Struktur der Bitmapinfo erstellen und Daten eintragen DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4);Structgröße abzüglich der Daten für die Palette DllStructSetData($tBMI, "Width", $iwidth) DllStructSetData($tBMI, "Height", -$iheight) ;minus =standard = bottomup DllStructSetData($tBMI, "Planes", 1) DllStructSetData($tBMI, "BitCount", 32) ;32 Bit = 4 Bytes => AABBGGRR Local $adib = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', $DIB_RGB_COLORS, 'ptr*', 0, 'ptr', 0, 'uint', 0) $hbmp = $adib[0] ;hbitmap handle auf die Bitmap, auch per GDI+ zu verwenden $ptr = $adib[4] ;pointer auf den Anfang der Bitmapdaten, vom Assembler verwendet ;_arraydisplay($adib) _WinAPI_SelectObject($hcdc, $hbmp) ;objekt hbitmap in DC Return $hcdc ;DC der Bitmap zurückgeben EndFunc ;==>_CreateNewBmp32 Func _DeleteBitmap32($DC, $ptr, $hbmp) _WinAPI_DeleteDC($DC) _WinAPI_DeleteObject($hbmp) $ptr = 0 EndFunc ;==>_DeleteBitmap32if someone wants to know if 2 pics are different, there are 2 ways: - compare each pixel of the two pics, if there is a difference between 2 pixels, pics are not the same. Comparing pixels need some time.....see link above or use something like prospeed.dll- bitblt them with $SRCINVERT-parameter (XOR transferes same pixel to black), copy the result into a string and use the awesome fast AutoIt-stringfunctions . Example:(yes i know that comparing "files" is not very useful, but with only a few changes it´s possible to compare bitmaps from memory, f.e. for motion detection)expandcollapse popup#include <GDIPlus.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> #include <StructureConstants.au3> #include <GDIConstants.au3> #include <ScreenCapture.au3> _GDIPlus_Startup() ;no manipulating with gdi+ in this script, but it´s easy to load files other than bmp... $picfile1 = "earth1.jpg" ;get them from here http://www.autoitscript.com/forum/index.php?showtopic=106815&view=findpost&p=753759 $picfile2 = "earth2.jpg" ;or use your own ;example of very big pictures ;~ _ScreenCapture_Capture("fullscreen1.jpg") ;makes fullscreenshot ;~ $picfile1 = "fullscreen1.jpg" ;~ $picfile2 = "fullscreen1.jpg" ;shows, that the 2 pics are the same $t = TimerInit() ;save timestamp ;get a DeviceContext from the bitmap-file, if alphachannel is not needed, 24Bit saves 25% ram and is faster when searching or manipulating pixels^^ Local $pointer1, $pointer2 ;we don´t need them in this script, the variables are used ByRef Local $struct1, $struct2 ;struct is need to copy Data into string, will be returned ByRef from the following function Local $width1, $height1, $width2, $height2 ;size of the pics, will be returned ByRef from the following function $hdc_pic1 = _getdcfromfile24_struct($picfile1, $pointer1, $struct1, $width1, $height1) ;get DC ,pointer is the pointer to the bitmapdata, if you want to manipulate pixels $hdc_pic2 = _getdcfromfile24_struct($picfile2, $pointer2, $struct2, $width2, $height2) ;get DC ,pointer is the pointer to the bitmapdata, if you want to manipulate pixels _WinAPI_BitBlt($hdc_pic1, 0, 0, $width1, $height2, $hdc_pic2, 0, 0, $SRCINVERT) ;XOR the 2 pics, compare is done, result is in pic1, XOR sets the same pixel to black ;because we have the struct (where are the bitmapdata-"pixels" inside), it is easy to copy the bitmapdata into a string $bmpstring = BinaryToString(DllStructGetData($struct1, 1)) ;makes string of RGB-Bytes StringReplace($bmpstring, Chr(0), "", 0, 1) ;count every black pixel in @extended, yeah, i like stringfunctions :o) $same = @extended ;number of same bytes $m = TimerDiff($t) ;difference between timestamp If $same = StringLen($bmpstring) Then MsgBox(0, "Compared " & StringLen($bmpstring) & " Bytes", "Pics are the same" & @CRLF & StringFormat("%.3f Milliseconds", $m)) Else MsgBox(0, "Compared " & StringLen($bmpstring) & " Bytes", "Pics are different" & @CRLF & StringFormat("%.3f Milliseconds", $m) & @CRLF & StringFormat("%.0f% are different", 100 - ($same * 100 / StringLen($bmpstring)))) EndIf _exit() Func _exit() _DeleteBitmap32($hdc_pic1, $pointer1, 0) _DeleteBitmap32($hdc_pic2, $pointer2, 0) _GDIPlus_Shutdown() Exit EndFunc ;==>_exit Func _getDCfromfile24_struct($bmpfile, ByRef $ptr, ByRef $tbits, ByRef $iwidth, ByRef $iheight) ;ptr to bitmapdata, it is possible to manipulate one pixel if needed, and struct Local $hbitmap = _GDIPlus_BitmapCreateFromFile($bmpfile) Local $hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hbitmap) $iwidth = _GDIPlus_ImageGetWidth($hbitmap) $iheight = _GDIPlus_ImageGetHeight($hbitmap) Local $ibitcount = 24 ;if alpha is not needed, 24Bit saves 25% of space Local $tBMI = DllStructCreate($tagBITMAPINFO) DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4) DllStructSetData($tBMI, "Width", $iwidth) DllStructSetData($tBMI, "Height", -$iheight) DllStructSetData($tBMI, "Planes", 1) DllStructSetData($tBMI, "BitCount", $ibitcount) Local $hdc = _WinAPI_GetDC(0) Local $hcdc = _WinAPI_CreateCompatibleDC($hdc) Local $adib = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'ptr', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', $DIB_RGB_COLORS, 'ptr*', 0, 'ptr', 0, 'uint', 0) ; select object _WinAPI_SelectObject($hcdc, $adib[0]) ; copy the content of the bitmap into the buffer ... _WinAPI_GetDIBits($hdc, $hbmp, 0, $iheight, $adib[4], DllStructGetPtr($tBMI), $DIB_RGB_COLORS) ; create the a dllstruct with the pointer $aDIB[4] Local $stride = 3 * $iwidth + Mod($iwidth, 4) ;number of bytes in one line (filled with some bytes, because it must be a multiple of four!) $tbits = DllStructCreate('byte[' & $stride * $iheight & ']', $adib[4]) $ptr = DllStructGetPtr($tbits) _GDIPlus_BitmapDispose($hbitmap) _WinAPI_DeleteObject($adib[0]) Return $hcdc ;MemoryDC of bitmap EndFunc ;==>_getDCfromfile24_struct Func _DeleteBitmap32($DC, $ptr, $hbmp) _WinAPI_DeleteDC($DC) _WinAPI_DeleteObject($hbmp) $ptr = 0 EndFunc ;==>_DeleteBitmap32//EDITwith help of some CPU-Mnemonics, comparing is really fast (tested XP32, Errorhandling is on your own....)_WinAPI_BitBlt($hdc_pic1, 0, 0, $width1, $height2, $hdc_pic2, 0, 0, $SRCINVERT) ;XOR the 2 pics, compare is done, result is in pic1, XOR sets the same pixel to black $tCodeBuffer = DllStructCreate("byte[30]") ;Memory for bytecode DllStructSetData($tCodeBuffer, 1, "0x5589E58B7D088B4D0CB800000000F3AF89C85DC3") ;a little assemblercode which compares a part of the memory with 0 $a = DllCall("user32.dll", "int", "CallWindowProcW", "ptr", DllStructGetPtr($tCodeBuffer),"ptr",dllstructgetptr($struct1),"int",DllStructGetSize($struct1)/4, "int", 0,"int",0);bytecode aufrufen, rückgabe in a[0] if $a[0]=0 then ;pics are the same Else ;pics are different endif Edited July 25, 2010 by AndyG
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