一、canvas的情况

canvas自从出来了之后,在前端的图像处理上面提供了各种各样的遍历,虽然很多的操作其实都是要应用到算法的,但是这个也给前端提供了很多的可能性,其中最终要的一个canvas函数(至少我认为)就是getImageData,这个函数可以提取图像每个像素的RGBA值。因为有这个函数所有才有丰富多彩的canvas图像处理。

二、预备知识

 2.1 获取一个canvas对象

<canvas id="test"></canvas>
<script>
var test = document.querySelector("#test");// 方法一
var test_1=document.getElementById("test");// 方法二
console.log(test);
console.log(test_1);
</script>

2.2 创建一个画布的空间类型(2D,3D)

创建一个2D的画布

var ctx = test.getContext("2d");

2.3 getImageData对象

getImageData对象可以获取画布中的图片对应的所有像素的RGBA值,这个有利于我们对图片进行重新的计算。在使用这个属性的时候,需要配置好HTTP的访问环境。

2.4 Uint8ClampedArray

这个代表的是一个无类型8位的字符串,也就是说明最多存储到255

2.5 Uint8ClampedArray与getImageData对象

Uint8ClampedArray包含在getImageData对象中,getImageData除了有Uint8ClampedArray之外,还有获取图片数据的长度和宽度。

三、多种图片效果canvas实现

1. 原图

2. 反色(负片)效果

3. 去色效果

4. 单色效果

5. 中国版画效果

6. 高斯模糊效果

7. 浮雕效果与刻雕效果

3.1 原图

通过canvas来渲染原图,首选我们在网上随意找一张图片。

  ·

window.onload = function () {
var img = new Image();
img.src = "rx.jpg";
// 加载完成图片之后才能够执行canvas的操作
img.onload = function () {
var canvas = document.querySelector("#canvas");
var cxt = canvas.getContext("2d");
canvas.width=293;
canvas.height=220;
cxt.drawImage(img, 0, 0, 293, 220);
}
}

其中canvas的width,height属性都是必须要设置的,不设置的话,canvas会采用默认的width=300,height=150来设置图片。

3.2 反色(负片)效果

图片反色的原理其实很简单不多做解释:将图片中的每一个元素进行如下的公式运算就可以得到最终的结果

 window.onload = function () {
var img = new Image();
img.src = "rx.jpg";
img.onload = function () {
var canvas = document.querySelector("#canvas");
var cxt = canvas.getContext("2d");
canvas.width = 293;
canvas.height = 220;
cxt.drawImage(img, 0, 0, canvas.width, canvas.height);
var imageData = cxt.getImageData(0, 0, canvas.width, canvas.height);
var imageData_length = imageData.data.length / 4;
// 解析之后进行算法运算
for (var i = 0; i < imageData_length; i++) {
imageData.data[i * 4] = 255 - imageData.data[i * 4];
imageData.data[i * 4 + 1] = 255 - imageData.data[i * 4 + 1];
imageData.data[i * 4 + 2] = 255 - imageData.data[i * 4 + 2];
}
cxt.putImageData(imageData, 0, 0); }
}

运行之后的效果如下:

3.3 去色效果

这里说的去色效果与第二种效果不同的是,去色效果相当于就是老旧相机拍出来的黑白照片。

要得到去色效果的照片有很多种方法,但是卤煮比较推崇的做法是采用基于人眼感觉的加权平均数来实现,这个算法的原理是采用人眼对RGB不同颜色的敏感程度不同,然后通过得出的加权平均数来运算出最后的结果

Gray = (Red * 0.3 + Green * 0.59 + Blue * 0.11)

代码如下实现:

 window.onload = function () {
var img = new Image();
img.src = "rx.jpg";
img.onload = function () {
var canvas = document.querySelector("#canvas");
var cxt = canvas.getContext("2d");
canvas.width = 293;
canvas.height = 220;
cxt.drawImage(img, 0, 0, canvas.width, canvas.height);
var imageData = cxt.getImageData(0, 0, canvas.width, canvas.height);
var imageData_length = imageData.data.length / 4;
// 解析之后进行算法运算
for (var i = 0; i < imageData_length; i++) {
var red = imageData.data[i * 4];
var green = imageData.data[i * 4 + 1];
var blue = imageData.data[i * 4 + 2];
var gray = 0.3 * red + 0.59 * green + 0.11 * blue;
imageData.data[i * 4] = gray;
imageData.data[i * 4 + 1] = gray;
imageData.data[i * 4 + 2] = gray;
}
cxt.putImageData(imageData, 0, 0); }
}

