IchBistTod Posted November 22, 2009 Posted November 22, 2009 (edited) I want to find the color of every pixel in and image and make it into a matrix like below 00FF00|00FF00| 00FF00|00FF00| thats would be a 2x2 pixel green image. the source code should explain the format it needs to be in. the problem with the method I have is that it take 30 mins, and is HIGHLY inaccurate, which is not acceptable as the algorithms I am using are created to compare two images to find the differences, meaning if the same image can have two different matricies it destroys the point of the program. So far this method had only brought 55% accuracy max(with the same exact image scanned twice then compared) and is usually at around 10%. getting this color info is the only problem standing in my way of completing my application. any help would be appreciated. current code: expandcollapse popup#include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> #Region ### START Koda GUI section ### Form= ;GUICreate(".", 0, 0, 1, 1) ;WinSetOnTop(".", "", 1) ;GUISetState() $Form1 = GUICreate("IS", 652, 443, 192, 124) $Pic1 = GUICtrlCreatePic("select.jpg", 16, 32, 300, 300, BitOR($SS_NOTIFY,$WS_GROUP,$WS_CLIPSIBLINGS)) $Pic2 = GUICtrlCreatePic("select.jpg", 335, 32, 300, 300, BitOR($SS_NOTIFY,$WS_GROUP,$WS_CLIPSIBLINGS)) $compare = GUICtrlCreateButton("scan", 288, 360, 75, 25, 0) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit case $Pic1 GUICtrlSetImage($Pic1, FileOpenDialog("select an image", @WorkingDir, "All Files(*.*)")) case $Pic2 GUICtrlSetImage($Pic2, FileOpenDialog("select an image", @WorkingDir, "All Files(*.*)")) case $compare $win = WinGetPos($Form1) Dim $string = "[300x300|]"&@CRLF $timer = TimerInit() for $i=32+$win[1] to 32+300+$win[1]-1 for $ix = 16+$win[0] to 300+16+$win[0]-1 $string &= hex(PixelGetColor($ix, $i))&"|" Next $string &= @CRLF Next ConsoleWrite(TimerDiff($timer)&@CRLF) FileWrite("pic.temp.IS", $string) EndSwitch WEnd if you for some reason need the compare funcs just pm me. Edited November 22, 2009 by IchBistTod [center][/center][center]=][u][/u][/center][center][/center]
Authenticity Posted November 22, 2009 Posted November 22, 2009 If you want to get the pixels of each image to compare them later for equality, you can do something like: expandcollapse popup#include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <Icons.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> _GDIPlus_Startup() Local $Form1, $Pic1, $Pic2, $compare Local $sFilename1, $sFilename2 $Form1 = GUICreate("IS", 652, 443, 192, 124) $Pic1 = GUICtrlCreateLabel("select.jpg", 16, 32, 300, 300, BitOR($SS_NOTIFY, $WS_GROUP, $WS_CLIPSIBLINGS)) $Pic2 = GUICtrlCreateLabel("select.jpg", 335, 32, 300, 300, BitOR($SS_NOTIFY, $WS_GROUP, $WS_CLIPSIBLINGS)) $compare = GUICtrlCreateButton("scan", 288, 360, 75, 25, 0) GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE _GDIPlus_Shutdown() Exit Case $Pic1 $sFilename1 = FileOpenDialog("select an image", @WorkingDir, "Images (*.bmp;*.dib;*.jpg;*.jpeg;*.jpe;*.jfif;*.gif;*.tif;*.tiff;*.png;*.ico)", 5) If $sFilename1 <> "" Then _SetImage($Pic1, $sFilename1) Case $Pic2 $sFilename2 = FileOpenDialog("select an image", @WorkingDir, "Images (*.bmp;*.dib;*.jpg;*.jpeg;*.jpe;*.jfif;*.gif;*.tif;*.tiff;*.png;*.ico)", 5) If $sFilename2 <> "" Then _SetImage($Pic2, $sFilename2) Case $compare ;~ $win = WinGetPos($Form1) ;~ Dim $string = "[300x300|]" & @CRLF ;~ $timer = TimerInit() ;~ For $i = 32 + $win[1] To 32 + 300 + $win[1] - 1 ;~ For $ix = 16 + $win[0] To 300 + 16 + $win[0] - 1 ;~ $string &= Hex(PixelGetColor($ix, $i)) & "|" ;~ Next ;~ $string &= @CRLF ;~ Next ;~ ConsoleWrite(TimerDiff($timer) & @CRLF) ;~ FileWrite("pic.temp.IS", $string) If $sFilename1 <> "" And $sFilename2 <> "" Then If _CompareImages($sFilename1, $sFilename2) Then ConsoleWrite("+Images are same" & @CRLF) Else ConsoleWrite("!Image are different" & @CRLF) EndIf EndIf EndSwitch WEnd Func _CompareImages($sImage1, $sImage2) Local $hImage1, $hImage2, $iBmp1, $iBmp2, $iW1, $iW2, $iH1, $iH2 Local $tBD1, $tBD2, $iWidth1, $iWidth2, $iHeight1, $iHeight2, $iStride1, $iStride2, $iFmt1, $iFmt2 Local $pData1, $pData2 Local $tPixels1, $tPixels2, $xBytes1, $xBytes2 Local $fResult = False If $sImage1 = $sImage2 Then Return True $hImage1 = _GDIPlus_ImageLoadFromFile($sImage1) If @error Then Return SetError(1, 0, 0) $hImage2 = _GDIPlus_ImageLoadFromFile($sImage2) If @error Then Return SetError(2, 0, 0) $iW1 = _GDIPlus_ImageGetWidth($hImage1) $iH1 = _GDIPlus_ImageGetHeight($hImage1) $iW2 = _GDIPlus_ImageGetWidth($hImage2) $iH2 = _GDIPlus_ImageGetHeight($hImage2) If $iW1 <> $iW2 Or $iH1 <> $iH2 Then Return False $hBmp1 = _GDIPlus_BitmapCloneArea($hImage1, 0, 0, $iW1, $iH1, $GDIP_PXF32ARGB) $hBmp2 = _GDIPlus_BitmapCloneArea($hImage2, 0, 0, $iW2, $iH2, $GDIP_PXF32ARGB) $tBD1 = _GDIPlus_BitmapLockBits($hBmp1, 0, 0, $iW1, $iH1, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32ARGB) $tBD2 = _GDIPlus_BitmapLockBits($hBmp2, 0, 0, $iW2, $iH2, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32ARGB) $iWidth1 = DllStructGetData($tBD1, 1) $iHeight1 = DllStructGetData($tBD1, 2) $iStride1 = DllStructGetData($tBD1, 3) $iFmt1 = DllStructGetData($tBD1, 4) $pData1 = DllStructGetData($tBD1, 5) $iWidth2 = DllStructGetData($tBD2, 1) $iHeight2 = DllStructGetData($tBD2, 2) $iStride2 = DllStructGetData($tBD2, 3) $iFmt2 = DllStructGetData($tBD2, 4) $pData2 = DllStructGetData($tBD2, 5) $tPixels1 = DllStructCreate("byte[" & $iWidth1 * $iHeight1 * 4 & "]", $pData1) $tPixels2 = DllStructCreate("byte[" & $iWidth2 * $iHeight2 * 4 & "]", $pData2) $xBytes1 = DllStructGetData($tPixels1, 1) $xBytes2 = DllStructGetData($tPixels2, 1) If $xBytes1 = $xBytes2 Then $fResult = True _GDIPlus_BitmapUnlockBits($hBmp1, $tBD2) _GDIPlus_BitmapUnlockBits($hBmp1, $tBD1) _WinAPI_DeleteObject($hBmp2) _WinAPI_DeleteObject($hBmp1) _GDIPlus_ImageDispose($hImage2) _GDIPlus_ImageDispose($hImage1) Return $fResult EndFunc If you want the pixels as a single dimension array you can take $xBytes1 and using StringRegExp() you can split the binary string each 8 characters. Turning the binary data to an array in the size of the image, for example $avArray[800][480] requires to go get the data as an array first, then using a nested loop from 0 to $iW, 0 to $iH you can build the array.
IchBistTod Posted November 22, 2009 Author Posted November 22, 2009 (edited) I just want it in the format i used above..... a textual matrix representation that is later turned into a two dimensional matrix with this functionfunc _ReadISFile($file) $timer = TimerInit() $data = FileRead($file) $darray = StringSplit(StringReplace($data, @CR, ""), @LF, 2) $demensions = _StringBetween($darray[0], "[", "|") $demensions = StringSplit($demensions[0], "x",2) Dim $ismatrix[$demensions[0]+1][$demensions[1]+1] for $i=1 to $demensions[0] $dm=StringSplit($darray[$i], "|") for $ix=1 to $demensions[0] $ismatrix[$i][$ix] = $dm[$ix] Next Next ConsoleWrite(TimerDiff($timer)&@CRLF) Return $ismatrix EndFuncAlso I thank you for this help, but I have no experience with regular expressions, or how to work with this data could you perhaps provide code of how to do this, then I can study it and learn from it? (what i want is each pixels data stored in an element of a matrix, each row being a Y coordinate and each column being a X coordinate)example:X1 X2 Y1 00FF00|00FF00| Y2 00FF00|00FF00|and the IS format for this would be[2x2|] 00FF00|00FF00| 00FF00|00FF00|two matrices are compared by this function:func _MatrixCompare($array1, $array2, $size, $decimal) $timer = TimerInit() local $match = 0 $size = StringSplit($size, "x", 2) for $i=1 to $size[0] for $i2 = 1 to $size[1] if $array1[$i][$i2] = $array2[$i][$i2] Then $match +=1 EndIf Next Next $total = $size[0]*$size[1] $return = ($match/$total)*100 if StringInStr($return, ".") Then $returnx = StringSplit($return, ".") $return = $returnx[1]&"."&StringLeft($returnx[2], $decimal) EndIf ConsoleWrite(TimerDiff($timer)&@CRLF) Return $return EndFuncthis returns an exact percentage two matrices match.so this is why i want each pixel color as one element of the matrix to compare pixel by pixel and get a difference percentage by using my functions to compare textual representations of the image.thanks for your help so far. Edited November 22, 2009 by IchBistTod [center][/center][center]=][u][/u][/center][center][/center]
junkew Posted November 22, 2009 Posted November 22, 2009 http://www.autoitscript.com/forum/index.php?showtopic=66545&hl=findbmp&st=0 will give you some directions including other links manipulating with bitmaps FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets
Authenticity Posted November 22, 2009 Posted November 22, 2009 expandcollapse popup#include <GDIPlus.au3> _GetImagePixels(@ScriptDir & "\1.jpg", @ScriptDir & "\Test.txt") Func _GetImagePixels($sImage, $sOutputFile) Local $hImage, $hBmp, $iW, $iH Local $tBD, $iWidth, $iHeight, $iStride, $iFmt Local $pData, $tPixels, $xBytes Local $avPixels, $hFile $hFile = FileOpen($sOutputFile, 2) If @error Then Return SetError(1, 1, 0) _GDIPlus_Startup() $hImage = _GDIPlus_ImageLoadFromFile($sImage) If @error Then Return SetError(1, 2, 0) $iW = _GDIPlus_ImageGetWidth($hImage) $iH = _GDIPlus_ImageGetHeight($hImage) $hBmp = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iW, $iH, $GDIP_PXF32ARGB) $tBD = _GDIPlus_BitmapLockBits($hBmp, 0, 0, $iW, $iH, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32ARGB) $iWidth = DllStructGetData($tBD, 1) $iHeight = DllStructGetData($tBD, 2) $iStride = DllStructGetData($tBD, 3) $iFmt = DllStructGetData($tBD, 4) $pData = DllStructGetData($tBD, 5) $tPixels = DllStructCreate("byte[" & $iW * $iH * 4 & "]", $pData) $xBytes = DllStructGetData($tPixels, 1) $sData = StringTrimRight(StringRegExpReplace(StringTrimLeft($xBytes, 2), "(.{" & 8 * $iWidth & "})", "\1@"), 1) $avData = StringSplit($sData, "@") FileWrite($hFile, StringRegExpReplace($avData[1], "(.{8})(?!$)", "\1|")) For $i = 2 To $avData[0] FileWrite($hFile, @CRLF & StringRegExpReplace($avData[1], "(.{8})(?!$)", "\1|")) Next FileClose($hFile) _GDIPlus_BitmapUnlockBits($hBmp, $tBD) _WinAPI_DeleteObject($hBmp) _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() EndFuncThe pixel colors are saved as "BBGGRRAA" so you may want to use Binary(Dec($Pixel)) to get the correct "AARRGGBB" pixel value.
AndyG Posted November 22, 2009 Posted November 22, 2009 Hi, this is a "relative" fast function. A 1680x1050 Bitmap takes about 12 Seconds to store the hexnumbers of the pixels to an array. expandcollapse popup#include <GUIConstantsEx.au3> #include <WinAPI.au3> #include <GDIPlus.au3> #include <GDIPlusConstants.au3> #include <StructureConstants.au3> #include <Array.au3> $bitmapfile = "pic2.jpg" ;some image ;$bitmapfile = "testfullscreen.bmp" ;1680x1050 $t = TimerInit() $array = _allpixel2array($bitmapfile) ;write pixelcolours from an image-file into an array $m = TimerDiff($t) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $m = ' & $m & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console ;****************Example: write the array into a window (setpixel)******************* $hGUI = GUICreate("GDI+", 300, 300); @DesktopWidth, @DesktopHeight) $hWnd = WinGetHandle("GDI+") GUISetState() _GDIPlus_Startup() $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd) For $x = 1 To UBound($array, 1) - 1 For $y = 0 To UBound($array, 2) - 1 $col = "0xFF" & StringMid($array[$x][$y], 5, 2) & StringMid($array[$x][$y], 3, 2) & StringMid($array[$x][$y], 1, 2) ;BGR to RGB $hPen = _GDIPlus_PenCreate($col) ; _GDIPlus_GraphicsDrawEllipse($hGraphic, $y, $x, 1, 1, $hPen) Next Next Do Until GUIGetMsg() = $GUI_EVENT_CLOSE ; Ressourcen freigeben _GDIPlus_GraphicsDispose($hGraphic) _GDIPlus_Shutdown() Func _allpixel2array($bmpfile) ;returns a 2d array with the colours BGR _GDIPlus_Startup() $pBitmap = _GDIPlus_BitmapCreateFromFile($bmpfile) If @error Then MsgBox(0, "", "Fehler BitmapCreateFromFile") ;_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("byte[" & (Abs($stride) * ($Height)) & "]", $Scan0) $BMPDataStart = StringTrimLeft(DllStructGetData($pixeldata, 1), 2) ;string im Struct-format, d.h. Byte+nulByte, in dem die pixeldaten im BGR-Format stehen ; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $BMPDataStart = ' & StringLeft($BMPDataStart, 100) & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console Dim $array[$Height + 1][$Width + 1] For $y = 0 To $Height - 1 ;to 1 step -1 ;bottomup bitmap, first line in image is last line in data For $i = 0 To $stride * 2 Step 6 ;every 3 byte are one pixel $array[$y + 1][$i / 6] = StringMid($BMPDataStart, ($y * $stride * 2) + $i + 1, 6) ;ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $array[$y][$i / 6] = ' & $array[$y][$i / 6] & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console Next Next ; _arraydisplay($array) $BMPDataStart = "" $pixeldata = 0 _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData) _GDIPlus_ImageDispose($pBitmap) _WinAPI_DeleteObject($pBitmap) _GDIPlus_Shutdown() Return $array EndFunc ;==>_allpixel2array2i hope it helps  little bit.....
IchBistTod Posted November 22, 2009 Author Posted November 22, 2009 expandcollapse popup#include <GDIPlus.au3> _GetImagePixels(@ScriptDir & "\1.jpg", @ScriptDir & "\Test.txt") Func _GetImagePixels($sImage, $sOutputFile) Local $hImage, $hBmp, $iW, $iH Local $tBD, $iWidth, $iHeight, $iStride, $iFmt Local $pData, $tPixels, $xBytes Local $avPixels, $hFile $hFile = FileOpen($sOutputFile, 2) If @error Then Return SetError(1, 1, 0) _GDIPlus_Startup() $hImage = _GDIPlus_ImageLoadFromFile($sImage) If @error Then Return SetError(1, 2, 0) $iW = _GDIPlus_ImageGetWidth($hImage) $iH = _GDIPlus_ImageGetHeight($hImage) $hBmp = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iW, $iH, $GDIP_PXF32ARGB) $tBD = _GDIPlus_BitmapLockBits($hBmp, 0, 0, $iW, $iH, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32ARGB) $iWidth = DllStructGetData($tBD, 1) $iHeight = DllStructGetData($tBD, 2) $iStride = DllStructGetData($tBD, 3) $iFmt = DllStructGetData($tBD, 4) $pData = DllStructGetData($tBD, 5) $tPixels = DllStructCreate("byte[" & $iW * $iH * 4 & "]", $pData) $xBytes = DllStructGetData($tPixels, 1) $sData = StringTrimRight(StringRegExpReplace(StringTrimLeft($xBytes, 2), "(.{" & 8 * $iWidth & "})", "\1@"), 1) $avData = StringSplit($sData, "@") FileWrite($hFile, StringRegExpReplace($avData[1], "(.{8})(?!$)", "\1|")) For $i = 2 To $avData[0] FileWrite($hFile, @CRLF & StringRegExpReplace($avData[1], "(.{8})(?!$)", "\1|")) Next FileClose($hFile) _GDIPlus_BitmapUnlockBits($hBmp, $tBD) _WinAPI_DeleteObject($hBmp) _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() EndFunc The pixel colors are saved as "BBGGRRAA" so you may want to use Binary(Dec($Pixel)) to get the correct "AARRGGBB" pixel value. This was easier to modify to my needs and seems to be quite fast, however is there a way to "shrink" an image to a smaller resolution, for say smaller scan time, or if there are two different sized images, so the largest could be shrunk to the smallest or vice versa (whichever would be more accurate) Hi, this is a "relative" fast function. A 1680x1050 Bitmap takes about 12 Seconds to store the hexnumbers of the pixels to an array. expandcollapse popup#include <GUIConstantsEx.au3> #include <WinAPI.au3> #include <GDIPlus.au3> #include <GDIPlusConstants.au3> #include <StructureConstants.au3> #include <Array.au3> $bitmapfile = "pic2.jpg" ;some image ;$bitmapfile = "testfullscreen.bmp" ;1680x1050 $t = TimerInit() $array = _allpixel2array($bitmapfile) ;write pixelcolours from an image-file into an array $m = TimerDiff($t) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $m = ' & $m & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console ;****************Example: write the array into a window (setpixel)******************* $hGUI = GUICreate("GDI+", 300, 300); @DesktopWidth, @DesktopHeight) $hWnd = WinGetHandle("GDI+") GUISetState() _GDIPlus_Startup() $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd) For $x = 1 To UBound($array, 1) - 1 For $y = 0 To UBound($array, 2) - 1 $col = "0xFF" & StringMid($array[$x][$y], 5, 2) & StringMid($array[$x][$y], 3, 2) & StringMid($array[$x][$y], 1, 2) ;BGR to RGB $hPen = _GDIPlus_PenCreate($col) ; _GDIPlus_GraphicsDrawEllipse($hGraphic, $y, $x, 1, 1, $hPen) Next Next Do Until GUIGetMsg() = $GUI_EVENT_CLOSE ; Ressourcen freigeben _GDIPlus_GraphicsDispose($hGraphic) _GDIPlus_Shutdown() Func _allpixel2array($bmpfile) ;returns a 2d array with the colours BGR _GDIPlus_Startup() $pBitmap = _GDIPlus_BitmapCreateFromFile($bmpfile) If @error Then MsgBox(0, "", "Fehler BitmapCreateFromFile") ;_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("byte[" & (Abs($stride) * ($Height)) & "]", $Scan0) $BMPDataStart = StringTrimLeft(DllStructGetData($pixeldata, 1), 2) ;string im Struct-format, d.h. Byte+nulByte, in dem die pixeldaten im BGR-Format stehen ; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $BMPDataStart = ' & StringLeft($BMPDataStart, 100) & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console Dim $array[$Height + 1][$Width + 1] For $y = 0 To $Height - 1 ;to 1 step -1 ;bottomup bitmap, first line in image is last line in data For $i = 0 To $stride * 2 Step 6 ;every 3 byte are one pixel $array[$y + 1][$i / 6] = StringMid($BMPDataStart, ($y * $stride * 2) + $i + 1, 6) ;ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $array[$y][$i / 6] = ' & $array[$y][$i / 6] & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console Next Next ; _arraydisplay($array) $BMPDataStart = "" $pixeldata = 0 _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData) _GDIPlus_ImageDispose($pBitmap) _WinAPI_DeleteObject($pBitmap) _GDIPlus_Shutdown() Return $array EndFunc ;==>_allpixel2array2i hope it helps little bit..... This was very useful too, however I wanted to be able to store the data in files for later use by my IS read function, although your example of how to draw the image back out was very nice. thank you all for your help [center][/center][center]=][u][/u][/center][center][/center]
laffo16 Posted May 10, 2010 Posted May 10, 2010 (edited) expandcollapse popup#include <GDIPlus.au3> _GetImagePixels(@ScriptDir & "\image.bmp", @ScriptDir & "\Test.txt") MsgBox(0, "", "pause to check if file is locked") Func _GetImagePixels($sImage, $sOutputFile) Local $hImage, $hBmp, $iW, $iH Local $tBD, $iWidth, $iHeight, $iStride, $iFmt Local $pData, $tPixels, $xBytes Local $avPixels, $hFile $hFile = FileOpen($sOutputFile, 2) If @error Then Return SetError(1, 1, 0) _GDIPlus_Startup() $hImage = _GDIPlus_ImageLoadFromFile($sImage) If @error Then Return SetError(1, 2, 0) $iW = _GDIPlus_ImageGetWidth($hImage) $iH = _GDIPlus_ImageGetHeight($hImage) $hBmp = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iW, $iH, $GDIP_PXF32ARGB) $tBD = _GDIPlus_BitmapLockBits($hBmp, 0, 0, $iW, $iH, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32ARGB) $iWidth = DllStructGetData($tBD, 1) $iHeight = DllStructGetData($tBD, 2) $iStride = DllStructGetData($tBD, 3) $iFmt = DllStructGetData($tBD, 4) $pData = DllStructGetData($tBD, 5) $tPixels = DllStructCreate("byte[" & $iW * $iH * 4 & "]", $pData) $xBytes = DllStructGetData($tPixels, 1) $sData = StringTrimRight(StringRegExpReplace(StringTrimLeft($xBytes, 2), "(.{" & 8 * $iWidth & "})", "\1@"), 1) $avData = StringSplit($sData, "@") FileWrite($hFile, StringRegExpReplace($avData[1], "(.{8})(?!$)", "\1|")) For $i = 2 To $avData[0] FileWrite($hFile, @CRLF & StringRegExpReplace($avData[1], "(.{8})(?!$)", "\1|")) Next FileClose($hFile) _GDIPlus_BitmapUnlockBits($hBmp, $tBD) _WinAPI_DeleteObject($hBmp) _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() EndFunc The bmp file seems to be locked after it is accessed with _GetImagePixels(), can anyone see any fault with the clean up mechanism which may cause the bmp to be locked? sorry im just no good with GDI stuff, i'll keep trying, pls reply if you understand the problem. edit: you must dispose of the BitmapCloneArea also, _GDIPlus_ImageDispose($hBmp) to release the image Edited May 10, 2010 by laffo16
Malkey Posted May 10, 2010 Posted May 10, 2010 expandcollapse popup#include <GDIPlus.au3> _GetImagePixels(@ScriptDir & "\image.bmp", @ScriptDir & "\Test.txt") MsgBox(0, "", "pause to check if file is locked") Func _GetImagePixels($sImage, $sOutputFile) Local $hImage, $hBmp, $iW, $iH Local $tBD, $iWidth, $iHeight, $iStride, $iFmt Local $pData, $tPixels, $xBytes Local $avPixels, $hFile $hFile = FileOpen($sOutputFile, 2) If @error Then Return SetError(1, 1, 0) _GDIPlus_Startup() $hImage = _GDIPlus_ImageLoadFromFile($sImage) If @error Then Return SetError(1, 2, 0) $iW = _GDIPlus_ImageGetWidth($hImage) $iH = _GDIPlus_ImageGetHeight($hImage) $hBmp = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iW, $iH, $GDIP_PXF32ARGB) $tBD = _GDIPlus_BitmapLockBits($hBmp, 0, 0, $iW, $iH, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32ARGB) $iWidth = DllStructGetData($tBD, 1) $iHeight = DllStructGetData($tBD, 2) $iStride = DllStructGetData($tBD, 3) $iFmt = DllStructGetData($tBD, 4) $pData = DllStructGetData($tBD, 5) $tPixels = DllStructCreate("byte[" & $iW * $iH * 4 & "]", $pData) $xBytes = DllStructGetData($tPixels, 1) $sData = StringTrimRight(StringRegExpReplace(StringTrimLeft($xBytes, 2), "(.{" & 8 * $iWidth & "})", "\1@"), 1) $avData = StringSplit($sData, "@") FileWrite($hFile, StringRegExpReplace($avData[1], "(.{8})(?!$)", "\1|")) For $i = 2 To $avData[0] FileWrite($hFile, @CRLF & StringRegExpReplace($avData[1], "(.{8})(?!$)", "\1|")) Next FileClose($hFile) _GDIPlus_BitmapUnlockBits($hBmp, $tBD) _WinAPI_DeleteObject($hBmp) _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() EndFunc The bmp file seems to be locked after it is accessed with _GetImagePixels(), can anyone see any fault with the clean up mechanism which may cause the bmp to be locked? sorry im just no good with GDI stuff, i'll keep trying, pls reply if you understand the problem. edit: you must dispose of the BitmapCloneArea also, _GDIPlus_ImageDispose($hBmp) to release the image Within your script replace $sData = StringTrimRight(StringRegExpReplace(StringTrimLeft($xBytes, 2), "(.{" & 8 * $iWidth & "})", "\1@"), 1) with $sData = StringTrimRight(StringRegExpReplace(StringTrimLeft($xBytes, 2), "(.{8})", "\1@"), 1) When you are finished with the bitmap object created with _GDIPlus_BitmapCloneArea(), you should release the bitmap object with either _GDIPlus_BitmapDispose (), or _GDIPlus_ImageDispose(). These two functions have the same workings.
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