Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Increase or decrease color saturation

I would like to know the algorithm to increase or decrease one RGB color saturation

for example if I have the color rgb(200, 30, 40) (red) the function stub would be

function Saturation(color, factor)
where color.r = 200, color.g= 30 and color.b=40

Anyone knows a library or has a code snippet that does that?

like image 819
Hoffmann Avatar asked Dec 10 '12 17:12

Hoffmann


People also ask

Which tool increases or decreases the color saturation of an image?

To adjust saturation, add a Hue/Saturation adjustment layer. Then click and drag the Saturation slider in the Properties panel to increase or decrease the saturation.

What does increasing saturation in an image do?

The higher the saturation of a color, the more vivid it is. The lower the saturation of a color, the closer it is to gray. Lowering the saturation of a photo can have a “muting” or calming effect, while increasing it can increase the feel of the vividness of the scene.

What color reduces saturation?

There are four different ways to lower the saturation of a pure colour. You can either add grey, add white, add black, or dilute a pure colour using its complementary colour.

Does saturation increase color intensity?

The higher the saturation of a color, the more vivid and intense it is. The lower a color's saturation, the closer it is to pure gray on the grayscale.


2 Answers

Following Bali Balo suggestion I came up with:

RGBtoHSV= function(color) {
        var r,g,b,h,s,v;
        r= color[0];
        g= color[1];
        b= color[2];
        min = Math.min( r, g, b );
        max = Math.max( r, g, b );


        v = max;
        delta = max - min;
        if( max != 0 )
            s = delta / max;        // s
        else {
            // r = g = b = 0        // s = 0, v is undefined
            s = 0;
            h = -1;
            return [h, s, undefined];
        }
        if( r === max )
            h = ( g - b ) / delta;      // between yellow & magenta
        else if( g === max )
            h = 2 + ( b - r ) / delta;  // between cyan & yellow
        else
            h = 4 + ( r - g ) / delta;  // between magenta & cyan
        h *= 60;                // degrees
        if( h < 0 )
            h += 360;
        if ( isNaN(h) )
            h = 0;
        return [h,s,v];
    };

HSVtoRGB= function(color) {
        var i;
        var h,s,v,r,g,b;
        h= color[0];
        s= color[1];
        v= color[2];
        if(s === 0 ) {
            // achromatic (grey)
            r = g = b = v;
            return [r,g,b];
        }
        h /= 60;            // sector 0 to 5
        i = Math.floor( h );
        f = h - i;          // factorial part of h
        p = v * ( 1 - s );
        q = v * ( 1 - s * f );
        t = v * ( 1 - s * ( 1 - f ) );
        switch( i ) {
            case 0:
                r = v;
                g = t;
                b = p;
                break;
            case 1:
                r = q;
                g = v;
                b = p;
                break;
            case 2:
                r = p;
                g = v;
                b = t;
                break;
            case 3:
                r = p;
                g = q;
                b = v;
                break;
            case 4:
                r = t;
                g = p;
                b = v;
                break;
            default:        // case 5:
                r = v;
                g = p;
                b = q;
                break;
        }
        return [r,g,b];
    }

by converting to the HSV (hue, saturation and value) format you can manually change the S component in this manner:

var hsv= RGBtoHSV ([200,100,100]);
alert(hsv)
hsv[1] *= 1.5;
alert(hsv)
var rgb= HSVtoRGB(hsv);
alert(rgb); //new color
like image 117
Hoffmann Avatar answered Sep 18 '22 16:09

Hoffmann


Here's a quick and dirty way that probably isn't correct in any technical way, but involves less computation than converting to HSV and back (so renders quicker if that matters):

Grayscale is the equivalent of calculating luminosity averaged over the RGB parts of the pixel. We can mix grayness by applying a value weighting to the gray part versus the colored part:

var pixels = context.getImageData(0, 0, canvas.width, canvas.height);
grayscale = function (pixels, value) {
    var d = pixels.data;
    for (var i = 0; i < d.length; i += 4) {
        var r = d[i];
        var g = d[i + 1];
        var b = d[i + 2];
        var gray = 0.2989*r + 0.5870*g + 0.1140*b; //weights from CCIR 601 spec
        d[i] = gray * value + d[i] * (1-value);
        d[i+1] = gray * value + d[i+1] * (1-value);
        d[i+2] = gray * value + d[i+2] * (1-value);
    }
    return pixels;
};

So instead of adding "grayness", we can take it away and add the relevant color back in to "saturate":

saturate = function (pixels, value) {
    var d = pixels.data;
    for (var i = 0; i < d.length; i += 4) {
        var r = d[i]; 
        var g = d[i + 1];
        var b = d[i + 2];
        var gray = 0.2989*r + 0.5870*g + 0.1140*b; //weights from CCIR 601 spec
        d[i] = -gray * value + d[i] * (1+value);
        d[i+1] = -gray * value + d[i+1] * (1+value);
        d[i+2] = -gray * value + d[i+2] * (1+value);
        //normalize over- and under-saturated values
        if(d[i] > 255) d[i] = 255;
        if(d[i+1] > 255) d[i] = 255;
        if(d[i+2] > 255) d[i] = 255;
        if(d[i] < 0) d[i] = 0;
        if(d[i+1] < 0) d[i] = 0;
        if(d[i+2] < 0) d[i] = 0;
    }
    return pixels;
};

Again, disclaimer that this "looks" saturated but probably in no way adheres to the technical definition of "saturation" (whatever that is); I've simply posted this in the hope that it's helpful to passers-by.

like image 27
Escher Avatar answered Sep 21 '22 16:09

Escher