运行效果如下:

3.4 单色效果

单颜色效果原理就是将当前像素的其他色值去除。

假设我们要实现的单颜色效果是红色,那么实现的代码如下:

 window.onload = function () {
var img = new Image();
img.src = "rx.jpg";
img.onload = function () {
var canvas = document.querySelector("#canvas");
var cxt = canvas.getContext("2d");
canvas.width = 293;
canvas.height = 220;
cxt.drawImage(img, 0, 0, canvas.width, canvas.height);
var imageData = cxt.getImageData(0, 0, canvas.width, canvas.height);
var imageData_length = imageData.data.length / 4;
// 解析之后进行算法运算
for (var i = 0; i < imageData_length; i++) {
imageData.data[i * 4 + 1] = 0;
imageData.data[i * 4 + 2] = 0;
}
cxt.putImageData(imageData, 0, 0); }
}

效果图:

3.5 中国版画效果

中国版画不同于去色和反色的效果,在中国版画的效果中除了黑就是白色,不存在其他的颜色,下面就是一张传统的中国版画的效果。

这个的实现算法比较的灵活一般是根据你要得到的效果来进行参数配置的,原理就是通过判断当前元素的色值是否高于这个给定值,高于我们就显示为黑色,小于我们就显示为白色这样的一种方法来实现的。

按照卤煮一般的设置值来说会设置为126.因为126是2的8次方的中间数。相对来说比较的对称

实现的代码如下:

window.onload = function () {
var img = new Image();
img.src = "rx.jpg";
img.onload = function () {
var canvas = document.querySelector("#canvas");
var cxt = canvas.getContext("2d");
canvas.width = 293;
canvas.height = 220;
cxt.drawImage(img, 0, 0, canvas.width, canvas.height);
var imageData = cxt.getImageData(0, 0, canvas.width, canvas.height);
var imageData_length = imageData.data.length / 4;
// 解析之后进行算法运算
for (var i = 0; i < imageData_length; i++) {
var red = imageData.data[i * 4];
var green = imageData.data[i * 4 + 1];
var blue = imageData.data[i * 4 + 2];
var gray = 0.3 * red + 0.59 * green + 0.11 * blue;
var new_black;
if (gray > 126) {
new_black = 255;
} else {
new_black = 0;
}
imageData.data[i * 4] = new_black;
imageData.data[i * 4 + 1] = new_black;
imageData.data[i * 4 + 2] = new_black;
}
cxt.putImageData(imageData, 0, 0); }
}

运行的效果如下:

如果是我们要渲染更多的黑颜色的话,我们应该要将值调高,反之将其调低,下面我们把值调到150运行一下:

3.6 高斯模糊效果

高斯模糊是一种两维的卷积模糊操作,简单的介绍就是通过让图片的每个像素与四周的像素按照某种权重进行分布求值,要了解具体的同学可以戳戳这里

这里我们就展示结论,推导不做介绍(二维高斯分布函数):

我们直接贴出实现的代码:

function gaussBlur(imgData) {
console.log(imgData);
var pixes = imgData.data;
var width = imgData.width;
var height = imgData.height;
var gaussMatrix = [],
gaussSum = 0,
x, y,
r, g, b, a,
i, j, k, len; var radius = 30;
var sigma = 5; a = 1 / (Math.sqrt(2 * Math.PI) * sigma);
b = -1 / (2 * sigma * sigma);
//生成高斯矩阵
for (i = 0, x = -radius; x <= radius; x++, i++){
g = a * Math.exp(b * x * x);
gaussMatrix[i] = g;
gaussSum += g; }
//归一化, 保证高斯矩阵的值在[0,1]之间
for (i = 0, len = gaussMatrix.length; i < len; i++) {
gaussMatrix[i] /= gaussSum;
}
//x 方向一维高斯运算
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
r = g = b = a = 0;
gaussSum = 0;
for(j = -radius; j <= radius; j++){
k = x + j;
if(k >= 0 && k < width){//确保 k 没超出 x 的范围
//r,g,b,a 四个一组
i = (y * width + k) * 4;
r += pixes[i] * gaussMatrix[j + radius];
g += pixes[i + 1] * gaussMatrix[j + radius];
b += pixes[i + 2] * gaussMatrix[j + radius];
// a += pixes[i + 3] * gaussMatrix[j];
gaussSum += gaussMatrix[j + radius];
}
}
i = (y * width + x) * 4;
// 除以 gaussSum 是为了消除处于边缘的像素, 高斯运算不足的问题
// console.log(gaussSum)
pixes[i] = r / gaussSum;
pixes[i + 1] = g / gaussSum;
pixes[i + 2] = b / gaussSum;
// pixes[i + 3] = a ;
}
}
//y 方向一维高斯运算
for (x = 0; x < width; x++) {
for (y = 0; y < height; y++) {
r = g = b = a = 0;
gaussSum = 0;
for(j = -radius; j <= radius; j++){
k = y + j;
if(k >= 0 && k < height){//确保 k 没超出 y 的范围
i = (k * width + x) * 4;
r += pixes[i] * gaussMatrix[j + radius];
g += pixes[i + 1] * gaussMatrix[j + radius];
b += pixes[i + 2] * gaussMatrix[j + radius];
// a += pixes[i + 3] * gaussMatrix[j];
gaussSum += gaussMatrix[j + radius];
}
}
i = (y * width + x) * 4;
pixes[i] = r / gaussSum;
pixes[i + 1] = g / gaussSum;
pixes[i + 2] = b / gaussSum;
}
}
console.log(imgData);
return imgData;
}

