Increase or decrease color saturation

前端 未结 3 839
忘掉有多难
忘掉有多难 2020-12-16 16:10

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

3条回答
  •  北荒
    北荒 (楼主)
    2020-12-16 17:07

    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.

提交回复
热议问题