Jump to content

Are there any way to get an array of pixelcolour almost instantly?


Recommended Posts

In javascript you can get all the pixel colours of a large image in and instant with canvas.getImageData

but for autoit pixelgetcolor only returns a single pixel hence i have to use a loop to get all pixelcolors of an image but it can take quite a long time if the image is large enough.

Are there any ways to get array of pixelcolour of an image quickly?

Link to comment
Share on other sites

2 hours ago, cyxstudio said:

get array of pixelcolour of an image

#include <ScreenCapture.au3>

$hBitmap = _ScreenCapture_Capture()

Global $tSize = _WinAPI_GetBitmapDimension($hBitmap), _
$iWidth = $tSize.X, $iHeight = $tSize.Y, $iIndex, _
$iSize = $iWidth * $iHeight, $aPixels[$iHeight][$iWidth], _
$tBits = DllStructCreate("dword[" & $iSize & "]")
_WinAPI_GetBitmapBits($hBitmap, 4 * $iSize, DllStructGetPtr($tBits))
_WinAPI_DeleteObject($hBitmap)
For $i = 0 To $iHeight - 1
  For $j = 0 To $iWidth - 1
    $iIndex += 1
    $aPixels[$i][$j] = DllStructGetData($tBits, 1, $iIndex)
  Next
Next

;~ #include <Array.au3>
;~ _ArrayDisplay($aPixels)

 

Edited by InnI
Link to comment
Share on other sites

@cyxstudio & @InnI

I would not recommend using _WinAPI_GetBitmapBits.  GetBitMapBits() is not impossible to use, but a lot harder because you need to "figure out" the format of the pixel information returned and extract the desired information.  There are lots of possible formats, it would be a pain.  Better use _WinAPI_GetDIBits.  GetDIBits will converts the pixel information from the stored format to any format you want.

But the best tool IMO remains GDI+.

 

Edited by Nine
Link to comment
Share on other sites

Hi,

the question is, why does anyone need an "AutoIt-Array of Pixels", every bitmap IS an array of width x height "pixels". 

So reading

$aPixels[$i][$j] = DllStructGetData($tBits, 1, $iIndex)

causes me physical pain...the slowest and wasteful memory method to "store" a bitmap...which is by the way loaded in RAM at this time...

Not that i prefer _GDIPlus_BitmapLockBits to get a pointer to a bitmap or CreateDIBSection (which gives you pointer/handle/DC...) but once you got the pointer, you can easily catch the color of the x- and y-koordinates by simply addressing it. 

$color = DllStructGetData($tBits, 1, ($Width*$y + $x)   ;x and y are the koordinates (0-based) of the "pixel" in the bitmap

 

Yes, AutoIt is very slow with calculations within nested loops, but dllstructgetdata() is as fast as $aPixels[$i][$j].

Very much faster are all native String-Functions in AutoIt. You can use them to find or manipulate "colors" in a bitmap:

$tBits = DllStructCreate("char[" & $iSize*4 & "]")  ;every ARGB is a "word" of 4 char

 gives you access to a "string". So a "pixelsearch" is easily and superfast done with a StringInstr()...

 

Edited by AndyG
Link to comment
Share on other sites

1 hour ago, AndyG said:

Very much faster are all native String-Functions in AutoIt. You can use them to find or manipulate "colors" in a bitmap:


$tBits = DllStructCreate("char[" & $iSize*4 & "]")  ;every ARGB is a "word" of 4 char

 gives you access to a "string". So a "pixelsearch" is easily and superfast done with a StringInstr()...

Hmmm, I am kind of skeptical.  You seem to pretend that we could use struct as an input to standard function of autoit like StringInStr().  Make my day, show me an example...

Link to comment
Share on other sites

12 hours ago, Nine said:

show me an example

Get an array of pixels of a certain color

#include <ScreenCapture.au3>
#include <Array.au3>

$iColor = 0xFF0000 ; red

$hBitmap = _ScreenCapture_Capture()
Global $iIndex, $tSize = _WinAPI_GetBitmapDimension($hBitmap), _
$iWidth = $tSize.X, $iHeight = $tSize.Y, $iSize = $iWidth * $iHeight, _
$aPixels[$iSize + 1][2]

; DllStructGetData test
$iTime = TimerInit()
$tBits = DllStructCreate("dword[" & $iSize & "]")
_WinAPI_GetBitmapBits($hBitmap, $iSize * 4, DllStructGetPtr($tBits))
For $i = 0 To $iHeight - 1
  For $j = 0 To $iWidth - 1
    $iIndex += 1
    If BitAND(DllStructGetData($tBits, 1, $iIndex), 0x00FFFFFF) = $iColor Then
      $aPixels[0][0] += 1
      $aPixels[$aPixels[0][0]][0] = $j
      $aPixels[$aPixels[0][0]][1] = $i
    EndIf
  Next
Next
ReDim $aPixels[$aPixels[0][0] + 1][2]
ConsoleWrite("DllStructGetData: " & Round(TimerDiff($iTime)) & "ms" & @CRLF)
_ArrayDisplay($aPixels)

; StringInStr test
$iTime = TimerInit()
$tBits = DllStructCreate('byte[' & $iSize * 4 & ']')
_WinAPI_GetBitmapBits($hBitmap, $iSize * 4, DllStructGetPtr($tBits))
$sText = StringTrimLeft(DllStructGetData($tBits, 1), 2)
$iStep = $iWidth * 8
Dim $aPixels[$iSize + 1][2], $aLines[$iHeight], $c = 0
For $i = 1 To StringLen($sText) Step $iStep
  $aLines[$c] = StringMid($sText, $i, $iStep)
  $c += 1
Next
Dim $iPos, $iStart, $iLen = StringLen($aLines[0])
$iColor = StringRegExpReplace(Hex($iColor, 6), "(.{2})(.{2})(.{2})", "$3$2$1")
For $i = 0 To $iHeight - 1
  $iStart = 1
  While $iStart <= $iLen
    $iPos = StringInStr($aLines[$i], $iColor, 1, 1, $iStart)
    If $iPos Then
      If Mod($iPos - 1, 8) Then
        $iStart = $iPos + 2
        ContinueLoop
      EndIf
      $aPixels[0][0] += 1
      $aPixels[$aPixels[0][0]][0] = ($iPos - 1) / 8
      $aPixels[$aPixels[0][0]][1] = $i
      $iStart = $iPos + 8
    Else
      ExitLoop
    EndIf
  WEnd
Next
ReDim $aPixels[$aPixels[0][0] + 1][2]
ConsoleWrite("StringInStr: " & Round(TimerDiff($iTime)) & "ms" & @CRLF)
_ArrayDisplay($aPixels)

_WinAPI_DeleteObject($hBitmap)

 

Link to comment
Share on other sites

@Nine AndyG is very much correct 

 

Local $iSize = 4096

Local $tBits = DllStructCreate("char[" & $iSize * 4 & "]") ;every ARGB is a "word" of 4 char

Local $sAlpha = "ACTG"

For $i = 1 To $iSize * 4
    DllStructSetData($tBits, 1, StringMid($sAlpha, Random(1, 4, 1), 1), $i)
Next

ConsoleWrite(StringInStr(DllStructGetData($tBits, 1), "TAGC") & @crlf)

@InnI Showoff :P

Edited by Bilgus
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...