Xibalba Posted January 18, 2014 Posted January 18, 2014 I'm experimenting with GetPixel functions (in order to find the fastest) and have this simple part in my script: Local $iWidth = 150 Local $iHeight = 300 Local $array[$iHeight][$iWidth] For $i = 1 To $iHeight Step 1 For $j = 1 To $iWidth Step 1 $array[$i-1][$j-1] = PixelGetColor($iHeight-1, $iWidth-1, $Handle) Next Next Trying to get the equivalent using the GDI+ library (more specifically, using the _GDIPlus_BitmapLockBits function) I've got this code: expandcollapse popupGlobal $Handle = WinGetHandle("Paint") Local $sWow64 = "" If @AutoItX64 Then $sWow64 = "\Wow6432Node" ; X64 running support ; Initialize GDI+ library _GDIPlus_Startup() ; Capture 32 bit bitmap to a HBITMAP WinActivate($Handle) Local $hBMP = _ScreenCapture_CaptureWnd("", $Handle) ; _ScreenCapture_CaptureWnd returns a handle to an HBITMAP if $sFileName is empty Local $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBMP) Local $iWidth = 150 Local $iHeight = 300 Local $array[$iHeight][$iWidth] Local $BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, $iWidth, $iHeight, $GDIP_ILMREAD, $GDIP_PXF32RGB) Local $Scan0 = DllStructGetData($BitmapData, "Scan0") Local $Stride = DllStructGetData($BitmapData, "Stride") Local $pixel = $Scan0 + $Stride + 4 Local $dPixel = DllStructCreate("dword", $pixel) MsgBox(0, "mBox", "$Scan0=" & $Scan0 & " $Stride=" & $Stride & " pixel=" & $pixel) For $i = 1 To $iHeight Step 1 For $j = 1 To $iWidth Step 1 ; <?> Next Next ; Clean up resources _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData) _GDIPlus_BitmapDispose($pBitmap) _WinAPI_DeleteObject($hBMP) _GDIPlus_Shutdown() And yeah, there's where I'm struggling at the moment (see ; <?> line). I don't get any return value from the DllStructCreate() call (to the $dPixel variable) The $pixel variable contains at this point 0x026D7A84. I need help to proceed, and I don't fully understand the $Scan0 and $Stride usage. And how to convert pixel data to x and y coordinates for use in the loop (i and j). My goal is to get the decimal value of each pixel into the array (exactly the same way as when using the PixelGetColor() method, see above) hAlp
UEZ Posted January 18, 2014 Posted January 18, 2014 Look in the help file for _GDIPlus_BitmapLockBits() example. There is an example how to read the color values of an image. Br, UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
Xibalba Posted January 18, 2014 Author Posted January 18, 2014 UEZ, I've of course looked at that example. I've tried again and again to recode that (and other examples in the forum) to work in my script. Every time I'm reaching a dead end. I need help to get my specific code to work (which by the way has a few fundamental differences to the example). Br
UEZ Posted January 18, 2014 Posted January 18, 2014 This will display the color values as decimal numbers. It is the modified code from the help file: expandcollapse popup#include <Array.au3> #include <Constants.au3> #include <GUIConstantsEx.au3> #include <GDIPlus.au3> Example() Func Example() ; X64 running support Local $sWow64 = "" If @AutoItX64 Then $sWow64 = "\Wow6432Node" ;get AutoIt install dir Local $sRegPath = "HKLM\SOFTWARE" & $sWow64 & "\AutoIt v3\AutoIt" Local $sFile = RegRead($sRegPath, "InstallDir") & "\Examples\GUI\logo4.gif" If Not FileExists($sFile) Then MsgBox(BitOR($MB_SYSTEMMODAL, $MB_ICONHAND), "", $sFile & " not found!", 30) Return False EndIf _GDIPlus_Startup() Local $hImage = _GDIPlus_ImageLoadFromFile($sFile) ;create an image object based on a file If @error Then _GDIPlus_Shutdown() MsgBox(BitOR($MB_SYSTEMMODAL, $MB_ICONHAND), "", "An error has occured - unable to load image!", 30) Return False EndIf Local $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage) ;get width and height of the image Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH) Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap) _GDIPlus_GraphicsDrawImageRect($hContext, $hImage, 0, 0, $iW, $iH) Local $tBitmapData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $iW, $iH, BitOR($GDIP_ILMWRITE, $GDIP_ILMREAD), $GDIP_PXF32ARGB) ;locks a portion of a bitmap for reading and writing. More infor at http://msdn.microsoft.com/en-us/library/windows/desktop/ms536298(v=vs.85).aspx Local $iScan0 = DllStructGetData($tBitmapData, "Scan0") ;get scan0 (pixel data) from locked bitmap Local $iSearchPixel = Int(0xFF000080), $iReplaceColor = 0x00000000 ;color format 0xAARRGGBB Local $tPixel = DllStructCreate("int[" & $iW * $iH & "];", $iScan0) Local $iRowOffset, $array[$iH][$iW] For $iY = 0 To $iH - 1 $iRowOffset = $iY * $iW + 1 For $iX = 0 To $iW - 1 ;get each pixel in each line and row $array[$iY][$iX] = DllStructGetData($tPixel, 1, $iRowOffset + $iX) ;get pixel color Next Next _GDIPlus_BitmapUnlockBits($hBitmap, $tBitmapData) ;unlocks a portion of a bitmap that was locked by _GDIPlus_BitmapLockBits _ArrayDisplay($array) ;cleanup resources _GDIPlus_ImageDispose($hImage) _GDIPlus_GraphicsDispose($hContext) _GDIPlus_BitmapDispose($hBitmap) _GDIPlus_Shutdown() EndFunc ;==>Example Br, UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
Xibalba Posted January 18, 2014 Author Posted January 18, 2014 UEZ, I've tried again with your modified code. I had to change this: Local $BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, $iWidth, $iHeight, $GDIP_ILMREAD, $GDIP_PXF32RGB) To this: Local $tBitmapData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $iW, $iH, BitOR($GDIP_ILMWRITE, $GDIP_ILMREAD), $GDIP_PXF32ARGB) Else it would crash with exception. However, with ARGB I do get values, but they are all negative - how to fix that in the fastest way? If possible I'd like to use 32RGB because it (should?) be slightly faster. Thanks so far =)
UEZ Posted January 18, 2014 Posted January 18, 2014 Use Hex instead. $array[$iY][$iX] = "0x" & Hex(DllStructGetData($tPixel, 1, $iRowOffset + $iX)) ;get pixel color Br, UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
Xibalba Posted January 18, 2014 Author Posted January 18, 2014 (edited) Ok so I went on and ended up with this code: WinActivate($Handle) Local $hBMP = _ScreenCapture_CaptureWnd("", $Handle) ; _ScreenCapture_CaptureWnd returns a handle to an HBITMAP if $sFileName is empty Local $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBMP) Local $iWidth = 150 Local $iHeight = 300 Local $array[$iHeight][$iWidth] Local $BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, $iWidth, $iHeight, BitOR($GDIP_ILMWRITE, $GDIP_ILMREAD), $GDIP_PXF32ARGB) Local $Scan0 = DllStructGetData($BitmapData, "Scan0") Local $tPixel = DllStructCreate("int[" & $iWidth * $iHeight & "];", $Scan0) Local $iRowOffset For $iY = 0 To $iHeight - 1 $iRowOffset = $iY * $iWidth + 1 For $iX = 0 To $iWidth - 1 ;get each pixel in each line and row $array[$iY][$iX] = DllStructGetData($tPixel, 1, $iRowOffset + $iX) ;get pixel color $array[$iY][$iX] = Abs($array[$iY][$iX]) Next Next _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData) ; Clean up resources _GDIPlus_BitmapDispose($pBitmap) _WinAPI_DeleteObject($hBMP) _GDIPlus_Shutdown() _ArrayDisplay($array) But now I'm getting strange results. For example, I get the value 1 at [1][1] to [299][1], the value 2830136 at [0][0] etc. I got no idea where those colors come from, they certainly aren't at the top-left on my handle at least. Perhaps X and Y is mixed up somehow? I played around changing those some but got even more unexpected values. And even so, what kind of value is 1? - to my knowledge, black=0 and white=16777215 in AutoIt? As said earlier, perhaps its easier to use 32RGB instead of 32ARGB - but how do I do that without crashing the script? Edit: sfdsdfsdasdafsdf How do I mark my code as AutoIt code (colors) and not just general code (no colors)? Edited January 18, 2014 by Xibalba
UEZ Posted January 18, 2014 Posted January 18, 2014 What you are doing with Abs($array[$iY][$iX]) makes no sense because you are change the color values! What is the problem to have hex color values? It is much easier to see what color values you have when it is encoded in hex. Br, UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
trancexx Posted January 19, 2014 Posted January 19, 2014 (edited) Based on your code it would probably be something like this:Local $aArray[$iHeight][$iWidth] Local $tBitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, $iWidth, $iHeight, BitOR($GDIP_ILMWRITE, $GDIP_ILMREAD), $GDIP_PXF32ARGB) Local $tPixel = DllStructCreate("dword[" & $iWidth * $iHeight & "];", DllStructGetData($tBitmapData, "Scan0")) For $iX = 0 To $iWidth - 1 For $iY = 0 To $iHeight - 1 $aArray[$iY][$iX] = BitAND(DllStructGetData($tPixel, 1, $iY * $iWidth + $iX + 1), 0xFFFFFF) Next Next _GDIPlus_BitmapUnlockBits($pBitmap, $tBitmapData)edit: cleaned a bit Edited January 19, 2014 by trancexx ♡♡♡ . eMyvnE
Xibalba Posted January 19, 2014 Author Posted January 19, 2014 trancexx, absolutely great, thanks! For a slight performance boost, consider this: Local $BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, $iWidth, $iHeight, $GDIP_ILMREAD, $GDIP_PXF32RGB) Notice! the last 2 parameters. How would I go about defining my DLLStructCreate then? (Hex or decimal return values doesn't matter - I'm looking for the fastest!) Local $tPixel = DllStructCreate("dword[" & $iWidth * $iHeight & "];", $Scan0) The following code then breaks (in the loop): $array[$iY][$iX] = DllStructGetData($tPixel, 1, $iY * $iWidth + $iX + 1) Probably this happens because I'm trying to get data from a place that doesn't exist(?). I still can't completely picture the data in my head - how does the $tPixel "look" after it's DllStructCreate? - Is it some sort of array? _ArrayDisplay() or something equivalent would make it much easier understand those data types.
trancexx Posted January 19, 2014 Posted January 19, 2014 Sorry, but can you provide the name of the application you are using? What is your endgame or is it a secret? LOL, I'm kidding. Pay no attention to those trolls in colors . $tPixel is array of integers representing pixel colors. That array isn't organized the way you would expect (the way picture looks), it's actually all backward because rendering engines expect it that way. It's following BMP format specification. That's why I used: $iY * $iWidth + $iX + 1 ...to get right pixel from the array at coordinates you expect them to be. If you would fill your array reading it flat (from the struct) then you would see your picture flipped and rotated. You could even do that and get correct data but before locking bitmap you would have to flip-rotate it (_GDIPlus_ImageRotateFlip). ♡♡♡ . eMyvnE
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