Zwischen 2 Farben Farbübergangsfarben ermitteln

  • Ich würde gerne mit Hilfe einer Funktion sämtliche Farbtöne zwischen zwei vorgegebenen Farbtönen ermitteln. Ich hab mir das so vorgestellt, dass man zum Beispiel

    [autoit]

    GetColorBetween(0x0000ff, 0xffffff, 50, 100)

    [/autoit]

    aufruft und dort dann die Farbe genau in der Mitte (50%) erhält, was also 0x8888ff sein müsste (der letzte Parameter gibt an, wie viele Zwischenschritte es geben soll).
    Ich habe selber schon versucht das hinzubekommen, was bislang aber noch nicht geklappt hat, vor allem weil AutoIt irgendwie gerne mal ungefragt Hex in Dec umwandelt :(.

  • Ganz billig nur 1 zwischen Farbe und wahrscheinlich sehr unnötig berechnet:

    Spoiler anzeigen
    [autoit]

    ConsoleWrite(_colorbetween("0x0000ff", "0xffffff"))
    Func _colorbetween($Farbe1, $Farbe2)
    $a1 = StringSplit($Farbe1, "", 3)
    $a2 = StringSplit($Farbe2, "", 3)
    Return "0x" & Hex(Int((Dec($a1[2] & $a1[3]) + Dec($a2[2] & $a2[3])) / 2), 2) & Hex(Int((Dec($a1[4] & $a1[5]) + Dec($a2[4] & $a2[5])) / 2), 2) & Hex(Int((Dec($a1[6] & $a1[7]) + Dec($a2[6] & $a2[7])) / 2), 2)
    EndFunc ;==>_colorbetween

    [/autoit]
    • Offizieller Beitrag

    und dort dann die Farbe genau in der Mitte (50%) erhält


    Ich bin gewiß kein Farbfreak, aber auch mir ist bekannt, dass das optische Empfinden der "Mitte" zwischen zwei Farben rein gar nix mit der "rechnerischen Mitte" zu tun hat.
    Hier mußt du dich mal in die verschiedenen Farbraumberechnungen begeben (gibt hier bei Skripten einige Umrechner) und deren Funktionsprinzip ergründen. Mir war das auch immer zu viel. ;)

  • Wenn er es linear berechnet ist die 88 auch falsch.
    88h = 136, Damit das die Mitte ist müsste es ja ein paar Farben mehr geben als sich mit 8Bit darstellen lassen.
    Mit Berechnungen unter Berücksichtigung des optischen Eindrucks habe ich schon herumgespielt, Du kannst z.B. den Farbraum Umrechner benutzen um ins XYZ oder LAB Format zu wechseln. In diesen Räumen müsste der lineare Abstand in etwa dem Empfundenen Abstand entsprechen.
    BugFix : Sei nicht so bescheiden, immerhin hast du die Funktionen für soetwas bereitgestellt :P

    lg
    M

  • Ich hab jetzt BugFixs Umwandler RGB-XYZ benutzt und mit dem Array lässt es sich auch besser rechnen als mit den grässlichen Hexadezimal-Werten.

    Nur besonders meine Umwandlung Hexadezimal in getrennte 0-255 Werte und zurück ist vermutlich ziemlich unprofessionell, da ich das über Umwandlung in Strings gemacht habe.

    Spoiler anzeigen
    [autoit]

    $Gui=GUICreate('Farbübergang',400,100)
    For $i=0 To 100
    GUICtrlCreateLabel('',0,$i,400,1)
    GUICtrlSetBkColor(-1,GetColorBetween(0xffffff,0x0000ff,$i))
    Next

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    Do
    Until GUIGetMsg()=-3

    [/autoit] [autoit][/autoit] [autoit]

    Func GetColorBetween($Color1,$Color2,$Value,$Max=100)
    ;Umwandeln in XYZ
    $Color1=String(Hex($Color1,6))
    $Color2=String(Hex($Color2,6))
    Dim $C1[3]
    Dim $C2[3]
    For $i=2 To 0 Step -1
    $C1[$i]=StringRight($Color1,2)
    $Color1=StringTrimRight($Color1,2)
    Next
    For $i=2 To 0 Step -1
    $C2[$i]=StringRight($Color2,2)
    $Color2=StringTrimRight($Color2,2)
    Next
    $Color1=_RGB_to_XYZ(Dec($C1[0]),Dec($C1[1]),Dec($C1[2]),1)
    $Color2=_RGB_to_XYZ(Dec($C2[0]),Dec($C2[1]),Dec($C2[2]),1)
    ;Das eigentliche Rechnen
    Dim $Diff[3]
    For $i=0 To 2
    $Diff[$i]=$Color2[$i]-$Color1[$i]
    Next
    Dim $NewColor[3]
    For $i=0 To 2
    $NewColor[$i]=$Color1[$i]+$Value*($Diff[$i]/$Max)
    Next
    ;Zurück in RGB umwandeln
    $NewColorRGB=_XYZ_to_RGB($NewColor[0],$NewColor[1],$NewColor[2],1)
    $NewColorRGBString=""
    For $i=0 To 2
    $NewColorRGBString&=StringRight(String(Hex($NewColorRGB[$i])),2)
    Next
    Return "0x"&$NewColorRGBString
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _RGB_to_XYZ($iR, $iG, $iB, $retType=0); 0=String, 1=Array
    ;https://autoit.de/index.php?page=Thread&threadID=16365
    If $iR < 0 Or $iR > 255 Or $iG < 0 Or $iG > 255 Or $iB < 0 Or $iB > 255 Then Return SetError(1,0,0)
    If $retType <> 0 Then $retType = 1
    Local $iX, $iY, $iZ
    $iR /= 255
    $iG /= 255
    $iB /= 255
    If $iR > 0.04045 Then
    $iR = (($iR + 0.055 ) / 1.055 ) ^ 2.4
    Else
    $iR /= 12.92
    EndIf
    If $iG > 0.04045 Then
    $iG = (($iG + 0.055 ) / 1.055 ) ^ 2.4
    Else
    $iG /= 12.92
    EndIf
    If $iB > 0.04045 Then
    $iB = (($iB + 0.055 ) / 1.055 ) ^ 2.4
    Else
    $iB /= 12.92
    EndIf
    $iR *= 100
    $iG *= 100
    $iB *= 100
    ; Observer = 2°, Illuminant = D65
    $iX = Round($iR * 0.4124 + $iG * 0.3576 + $iB * 0.1805, 3)
    $iY = Round($iR * 0.2126 + $iG * 0.7152 + $iB * 0.0722, 3)
    $iZ = Round($iR * 0.0193 + $iG * 0.1192 + $iB * 0.9505, 3)
    If $retType Then
    Local $Out[3] = [$iX,$iY,$iZ]
    Else
    Local $delim = Opt('GUIDataSeparatorChar')
    Local $Out = $iX & $delim & $iY & $delim & $iZ
    EndIf
    Return $Out
    EndFunc ;==>_RGB_to_XYZ

    [/autoit] [autoit][/autoit] [autoit]

    Func _XYZ_to_RGB($iX, $iY, $iZ, $retType=0)
    If $retType <> 0 Then $retType = 1
    Local $iR, $iG, $iB
    $iX /= 100
    $iY /= 100
    $iZ /= 100
    ; Observer = 2°, Illuminant = D65
    $iR = ($iX * 3.2406) + ($iY * -1.5372) + ($iZ * -0.4986)
    $iG = ($iX * -0.9689) + ($iY * 1.8758) + ($iZ * 0.0415)
    $iB = ($iX * 0.0557) + ($iY * -0.2040) + ($iZ * 1.0570)
    If $iR > 0.0031308 Then
    $iR = 1.055 * ($iR ^ (1/2.4)) - 0.055
    Else
    $iR *= 12.92
    EndIf
    If $iG > 0.0031308 Then
    $iG = 1.055 * ($iG ^ (1/2.4)) - 0.055
    Else
    $iG *= 12.92
    EndIf
    If $iB > 0.0031308 Then
    $iB = 1.055 * ($iB ^ (1/2.4)) - 0.055
    Else
    $iB *= 12.92
    EndIf
    $iR = Int($iR*255)
    $iG = Int($iG*255)
    $iB = Int($iB*255)
    If $retType Then
    Local $Out[3] = [$iR,$iG,$iB]
    Else
    Local $delim = Opt('GUIDataSeparatorChar')
    Local $Out = $iR & $delim & $iG & $delim & $iB
    EndIf
    Return $Out
    EndFunc ;==>_XYZ_to_RGB

    [/autoit]


    Funktioniert soweit aber.

    • Offizieller Beitrag

    Nur besonders meine Umwandlung Hexadezimal in getrennte 0-255 Werte und zurück ist vermutlich ziemlich unprofessionell


    Hier mal "rechnende" Versionen ;)

    Spoiler anzeigen
    [autoit]

    Func _GetR($RGB)
    Return BitAND(BitShift($RGB, 16), 0xFF)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _GetG($RGB)
    Return BitAND(BitShift($RGB, 8), 0xFF)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _GetB($RGB)
    Return BitAND($RGB, 0xFF)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _RGB2Hex($R, $G, $B)
    Return '0x' & Hex($R, 2) & Hex($G, 2) & Hex($B, 2)
    EndFunc

    [/autoit]
  • ...und da ich gerade über diesen Thread gestolpert bin, HIER gibt es weitere Beispiele für Scripte mit Farbverläufen