corz.org text viewer..
[currently viewing: /public/machine/source/windows/AutoIt Includes/corz_colors.au3 - raw]
#include-once
#include "corz_essentials.au3"
#include <misc.au3>

#cs

  corz color functions v0.4
  miscellaneous functions for manipulating colors and their values

  (c) cor + corz.org 2007->tomorrow!


    function list..

        ConvertColorValue( string{RGB hex color value}, string{output mode} [, boolean{add prefix=false} [, GUI-bool{lower-case]]})

        RGBToCMYK( string{hex rgb color[, bool{normalize to percentage}])

        RGBToHSL( string{hex rgb color)[, int{index to return}])

        RegColorToRGBHexColor()

        ; standard UDF (Color.au3) functions..
        GetColorRed($nColor)
        GetColorGreen($nColor)
        GetColorBlue($nColor)

        ColorChooser(array {Custom Colors}, HWND {Ownder})

#ce



;
; ConvertColorValue()
;
; Accepts a standard RGB hex color value, returns something else.
; This does not convert colors, it converts color *values* ..
;
; Available modes (values are case-insensitive)..
;
;        Web RGB Hex        use:    nothing (if no prefix is required), else use: "Web Hex""Web""Hex", or "w"
;        AutoIt:            use:    "Autoit RGB Hex""Autoit RGB""AutoIt Hex""AutoIt", or "a"
;        AutoIt GBR:        use:    "Autoit BGR Hex""Autoit BGR""BGR Hex", or "bgr", or "b"
;        Visual C++:        use:    "Visual C++ Hex""Visual C++ BGR""Visual C++""Visual C++ BGR Hex""C++", or "vc"
;        Delphi:            use:    "Delphi""Delphi hex", or "d"
;        RGB Integer:    use:    "RGB Integer""RGB Int""int", or "i"
;        RGB Float:        use:    "RGB Float""float", or "f"
;        Hue/Sat/Lum:    use:    "Hue/Sat/Lum""HSL", or "h"
;        CMYK:            use:    "cmyk", or "k"
;
; If no mode, or an incorrect mode is specified, ConvertColorValue() returns
; the original plain RGB hex value
;
; The third (optional) paramterer is the prefix, defaults to false.
; If set to true, the standard prefix, where applicable, is added to the
; output. eg, FF00FF becomes #FFOOFF. Currently only web hex and Delphi
; formats have a prefix. You can also use a checkbox boolean value for the
; prefix parameter. In other words, you can send a 4 for false.
;
; There is a special usage of the prefix option; if you request a CMYK value,
; and specify a prefix, you get the value "normalized", that is, re-scaled to
; percentages, which is a commonly found CMYK format.
;
; The optional fourth parameter ($index) only works when retrieving decimal
; (integer) color values ("i") You can supply the color index you wish to
; retrieve; 1=red value, 2=green value, 3=blue value.
;
; To retrieve individual HSL values, use RGBToHSL() directly (see below).
;
; ConvertColorValue() Returns a ready-to-use string (or integer, depending)
; of the required color value. Decimal, Float, CMYK, and HSL values are
; delimited by a comma, e.g. "124,90,64" (HSL: Hue:0-360,Sat:0-100,Lum: 0-100)
;
; If you want a color for use in dll calls, the Visual C++ value is the one
; you want (use "vc", or "v")
;
; The 5th parameter is Case. $ON = lower case, $OFF = UPPER CASE.
;
func ConvertColorValue($color$mode="web"$prefix=false, $index=0, $lowercase=$OFF)
    if StringLeft($color, 1) = "#" then $color = StringTrimLeft($color, 1)
    $pre = ""
    switch $mode
        ; the more long-winded options enable us to easily use human-readable names in the code
        ; utilizing the text of the menu options directly..
        case "i""RGB Integer""RGB Int""int"
            switch $index
                case 0
                    $color = Dec(StringLeft($color, 2)) & "," & Dec(StringMid($color, 3, 2)) & "," & Dec(StringRight($color, 2))
                case 1
                    return Dec(StringLeft($color, 2))
                case 2
                    return Dec(StringMid($color, 3, 2))
                case 3
                    return Dec(StringRight($color, 2))
            endswitch
        case "a""Autoit RGB Hex""Autoit RGB""AutoIt Hex""AutoIt"
            $color = '0x' & $color

        case "b""Autoit BGR Hex""Autoit BGR""BGR Hex""bgr"
            $color = '0x' & StringRight($color, 2) & StringMid($color, 3, 2) & StringLeft($color, 2)

        case "d""Delphi""Delphi Hex"
            $color = "00" & StringRight($color, 2) & StringMid($color, 3, 2) & StringLeft($color, 2)
            $pre = "$"

        case "v""vc""Visual C++ Hex""Visual C++ BGR""Visual C++""Visual C++ BGR Hex""C++"
            $color = "0x00" & StringRight($color, 2) & StringMid($color, 3, 2) & StringLeft($color, 2)

        case "RGB Float""float""f"
            $r = Round((1/255) * Dec(StringLeft($color, 2)), 2)
            $g = Round((1/255) * Dec(StringMid($color, 3, 2)), 2)
            $b = Round((1/255) * Dec(StringRight($color, 2)),2)
            $color = StringFormat("%#.2f"$r) & "," & StringFormat("%#.2f"$g) & "," & StringFormat("%#.2f"$b)

        case "h""Hue/Sat/Lum""HSL""h/s/l"
            $color = RGBToHSL($color",", 100)

        case "k""cmyk""c/m/y/k"
            if $prefix = 1 then
                $color = RGBToCMYK($color, true)
            else
                $color = RGBToCMYK($color)
            endif

        case "w""Web Hex""Web""Hex"
            $pre = "#"

    endswitch
    if not $prefix or $prefix = 4 then $pre = ""
    if $lowercase = $ON then $color = StringLower($color)
    return $pre & $color
endfunc


;
; RGBToCMYK()
;
; 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"
;
func RGBToCMYK($rgb_color$norm=0)

    ; get decimal rgb values and scale to 0-1..
    $rc_r = ConvertColorValue($rgb_color"i", 0, 1) / 255
    $rc_g = ConvertColorValue($rgb_color"i", 0, 2) / 255
    $rc_b = ConvertColorValue($rgb_color"i", 0, 3) / 255

    $k = MinMin(1-$rc_r, 1-$rc_g, 1-$rc_b)

    $c = (1 - $rc_r - $k) / ( 1 - $k)
    $m = (1 - $rc_g - $k) / ( 1 - $k)
    $y = (1 - $rc_b - $k) / ( 1 - $k)

    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


;
; RGBToHSL()
;
; Calculate an HSL color from an RGB color
;
; Returns a 4-element AutoIt array with element zero being the total (3)
; and the three HSL integer values..
;
;    [3, Hue (0-360 degrees), Saturation (0-1), Luminance/Lightness (0-1)]
;
; You can also specify an optional second paramter; index, being either
; 1, 2, or 3, to return ONLY Hue, Saturation, or Lightness, respectively.
;
; If you specify an index, the return value will be a single float/integer.
;
; There is also a special usage for index, which gets you back the HSL
; as a string, delimited by whatever character you set as the index value.
;
; HSL values come in all sorts of weird scales, sometimes percentages,
; sometimes 0-240, or 0-255, and others. You can deal with that at your end; or
; else feed RGBToHSL the optional third parameter, which automatically multiplies
; the Saturation and Lightness by whatever you like. 100 is common. Hue values
; are always returned in degrees, though it would be easy enough to hack that.
;
; Usage.
;
;    To retrieve the HSL as an AutoIt array..
;
;        $color_array = RGBToHSL($my_hex_color)
;
;    To retrieve the Lightness of an RGB Hex value..
;
;        $lightness = RGBToHSL($my_hex_color, 3)
;
;    To get back the HSL as a comma-delimited string..
;
;        RGBToHSL("650003"",")     [ returns:    "358,1.0,0.2" - a dark brown]
;
;
func RGBToHSL($rgb_color$idx=""$simple_array=false, $hsl_scale=1)

    $rh_r = ConvertColorValue($rgb_color"i", 0, 1) / 255
    $rh_g = ConvertColorValue($rgb_color"i", 0, 2) / 255
    $rh_b = ConvertColorValue($rgb_color"i", 0, 3) / 255

    $rh_min = MinMin($rh_r$rh_g$rh_b)
    $rh_max = MaxMax($rh_r$rh_g$rh_b)
    $rh_delta = $rh_max - $rh_min

    if $idx <> 1 then ; every little helps

        ; not perfect, this, but it's the standard method..
        $rh_lightness = ($rh_min + $rh_max) / 2
        if $idx = 3 then return Round($rh_lightness*$hsl_scale, 2)

        $rh_saturation = 0
        if $rh_lightness > 0 and $rh_lightness < 1 then
            if $rh_lightness < 0.5 then
                $rh_saturation = $rh_delta / (2 * $rh_lightness)
            else
                $rh_saturation = $rh_delta / (2 - 2 * $rh_lightness)
            endif
        endif
        if $idx = 2 then return Round($rh_saturation*$hsl_scale, 2)
    endif

    $rh_hue = 0
    if $rh_delta > 0 then
        if $rh_max = $rh_r and $rh_max <> $rh_g then
            $rh_hue += ($rh_g - $rh_b) / $rh_delta
        endif
        if $rh_max = $rh_g and $rh_max <> $rh_b then
            $rh_hue += 2 + ($rh_b - $rh_r) / $rh_delta
        endif
        if $rh_max = $rh_b and $rh_max <> $rh_r then
            $rh_hue += 4 + ($rh_r - $rh_g) / $rh_delta
        endif
        $rh_hue *= 60
    endif
    if $rh_hue < 0 then $rh_hue += 360 ; hack
    if $idx = 1 then return Round($rh_hue)

    $do_string = true
    if not $idx then
        $idx = ","
        $do_string = false
    endif

    local $hsl_arr[3]
    $hsl_arr[0] = Round($rh_hue)
    $hsl_arr[1] = Round($rh_saturation*$hsl_scale, 2)
    $hsl_arr[2] = Round($rh_lightness*$hsl_scale, 2)
    $hsl = $hsl_arr[0] & $idx & $hsl_arr[1] & $idx & $hsl_arr[2]

    if $do_string then return $hsl
    if $simple_array then return $hsl_arr
    return StringSplit($hsl$idx)
endfunc



; convert windows registry color to RGB Hex..
;
func RegColorToRGBHexColor($RegVal)
    $col = StringSplit($RegVal" ")
    if $col[0] < 2 then return ""
    return Hex($col[1], 2) & Hex($col[2], 2) &  Hex($col[3], 2)
endfunc



; returns an array with three elements (R, G, B)
func ConvertRGBtoDecArray($color)
    local $c_arr[3]
    $c_arr[0] = Dec(StringLeft($color, 2))
    $c_arr[1] = Dec(StringMid ($color, 3 , 2))
    $c_arr[2] = Dec(StringRight($color, 2))
    return $c_arr
endfunc



; I have other color conversion functions ;o)