运行之后的效果如下:

3.7 浮雕效果与刻雕效果

这里要感谢CSDN的算法专家gloomyfish,他的博文给我提供了一个好的思路,同时根据他的一个代码逻辑我们可以得出如下的公式:

    (C常量,Xa后一个像素的RGB,Xb前一个像素的RGB)

其中color代表的是最后的色值,Xa和Xb代表的是当前像素前后两点的RGB(中的某一个值),C代表的是一个常量【根据你的具体需要来定】

原理就是将某个像素与周边的差值较大的检测出来,然后替换成为255,一般我们将这个常量C设置成为128【255的一半】

/**
* after pixel value - before pixel value + 128
* 代码引用自 gloomyfish
* 浮雕效果
*/
reliefProcess: function(context, canvasData) {
//caontext 画布对象 document.querySelector().getContext("2d");
// conavas document.querySelector().getContext("2d").getImageData();
console.log("Canvas Filter - relief process");
var tempCanvasData = this.copyImageData(context, canvasData);
for ( var x = 0; x < tempCanvasData.width-1; x++)
{
for ( var y = 0; y < tempCanvasData.height-1; y++)
{ // Index of the pixel in the array
var idx = (x + y * tempCanvasData.width) * 4;
var bidx = ((x-1) + y * tempCanvasData.width) * 4;
var aidx = ((x+1) + y * tempCanvasData.width) * 4; // calculate new RGB value
var nr = tempCanvasData.data[aidx + 0] - tempCanvasData.data[bidx + 0] + 128;
var ng = tempCanvasData.data[aidx + 1] - tempCanvasData.data[bidx + 1] + 128;
var nb = tempCanvasData.data[aidx + 2] - tempCanvasData.data[bidx + 2] + 128;
nr = (nr < 0) ? 0 : ((nr >255) ? 255 : nr);
ng = (ng < 0) ? 0 : ((ng >255) ? 255 : ng);
nb = (nb < 0) ? 0 : ((nb >255) ? 255 : nb); // assign new pixel value
canvasData.data[idx + 0] = nr; // Red channel
canvasData.data[idx + 1] = ng; // Green channel
canvasData.data[idx + 2] = nb; // Blue channel
canvasData.data[idx + 3] = 255; // Alpha channel
}
}
},

运行的图像如下:

 其中常量的数值越大,浮雕的颜色越浅,反之加深。我们把它设置到50看下效果:

刻雕效果与浮雕效果基本一样,就是要调整公式里面的Xa和Xb的位置,调整如下:

四、小结

由于canvas涉及到的知识点比较的深奥,所以里面有很多的内容没法再这里一一的进行说明,这一篇文章也就是对于canvas实际应用的一个简单的说明,在图形学方面,磨皮处理和高通滤波,低通滤波等等方面的处理还没有实现,在一些粒子化,动画,碰撞方面也不能一一道来,深表遗憾

