Kurze Frage: RGB - Farbkomplement



  • hallo nochmals:
    Es gibt doch sicher eine kleine Funktion, die mir zu einem RGB() Farbwert die Komplementärfarbe sagt, oder?

    matthias



  • Ich kann dir da Javacode anbieten. Den müßtest du natürlich entsprechend umschreiben.



  • das wäre kein problem!
    kannst du ihn mir bitte posten? So lange wird der ja nicht sein, oder?

    matthias



  • Da:

    Das ist eine Methode, um in einem ganzen Bild den Farbkreis letztendlich zu verdrehen. Die Komplementärfarben gibt es natürlich, wenn man den Farbkreis um Pi verdreht. 🙂
    [java]
    public static Image createConvertedImage (BufferedImage image, float angle)
    {
    final int width = image.getWidth();
    final int height = image.getHeight();
    final BufferedImage outImage = new BufferedImage (width,height,BufferedImage.TYPE_INT_RGB);
    final float twoPi = 2.0f * (float)Math.PI;
    for (int x = 0 ; x < width ; ++x)
    {
    for (int y = 0 ; y < height ; ++y)
    {
    int rgbValue = image.getRGB (x,y);
    float hue = hueConvert(rgbValue);
    final float saturation = saturationConvert(rgbValue);
    final float intensity = intensityConvert(rgbValue);
    if (hue >= 0)
    {
    hue += angle;
    if (hue > twoPi) hue -= twoPi;
    rgbValue = convertHsiToRgb(hue,saturation,intensity);
    }
    outImage.setRGB (x,y,rgbValue);
    }
    }
    return outImage;
    }

    public static int convertHsiToRgb (float hue, final float saturation,
    final float intensity)
    {
    int red = 0;
    int green = 0;
    int blue = 0;
    if (hue <= (2.0 * Math.PI / 3.0))
    {
    red = MyMath.round(intensity * (1.0f+(saturation * (float)Math.cos(hue))/
    ((float)Math.cos(((float)Math.PI/3.0f)-hue))));
    blue = MyMath.round(intensity * (1.0f - saturation));
    green = MyMath.round(3.0f * intensity) - red - blue;
    }
    else if (hue > (4.0 * Math.PI / 3.0))
    {
    hue -= 4.0f * (float)Math.PI / 3.0f;
    blue = MyMath.round(intensity * (1.0f+(saturation * (float)Math.cos(hue))/
    ((float)Math.cos(((float)Math.PI/3.0f)-hue))));
    green = MyMath.round(intensity * (1.0f - saturation));
    red = MyMath.round(3.0f * intensity) - green - blue;
    }
    else
    {
    hue -= 2.0f * (float)Math.PI / 3.0f;
    green = MyMath.round(intensity * (1.0f+(saturation * (float)Math.cos(hue))/
    ((float)Math.cos(((float)Math.PI/3.0f)-hue))));
    red = MyMath.round(intensity * (1.0f - saturation));
    blue = MyMath.round(3.0f * intensity) - red - green;
    }

    red = (red > 255 ) ? 255 : red;
    green = (green > 255 ) ? 255 : green;
    blue = (blue > 255 ) ? 255 : blue;
    red = (red < 0 ) ? 0 : red;
    green = (green < 0 ) ? 0 : green;
    blue = (blue < 0 ) ? 0 : blue;
    return (red << 16) | (green << 😎 | blue;
    }

    private static float hueConvert (int rgbValue)
    {
    final float red = ((float)(((int)rgbValue >> 16) & 0x000000ff))/255.0f;
    final float green = ((float)(((int)rgbValue >> 😎 & 0x000000ff))/255.0f;
    final float blue = ((float)(rgbValue & 0x000000ff))/255.0f;
    if ((red == green) && (red == blue)) return -1.0f;
    final float hue = (float)Math.acos (((red - 0.5f*(green+blue))/
    (float)Math.sqrt((red-green)(red-green)+(red-blue)(green-blue))));
    if (blue > green) return (float)Math.PI * 2.0f - hue;
    return hue;
    }

    private static float saturationConvert (int rgbValue)
    {
    final float red = ((float)(((int)rgbValue >> 16) & 0x000000ff))/255.0f;
    final float green = ((float)(((int)rgbValue >> 😎 & 0x000000ff))/255.0f;
    final float blue = ((float)(rgbValue & 0x000000ff))/255.0f;
    if ((red == 0.0f)&&(green == 0.0f)&&(blue == 0.0f)) return -1.0f;
    return 1.0f-(3.0f/(red+green+blue))*Math.min(red,Math.min(green,blue));
    }

    private static float intensityConvert (int rgbValue)
    {
    return ((float) ((rgbValue & 0x000000ff) + ((rgbValue >>> 😎 & 0x000000ff) +
    ((rgbValue >>> 16) & 0x000000ff))) / 3.0f;
    }[/code]



  • ...vielleicht mußt du dir aber noch ne kleine Methode ausdenken, um die Intensität etwas zu "korrigieren", aber das wird dir schon selbst auffallen... 🙄

    ...wenn da jemand eine entsprechende Methode kennt, dann würde mich die auch interessieren.



  • man dankt.
    ich hätte allerdings nicht gedacht, dass solche doch relativ komplexen Algorithmen von nöten sind...

    matthias



  • was kommt raus, wenn man schlicht die 3 farbwerte ivertiert?
    also in c++ eher sowas wie

    c=RGB(255,255,255)-c;
    

    ?



  • was kommt raus, wenn man schlicht die 3 farbwerte ivertiert?
    also in c++ eher sowas wie

    c=RGB(255,255,255)-c;

    Tja, dann kommt CMY heraus! Und was ist CMY? -> Komplementär zu RGB!

    Aber warum einfach, wenn es auch umständlich geht? 😉

    Das Programm sieht auf jeden Fall nett aus und funktioniert sicherlich auch... 😃

    Shaggy



  • Original erstellt von volkard:
    **was kommt raus, wenn man schlicht die 3 farbwerte ivertiert?
    also in c++ eher sowas wie

    c=RGB(255,255,255)-c;
    

    ?**

    Wie ist c definiert ?
    Ich mein, du subtrahierst es, noch bevor es einen erkennbaren Wert hat...

    Devil

    [ Dieser Beitrag wurde am 24.03.2003 um 12:09 Uhr von devil81 editiert. ]



  • Wenn man 3 Farbwerte invertiert, dann kommt so ne Negativfarbe raus. Das ist vielleicht die Komplementärfarbe, aber zusätzlich werden helle Farben dunkel etc.

    Wenn man ein ein ganz helles Gelb invertiert, dann kriegt man zum Beispiel ein ganz dunkles Blau, aus einem Weiß wird ein Schwarz und umgekehrt,...

    [ Dieser Beitrag wurde am 24.03.2003 um 12:28 Uhr von Gregor editiert. ]



  • Der dicke Algorithmus oben dient ja auch dazu - soweit ich ihn verstanden habe - den Farbkreis um einen gewissen Winkel (!) - z.B. 12.5 ° - zu VERDREHEN! Das ist natürlich viel komplexer, als einfach das Komplement auszurechnen. Ein Bitmap kann ich auch einfacher "upside-down" zeichnen als daß ich es um 27 ° verdreht zeichne...



  • Mein armer CoPro 😉

    Ohne grossartig zu optimieren schätze ich mal, könnte das ganze, was auf den 1. Blick in Integerarithmetik gerechnet werden kann, den Algorithmus doppelt so schnell machen.



  • Was willst du mit Integerarithmetik rechnen?! Bezog sich das auf meinen Code? 😮 ...das will ich sehen!



  • hallo nochmals:
    Es gibt doch sicher eine kleine Funktion, die mir zu einem RGB() Farbwert die Komplementärfarbe sagt, oder?
    matthias

    Nichts gegen das Programm, aber eigentlich ging es doch um obere Frage, oder!? Und da ist nach einer KLEINEN Funktion gefragt, die zu einem RGB() Farbwert die Komplementärfarbe ermittelt. Das Farbkreisprogramm mag ja ganz schick sein, hilft dem guten Mann aber nicht weiter.

    Und das tut z.B. folgender Programmcode:

    #define CMP(x) (RGB(255,255,255)-x)
    
    COLORREF c;
    c = RGB(255, 0, 0);
    c = CMP(c);
    

    Das ist halt reine Komplementärfarbe, ohne Intensitätanpassungs. Das ist richtig. Kleiner Einwand, wenn ich die Farbe weiß habe, wie soll ich dann das schwarz (das ja die Komplementärfarbe (wobei weiß und schwarz eigentlich keine Farben sind, sondern Kontraste) zu weiß ist) genau so hell kriegen, wie weiß!? 😉

    Um die Helligkeit zu ändern muss man - soweit ich weiß - die RGB-Anteile mit einem gleichen Faktor multiplizieren. Das klappt natürlich nicht, wenn ein Anteil 0 ist, da muss man sich dann halt was einfallen lassen.

    Shaggy



  • Konvertierung rein integermässig 😉
    Allerdings als C++-Code

    void RGB2HSV( int r, int g, int b, int *H, int *S, int *V)
    {
        const int max = r, min = r;
        // find maximum and minimum RGB values
        if( g > max)     max = g;
        else                min = g;
        if( b > max)     max = b;
        else if( b < min)    min = b;
    
        *V = max;   // value
        const int delta = max - min;
        *S = max ? (510*delta+max)/(2*max) : 0; // saturation
    
        // calc hue
        if( *S == 0)
            *H = -1; // undefined hue
        else if( r == max)  // red
            *H = (r >= b) ? (120*(g-b)+delta)/(2*delta) : (120*(g-b+delta)+delta)/(2*delta) + 300;
        else if( g == max)  // green
            *H = (B > R) ? 120 + (120*(b-r)+delta)/(2*delta) : 60 + (120*(b-r+delta)+delta)/(2*delta);
        else // blue
            *H = (R > G) ? 240 + (120*(r-g)+delta)/(2*delta) : 180 + (120*(r-g+delta)+delta)/(2*delta);
    }
    
    void HSV2RGB( int h, int s, int v, int *R, int *G, int *B)
    {
        *R = *G = *B = v;
        if( S && H != -1) // chromatic
        {
            div_t dt = div( h%360, 60);
            int f = dt.rem;
            h = dt.quot;
            int p = (2*v*(255-s)+255)/510;
            if( h & 1)
            {
                int q = (2*v*(15300-s*f)+15300)/30600;
                switch( h)
                {
                    case 1: *R = q; *G = v; *B = p; break;
                    case 3: *R = p; *G = q; *B = v; break;
                    case 5: *R = v; *G = p; *B = q; break;
                }
            }
            else
            {
                int t = (2*v*(15300-(s*(60-f)))+15300)/30600;
                switch( h)
                {
                    case 0: *R = v; *G = t; *B = p; break;
                    case 2: *R = p; *G = v; *B = t; break;
                    case 4: *R = t; *G = p; *B = v; break;
                }
            }
        }
    }
    


  • Original erstellt von <Shaggy>:
    **
    Das ist halt reine Komplementärfarbe, ohne Intensitätanpassungs. Das ist richtig. Kleiner Einwand, wenn ich die Farbe weiß habe, wie soll ich dann das schwarz (das ja die Komplementärfarbe (wobei weiß und schwarz eigentlich keine Farben sind, sondern Kontraste) zu weiß ist) genau so hell kriegen, wie weiß!? 😉
    **

    Wie du schon sagst, ist weiß keine Farbe. Entsprechend gibt es keine Komplementärfarbe. Mein Programm läßt weiß deshalb weiß. ...und ein Weiß mit einem kleinen bischen Blau drin wird bei mir zu einem Weiß mit einem kleinen bischen Gelb drin. Wenn man invertiert, dann wird es fast zu nem Schwarz.

    Mein Code erzeugt halt die Komplementärfarbe, ohne an anderen Farbeigenschaften zu drehen. Das ist der Unterschied.

    BTW: Was ist nun eigentlich gesucht? Vielleicht soll ja weiß zu schwarz werden etc.



  • @ RenéG : OK, danke! ...werd ich mir mal angucken! 🙂 ...das kann ich gut gebrauchen.



  • Original erstellt von devil81:
    Wie ist c definiert ?
    Ich mein, du subtrahierst es, noch bevor es einen erkennbaren Wert hat...
    Devil

    c ist ein 32-bittiger int, von dem 24 bits benutzt werden, um farben darzustellen.
    mit #define RGB(r,b,g) (r<<16+b<<8+b) //oder wars andersrum?
    kann mann dann fein direkt rgb-werte angeben, fast wie in html.
    wenn ich nen wert in c habe, in den auf solche weise 3 farben gepackt sind,
    dann kann iahc machen:
    r=c>>16;
    b=(c>>8)&0xff;
    g=c&0xff;
    r=255-r;
    b=255-b;
    g=255-g;
    c=r<<16+b<<8+b;
    aber man darf sich auch zur kenntnis führen, daß beii der subtraktion von
    c=RGB(255,255,255)-c;
    im 256-er-system kein übertrag vorkommen kann, und deshalb der kleine ausdruck identisch ist.


Anmelden zum Antworten