; The standard AutoIt UDF color functions
; re-named and here for convenience
;
Func GetColorRed($nColor)
    Return BitAND(BitShift($nColor, 16), 0xff)
EndFunc

Func GetColorGreen($nColor)
    Return BitAND(BitShift($nColor, 8), 0xff)
EndFunc

Func GetColorBlue($nColor)
    Return BitAND($nColor, 0xff)
EndFunc





; ColorChooser() By Cor
;
; An alternative version of the system color chooser dialog function.
; This version can store and retrieve the 16 custom colors. Nifty.
;
; Send an array of 17 AutoIt RGB (e.g. 0xF0EBC3) colors, the first $array[0] being the
; color you wish to initially set in the picker, and the other 16, any custom colors
; you want to set. Empty values can be set to 0.
;
; Returns an array of 17 colors, $array[0] being the color "picked", and the other 16,
; any custom colors the user may have chosen. You can, of course, store these and then
; send them back to the color picker the next time it is called. At last! Store them
; in an ini file or wimilar and use them after next launch.
;
; NOTE: This function accepts and returns AutoIt RGB colors. If you need to convert to
; and from other color values, use ConvertColorValue(above)
;
func ColorChooser($CustomColors=0, $hWndOwnder=0)

    if not IsArray($CustomColors) or Ubound($CustomColors) < 17 then
        $CustomColors = StringSplit("0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"",", 2)
    endif

    local $ret_array[17], $color_picked$aResult

    local $custcolors = "int ccolors[16]"
    local $col_STRUCT = "dword Size;hwnd hWndOwnder;handle hInstance;dword rgbResult;ptr CustColors;dword Flags;lparam lCustData;ptr lpfnHook;ptr lpTemplateName"
    local $tChoose = DllStructCreate($col_STRUCT)
    local $tcc = DllStructCreate($custcolors)

    $CustomColors[0] = '0x' & StringMid($CustomColors[0], 7, 2) & StringMid($CustomColors[0], 5, 2) & StringMid($CustomColors[0], 3, 2)

    DllStructSetData($tChoose"Size", DllStructGetSize($tChoose))
    DllStructSetData($tChoose"hWndOwnder"$hWndOwnder)
    DllStructSetData($tChoose"rgbResult"$CustomColors[0])
    DllStructSetData($tChoose"CustColors", DllStructGetPtr($tcc))
    DllStructSetData($tChoose"Flags", BitOR($__MISCCONSTANT_CC_ANYCOLOR$__MISCCONSTANT_CC_FULLOPEN$__MISCCONSTANT_CC_RGBINIT))

    for $i = 1 to 16 ; set the custom colors..
        $ccolor = Dec(StringMid($CustomColors[$i], 7, 2) & StringMid($CustomColors[$i], 5, 2) & StringMid($CustomColors[$i], 3, 2))
        DllStructSetData($tcc"ccolors"$ccolor$i)
    next

    $aResult = DllCall("comdlg32.dll""bool""ChooseColor""struct*"$tChoose)
    if ($aResult[0] == 0) then return SetError(-3, -3, -1)
    if @error then return SetError(@error, @extended, -1)

    $color_picked = Hex(String(DllStructGetData($tChoose"rgbResult")), 6)
    if $color_picked < 0 then return SetError(-4, -4, -1)

    $ret_array[0] = '0x' & StringMid($color_picked, 5, 2) & StringMid($color_picked, 3, 2) & StringMid($color_picked, 1, 2)
    for $i = 1 to 16 ; create custom color array for return
        $cc = Hex(DllStructGetData($tcc"ccolors"$i), 6)
        $ret_array[$i] = '0x' & StringMid($cc, 5, 2) & StringMid($cc, 3, 2) & StringMid($cc, 1,   2)
    next
    return $ret_array
