# Search area for DARKEST pixel

## Recommended Posts

Is there a way to search an area for the darkest pixel in it no matter what the color ends up being?

##### Share on other sites

Is there a way to search an area for the darkest pixel in it no matter what the color ends up being?

No problem, as long as you can mathematically define "darkest", given that the pixel color is a 24-bit RGB number. For example, do you consider 0xFF0000 to be darker than 0x0000FF?

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

##### Share on other sites

blacks and browns would be considered the darkest

##### Share on other sites

Here is what I came up with...it isn't very fast, then again I have a 24 inch monitor at 1900 x 1200.

```#include <Color.au3>

\$result = FindDarkestPixel(0, 0, 400, 400)
MsgBox(0,"","Darkest pixel found at X: " & \$result[0] & " Y: " & \$result[1])

Func FindDarkestPixel(\$LL = 0, \$TT = 0, \$RR = @DesktopWidth, \$BB = @DesktopHeight)
Local \$darkest[2] = [0,0]
Local \$darkestColor = 255

For \$T = \$TT to \$BB
For \$L = \$LL to \$RR

\$result = PixelGetColor ( \$L , \$T )
\$grayscale = (_ColorGetBlue ( \$result ) + _ColorGetRed ( \$result ) + _ColorGetGreen ( \$result )) / 3
If \$grayscale < \$darkestColor Then
\$darkest[0] = \$L
\$darkest[1] = \$T
\$darkestColor = \$grayscale
EndIf

Next
Next

Return \$darkest
EndFunc```

##### Share on other sites

You'd have to write the equivalent of a guassian blur formula, where the program takes a pixel and then gets the values surrounding it in all 8 positions and compares each one. If it finds a darker one, jump to that pixel and re-compare.

OR

Start at the beginning of your bounding box and compare each pixel going forward, left to right and then down. Store the pixel colour value, go to the next one. If lower, re-store the value and continue, otherwise ... skip it.

Caveat Emptor: Browns are in the red/yellow range .... and if you have a brown next to your blue, the blue will read as "lower" with this method, due to the way that hex numbers are calculated. You may want to use the option that swaps the "normal" way of reading colour from 0xRGB to 0xBGR

Lofting the cyberwinds on teknoleather wings, I am...The Blue Drache

##### Share on other sites

Here is another version that doesn't use the _ColorGet functions:

```\$result = FindDarkestPixel(0, 0, 400, 400)
MsgBox(0,"","Darkest pixel found at X: " & \$result[0] & " Y: " & \$result[1])

Func FindDarkestPixel(\$LL = 0, \$TT = 0, \$RR = @DesktopWidth, \$BB = @DesktopHeight)
Local \$darkest[2] = [0,0]
Local \$darkestColor = 0xFFFFFF

For \$T = \$TT to \$BB
For \$L = \$LL to \$RR

\$grayscale = Hex(PixelGetColor ( \$L , \$T ))

If \$grayscale < \$darkestColor Then
\$darkest[0] = \$L
\$darkest[1] = \$T
\$darkestColor = \$grayscale
EndIf

Next
Next

Return \$darkest
EndFunc```

##### Share on other sites

Im assuming 400 by 400 is the measurements pixel wise of the search area?

Edit: Nvm, is there a way of changing that to search an area within a rectangle? Like Pixelsearch

Edited by Syruz

##### Share on other sites

You are correct. If speed is critical you could add a Step 2 or Step 3 to the For loops to skip a few pixels each time it checks; however, accuracy will be lost.

Edit: For clarification the parameters are absolute so FindDarkestPixel(LEFT, TOP, RIGHT, BOTTOM)

Edited by weaponx

##### Share on other sites

Here is another version that doesn't use the _ColorGet functions:

```\$result = FindDarkestPixel(0, 0, 400, 400)
MsgBox(0,"","Darkest pixel found at X: " & \$result[0] & " Y: " & \$result[1])

Func FindDarkestPixel(\$LL = 0, \$TT = 0, \$RR = @DesktopWidth, \$BB = @DesktopHeight)
Local \$darkest[2] = [0,0]
Local \$darkestColor = 0xFFFFFF

For \$T = \$TT to \$BB
For \$L = \$LL to \$RR

\$grayscale = Hex(PixelGetColor ( \$L , \$T ))

If \$grayscale < \$darkestColor Then
\$darkest[0] = \$L
\$darkest[1] = \$T
\$darkestColor = \$grayscale
EndIf

Next
Next

Return \$darkest
EndFunc```
By that comparison, the bright Green color 0x00FF00 is "darker" than the almost-black red of 0x010000. Simple numeric compares just won't do for this.

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

