Wie RGB-Farbklasse am besten realisieren?



  • Hallo zusammen :schland: ,

    ich habe eine Color-Klasse mit red green und blue komponente (ints).
    Jetzt will ich, dass diese Klasse einfacher zu benutzen ist, indem man z.B. im Konstruktur eine Farbe vorgeben kann:

    Color col(Color::DarkBlue);
    

    Hierfür hätte ich in der Klasse dann eine Enumeration Colors:

    enum Colors {
                Black,
                White,
                DarkGray,
                Gray,
                LightGray,
                Red,
                Green,
                Blue,
                Cyan,
                Magenta,
                Yellow,
                DarkRed,
                DarkGreen,
                DarkBlue,
                DarkCyan,
                DarkMagenta,
                DarkYellow
            };
    

    Aber wie würde ich das jetzt im Konstruktor oder z.B. in der folgenden set-Methode auswerten?

    Color col,
     col.setColor(Color::DarkBlue);
    

    Tatsächlich mit einer ganz langen switch-Anweisung, die dann folgendes macht?

    switch(newCol) {
    case DarkBlue:
    r = g = 0;
    b = 128;
    break;
    
    // usw.
    

    Bitte um Hilfe 😋



  • müsstest du einzeln parsen.

    generell werden farben aber eigentlich in integern hinterlegt.

    du brauchst dann nur methoden wie:

    setr, setg, setb und getr, getg, getb um die farbwerte zu bearbeiten.

    Denk mal nach! In einer Int ist GENUG platz, um die 3 Farbwerte zu speichern!



  • Anders angehen, denn enum kann man nur mit integralen Konstanten direkt assoziieren. Erstelle eine Sammlung von Konstanten in einem Namensraum.

    namespace Colors
    {
        const Color Black(0, 0, 0);
        const Color Red(255, 0, 0);
        // ...
    };
    

    Vielleicht auch extern machen und in einer .cpp-Datei definieren, dann existiert jede Konstante nur einmal und nicht pro Modul.



  • Für die RGB-Farbwerte kannst du jeweils ein unsigned char nehmen.



  • Etwas OffTopic:

    farbkenner schrieb:

    In einer Int ist GENUG platz, um die 3 Farbwerte zu speichern!

    Interessant, daran hab ich gar nicht gedacht. Hm, im Hinblick auf die aktuelle Diskussion scheint sich da doch noch ein Anwendungszweck für Compilezeit-Berechnungen mit Template-Metaprogrammierung zu ergeben. 😉

    typedef unsigned int Uint32;
    typedef unsigned char Uint8;
    
    template <Uint8 R, Uint8 G, Uint8 B>
    struct ComposeRGB
    {
        static const Uint32 Value = (R << 24) | (G << 16) | (B << 8);
    };
    
    template <Uint32 RGB>
    struct DecomposeRGB
    {
        static const Uint8 ValueR = (RGB >> 24) & 0xff;
        static const Uint8 ValueG = (RGB >> 16) & 0xff;
        static const Uint8 ValueB = (RGB >> 8) & 0xff;
    };
    
    enum ColorType
    {
        Black = ComposeRGB<0, 0, 0>::Value,
        Red = ComposeRGB<255, 0, 0>::Value,
        // ...
    };
    
    template <Uint32 RGB>
    Color CreateColor()
    {
        return Color(
            DecomposeRGB<RGB>::ValueR,
            DecomposeRGB<RGB>::ValueG,
            DecomposeRGB<RGB>::ValueB);
    }
    

    Man könnte auch leicht Alpha einbauen. Aber diese Lösung nicht in der Praxis verwenden! ⚠
    Wäre höchstens sinnvoll, wenn man noch weitere Dinge zur Compilezeit berechnen müsste, was ich mir aber schlecht vorstellen kann.

    Realisieren würde ichs nach wie vor mit meinem oberen Ansatz.



  • Das brauchst du eigentlich alles gar nicht.

    Am Sinnvollsten ist es doch einfach, eine stinknormale int zu verwenden und in einer Bibliothek die Funktionen zur Farbauswertung zu schreiben.

    Dann kannst du z.B sowas machen:

    int red;
    black = makecol(255, 0, 0);

    draw_circle(red, circlepos, 5);//draw_circle(int color color, pos position, int radius);



  • gemeint war natürlich: red = makecol(255, 0, 0);

    nix black 😛



  • Farbkenner schrieb:

    Am Sinnvollsten ist es doch einfach, eine stinknormale int zu verwenden und in einer Bibliothek die Funktionen zur Farbauswertung zu schreiben.

    Aber warum zuerst drei einzelne RGB-Werte haben, die in einen int stopfen, und diesen int nachher wieder zerstückeln? Für sowas hat er ja eine Klasse Color , die wahrscheinlich einzelne R-, G- und B-Werte hat. Ist auch schneller.

    Oder sag mir, was an deinem Vorschlag besser als an

    namespace Colors
    {
        const Color Black(0, 0, 0);
        const Color Red(255, 0, 0);
        // ...
    };
    

    ist.



  • Gibt vor- und nachteile.

    Meine Lösung ist einfacher zu schreiben - zweifels ohne - und mindestens gleich gut bis besser zu warten.

    Zudem ist es ein Vorteil bzgl. Kapselung:

    Alle anderen Klassen/whatever müssen nichts wissen von einer "Farbklasse". du gibts ihnen einen int Wert mit. Dass dieser eine Farbe beinhaltet kann egal sein.

    Mitlinken musst du die Bibliothek dann sowieso.

    Aber wie gesagt. Gibt einige pro und contra argumente.



  • Ich werde es nun wie Nexus lösen, besten dank an euch 👍



  • kein problem



  • Farbkenner schrieb:

    Meine Lösung ist einfacher zu schreiben - zweifels ohne - und mindestens gleich gut bis besser zu warten.

    Schlechter Wartbar da du keine Typsicherheit hast.

    Zudem ist es ein Vorteil bzgl. Kapselung:

    Alle anderen Klassen/whatever müssen nichts wissen von einer "Farbklasse". du gibts ihnen einen int Wert mit. Dass dieser eine Farbe beinhaltet kann egal sein.

    Ne, das macht keinen Sinn was du da sagst.

    Gibt einige pro und contra argumente.

    Gibt eigentlich nur eins dazu zu sagen: mach es so wie Nexus sagt, alles andere ist dumm.


Log in to reply