endfunc

#cs

; a full implementation..


; to store any system picked custom colors..
global $MyColors[17] = [""]


; System Color Picker..

func HotKeySystemPicker()
    SystemPicker($current_color)
endfunc

func SystemPicker($color)
    UnSetHotKeys()
    LoadCustomColors()
    $MyColors[0] = '0x' & $color
    $ret_colors = ColorChooser($MyColors$MyGUI)
    if @error then return false
    switch $ret_colors[0]
        case -1, -3, -4, ""
            SetHotKeys()
            return false
        case else
            $MyColors = $ret_colors
            $new_color = StringTrimLeft($MyColors[0], 2)
            SaveCustomColors()
            SetHotKeys()
    endswitch
endfunc

func SaveCustomColors()
    if not IsArray($MyColors) or UBound($MyColors) < 17 then return false
    local $color_str
    for $i = 1 to 16
        $color_str &= $MyColors[$i] & ","
    next
    $color_str = StringTrimRight($color_str, 1)
    if IniWrite($cpc_ini_path$cpc_my_name"custom_colors"$color_str) then return true
endfunc

func LoadCustomColors()
    local $color_str = IniRead($cpc_ini_path$cpc_my_name"custom_colors""")
    $MyColors = StringSplit($color_str",")
endfunc


#ce

Welcome to corz.org!

Since switching hosts (I hope you are alright, Ed! Wherever you are …) quite a few things seems to be wonky.

Juggling two energetic boys (of very different ages) on Coronavirus lockdown, I'm unlikely to have them all fixed any time soon. Mail me! to prioritise!