2017-10-18 3 views
0

Ich versuche, eine Methode zu schreiben, die auf WPFs Color struct funktioniert, um ein Byte zurückzugeben, das den Farbton des darstellt. Ich kämpfe mit der Formel, ich habe Komponententests für die Farbtöne Schwarz (255, 255, 255), Rot (255, 0, 0), Grün (0, 255, 0), Blau (0, 0, 255) geschrieben), Gelb (255, 255, 0), Cyan (0, 255, 255), Magenta (255, 0, 255) und Weiß (255, 255, 255) - sie alle außer Gelb (das 1 statt 42 zurückgibt)) und Magenta (die versucht, -1 anstelle von 212 zurückzugeben, schlägt jedoch fehl, da -1 nicht in ein Byte umgewandelt wird).Berechnen des Farbtons einer Farbe als 0 - 255 Bereich

Meine Erweiterungsmethoden für GetHue wie folgt aussehen:

public static byte GetHue(this Color color) 
    => GetHue(color.ToRgbDictionary(), color.GetMinComponent(), color.GetMaxComponent()); 

private static byte GetHue(Dictionary<ColorComponent, byte> rgbDictionary, ColorComponent minimumRgbComponent, ColorComponent maximumRgbComponent) 
{ 
    decimal chroma = rgbDictionary[maximumRgbComponent] - rgbDictionary[minimumRgbComponent]; 

    return (byte) 
    (
     chroma == 0 
     ? 0 
     : thirdOfByte 
     * (byte)maximumRgbComponent 
     + 
     (
      rgbDictionary[MathHelper.Wrap(maximumRgbComponent + 1)] 
      - rgbDictionary[MathHelper.Wrap(maximumRgbComponent - 1)] 
     ) 
     /chroma 
    ); 
} 

ToRgbDictionary einfach die Color in ein Wörterbuch seiner roten, grünen und blauen Komponenten dreht; ColorComponent ist eine Enumeration, die als Schlüssel für diese Komponenten verwendet wird. MathHelper.Wrap ist eine Methode, die eine Aufzählung in den deklarierten Bereich zurückbringt, wenn sie über- oder unterläuft. GetMinComponent und sind zwei weitere Erweiterungsmethoden auf Color, die die erste niedrigste und erste höchste ColorComponent s der (wo die ColorComponent Reihenfolge ist: Rot, Grün, Blau) zurückgeben. thirdOfByte ist eine Konstante gleich byte.MaxValue/3.

Ich habe basierend auf einem anderen diese Formel I hier (http://www.blackwasp.co.uk/rgbhsl_2.aspx), die wie folgt aussieht:

private decimal GetH(RGB rgb, decimal max, decimal chroma) 
{ 
    decimal h; 
    if (rgb.R == max) 
     h = ((rgb.G - rgb.B)/chroma); 
    else if (rgb.G == max) 
     h = ((rgb.B - rgb.R)/chroma) + 2M; 
    else 
     h = ((rgb.R - rgb.G)/chroma) + 4M; 
    return 60M * ((h + 6M) % 6M); 
} 

Das Problem mit dieser Formel wird es auf einen 0 zugeordnet wird - 360 Farbtonbereich, keine 0-255 Bereich, was ich brauche. Ich bin nicht sicher, was die konstanten Zahlen in dieser Formel tun, aber ich rate, dass die 60 etwas mit 360/3 = 120 zu tun hat, daher mein Drittel von Byte konstant, um zu versuchen, etwas Ähnliches zu tun. Was die 6M angeht, habe ich keine Ahnung woher sie kommen und warum sie zu diesem Zeitpunkt mit dem Farbtonwert addiert und modulisiert werden. Könnte mir jemand mit einem Sinn für Mathematik hier helfen?

UPDATE Der Grund für den 0-255 Bereich war, dass ich dachte, dass war alles, was es in einem anderen Stück Software verwendet gesehen erforderlich war, haben (wie dargestellt) für Farbton, Sättigung und Helligkeit. Dort habe ich auch den 42-Hue-Wert für Gelb erhalten. Ich versuche nun, den richtigen Bereich für Hues zu finden, um alle möglichen unterschiedlichen Farbtöne in einem 16777216 (256 * 256 * 256) Farbbereich abzudecken.

enter image description here

Antwort

0
  • Ihr "... außer Gelb (die 1 anstelle von 42 zurück)", was hinter der Logik ein 42 erwartet?

  • Es ist "zugeordnet zu einem 0 - 360 Farbton Bereich", weil es 360 Farben im Farbrad gibt. Selbst wenn Sie ein Byte ohne Vorzeichen hätten (mit 256 Werten), würden Sie die anderen 104 möglichen Farbtöne abschneiden. Es wird keine genaue Darstellung sein.

  • Warum nicht einfach ein 2-Byte short verwenden, um die möglichen 360 Farbtöne anstelle von 1 Byte zu halten?

Wenn Sie noch 360 in einem 255 Bereich passen wollen, tun nur einfache Mathematik:

byte_value = hue_value/(360/255); //where hue_value is the 0-360 amount. 

Versuchen Math methods wie Math.round die keine Fraktionen als letzter Byte-Wert zu erhalten.

Beispiel 180 Farbton:

byte_value = Math.round(180/(360/255)); //gives 127 
+0

Ich bin überdenken mit 0-255 jetzt, dass du das gesagt hast; Ich möchte die Wertauflösung nicht verlieren, um 1 Byte zu sparen! Das bedeutet, dass ich die Formel jetzt kopieren könnte, aber ich würde es immer noch gerne verstehen (was ist die Bedeutung von 60M, die zwei 6Ms, die 4M und die 2M). Ich nehme an, dass der Modulus als Dezimalzahl wegen der nachfolgenden Multiplikation wichtig ist (nach der die Rundung angewendet werden könnte). – Sphynx

+0

Nur um zu klären, ist 360 die Gesamtzahl der möglichen Farben für 255 * 255 * 255 Farben oder nur eine Möglichkeit, diese Hues in einen 1-Farbton-pro-Grad-Kreis abzubilden? Ich bin nach der Genauigkeit über die Kopplung von Farbtönen an die Form eines bestimmten Benutzersteuerelements. – Sphynx

Verwandte Themen