Syruz Posted October 22, 2007 Share Posted October 22, 2007 Is there a way to search an area for the darkest pixel in it no matter what the color ends up being? Link to comment Share on other sites More sharing options...
PsaltyDS Posted October 22, 2007 Share Posted October 22, 2007 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 Link to comment Share on other sites More sharing options...
Syruz Posted October 22, 2007 Author Share Posted October 22, 2007 blacks and browns would be considered the darkest Link to comment Share on other sites More sharing options...
weaponx Posted October 22, 2007 Share Posted October 22, 2007 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 Link to comment Share on other sites More sharing options...
Blue_Drache Posted October 22, 2007 Share Posted October 22, 2007 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 Link to comment Share on other sites More sharing options...
weaponx Posted October 22, 2007 Share Posted October 22, 2007 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 Link to comment Share on other sites More sharing options...
Syruz Posted October 22, 2007 Author Share Posted October 22, 2007 (edited) 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 October 22, 2007 by Syruz Link to comment Share on other sites More sharing options...
weaponx Posted October 22, 2007 Share Posted October 22, 2007 (edited) 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 October 22, 2007 by weaponx Link to comment Share on other sites More sharing options...
PsaltyDS Posted October 22, 2007 Share Posted October 22, 2007 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 Link to comment Share on other sites More sharing options...
Blue_Drache Posted October 22, 2007 Share Posted October 22, 2007 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 Link to comment Share on other sites More sharing options...
weaponx Posted October 22, 2007 Share Posted October 22, 2007 Well then stick with the first version I posted. It converts the pixel color to grayscale for comparison. Link to comment Share on other sites More sharing options...
Blue_Drache Posted October 22, 2007 Share Posted October 22, 2007 Didn't notice that. Lofting the cyberwinds on teknoleather wings, I am...The Blue Drache Link to comment Share on other sites More sharing options...
PsaltyDS Posted October 22, 2007 Share Posted October 22, 2007 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: expandcollapse popup#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 $Input = Number(GUICtrlRead($Input_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 $Input = Number(GUICtrlRead($Input_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 Link to comment Share on other sites More sharing options...
weaponx Posted October 23, 2007 Share Posted October 23, 2007 PsaltyDS....ouch....drivebyI 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=brightnessI also tried converting this .NET code but the return values don't seem to match Photoshop:http://www.xtremevbtalk.com/showpost.php?p=746148expandcollapse popupRGB2HSL("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 Link to comment Share on other sites More sharing options...
Blue_Drache Posted October 23, 2007 Share Posted October 23, 2007 (edited) Does the VB code create values that match photoshop? Edited October 23, 2007 by Blue_Drache Lofting the cyberwinds on teknoleather wings, I am...The Blue Drache Link to comment Share on other sites More sharing options...
weaponx Posted October 23, 2007 Share Posted October 23, 2007 (edited) 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 October 23, 2007 by weaponx Link to comment Share on other sites More sharing options...
weaponx Posted October 23, 2007 Share Posted October 23, 2007 (edited) 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): expandcollapse popup$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 October 23, 2007 by weaponx Link to comment Share on other sites More sharing options...
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