emog Posted June 14, 2011 Posted June 14, 2011 (edited) Hi guys, I'm using PixelGetColor to scan an image into a long array of coloured pixels. Problem is it's lightning fast on Windows XP 32-bit, takes about two seconds to read a 64x64 image (4096 pixels total), however running the same script on Vista takes nearly a full minute. Unfortunately now I need to scale things up by scanning much larger images, so the performance loss is really hitting hard. Unfortunately I don't have XP on this system any more. However I keep a very tight ship on this Vista system, with no unnecessary programs/widgets installed nor running in the background. Really simple script: $numberofpixels = ($xmax - $xmin) * ($ymax - $ymin) Global $pixelarray[$numberofpixels] $arraycounter = 0 For $yaxis = $ymin to $ymax Step 1 For $xaxis = $xmin to $xmax Step 1 $pixelarray[$arraycounter] = PixelGetColor($xaxis, $yaxis) $arraycounter = $arraycounter + 1 Next Next msgbox(0, "Script", "Finished") ... it just reads the pixels of an image left to right, line by line, storing all the pixel colour data in an array. Anything I can do? Disabling Aero/transparency in Vista doesn't speed things up, either. Much appreciated, eMog. Edited June 14, 2011 by emog
monoscout999 Posted June 15, 2011 Posted June 15, 2011 theres other way to get the entire raw data... imagine that windows always keep the bitmap data on the memory because is too fast... there are functions that extract that data whitout rescaning the screen for it... take a look at this that i wrote... you will get the idea... all the credits are for the people who wrote the functions... expandcollapse popup#include <misc.au3> #include <WindowsConstants.au3> #include <winapi.au3> #include <Array.au3> #include <GUIConstantsEx.au3> #include <ScreenCapture.au3> HotKeySet("{esc}", "_exit") Global $pos $Gui = GUICreate("selection tool", 300, 50, -1, -1) $bnSelect = GUICtrlCreateButton("start select", 0, 0, 100, 50) $bnShowRaw = GUICtrlCreateButton("ShowRawData", 100, 0, 100, 50) GUICtrlSetState($bnShowRaw, $GUI_DISABLE) $bnShowFromRD = GUICtrlCreateButton("ShowScrenfromRD", 200, 0, 100, 50) GUICtrlSetState($bnShowFromRD, $GUI_DISABLE) GUISetState() While 1 $nmsg = GUIGetMsg() Switch $nmsg Case -3 _exit() Case $bnSelect $sel = _drawbox() If IsArray($sel) Then GUICtrlSetState($bnShowRaw, $GUI_ENABLE) EndIf Case $bnShowRaw $begin1 = TimerInit() $rawdata = _Getrawdata($sel[4]) If Not @error Then ConsoleWrite("Time in ms to do all the work = " & TimerDiff($begin1) & @CRLF) GUICtrlSetState($bnShowFromRD, $GUI_ENABLE) _arraydisplay($rawdata) EndIf Case $bnShowFromRD $ShowGUI = GUICreate("screen show", $sel[2], $sel[3], $sel[0], $sel[1], $WS_POPUP) $graph = GUICtrlCreateGraphic(0, 0, $sel[2], $sel[3]) _printrawdata($rawdata, $graph) GUISetState(@SW_SHOW, $ShowGUI) GUICtrlSetState($graph, $GUI_SHOW) MsgBox(0, "tip", "Press ´BackSpace´key to close Show window") Do Sleep(50) Until _IsPressed("08") ; BackSpace GUIDelete($ShowGUI) EndSwitch WEnd Func _Exit() Exit EndFunc ;==>_Exit Func _drawbox() $hGui = GUICreate("selectionbox", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOPMOST) GUISetBkColor(0x000000, $hGui) WinSetTrans($hGui, "", 20) GUISetState() GUISetCursor(3) $DLL = DllOpen("user32.dll") While Not _IsPressed("01", $DLL) $pos = MouseGetPos() Sleep(10) WEnd $iX = $pos[0] $iW = 0 $iY = $pos[1] $iH = 0 While _IsPressed(01, $DLL) $pos2 = MouseGetPos() Select Case $pos2[0] < $pos[0] $iX = $pos2[0] $iW = $pos[0] - $pos2[0] Case $pos[0] < $pos2[0] $iX = $pos[0] $iW = $pos2[0] - $pos[0] EndSelect Select Case $pos2[1] < $pos[1] $iY = $pos2[1] $iH = $pos[1] - $pos2[1] Case $pos[1] < $pos2[1] $iY = $pos[1] $iH = $pos2[1] - $pos[1] EndSelect _GUICreateInvRect($hGui, $iX, $iY, $iW, $iH) WEnd GUIDelete($hGui) DllClose($DLL) $begin = TimerInit() $hBMP = _ScreenCapture_Capture("", $iX, $iY, $iW + $iX, $iH + $iY) ConsoleWrite("Time in ms. to take a screen from a " & $iW & "X" & $iH & " Area = " & TimerDiff($begin) & @CRLF) Local $selectedpos[5] = [$iX, $iY, $iW, $iH, $hBMP] Return $selectedpos EndFunc ;==>_drawbox Func _GUICreateInvRect($hWnd, $iX, $iY, $iW, $iH) $hMask_1 = _WinAPI_CreateRectRgn(0, 0, @DesktopWidth, $iY) $hMask_2 = _WinAPI_CreateRectRgn(0, 0, $iX, @DesktopHeight) $hMask_3 = _WinAPI_CreateRectRgn($iX + $iW, 0, @DesktopWidth, @DesktopHeight) $hMask_4 = _WinAPI_CreateRectRgn(0, $iY + $iH, @DesktopWidth, @DesktopHeight) _WinAPI_CombineRgn($hMask_1, $hMask_1, $hMask_2, 2) _WinAPI_CombineRgn($hMask_1, $hMask_1, $hMask_3, 2) _WinAPI_CombineRgn($hMask_1, $hMask_1, $hMask_4, 2) _WinAPI_DeleteObject($hMask_2) _WinAPI_DeleteObject($hMask_3) _WinAPI_DeleteObject($hMask_4) _WinAPI_SetWindowRgn($hWnd, $hMask_1, 1) EndFunc ;==>_GUICreateInvRect Func _Getrawdata($hBMP) ; Credits to Malkey http://www.autoitscript.com/forum/index.php?app=forums&module=forums§ion=findpost&pid=718522 _GDIPlus_Startup() $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBMP) $width = _GDIPlus_ImageGetWidth($hBitmap) $height = _GDIPlus_ImageGetHeight($hBitmap) Local $aSize = DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $hBMP, 'int', 0, 'ptr', 0) If Not @error Then $tBits = DllStructCreate('byte[' & $aSize[0] & ']') $begin = TimerInit() DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $hBMP, 'int', $aSize[0], 'ptr', DllStructGetPtr($tBits)) $sHex = Hex(DllStructGetData($tBits, 1)) ConsoleWrite("Time in ms. to get the rawdata and save it in a variable = " & TimerDiff($begin) & @CRLF) $begin = TimerInit() $sHex = StringRegExpReplace($sHex, "([[:xdigit:]]{6})(FF)", "\1 ") Local $pix[$height][$width], $aTemp $aArr = StringRegExp($sHex, "(.{" & ($width * 7) & "})", 3) ConsoleWrite("Time in ms to preparate the rawdata to be indexed in an array = " & TimerDiff($begin) & @CRLF) $porcent = $height*$width/100 ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $porcent = ' & $porcent & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console $begin = TimerInit() local $a = 1 For $width = 0 To UBound($aArr) - 1 $aTemp = StringRegExp($aArr[$width] & " ", "(.{6}) ", 3) For $height = 0 To UBound($aTemp) - 1 $pix[$width][$height] = StringRegExpReplace($aTemp[$height], "(.{2})(.{2})(.{2})", "\3\2\1") ; To RGB format Next Next ConsoleWrite("Time in ms to put the entire raw in an array = " & TimerDiff($begin) & @CRLF) Else SetError(@error) Return "" EndIf _GDIPlus_BitmapDispose($hBitmap) _WinAPI_DeleteObject($hBMP) _GDIPlus_Shutdown() Return $pix EndFunc ;==>_Getrawdata Func _printrawdata($ArBMPRawdata, $hgraphic) $begin = TimerInit() For $x = 0 To UBound($ArBMPRawdata) - 1 For $y = 0 To UBound($ArBMPRawdata, 2) - 1 $color = "0x" & $ArBMPRawdata[$x][$y] GUICtrlSetGraphic($hgraphic, $GUI_GR_COLOR, $color) GUICtrlSetGraphic($hgraphic, $GUI_GR_PIXEL, $y, $x) ; :S GUICtrlSetState($graph, $GUI_SHOW) Next Next ConsoleWrite("Time in ms to print from the rawdata using GuictrlsetGraphics = " & TimerDiff($begin) & @CRLF) EndFunc ;==>_printrawdata
emog Posted June 15, 2011 Author Posted June 15, 2011 (edited) Many thanks for your time but my level of coding is near enough absolute beginner and unfortunately I can't even begin to follow the above, my apologies. Seems like using a sledgehammer to crack a nut. I really don't require a GUI or any fancy mouse selection tool or similar as the screen co-ordinates and data display (tooltip, msgbox and _arraydisplay) are all taken care of with my existing code. Thanks. Edited June 15, 2011 by emog
monoscout999 Posted June 16, 2011 Posted June 16, 2011 What i want to say is that are APIs that get the PixelInfo of Any area you want... the method Using for next loops and PixelGetColor always is a little slow.... theres a lot of post asking for the same on the forum i get the method that i show you avobe from one of those... if as you said you dont want to complicate anymore you can try the that is a lot more faster and simple usage...
JohnOne Posted June 16, 2011 Posted June 16, 2011 The only thing I have ever seen slow that down is Aeroglass, and since you have disabled it, I cant see whay its so slow. Thats assuming of course that your logic is sound and you are not getting more pixels than you need. AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans.
AdmiralAlkex Posted June 20, 2011 Posted June 20, 2011 @emog You want to disable DWM, do a forum search and you'll find some posts on it. .Some of my scripts: ShiftER, Codec-Control, Resolution switcher for HTC ShiftSome of my UDFs: SDL UDF, SetDefaultDllDirectories, Converting GDI+ Bitmap/Image to SDL Surface
AmnonS Posted July 26, 2012 Posted July 26, 2012 Hello. I also have this problem and I slove it by changing the background of the OS to a simple one. Good luck.
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