Sign in to follow this  
Followers 0
Matthy

PixelGetColor in a image

14 posts in this topic

#1 ·  Posted (edited)

hi,

i want to use the PixelGetColor to sort out images. but i have a problem.

this type of colorgetting needs the X and a Y of your screen, and i want to run it at the background.

in the help file i have seen something about a handle but can find how to use it.

Example.

i want to read the pixels a image on my pc (script dir) like test.jpg

and check how many black pixels it has. it is possible with using the whole screen but then i cant do other stuff next to it.

and have to let my pc on in the night.

Meaby its very simple using the handle but dont know how to use that.

anyone?

Thanks

Matthy

EDIT:

tried finding the handle of image prview in Autoit window info but it keeps changing so i dont think i can use that. or can i?

Edited by Matthy

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

So you want a pixel finder / counter, to search a minimized or non-visible window?

(Just trying to clarify things for future people)

just found this:

You can't do Pixel functions on a Non-Focused window.

Edited by igotandrew

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

hi,

i want to use the PixelGetColor to sort out images. but i have a problem.

this type of colorgetting needs the X and a Y of your screen, and i want to run it at the background.

in the help file i have seen something about a handle but can find how to use it.

Example.

i want to read the pixels a image on my pc (script dir) like test.jpg

and check how many black pixels it has. it is possible with using the whole screen but then i cant do other stuff next to it.

and have to let my pc on in the night.

Meaby its very simple using the handle but dont know how to use that.

anyone?

Thanks

Matthy

EDIT:

tried finding the handle of image prview in Autoit window info but it keeps changing so i dont think i can use that. or can i?

Black is colour 0x000000, in the RGB and BGR colour systems.

0x010101 may look black, and if searching for black,0x000000 will not find 0x010101.

This example scripts finds all colours in an image file below 0x202020. You may be able to change it to suit your needs.

;=========================================================
; Produces an array of pixel colours used in an image that are below the colour 0x202020 (array[n][0]),
; Number of times that colour is used (array[n][1]), and,
; the percentage of the numer of times the colour is used over the total number of pixels in the image (array[n][2]).
; Array[0][0] contains the number of unique pixels used in the image below 0x202020 colour.
; Array[0][1] contains the total number of pixels used in the image below 0x202020 colour.
; Array[0][2] contains the percentage of the total number of pixels used in the image below 0x202020 colour.
;============================================================

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

Dim $pixels, $iTotalReplace
Local $Path = FileOpenDialog("Choose Image File", @ScriptDir & "", "Images (*.gif;*.png;*.jpg;*.bmp)| All (*.*)")
If $Path <> "" Then
    _GDIPlus_Startup()

    $hImage = _GDIPlus_ImageLoadFromFile($Path)
    $width = _GDIPlus_ImageGetWidth($hImage)
    $height = _GDIPlus_ImageGetHeight($hImage)
    $hBmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)

    $aSize = DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $hBmp, 'int', 0, 'ptr', 0)
    If $aSize[0] Then
        $tBits = DllStructCreate('byte[' & $aSize[0] & ']')
        DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $hBmp, 'int', $aSize[0], 'ptr', DllStructGetPtr($tBits))
        $sHex = Hex(DllStructGetData($tBits, 1))

        ; Selects all pixels below/less than 0x202020
        $pixels = StringRegExp($sHex, "([01][0-9A-F][01][0-9A-F][01][0-9A-F])FF", 3)
        
        ; Selects all pixels below/less than 0x505050 (Can take a while)
        ;$pixels = StringRegExp($sHex, "([0-5][0-9A-F][0-5][0-9A-F][0-5][0-9A-F])FF", 3)
        
        $sHexReduced = _ArrayToString($pixels) & "|"

        Dim $pixels[1][3]
        While StringLen($sHexReduced) > 6
            ReDim $pixels[UBound($pixels) + 1][3]
            $PixTemp = StringLeft($sHexReduced, 7)
            $sHexReduced = StringReplace($sHexReduced, $PixTemp, "", 0)
            $numreplacements = @extended

            $pixels[UBound($pixels) - 1][1] = $numreplacements
            $pixels[UBound($pixels) - 1][0] = StringTrimRight($PixTemp, 1)
            $pixels[UBound($pixels) - 1][2] = StringFormat("%1.4f%%", $numreplacements * 100 / ($height * $width))
            $iTotalReplace += $numreplacements

        WEnd
        $pixels[0][0] = UBound($pixels) - 1
        $pixels[0][1] = $iTotalReplace
        $pixels[0][2] = StringFormat("%1.4f%%", $iTotalReplace * 100 / ($height * $width))
    EndIf
    _ArraySort($pixels, 0, 1, 0, 0)
    _ArrayDisplay($pixels,$Path)
    _WinAPI_DeleteObject($hBmp)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_Shutdown()