##### Share on other sites

One would have to do three comparisons. One for the blue channel, one for the green channel, one for the red channel and compare the hex values. (0x00 to 0xFF)

Lofting the cyberwinds on teknoleather wings, I am...The Blue Drache

##### Share on other sites

Well then stick with the first version I posted. It converts the pixel color to grayscale for comparison.

##### Share on other sites

Didn't notice that.

Lofting the cyberwinds on teknoleather wings, I am...The Blue Drache

##### Share on other sites

Well then stick with the first version I posted. It converts the pixel color to grayscale for comparison.

I see what you mean, and that's good if the OP accepts that mathematical definition of "darkest", but I don't think it produces visually natural results. For example, the following demo allows testing various values and comparing them side by side for visual "darkness". The default values that it starts with are 0x800080 and 0x00FF00. The second is mathematically "darker", but doesn't look that way on the screen:

```#include <guiconstants.au3>

Opt("GuiOnEventMode", 1)

Global \$Color_1 = 0x800080, \$Color_2 = 0x00FF00
\$hGUI = GUICreate("Test", 400, 300)
GUISetOnEvent(\$GUI_EVENT_CLOSE, "_Quit")

\$Graphic_1 = GUICtrlCreateGraphic(10, 10, 185, 185)
GUICtrlSetBkColor(-1, \$Color_1)
\$Input_1 = GUICtrlCreateInput("0x" & Hex(\$Color_1, 6), 10, 205, 185, 20)
\$Button_1 = GUICtrlCreateButton("Set Color 1", 30, 235, 145, 30)
GUICtrlSetOnEvent(-1, "_ButtonHit")

\$Graphic_2 = GUICtrlCreateGraphic(205, 10, 185, 185)
GUICtrlSetBkColor(-1, \$Color_2)
\$Input_2 = GUICtrlCreateInput("0x" & Hex(\$Color_2, 6), 205, 205, 185, 20)
\$Button_2 = GUICtrlCreateButton("Set Color 1", 225, 235, 145, 30)
GUICtrlSetOnEvent(-1, "_ButtonHit")

GUISetState()

While 1
Sleep(20)
WEnd

Func _ButtonHit()
Switch @GUI_CtrlId
Case \$Button_1
If \$Input <> \$Color_1 And \$Input >= 0 And \$Input <= 0xFFFFFF Then \$Color_1 = \$Input
GUICtrlSetBkColor(\$Graphic_1, \$Color_1)
GUICtrlSetData(\$Input_1, "0x" & Hex(\$Color_1, 6))
Case \$Button_2
If \$Input <> \$Color_2 And \$Input >= 0 And \$Input <= 0xFFFFFF Then \$Color_2 = \$Input
GUICtrlSetBkColor(\$Graphic_2, \$Color_2)
GUICtrlSetData(\$Input_2, "0x" & Hex(\$Color_2, 6))
EndSwitch
EndFunc

Func _Quit()
Exit
EndFunc```

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

##### Share on other sites

PsaltyDS....ouch....driveby

I was thinking about using HSB / HSL color format and using the lightness / brightness value for comparison but...converting to those values takes a lot of code and it's slow already.

I found this RGBtoHSL function here in the forum but it depends on another seperate UDF on top:

http://www.autoitscript.com/forum/index.ph...p;hl=brightness

I also tried converting this .NET code but the return values don't seem to match Photoshop:

http://www.xtremevbtalk.com/showpost.php?p=746148

```RGB2HSL("000255000")

Func RGB2HSL(\$pRGB)
\$pRGBR = StringLeft ( \$pRGB, 3)
\$pRGBG = StringMid ( \$pRGB,4, 3)
\$pRGBB = StringRight ( \$pRGB, 3)

Local \$Rd, \$Gd, \$Bd
Local \$Max, \$Min, \$Dif, \$Sum

;scale down the RGB color values to a 0-1 range
\$Rd = \$pRGBR / 255
\$Gd = \$pRGBG / 255
\$Bd = \$pRGBB / 255

;get the strongest color
\$Max = 0

If \$Rd > \$Max Then \$Max = \$Rd
If \$Gd > \$Max Then \$Max = \$Gd
If \$Bd > \$Max Then \$Max = \$Bd

;get the weakest color
\$Min = 1

If \$Rd < \$Min Then \$Min = \$Rd
If \$Gd < \$Min Then \$Min = \$Gd
If \$Bd < \$Min Then \$Min = \$Bd

;calculate Luminosity
\$HSLL = (\$Max + \$Min) / 2

If \$Max = \$Min Then ;the color is gray (all RGB values are equal)
\$HSLS = 0
;this is actually undefined
\$HSLH = 0
Else
\$Dif = (\$Max - \$Min)
\$Sum = (\$Max + \$Min)

;calculate Saturation
If \$HSLL > 0.5 Then
\$HSLS = \$Dif / \$Sum
Else
\$HSLS = \$Dif / (2 - \$Sum)
EndIf

;calculate Hue
Switch \$Max
Case \$Rd
\$HSLH = ((\$Gd - \$Bd) / \$Dif)
Case \$Gd
\$HSLH = ((\$Bd - \$Rd) / \$Dif) + 2
Case \$Bd
\$HSLH = ((\$Rd - \$Gd) / \$Dif) + 4
EndSwitch

\$HSLH = \$HSLH / 6

If \$HSLH < 0 Then \$HSLH = \$HSLH + 1

EndIf

;return the results
;Return = \$HSL
MsgBox(0,"","Luminosity: " & \$HSLL & @CRLF & "Saturation: " & \$HSLS & @CRLF & "Hue: " & \$HSLH)

EndFunc```

