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

下面用ps截图举一个例子:
下图的取到的点对应的HSV是(16,71,97),而RGB是(248,120,73)这里通过HSV可以看出亮度是97,非常直观。

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

调整图片亮度的方案
- 通过
rgba和hsv之间的转换 - 通过在原图片的上层盖上一层具有一定透明度的黑色遮罩
这里方案2实施起来比较简单,不过在处理具备透明度的png图片时,会导致透明部分也被遮罩导致变得非透明。所以方案1会比较通用。
实现方案一
从RGB到HSV的转换
转换的公式
设 (r, g, b)分别是一个颜色的红、绿和蓝坐标,它们的值是在0到1之间的实数。设max等价于r, g和b中的最大者。设min等于这些值中的最小者。要找到在HSL空间中的 (h, s, l)值,这里的h ∈ [0, 360)度是角度的色相角,而s, l ∈ [0,1]是饱和度和亮度,计算为:

h的值通常规范化到位于0到360°之间。而h = 0用于max = min的(定义为灰色)时候而不是留下h未定义。
HSL和HSV有同样的色相定义,但是其他分量不同。HSV颜色的s和v的值定义如下:

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之间的s和v,在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-修改图片亮度的更多相关文章
- Android动态修改图片颜色的实现方式分析
版权声明:本文为博主原创文章,未经博主允许不得转载. 1.修改色相.饱和度.亮度 参看:http://blog.csdn.NET/sjf0115/article/details/7267063 2.使 ...
- BackgroundCheck – 根据图片亮度智能切换元素样式
BackgroundCheck 是一个轻量的 JavaScript 库,能够根据元素后面的图片的亮度自动切换元素样式.例如在图片幻灯片功能中,根据图片亮度调整导航箭头的颜色,这样让图片和导航的颜色形成 ...
- 使用HTML5的canvas做图片剪裁
前言 图片裁剪上传,不仅是一个很贴合用户体验的功能,还能够统一特定图片尺寸,优化网站排版,一箭双雕. 需求就是那么简单,在浏览器里裁剪图片并上传到服务器. 我第一个想到的方法就是,将图片和裁剪参数(x ...
- android 通过修改图片像素实现CircleImageView
CircleImageView实现方法有很多种,各有优缺点,因此需要按照不同的场景使用.我们今天使用修改图片像素的方法实现CircleImageView,主要知识点无非是勾股定理和点到圆形的距离. 素 ...
- PHP修改图片
这篇是关于修改图片的效果,主要还是用到php中的GD库中的函数,没想到php还有这凶残能力,出乎我的预料. 先看代码upload_image.php,主要是一个上传控件,用来选择图片 <html ...
- 神奇的canvas——巧用 canvas 为图片添加水印
代码地址如下:http://www.demodashi.com/demo/11637.html 很久之前写过一篇关于 canvas 的文章,是通过 canvas 来实现一个绚丽的动画效果,不管看过没看 ...
- 利用Photoshop修改图片以达到投稿要求
摘自:http://www.dxy.cn/bbs/thread/8602152#8602152 利用Photoshop修改图片以达到投稿要求 软件版本为Photoshop CS V8.0.1(中文版) ...
- canvas学习笔记:canvas对图片的像素级处理--ImageData的应用
学习了canvas的基本绘图功能后,惊喜的发现canvas对图片数据也有相当强大的处理功能,能够从像素级别操作位图,当然[lte ie8]不支持. 主要的函数有三个: ctx.createImageD ...
- 【faster-rcnn】训练自己的数据——修改图片格式、类别
修改图片格式 matlab代码 其实内部一些代码是用了rbg的fast-rcnn代码的. \datasets\VOCdevkit2007\VOCcode\VOCinit.m里面,查找'jpg',改成' ...
随机推荐
- 北京网络赛G BOXES 大模拟+BFS
题目描述 Description There is a strange storehouse in PKU. In this storehouse there are n slots for boxe ...
- WMI在渗透测试中的重要性
0x01 什么是wmi WMI可以描述为一组管理Windows系统的方法和功能.我们可以把它当作API来与Windows系统进行相互交流.WMI在渗透测试中的价值在于它不需要下载和安装, 因为WMI是 ...
- 链接脚本再探和VMA与LMA
链接脚本简单描述 连接脚本的描述都是以节(section)的单位的,网上也有很多描述链接脚本语法的好文章,再不济还有官方的说明文档可以用来学习,其实主要就是对编译构建的整个过程有了深入的理解后就能对链 ...
- useful tools for programmer programming
useful tools for programmer programming devtools repl & playground https://repl.it/@xgqfrms/ htt ...
- DOM & Shadow DOM & Virtual DOM
DOM & Shadow DOM & Virtual DOM What is the difference between Shadow DOM and Virtual DOM? ht ...
- react fiber
react fiber https://github.com/acdlite/react-fiber-architecture https://github.com/facebook/react/is ...
- EventEmitter & custom events & sub/pub
EventEmitter & custom events & sub/pub https://repl.it/@xgqfrms/PPLabs-frontend-answers // 5 ...
- 在gradle中构建java项目
目录 简介 构建java项目的两大插件 管理依赖 编译代码 管理resource 打包和发布 生成javadoc 简介 之前的文章我们讲到了gradle的基本使用,使用gradle的最终目的就是为了构 ...
- 鸿蒙js开发7 鸿蒙分组列表和弹出menu菜单
鸿蒙入门指南,小白速来!从萌新到高手,怎样快速掌握鸿蒙开发?[课程入口]目录:1.鸿蒙视图效果2.js业务数据和事件3.页面视图代码4.跳转页面后的视图层5.js业务逻辑部分6.<鸿蒙js开发& ...
- Kubernetes和docker----1.开始使用k8s和docker
开始使用Kubernetes和docker docker命令 运行一个容器 docker run busybox echo "Hello world" 构建容器镜像 docker ...