canvas图像处理汇总的更多相关文章

  1. 基于canvas图像处理的图片展示demo

    图片展示网页往往色彩繁杂,当一个网页上有多张图片的时候用户的注意力就很不容易集中,而且会造成网站整个色调风格的不可把控. 能不能把所有的预览图变成灰度图片,等用户激活某张图片的时候再上色呢? 以前,唯 ...

  2. 基于canvas图像处理的图片 灰色图像

    图片展示网页往往色彩繁杂,当一个网页上有多张图片的时候用户的注意力就很不容易集中,而且会造成网站整个色调风格的不可把控. 能不能把所有的预览图变成灰度图片,等用户激活某张图片的时候再上色呢? 以前,唯 ...

  3. HTML5标签canvas图像处理

    摘要: canvas可以读取图片后,使用drawImage方法在画布内进行重绘.本文介绍canvas的图像处理 drawImage drawImage() 方法在画布上绘制图像.画布或视频.drawI ...

  4. Canvas知识点汇总

    本文主要记录Canvas基础知识汇总. 1.Canvas定义 <canvas> 元素是HTML5中的新元素,通过它可以在网页中绘制出所需的图形.<canvas>标签只是图形的容 ...

  5. 微信小游戏开发Canvas资源汇总

    Demo: 微信小程序demo组件:股票分时图 微信小程序小组件:仿直播点赞气泡效果,基于Canvas 优质demo推荐:二维码生成器:使用canvas与纯JS版二维码生成 微信小程序学习用完整dem ...

  6. html5 canvas 图像处理

    1.图像放大缩小 <script> var cvs = document.getElementById("canvas"); cvs.width = cvs.heigh ...

  7. HTML5新特性之Canvas+drag(拖拽图像实现图像反转)

    1.什么是canvas 在网页上使用canvas元素时,会创建一块矩形区域,默认矩形区域宽度300px,高度150px.. 页面中加入canvas元素后,可以通过javascript自由控制.可以在其 ...

  8. canvas学习和滤镜实现

    最近学习了 HTML5 中的重头戏--canvas.利用 canvas,前端人员可以很轻松地.进行图像处理.其 API 繁多,这次主要学习常用的 API,并且完成以下两个代码: 实现去色滤镜 实现负色 ...

  9. Atitit.attilax软件研发与项目管理之道

    Atitit.attilax软件研发与项目管理之道 1. 前言4 2. 鸣谢4 3. Genesis 创世记4 4. 软件发展史4 5. 箴言4 6. 使徒行传 4 7. attilax书 4 8. ...

随机推荐

  1. nodejs实现OAuth2.0授权服务

    OAuth是一种开发授权的网络标准,全拼为open authorization,即开放式授权,最新的协议版本是2.0. 举个栗子: 有一个"云冲印"的网站,可以将用户储存在Goog ...

  2. 理解spread运算符与rest参数

    理解spread运算符与rest参数 spread运算符与rest参数 是ES6的新语法.它们的作用是什么?能做什么事情? 1. rest运算符用于获取函数调用时传入的参数. function tes ...

  3. 解决iOS手势冲突问题

    今天在做一个效果的时候,由于子视图和父视图都有响应的事件,子视图的事件理所当然被父视图拦截掉了,接下来就做分析解决 1.  tableviewcell可以触发点击,同时tableview的父视图有点击 ...

  4. 《深入浅出node.js(朴灵)》【PDF】下载

    <深入浅出node.js(朴灵)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062563 内容简介 <深入浅出Node. ...

  5. DotNetCasClient 如何获取Cas服务器返回的attributes中的数据

    最近开始接触做与其它认证系统的集成,其中有个是与某学校的CAS服务器集成.cas服务器认证成功后返回的数据格式如下: 其中红色部分是我需要取出来用于识别用户身份的数据. 一开始,我根据网上的教程,引用 ...

  6. 轨迹系列——Socket总结及实现基于TCP或UDP的809协议方法

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 在上一篇博客中我详细介绍了809协议的内容.809协议规范了通 ...

  7. DotNetCore跨平台~Moq框架实现模拟测试

    回到目录 当我们进行软件开发时,一般会写单元测试,而对于业务情景来说,一般是测试它的业务逻辑准确性,对于你的测试数据是否来自数据库还是文件,是否为真实还是模拟,并不是很关心!我关心的就是我的业务逻辑是 ...

  8. 使用Python Shapefile Library创建和编辑Shapefile文件

    介绍 shapefile是GIS中非常重要的一种数据类型,在ArcGIS中被称为要素类(Feature Classes),主要包括点(point).线(polyline)和多边形(polygon).P ...

  9. VS 2017 Web项目需要安装Sql Server 2012 Express LocalDB问题

    最近在做mvc5的练习 ,结果到了数据库连接这一阶段就出现了问题,开始我以为<add name="MovieDBContext" connectionString=" ...

  10. 我知道你不知道的负Margin

    现如今,负margin技术的应用可谓越来越广,任一个大型站点惊鸿一瞥之下都会有其身影所在.个人认为负margin技术是学习css路上必不可缺少的课题之一,许多高级应用及疑难杂症修复都可以使用负marg ...