##### Share on other sites
Does the VB code create values that match photoshop? Edited by Blue_Drache

Lofting the cyberwinds on teknoleather wings, I am...The Blue Drache

##### Share on other sites

Didn't try it. I think it was .NET code and I don't have .NET Studio

But with the code I posted I entered this

R 0

G 255

B 0

Which returns:

B: .5

S: 1

H: .3333333333

Photoshop:

B: 100%

S: 100%

H: 120 degrees

Edited by weaponx

##### Share on other sites

This is my last submission...this version will convert each pixel into HSV / HSB format for comparison, using the brightness as the metric (very slow):

```\$result = FindDarkestPixel(0, 0, 200, 200)
MsgBox(0,"","Darkest pixel found at X: " & \$result[0] & " Y: " & \$result[1])

Func FindDarkestPixel(\$LL = 0, \$TT = 0, \$RR = @DesktopWidth, \$BB = @DesktopHeight)
Local \$darkest[2] = [0,0]
Local \$darkestValue = 100

For \$T = \$TT to \$BB
For \$L = \$LL to \$RR

;Store hex color code
\$nColor = Hex(PixelGetColor ( \$L , \$T ))

;Return HSV color value from decimal number converted to hex
\$HSV = RGB2HSL(BitAND( BitShift(\$nColor, 16), 0xff), BitAND( BitShift(\$nColor, 8), 0xff), BitAND(\$nColor, 0xff))

;If new color is darker, store its coordinates and its brightness value
If \$HSV[2] < \$darkestValue Then
\$darkest[0] = \$L
\$darkest[1] = \$T
\$darkestValue = \$HSV[2]
EndIf

Next
Next

Return \$darkest
EndFunc

;This function will return an array [0]:H [1]:S [2]:V
Func RGB2HSL(\$RRR, \$BBB, \$GGG)
Local \$H, \$S, \$V, \$largest
Local \$hsvArray[3] = [0,0,0]

;Determine highest component value
\$Max = 0

If \$RRR > \$Max Then
\$Max = \$RRR
\$largest = "R"
EndIf
If \$GGG > \$Max Then
\$Max = \$GGG
\$largest = "G"
EndIf
If \$BBB > \$Max Then
\$Max = \$BBB
\$largest = "B"
EndIf

;Determine lowest component value
\$Min = 1

If \$RRR < \$Min Then \$Min = \$RRR
If \$GGG < \$Min Then \$Min = \$GGG
If \$BBB < \$Min Then \$Min = \$BBB

;Color is grey
If \$Max = \$Min Then
\$H = 0
Else
;Determine Hue
Switch \$largest
Case "R"
\$H = 60 * (\$GGG - \$BBB) / (\$Max - \$Min)
Case "G"
\$H = 180 * (\$BBB - \$RRR) / (\$Max - \$Min)
Case "B"
\$H = 300 * (\$RRR - \$GGG) / (\$Max - \$Min)
Case Else
\$H = 0
EndSwitch
EndIf

;Determine Saturation
\$S = (\$Max - \$Min) / \$Max

;Determine Value
\$V = (\$Max / 255) * 100

;MsgBox(0,"","H:" & \$H & @CRLF & "S:" & \$S & @CRLF & "V:" & \$V)
\$hsvArray[0] = \$H
\$hsvArray[1] = \$S
\$hsvArray[2] = \$V

Return \$hsvArray
EndFunc```
Edited by weaponx

## Create an account

Register a new account

• ### Recently Browsing   0 members

×

• Wiki

• Back

• #### Beta

• Git
• FAQ
• Our Picks
×
• Create New...