EndIf

Edit: Added & "|" to $sHexReduced = _ArrayToString($pixels) & "|" . At the end of the loop $sHexReduced is now empty.

Edited by Malkey

Share this post


Link to post
Share on other sites

Many thanks this was exactly what i was looking for :)

Matthy

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

omg. Don't think that possible.

Have same request for other colors, is possible to implement sort of color picker ?

(for set color range +-)

m.

Edited by myspacee

Share this post


Link to post
Share on other sites

Awesome!!

8)


NEWHeader1.png

Share this post


Link to post
Share on other sites

omg. Don't think that possible.

Have same request for other colors, is possible to implement sort of color picker ?

(for set color range +-)

m.

look at

$pixels = StringRegExp($sHex, "([01][0-9A-F][01][0-9A-F][01][0-9A-F])FF", 3)

here you can set your colour :)

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

thank you Matthy,

but need help to understand 'conversion' between human readable 'color' value and script string...

help us a little more ? :)

m.

Edited by myspacee

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

I think you need to start reading on as there is a lot on colors and RGB

http://www.w3schools.com/Html/html_colors.asp

http://en.wikipedia.org/wiki/RGB_color_model

http://en.wikipedia.org/wiki/RGB_color_space

http://www.rgbworld.com/color.html

Summarized using cubes of http://en.wikipedia.org/wiki/RGB_color_space

A color in RGB can be visualised as a cube.

The cube consists of 256*256*256 different colors.

If you have defined to know/see 8 human readable colors you should imagine the cube to consist of 8 equal cubes within the total cube.

This means 4 cubes you can see if you look to the front of the cube.

Lets call them cube 1 thru 4 the ones you see on the front and 5 thru 8 on the back. (5 is behind 1)

Internal cube 1 can then be defined as yellow which are then all colors in the R > 128, G >128, B < 128

Internal cube 5 can then be defined as red which are then all colors in the R > 128 , G < 128, B < 128

** Note calculation above is not fully correct as the human eye interprets colors a little different

Edited by junkew

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Based on the cube definition of yellow

yellow = R from 80 thru FF, G from 80 thru FF, B from 0 thru 80

Unclear why there is an FF at the end but as it was in the original example I left it there

; Selects all pixels beeing "yellow"
  $pixels = StringRegExp($sHex, "([8-9A-F][0-9A-F][8-9A-F][0-9A-F][0-8][0-9A-F])FF", 3)
Edited by junkew

Share this post


Link to post
Share on other sites

ok, try to read rgb materials find around.

In our production we work with CMYK, i know is a good exercise for me,

but anyone has Malkey_junkew conversion already done for these colors/standard ?

(Read a lot also for imagemagick, but Autoit is my favourite choice)

thank you all,

m.

Share this post


Link to post
Share on other sites

Unclear why there is an FF at the end but as it was in the original example I left it there

If you look at the raw data in the string $sHex, it looks like the image has loaded with 32 bit colours with a RRGGBBAA colour format. The AA being the alpha channel. All the colours have "FF" in the alpha channel meaning that the RGB colour is fully opaque. The search only needed to return the RGB colour. This is my explanation of what I found in the $sHex string, and I hope that the colours are not really in ARGB format, and I've screwed something up.

ok, try to read rgb materials find around.

In our production we work with CMYK, i know is a good exercise for me,

but anyone has Malkey_junkew conversion already done for these colors/standard ?

(Read a lot also for imagemagick, but Autoit is my favourite choice)

thank you all,

m.

Here is an example of two functions

One converts RGB to CMYK - the RGBToCMYK () function, and the other

converts CMYK to RGB - the CMYKToRGB () function.

It is not completely accurate. A small error can be seen on some of the darker colours.

#include <Math.au3>

$Black = RGBToCMYK("000000")
$Yellow = RGBToCMYK("FFFF00")
$Mag = RGBToCMYK("FF00FF")
$Cyan = RGBToCMYK("00FFFF")
$Mar = RGBToCMYK("8B1C62")
$Dark = RGBToCMYK("011C02")

MsgBox(0, "Converts RGB Colour to CMYK and then converts CMYK to RGB", _
        "RGB Colour black   0x000000 = CMYK " & $Black & "  -> RGB " & CMYKToRGB($Black) & @CRLF & @CRLF & _
        "RGB Colour yellow  0xFFFF00 = CMYK " & $Yellow & "  -> RGB " & CMYKToRGB($Yellow) & @CRLF & @CRLF & _
        "RGB Colour magenta 0xFF00FF = CMYK " & $Mag & "  -> RGB " & CMYKToRGB($Mag) & @CRLF & @CRLF & _
        "RGB Colour cyan    0x00FFFF = CMYK " & $Cyan & "  -> RGB " & CMYKToRGB($Cyan) & @CRLF & @CRLF & _
        "RGB Colour maroon  0x8B1C62 = CMYK " & $Mar & "  -> RGB " & CMYKToRGB($Mar) & @CRLF & @CRLF & _
        "RGB a dark colour  0x011C02 = CMYK " & $Dark & "  -> RGB " & CMYKToRGB($Dark) & @CRLF & @CRLF)

