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 红紫色

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

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

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

调整图片亮度的方案

  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]是饱和度和亮度,计算为:

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

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

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之间):

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
}

canvas-修改图片亮度的更多相关文章

  1. Android动态修改图片颜色的实现方式分析

    版权声明:本文为博主原创文章,未经博主允许不得转载. 1.修改色相.饱和度.亮度 参看:http://blog.csdn.NET/sjf0115/article/details/7267063 2.使 ...

  2. BackgroundCheck – 根据图片亮度智能切换元素样式

    BackgroundCheck 是一个轻量的 JavaScript 库,能够根据元素后面的图片的亮度自动切换元素样式.例如在图片幻灯片功能中,根据图片亮度调整导航箭头的颜色,这样让图片和导航的颜色形成 ...

  3. 使用HTML5的canvas做图片剪裁

    前言 图片裁剪上传,不仅是一个很贴合用户体验的功能,还能够统一特定图片尺寸,优化网站排版,一箭双雕. 需求就是那么简单,在浏览器里裁剪图片并上传到服务器. 我第一个想到的方法就是,将图片和裁剪参数(x ...

  4. android 通过修改图片像素实现CircleImageView

    CircleImageView实现方法有很多种,各有优缺点,因此需要按照不同的场景使用.我们今天使用修改图片像素的方法实现CircleImageView,主要知识点无非是勾股定理和点到圆形的距离. 素 ...

  5. PHP修改图片

    这篇是关于修改图片的效果,主要还是用到php中的GD库中的函数,没想到php还有这凶残能力,出乎我的预料. 先看代码upload_image.php,主要是一个上传控件,用来选择图片 <html ...

  6. 神奇的canvas——巧用 canvas 为图片添加水印

    代码地址如下:http://www.demodashi.com/demo/11637.html 很久之前写过一篇关于 canvas 的文章,是通过 canvas 来实现一个绚丽的动画效果,不管看过没看 ...

  7. 利用Photoshop修改图片以达到投稿要求

    摘自:http://www.dxy.cn/bbs/thread/8602152#8602152 利用Photoshop修改图片以达到投稿要求 软件版本为Photoshop CS V8.0.1(中文版) ...

  8. canvas学习笔记:canvas对图片的像素级处理--ImageData的应用

    学习了canvas的基本绘图功能后,惊喜的发现canvas对图片数据也有相当强大的处理功能,能够从像素级别操作位图,当然[lte ie8]不支持. 主要的函数有三个: ctx.createImageD ...

  9. 【faster-rcnn】训练自己的数据——修改图片格式、类别

    修改图片格式 matlab代码 其实内部一些代码是用了rbg的fast-rcnn代码的. \datasets\VOCdevkit2007\VOCcode\VOCinit.m里面,查找'jpg',改成' ...

随机推荐

  1. codeforces 5E(非原创)

    E. Bindian Signalizing time limit per test 4 seconds memory limit per test 256 megabytes input stand ...

  2. 全局ID生成--雪花算法

    分布式ID常见生成策略: 分布式ID生成策略常见的有如下几种: 数据库自增ID. UUID生成. Redis的原子自增方式. 数据库水平拆分,设置初始值和相同的自增步长. 批量申请自增ID. 雪花算法 ...

  3. 进程控制——fork-and-exec、system、wait

    forc-and-exec流程 父进程与子进程之间的关系十分复杂,最大的复杂点在于进程间相互调用.Linux下这一流程称为fork-and-exec.父进程通过fork的方式产生一个一模一样的子进程, ...

  4. 深入剖析JavaScript中的对象与原始值之间的转换机制

    我们都知道原始值之间是可以互相转换的,但是如果对象转原始值呢? 所有的对象在布尔上下文(context)中均为 true .所以对于对象,不存在 to-boolean 转换, 只有字符串和数值转换. ...

  5. awesome youtube programming video tutorials

    awesome youtube programming video tutorials youtube programming tutorials https://www.youtube.com/fe ...

  6. H5 直播 & App 直播

    H5 直播 & App 直播 polyv 直播 https://github.com/polyv 宝利威 直播 https://www.polyv.net/live/ SDK https:// ...

  7. 生态建设者为何青睐低风险、低成本的NGK算力?

    自从BGV推向市场以来,生态建设者的目光都聚集于BGV这个去中心化金融的新星,其实NGK的其他项目也都在稳健进行当中. NGK在未来将推出"算力市场奖励计划",NGK将会对算力市场 ...

  8. 为什么10月上线的NGK Global即将燎原资本市场

    近日据社区透露,NGK Global将在10月全面启动,数据公开透明,人人可以参与运营监管. 现在,区块链经济已经处于爆发前夜.金融行业的探索领先一筹,而其他行业的应用正在快速展开.区块链行业应用头部 ...

  9. 为什么NGK推出的DEFI项目这么火热?

    进入到2020年的下半年,DeFi的锁仓量基本上是以日破新高的态势,不断的成为一个独角兽.DeFi逐渐形成一个独角兽的同时,也在不断的给区块链生态赋能,源源不断进行金融价值输送.所以加密货币体量的不断 ...

  10. java的单例模式小知识点

    单例模式 目的 为了让一个类有且仅有一个实例 优点 只允许一个,节省空间 不用频繁创建删除,提高性能 缺点 不容易扩展 长期不使用会被系统当作垃圾回收,造成系统状态的丢失 实现 要点 防止外界随意的创 ...