• canvas-修改图片亮度


    canvas操作-修改图片亮度

    图片亮度的概念

    我们一般对图片的概念就是又很多像素点构成的一幅图片,一个像素点由RGBA四个值表示。

    • R:红色
    • G:绿色
    • B:蓝色
    • A:透明度

    不过RGBA并不能直观的表现出像素点的亮度,它比较适合机器理解,给一个rgba的像素我们可以猜出它是偏什么颜色的,不过却不能理解它的亮度值。所以rgba并不是一个很好作为图片处理的格式,这里我们引入HSV(HSB)它的组成为:

    • H:色调代表的是颜色,在这个模型中,色调是从0度到360度。
    • S:饱和度表示颜色空间中的灰色范围。它的范围从0到100%(0~1)。当值为0时,颜色为灰色,当值为1时,颜色为原色。一个比较淡的颜色是由于饱和度较低,也就是颜色包含更多的灰色。
    • V(B):值是颜色的亮度,并随颜色饱和度而变化。它的范围从0到100%,值为0时,颜色空间将全部变黑。随着数值的增加,色彩空间亮度增加并显示出各种颜色。

    用下面这个圆柱体来表示 HSV 颜色空间,圆柱体的横截面可以看做是一个极坐标系 ,H 用极坐标的极角表示,S 用极坐标的极轴长度表示,V 用圆柱中轴的高度表示。

    这里色调各个角度表示的颜色如下:

    角度 颜色
    0-60 红色
    60-120 黄色
    120-180 绿色
    180-240 青色
    240-300 蓝色
    300-360 红紫色

    image-20210315225621390

    下面用ps截图举一个例子:

    下图的取到的点对应的HSV是(16,71,97),而RGB是(248,120,73)这里通过HSV可以看出亮度是97,非常直观。

    image-20210315001231722

    而下面这张图是通过滤镜给图片增加了一个50%透明黑色遮罩,就是降低了50%的亮度。通过HSV可以看出亮度为49。所以我们可以通过rgba和hsv之间的转换来调整图片的亮度。

    image-20210315001939110

    调整图片亮度的方案

    1. 通过rgbahsv之间的转换
    2. 通过在原图片的上层盖上一层具有一定透明度的黑色遮罩

    这里方案2实施起来比较简单,不过在处理具备透明度的png图片时,会导致透明部分也被遮罩导致变得非透明。所以方案1会比较通用。

    实现方案一

    从RGB到HSV的转换

    转换的公式

    设 (r, g, b)分别是一个颜色的红、绿和蓝坐标,它们的值是在0到1之间的实数。设max等价于r, gb中的最大者。设min等于这些值中的最小者。要找到在HSL空间中的 (h, s, l)值,这里的h ∈ [0, 360)是角度的色相角,而s, l ∈ [0,1]是饱和度和亮度,计算为:

    image-20210315232621310

    h的值通常规范化到位于0到360°之间。而h = 0用于max = min的(定义为灰色)时候而不是留下h未定义。

    HSL和HSV有同样的色相定义,但是其他分量不同。HSV颜色的sv的值定义如下:

    image-20210315232730896

    javascript实现代码

    // arr: rgb数组
    function rgb2hsv (arr) {
        let rr;
        let gg;
        let bb;
        let r = arr[0] / 255;
        let g = arr[1] / 255;
        let b = arr[2] / 255;
        let h;
        let s;
        let v = Math.max(r, g, b);
        let diff = v - Math.min(r, g, b);
        let diffc = function (c) {
            return (v - c) / 6 / diff + 1 / 2;
        };
    
        if (diff === 0) {
            h = s = 0;
        } else {
            s = diff / v;
            rr = diffc(r);
            gg = diffc(g);
            bb = diffc(b);
    
            if (r === v) {
                h = bb - gg;
            } else if (g === v) {
                h = (1 / 3) + rr - bb;
            } else if (b === v) {
                h = (2 / 3) + gg - rr;
            }
            if (h < 0) {
                h += 1;
            } else if (h > 1) {
                h -= 1;
            }
        }
        return [Math.round(h * 360), Math.round(s * 100), Math.round(v * 100)]
    }
    

    从HSV到RGB的转换

    转换的公式

    给定在HSV中 (h, s, v)值定义的一个颜色,带有如上的变化于0到360之间的h,和分别表示饱和度和明度的变化于0到1之间的sv,在RGB空间中对应的 (r, g, b)三原色可以计算为(R,G,B变化于0到1之间):

    image-20210315233245933

    javascript实现代码

    function hsv2rgb (hsv) {
        let _l = hsv[0];
        let _m = hsv[1];
        let _n = hsv[2];
        let newR;
        let newG;
        let newB;
        if (_m === 0) {
            _l = _m = _n = Math.round(255 * _n / 100);
            newR = _l;
            newG = _m;
            newB = _n;
        } else {
            _m = _m / 100;
            _n = _n / 100;
            let p = Math.floor(_l / 60) % 6;
            let f = _l / 60 - p;
            let a = _n * (1 - _m);
            let b = _n * (1 - _m * f);
            let c = _n * (1 - _m * (1 - f));
            switch (p) {
                case 0:
                    newR = _n; newG = c; newB = a;
                    break;
                case 1:
                    newR = b; newG = _n; newB = a;
                    break;
                case 2:
                    newR = a; newG = _n; newB = c;
                    break;
                case 3:
                    newR = a; newG = b; newB = _n;
                    break;
                case 4:
                    newR = c; newG = a; newB = _n;
                    break;
                case 5:
                    newR = _n; newG = a; newB = b;
                    break;
            }
            newR = Math.round(255 * newR);
            newG = Math.round(255 * newG);
            newB = Math.round(255 * newB);
        }
        return [newR, newG, newB]
    }
    

    实现亮度的调整

    下面的代码是实现降低图片50%亮度的实现

    <body>
      <img src="./pic.jpg" id="pic">
      <canvas id="canvas" width="200" height="273"></canvas>
    </body>
    
    const pic = document.querySelector('#pic')
    const canvas = document.querySelector('#canvas')
    const ctx = canvas.getContext('2d')
    ctx.drawImage(pic, 0, 0, 200, 273);
    const imgData = ctx.getImageData(0, 0, 200, 273)
    // 降低50%的亮度
    ctx.putImageData(changeLuminance(imgData, -0.5), 0, 0)
    
    // 修改图片亮度, imgdata为从canvas获取到的rgba数组,value为需要增加或减少的亮度值(0~1)
    function changeLuminance (imgdata, value) {
        const data = imgdata.data
        for (let i = 0; i < data.length; i+=4) {
            const hsv = rgb2hsv([data[i], data[i + 1], data[i + 2]])
            hsv[2] *= (1 + value)
            const rgb = hsv2rgb([...hsv])
            data[i] = rgb[0];
            data[i + 1] = rgb[1];
            data[i + 2] = rgb[2];
        }
        return imgdata
    }
    

    image-20210316002808817

  • 相关阅读:
    [HAOI2010]软件安装
    「HNOI2015」菜肴制作
    [ZJOI2007] 小Q的矩阵游戏 (模板—Dinic)
    「POI2012」约会 Rendezvous
    [APIO2016]划艇
    [CQOI2011]放棋子
    【SDOI2015】bzoj3990 排序
    [bzoj2242] [SDOI2011]计算器
    模板—BSGS
    【BZOJ1227】[SDOI2009]虔诚的墓主人
  • 原文地址:https://www.cnblogs.com/suyuanli/p/14541067.html
Copyright © 2020-2023  润新知