获取图片颜色平均值 canvas初级使用
昨天看到群里一个人的主题,首页的轮播很有意思,然后他的轮播底色是根据文章图片颜色来自动变动的,我当时就觉得蛮有意思的,但是我没怎么接触过canvas这个东西,html5的时候匆匆带过,然后js的时候也没有讲,索性就自己百度看看教程了,找了好久,大部分都是转载的同一篇文章,然后大佬的那个js算法我实在看不懂,搞不懂为什么要for循环的时候i要乘以图片的宽度,然后再乘以4,在加123这些,后面慢慢搞懂了*4和+123这些意思,但是还是不太懂为啥要乘以图片宽度,嘛,这些暂时不管了,先看看我的想法吧!
获取颜色平均值理论阶段
首先通过canvas获取到图片的每个像素点的rgba值,然后for循环的时候将r、g、b、a四个的值对应的相加,最后得到的rgba值是全部像素的总和,然后用这个对应的总和除以图片的像素点总和,最终求得每个像素点的平均值。
当然这只是理论的平均值,其实每张图片他有深色和浅色区域,往往深色区域的值高于浅色区域好多倍,那么这样得到的平均值是否就是我们需要的值呢,这个就要考虑下算法了,不过我们目前先将这个想法实现为目的。
了解canvas
canvas是用于绘制图像的,复杂点你甚至能玩出花样,但是canvas元素本身是没有绘画能力的,我初次使用感觉就是复制,有点像是拼图,你实现准备好图片,然后通过js进行拼接,这里我们只是使用到convas的复制图片的能力。
首先我们要了解需要使用到的几个代码:
getContext("2d")
drawImage(img,0,0)
getImageData(0,0,width,height)
.data
第一个getContext("2d")
;是表示canvas要绘制一个2d图像,而且只有这一个选项,canvas目前只支持2d,所以你没得选,照着写就对了。
第二个是drawImage(img,0,0)
;表示规定要使用的图像,后面两个0表示开始裁剪这个图片的x,y轴坐标,其实他后面还有填值,具体我就拿w3c的说明吧!
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
参数 | 描述 |
---|---|
img | 规定要使用的图像、画布或视频。 |
sx | 可选。开始剪切的 x 坐标位置。 |
sy | 可选。开始剪切的 y 坐标位置。 |
swidth | 可选。被剪切图像的宽度。 |
swidth | 可选。被剪切图像的宽度。 |
sheight | 可选。被剪切图像的高度。 |
x | 在画布上放置图像的 x 坐标位置。 |
y | 在画布上放置图像的 y 坐标位置。 |
width | 可选。要使用的图像的宽度。(伸展或缩小图像) |
height | 可选。要使用的图像的高度。(伸展或缩小图像) |
第三个getImageData(0,0,width,height)
;表示计算图片的像素数据,第一个0表示x轴哪个位置开始就算,第二个0表示从y轴哪个位置计算,width和height表示计算的宽高大小。
第四个.data
是和getImageData配合使用的,只有使用了.data
才能拿到对应的像素数据。
注意:
获取的像素数据是一个数组集合,每个下标分别保存r、g、b、a四个值的信息,也就是这样[r,g,b,a,r,g,b,a,.....]这样循环下去。
创建canvas并获取到图片信息
window.onload = function() {
//获取图片颜色平均值
(function getcolor() {
//js创建一个canvas元素
var canvas = document.createElement('canvas');
//设置canvas的大小,默认是300*150,这样就无法获取到全部的图片像素了,这个值也是看你怎么设置的,动态获取也是可以的。
canvas.width = 900;
canvas.height = 350;
//表示绘制一个2d图
var context = canvas.getContext("2d");
//获取图片元素
var img = document.getElementById('myimg');
//创建图片元素用来加载图片地址
var nimg = new Image();
nimg.onload = function(){
var r = 0;
var g = 0;
var b = 0;
var a = 0;
var fxs = 900 * 300;
//设置要绘制的图片
context.drawImage(nimg,0,0);
//获取图片的像素信息,并.data获得数组
var data = context.getImageData(0,0,900,300).data;
//获取所有的rgba的和
for(var i = 0;i<data.length/4;i++) {
r += data[i * 4];
g += data[i * 4 + 1];
b += data[i * 4 + 2];
a += data[i * 4 + 3];
}
//获得平均值
var rgba = 'rgba('+ parseInt(r/fxs) +','+ parseInt(g/fxs) +','+ parseInt(b/fxs) +','+ parseInt(a/fxs) +')';
document.documentElement.style.backgroundColor = rgba;
})
//将图片地址传给nimg
nimg.src = img.src ;
})();
}
效果图
进阶想法
通过上面这个我们可以获取到图片的平均色,但是有时候并不是很如意,我们可以自行去调整算法,比如,你只需要计算某一个角,如80*80的大小,或者5x5的方块取一个点,如图:
并且还可以骚一点,取高亮色或者低亮色,那么怎么计算呢,你可以先取得平均色,然后再一个个for循环判断,如果这个颜色大于平均色50个值以上,那就push这个rgba到新的数组中,然后再求一次这个新数组的平均色,或者再复杂一点,多次for循环,直到高亮色的数组length不超过30对,那么再求平均估计会好很多,这个后续我要是有时间肯定会再次研究了,欢迎讨论。
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
全部评论 1
木灵鱼儿
FireFox Windows 10