;http://www.autoitscript.com/forum/index.php?s=&showtopic=54567&view=findpost&p=413494
; RGBToCMYK()  by  corz
;
; Very simple calculations. Basically, rgb is "additive" color, and
; CMYK is "subtractive", in other words, with CMYK, you start with
; white, and work up to black (paper) substracting brightness; and
; with rgb, you start with black, and work up to white (peecee monitor),
; adding brightness. So it's the same, but backwards. You could do it
; on your fingers.
;
; Set the optional second paramter to True get the values "normalized",
; that is, re-scaled to percentages, which is a commonly found CMYK format.
;
; Returns a comma-delimited string; "c,m,y,k", e.g. "0.761,0.08,0,0.016"
; By the way, that same value "normalized", is..    "76.1,8,0,1.6"
; Modified Malkey
Func RGBToCMYK($rgb_color, $norm = 1)
    If $rgb_color = "000000" Then
        Local $k = 1, $c = 0, $m = 0, $y = 0
    Else
        ; get decimal rgb values and scale to 0-1..
        $rc_r = (Dec(StringLeft($rgb_color, 2))) / 255
        $rc_g = Dec(StringMid($rgb_color, 3, 2)) / 255
        $rc_b = Dec(StringRight($rgb_color, 2)) / 255
        ConsoleWrite("$rc_b  " & $rc_b & @CR)
        $k = _Min(_Min(1 - $rc_r, 1 - $rc_g), 1 - $rc_b)
        ConsoleWrite(" $k  " & $k & @CR)
        $c = (1 - $rc_r - $k) / (1 - $k)
        $m = (1 - $rc_g - $k) / (1 - $k)
        $y = (1 - $rc_b - $k) / (1 - $k)
        ConsoleWrite(" $y  " & $y & @CR)
    EndIf
    If $norm Then
        Return Round($c * 100, 1) & ", " & Round($m * 100, 1) & ", " & Round($y * 100, 1) & ", " & Round($k * 100, 1)
    Else
        Return Round($c, 3) & ", " & Round($m, 3) & ", " & Round($y, 3) & ", " & Round($k, 3)
    EndIf
EndFunc   ;==>RGBToCMYK

; Not by corz
Func CMYKToRGB($cmyk_color)
    Local $k, $rc_r, $rc_g, $rc_b, $rgb_color
    $aCMCK = StringRegExp(StringStripWS($cmyk_color, 8) & ",", "([0-9.]+),", 3)
    If $aCMCK[3] > 1 Or $aCMCK[0] > 1 Or $aCMCK[1] = 0 Or $aCMCK[2] > 1 Then
        $aCMCK[0] = $aCMCK[0] / 100
        $aCMCK[1] = $aCMCK[1] / 100
        $aCMCK[2] = $aCMCK[2] / 100
        $aCMCK[3] = $aCMCK[3] / 100
    EndIf
    If $aCMCK[3] = 1 And $aCMCK[0] = 0 And $aCMCK[1] = 0 And $aCMCK[2] = 0 Then
        $rgb_color = "000000"
    Else
        $k = $aCMCK[3]
        $rc_r = ($aCMCK[0] - 1) * (-1 + $k) * 255
        $rc_g = ($aCMCK[1] - 1) * (-1 + $k) * 255
        $rc_b = ($aCMCK[2] - 1) * (-1 + $k) * 255
        $k = $k * 255
        If $rc_r < 0 Then $rc_r = $k
        If $rc_g < 0 Then $rc_g = $k
        If $rc_b < 0 Then $rc_b = $k
        $rgb_color = Hex(Ceiling($rc_r), 2) & Hex(Ceiling($rc_g), 2) & Hex(Ceiling($rc_b), 2)
    EndIf
    Return $rgb_color
EndFunc   ;==>CMYKToRGB

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

This is a slightly modified version of my first reply with an added routine that shows the X Y positions of the found colours from the image file.

It takes a longer time to complete.

