RGB to HSV (nach der Formel von Wikipedia)

  • Hallöchen,

    ich weiß, dass AutoIt _ColorConvert Funktionen hat. Ich wollte ursprünglich eine Convert-Funktion für in C++ schreiben. Ich hatte mich dazu an den Beschreibungen hier orientiert. Ich habe das ganze dann mal in AutoIt umgesetzt, nachdem es in C++ nicht funktioniert hat. In AutoIt kommen jedoch die gleichen, falschen Werte heraus. Ich könnte nun auch einfach die ConvertFunktionen von Autoit in c++ umsetzen, dann hätte ich eine Funktion - allerdings möchte ich jetzt wissen, warum die Funktion nach Wikipedia nicht funktioniert.

    Hier mein Code...
    [autoit]

    Global Const $PI = 3.1415926535897932384626433832795

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

    ; get biggest number
    Func max($x,$y,$z)
    If ($x >= $y And $x >= $z) Then
    Return $x
    ElseIf ($y >= $x And $y >= $z) Then
    Return $y
    Else
    Return $z
    EndIf
    EndFunc

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

    ; get smallest number
    Func min($x,$y,$z)
    If ($x <= $y And $x <= $z) Then
    Return $x
    ElseIf ($y <= $x And $y <= $z) Then
    Return $y
    Else
    Return $z
    EndIf
    EndFunc

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

    ; get radiant of degree
    Func rad($a)
    Return $a * $PI / 180
    EndFunc

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

    ; RGB byte to RGB in [0, 1]
    Func RGB($r, $g, $b)
    Local $RGB[3] = [$r/255, $g/255, $b/255]
    Return $RGB
    EndFunc

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

    ; RGB to HSV
    Func RGB2HSV($RGB)
    Local $R, $G, $B, $MAX, $MIN ; in [0, 1]
    Local $H ; in [0°, 360°]
    Local $S, $V ; in [0, 1]
    Local $HSV[3]

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

    ; red, green, blue
    $R = $RGB[0]
    $G = $RGB[1]
    $B = $RGB[2]

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

    ; max and min
    $MAX = max($R, $G, $B)
    $MIN = min($R, $G, $B)

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

    ; hue
    Switch $MAX
    Case $MIN
    $H = 0
    Case $R
    $H = rad(60) * (0 + ($G - $B) / ($MAX - $MIN))
    Case $G
    $H = rad(60) * (2 + ($B - $R) / ($MAX - $MIN))
    Case $B
    $H = rad(60) * (4 + ($R - $G) / ($MAX - $MIN))
    EndSwitch

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

    ; saturation
    If $MAX == 0 Then
    $S = 0
    Else
    $S = ($MAX - $MIN) / $MAX
    EndIf

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

    ; value
    $V = $MAX

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

    ; HSV triple
    $HSV[0] = $H
    $HSV[1] = $S
    $HSV[2] = $V
    Return $HSV
    EndFunc

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

    ; HSV to RGB
    Func HSV2RGB($HSV)
    Local $H, $S, $V, $R, $G, $B ; in [0, 1]
    Local $hi, $f, $p, $q, $t
    Local $RGB[3]

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

    ; $HSV to $H, $S, $V
    $H = $HSV[0]
    $S = $HSV[1]
    $V = $HSV[2]

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

    ; ...
    $hi = $H / rad(60)
    $f = $H / rad(60) - $hi
    $p = $V * (1 - $S)
    $q = $V * (1 - $S * $f)
    $t = $V * (1 - $S * (1 - $f))

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

    ; get values for $R, $G, $B
    Switch $hi
    Case 1
    $R = $q
    $G = $V
    $B = $p
    Case 2
    $R = $p
    $G = $V
    $B = $t
    Case 3
    $R = $p
    $G = $q
    $B = $V
    Case 4
    $R = $t
    $G = $p
    $B = $V
    Case 5
    $R = $V
    $G = $p
    $B = $q
    Case Else
    $R = $V
    $G = $t
    $B = $p
    EndSwitch

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

    ; return RGB triple
    $RGB[0] = $R
    $RGB[1] = $G
    $RGB[2] = $B
    Return $RGB
    EndFunc

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

    ; Test
    Local $hsv, $rgb
    $hsv = RGB2HSV(RGB(255, 201, 14))
    $rgb = HSV2RGB($hsv)
    ConsoleWrite("R: " & $rgb[0] * 255 & "; G: " & $rgb[1] * 255 & "; B: " & $rgb[2] * 255 & @CRLF)

    [/autoit]

    Ich habe in Paint einfach mal irgendeine Farbe ausgesucht und davon den RGB Wert aufgeschrieben. Ich wandle die Farbe dann in HSV um und von HSV wieder zurück in RGB. Es sollte normalerweise die gleiche Farbe dabei wieder herauskommen. Tuts aber nicht ?(

    lg,
    Developer30

    "Je mehr Käse, desto mehr Löcher; je mehr Löcher, desto weniger Käse. Ergo: Je mehr Käse, desto weniger Käse. 8| "
    "Programmers never die: they just GOSUB without RETURN"
    "I tried to change the world but I couldn't find the source code."

    Einmal editiert, zuletzt von Developer30 (15. Juni 2013 um 18:53)

  • Wie ich bereits geschrieben hab ist mir durchaus bewusst, dass es dazu bereits Funktionen gibt. Es geht mir, wie bereits gesagt, immernoch darum zu wissen, was ich falsch gemacht hab. Trotzdem danke für deine Funktionen, vielleicht kann ich anhand dessen ja verstehen, was bei meinen nicht stimmt.

    "Je mehr Käse, desto mehr Löcher; je mehr Löcher, desto weniger Käse. Ergo: Je mehr Käse, desto weniger Käse. 8| "
    "Programmers never die: they just GOSUB without RETURN"
    "I tried to change the world but I couldn't find the source code."

  • Du solltest vielleicht mal dein Verständnis von mathematischen Symbolen aufbessern ^^. Diese eckigen, nach oben geöffneten Klammern bei der Formel für das Grundfarbenintervall hi haben durchaus eine Bedeutung... Sie stehen für die größte ganze Zahl kleiner/gleich dem Wert in den Klammern. Das Gegenstück zu dieser Rechnung ist in den meisten Programmiersprachen die Floor() Funktion, so auch in AutoIt. Du versuchst in 99% der Fälle einen Dezimalbruch mit einem Integer zu vergleichen, was dazu führt dass immer der Else Zweig der Switch Abfrage ausgeführt wird.
    Ersetze mal die Zeile zur Berechnung von hi in deinem Script durch das hier:

    [autoit]

    $hi = Floor($H / rad(60))

    [/autoit]
  • Danke name22! :thumbup:
    Mit der Zeile funktionierts. Mir ist garnicht aufgefallen, dass die Klammern oben geöffnet waren.

    "Je mehr Käse, desto mehr Löcher; je mehr Löcher, desto weniger Käse. Ergo: Je mehr Käse, desto weniger Käse. 8| "
    "Programmers never die: they just GOSUB without RETURN"
    "I tried to change the world but I couldn't find the source code."