;=========================================================
; Produces two arrays:-
;First array contains the pixel colours used in an image that are below the colour 0x101010 (array[n][0]),
; Number of times that colour is used (array[n][1]), and,
; the percentage of the numer of times the colour is used over the total number of pixels in the image (array[n][2]).
; Array[0][0] contains the number of unique pixels used in the image below 0x101010 colour.
; Array[0][1] contains the total number of pixels used in the image below 0x101010 colour.
; Array[0][2] contains the percentage of the total number of pixels used in the image below 0x202020 colour.
; Second array contains all the pixel colours used in an image that are below the colour 0x101010 (array2[n][0]), and
; array2[n][1] contains the X position of the pixel colour in array2[n][0], and
; array2[n][2] contains the Y position of the pixel colour in array2[n][0].
; The more colours found, the longer time it is going to take to complete.
;============================================================

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

Dim $pixels, $iTotalReplace,$Count = 0
Local $Path = FileOpenDialog("Choose Image File", @ScriptDir & "", "Images (*.gif;*.png;*.jpg;*.bmp)| All (*.*)")
If $Path <> "" Then
    _GDIPlus_Startup()
    $hImage = _GDIPlus_ImageLoadFromFile($Path)
    $width = _GDIPlus_ImageGetWidth($hImage)
    $height = _GDIPlus_ImageGetHeight($hImage)
    $hBmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    $aSize = DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $hBmp, 'int', 0, 'ptr', 0)
    If $aSize[0] Then
        $tBits = DllStructCreate('byte[' & $aSize[0] & ']')
        DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $hBmp, 'int', $aSize[0], 'ptr', DllStructGetPtr($tBits))
        $sHex = Hex(DllStructGetData($tBits, 1))
        $sHex = StringRegExpReplace($sHex, "([[:xdigit:]]{6})(FF)", "\1|")

        ; Find all green pixels, 0x00FF00
        ;$pixels = StringRegExp($sHex, "(00FF00)\|", 3)

        ; Find all black pixels, 0x000000
        ;$pixels = StringRegExp($sHex, "([0]{6})\|", 3)

        ; Selects all pixels below/less than 0x101010
        $pixels = StringRegExp($sHex, "([0][0-9A-F][0][0-9A-F][0][0-9A-F])\|", 3)

        ; Selects all pixels below/less than 0x505050 (Can take a while)
        ;$pixels = StringRegExp($sHex, "([0-5][0-9A-F][0-5][0-9A-F][0-5][0-9A-F])\|", 3)

        $sHexReduced = _ArrayToString($pixels) & "|"
        Dim $pixels[20000][3] ; Max No. of entries in an array is 16,777,216
        While StringLen($sHexReduced) > 6
            ;ReDim $pixels[UBound($pixels) + 1][3]
            $PixTemp = StringLeft($sHexReduced, 7)
            $sHexReduced = StringReplace($sHexReduced, $PixTemp, "", 0)
            $numreplacements = @extended
            $Count += 1
            $pixels[$Count][1] = $numreplacements
            $pixels[$Count][0] = StringTrimRight($PixTemp, 1)
            $pixels[$Count][2] = StringFormat("%1.4f%%", $numreplacements * 100 / ($height * $width))
            $iTotalReplace += $numreplacements
        WEnd
        $pixels[0][0] =  $Count
        $pixels[0][1] = $iTotalReplace
        $pixels[0][2] = StringFormat("%1.4f%%", $iTotalReplace * 100 / ($height * $width))
        ReDim $pixels[$Count + 1][3]        
        
        ;==== Find x y positions of the colours in the array ======     
        Dim $colPos[$iTotalReplace + 1][3]
        $colPos[0][0] = "Colour"
        $colPos[0][1] = "X Pos"
        $colPos[0][2] = "Y Pos"
        Local $Count = 0
        For $n = 1 To $pixels[0][0]
            For $Rep = 1 To $pixels[$n][1]
                $Count += 1
                $colPos[$Count][0] = $pixels[$n][0]
                $Pos = (StringInStr($sHex, $pixels[$n][0], 0, $Rep) - 1) / 7
                $colPos[$Count][2] = Int($Pos / $width) ; Y Pos
                $colPos[$Count][1] = ($Pos - ($colPos[$Count][2] * $width)); X Pos
            Next
        Next
        ;=====> End of Find x y positions =====
        
    EndIf
    _ArraySort($pixels, 0, 1, 0, 0)
    _ArraySort($colPos, 0, 1, 0, 2)
    _ArraySort($colPos, 0, 1, 0, 1)
    _ArrayDisplay($pixels, $width & "x" & $height & $Path)
    _ArrayDisplay($colPos, $width & "x" & $height & $Path)
    _WinAPI_DeleteObject($hBmp)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_Shutdown()
EndIf

Edit: Removed ReDim from inside loop.

Edited by Malkey

Share this post


Link to post
Share on other sites

without words.

m.

Share this post


Link to post
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
Sign in to follow this  
Followers 0