纯JavaScript实现HTML5 Canvas六种特效滤镜示例


Posted in Javascript onJune 28, 2013

小试牛刀,实现了六款简单常见HTML5 Canvas特效滤镜,并且封装成一个纯JavaScript可调用的API文件gloomyfishfilter.js。支持的特效滤镜分别为:
1.反色
2.灰色调
3.模糊
4.浮雕
5.雕刻
6.镜像

滤镜原理解释:
1.反色:获取一个像素点RGB值r, g, b则新的RGB值为(255-r, 255-g, 255-b)
2.灰色调:获取一个像素点RGB值r, g, b则新的RGB值为

newr = (r * 0.272) + (g * 0.534) + (b * 0.131); 
newg = (r * 0.349) + (g * 0.686) + (b * 0.168); 
newb = (r * 0.393) + (g * 0.769) + (b * 0.189);

3.模糊:基于一个5*5的卷积核
4.浮雕与雕刻:
基于当前像素的前一个像素RGB值与它的后一个像素的RGB值之差再加上128
5.镜像:模拟了物体在镜子中与之对应的效果。
杂项准备
1.如何获取Canvas 2d context对象
var canvas = document.getElementById("target"); 
canvas.width = source.clientWidth; 
canvas.height = source.clientHeight; 
if(!canvas.getContext) { 
console.log("Canvas not supported. Please install a HTML5compatible browser."); 
return; 
} 
// get 2D context of canvas and draw image 
tempContext = canvas.getContext("2d");

2.如何绘制一个DOM img对象到Canvas对象中
var source = document.getElementById("source"); 
tempContext.drawImage(source, 0, 0, canvas.width,canvas.height);

3.如何从Canvas对象中获取像素数据
var canvas = document.getElementById("target"); 
varlen = canvas.width * canvas.height * 4; 
var canvasData = tempContext.getImageData(0, 0, canvas.width, canvas.height); 
var binaryData = canvasData.data;

4.如何对DOM对象实现鼠标Click事件绑定
function bindButtonEvent(element, type, handler) 
{ 
if(element.addEventListener){ 
element.addEventListener(type, handler,false); 
}else { 
element.attachEvent('on'+type, handler);// for IE6,7,8 
} 
}

5.如何调用实现的gfilter API完成滤镜功能
<scriptsrc="gloomyfishfilter.js"></script> //导入API文件 
gfilter.colorInvertProcess(binaryData, len); //调用 API

6.浏览器支持:IE, FF, Chrome上测试通过,其中IE上支持通过以下标签实现:
<meta http-equiv="X-UA-Compatible"content="chrome=IE8">

效果演示:
纯JavaScript实现HTML5 Canvas六种特效滤镜示例 
应用程序源代码:
CSS部分:
#svgContainer { 
width:800px; 
height:600px; 
background-color:#EEEEEE; 
} 
#sourceDiv { float: left; border: 2px solid blue} 
#targetDiv { float: right;border: 2px solid red}

filter1.html中HTML源代码:
<!DOCTYPE html> 
<html> 
<head> 
<meta http-equiv="X-UA-Compatible" content="chrome=IE8"> 
<meta http-equiv="Content-type" content="text/html;charset=UTF-8"> 
<title>Canvas Filter Demo</title> 
<link href="default.css" rel="stylesheet" /> 
<script src="gloomyfishfilter.js"></scrip> 
</head> 
<body> 
<h1>HTML Canvas Image Process - By Gloomy Fish</h1> 
<div id="svgContainer"> 
<div id="sourceDiv"> 
<img id="source" src="../test.png" /> 
</div> 
<div id="targetDiv"> 
<canvas id="target"></canvas> 
</div> 
</div> 
<div id="btn-group"> 
<button type="button" id="invert-button">反色</button> 
<button type="button" id="adjust-button">灰色调</button> 
<button type="button" id="blur-button">模糊</button> 
<button type="button" id="relief-button">浮雕</button> 
<button type="button" id="diaoke-button">雕刻</button> 
<button type="button" id="mirror-button">镜像</button> 
</div> 
</body> 
</html>

filter1.html中JavaScript源代码:
var tempContext = null; // global variable 2d context 
window.onload = function() { 
var source = document.getElementById("source"); 
var canvas = document.getElementById("target"); 
canvas.width = source.clientWidth; 
canvas.height = source.clientHeight; if (!canvas.getContext) { 
console.log("Canvas not supported. Please install a HTML5 compatible browser."); 
return; 
} 
// get 2D context of canvas and draw image 
tempContext = canvas.getContext("2d"); 
tempContext.drawImage(source, 0, 0, canvas.width, canvas.height); 
// initialization actions 
var inButton = document.getElementById("invert-button"); 
var adButton = document.getElementById("adjust-button"); 
var blurButton = document.getElementById("blur-button"); 
var reButton = document.getElementById("relief-button"); 
var dkButton = document.getElementById("diaoke-button"); 
var mirrorButton = document.getElementById("mirror-button"); 
// bind mouse click event 
bindButtonEvent(inButton, "click", invertColor); 
bindButtonEvent(adButton, "click", adjustColor); 
bindButtonEvent(blurButton, "click", blurImage); 
bindButtonEvent(reButton, "click", fudiaoImage); 
bindButtonEvent(dkButton, "click", kediaoImage); 
bindButtonEvent(mirrorButton, "click", mirrorImage); 
} 
function bindButtonEvent(element, type, handler) 
{ 
if(element.addEventListener) { 
element.addEventListener(type, handler, false); 
} else { 
element.attachEvent('on'+type, handler); // for IE6,7,8 
} 
} 
function invertColor() { 
var canvas = document.getElementById("target"); 
var len = canvas.width * canvas.height * 4; 
var canvasData = tempContext.getImageData(0, 0, canvas.width, canvas.height); 
var binaryData = canvasData.data; 
// Processing all the pixels 
gfilter.colorInvertProcess(binaryData, len); 
// Copying back canvas data to canvas 
tempContext.putImageData(canvasData, 0, 0); 
} 
function adjustColor() { 
var canvas = document.getElementById("target"); 
var len = canvas.width * canvas.height * 4; 
var canvasData = tempContext.getImageData(0, 0, canvas.width, canvas.height); 
var binaryData = canvasData.data; 
// Processing all the pixels 
gfilter.colorAdjustProcess(binaryData, len); 
// Copying back canvas data to canvas 
tempContext.putImageData(canvasData, 0, 0); 
} 
function blurImage() 
{ 
var canvas = document.getElementById("target"); 
var len = canvas.width * canvas.height * 4; 
var canvasData = tempContext.getImageData(0, 0, canvas.width, canvas.height); 
// Processing all the pixels 
gfilter.blurProcess(tempContext, canvasData); 
// Copying back canvas data to canvas 
tempContext.putImageData(canvasData, 0, 0); 
} 
function fudiaoImage() 
{ 
var canvas = document.getElementById("target"); 
var len = canvas.width * canvas.height * 4; 
var canvasData = tempContext.getImageData(0, 0, canvas.width, canvas.height); 
// Processing all the pixels 
gfilter.reliefProcess(tempContext, canvasData); 
// Copying back canvas data to canvas 
tempContext.putImageData(canvasData, 0, 0); 
} 
function kediaoImage() 
{ 
var canvas = document.getElementById("target"); 
var len = canvas.width * canvas.height * 4; 
var canvasData = tempContext.getImageData(0, 0, canvas.width, canvas.height); 
// Processing all the pixels 
gfilter.diaokeProcess(tempContext, canvasData); 
// Copying back canvas data to canvas 
tempContext.putImageData(canvasData, 0, 0); 
} 
function mirrorImage() 
{ 
var canvas = document.getElementById("target"); 
var len = canvas.width * canvas.height * 4; 
var canvasData = tempContext.getImageData(0, 0, canvas.width, canvas.height); 
// Processing all the pixels 
gfilter.mirrorProcess(tempContext, canvasData); 
// Copying back canvas data to canvas 
tempContext.putImageData(canvasData, 0, 0); 
}

滤镜源代码(gloomyfishfilter.js):
var gfilter = { 
type: "canvas", 
name: "filters", 
author: "zhigang", 
getInfo: function () { 
return this.author + ' ' + this.type + ' ' + this.name; 
}, 
/** 
* invert color value of pixel, new pixel = RGB(255-r, 255-g, 255 - b) 
* 
* @param binaryData - canvas's imagedata.data 
* @param l - length of data (width * height of image data) 
*/ 
colorInvertProcess: function(binaryData, l) { 
for (var i = 0; i < l; i += 4) { 
var r = binaryData[i]; 
var g = binaryData[i + 1]; 
var b = binaryData[i + 2]; binaryData[i] = 255-r; 
binaryData[i + 1] = 255-g; 
binaryData[i + 2] = 255-b; 
} 
}, 
/** 
* adjust color values and make it more darker and gray... 
* 
* @param binaryData 
* @param l 
*/ 
colorAdjustProcess: function(binaryData, l) { 
for (var i = 0; i < l; i += 4) { 
var r = binaryData[i]; 
var g = binaryData[i + 1]; 
var b = binaryData[i + 2]; 
binaryData[i] = (r * 0.272) + (g * 0.534) + (b * 0.131); 
binaryData[i + 1] = (r * 0.349) + (g * 0.686) + (b * 0.168); 
binaryData[i + 2] = (r * 0.393) + (g * 0.769) + (b * 0.189); 
} 
}, 
/** 
* deep clone image data of canvas 
* 
* @param context 
* @param src 
* @returns 
*/ 
copyImageData: function(context, src) 
{ 
var dst = context.createImageData(src.width, src.height); 
dst.data.set(src.data); 
return dst; 
}, 
/** 
* convolution - keneral size 5*5 - blur effect filter(模糊效果) 
* 
* @param context 
* @param canvasData 
*/ 
blurProcess: function(context, canvasData) { 
console.log("Canvas Filter - blur process"); 
var tempCanvasData = this.copyImageData(context, canvasData); 
var sumred = 0.0, sumgreen = 0.0, sumblue = 0.0; 
for ( var x = 0; x < tempCanvasData.width; x++) { 
for ( var y = 0; y < tempCanvasData.height; y++) { 
// Index of the pixel in the array 
var idx = (x + y * tempCanvasData.width) * 4; 
for(var subCol=-2; subCol<=2; subCol++) { 
var colOff = subCol + x; 
if(colOff <0 || colOff >= tempCanvasData.width) { 
colOff = 0; 
} 
for(var subRow=-2; subRow<=2; subRow++) { 
var rowOff = subRow + y; 
if(rowOff < 0 || rowOff >= tempCanvasData.height) { 
rowOff = 0; 
} 
var idx2 = (colOff + rowOff * tempCanvasData.width) * 4; 
var r = tempCanvasData.data[idx2 + 0]; 
var g = tempCanvasData.data[idx2 + 1]; 
var b = tempCanvasData.data[idx2 + 2]; 
sumred += r; 
sumgreen += g; 
sumblue += b; 
} 
} 
// calculate new RGB value 
var nr = (sumred / 25.0); 
var ng = (sumgreen / 25.0); 
var nb = (sumblue / 25.0); 
// clear previous for next pixel point 
sumred = 0.0; 
sumgreen = 0.0; 
sumblue = 0.0; 
// 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 
} 
} 
}, 
/** 
* after pixel value - before pixel value + 128 
* 浮雕效果 
*/ 
reliefProcess: function(context, canvasData) { 
console.log("Canvas Filter - relief process"); 
var tempCanvasData = this.copyImageData(context, canvasData); 
for ( var x = 1; x < tempCanvasData.width-1; x++) 
{ 
for ( var y = 1; 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 
} 
} 
}, 
/** 
* before pixel value - after pixel value + 128 
* 雕刻效果 
* 
* @param canvasData 
*/ 
diaokeProcess: function(context, canvasData) { 
console.log("Canvas Filter - process"); 
var tempCanvasData = this.copyImageData(context, canvasData); 
for ( var x = 1; x < tempCanvasData.width-1; x++) 
{ 
for ( var y = 1; 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[bidx + 0] - tempCanvasData.data[aidx + 0] + 128; 
var ng = tempCanvasData.data[bidx + 1] - tempCanvasData.data[aidx + 1] + 128; 
var nb = tempCanvasData.data[bidx + 2] - tempCanvasData.data[aidx + 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 
} 
} 
}, 
/** 
* mirror reflect 
* 
* @param context 
* @param canvasData 
*/ 
mirrorProcess : function(context, canvasData) { 
console.log("Canvas Filter - process"); 
var tempCanvasData = this.copyImageData(context, canvasData); 
for ( var x = 0; x < tempCanvasData.width; x++) // column 
{ 
for ( var y = 0; y < tempCanvasData.height; y++) // row 
{ 
// Index of the pixel in the array 
var idx = (x + y * tempCanvasData.width) * 4; 
var midx = (((tempCanvasData.width -1) - x) + y * tempCanvasData.width) * 4; 
// assign new pixel value 
canvasData.data[midx + 0] = tempCanvasData.data[idx + 0]; // Red channel 
canvasData.data[midx + 1] = tempCanvasData.data[idx + 1]; ; // Green channel 
canvasData.data[midx + 2] = tempCanvasData.data[idx + 2]; ; // Blue channel 
canvasData.data[midx + 3] = 255; // Alpha channel 
} 
} 
}, 
};
Javascript 相关文章推荐
nicejforms——美化表单不用愁
Feb 20 Javascript
javascript去掉前后空格的实例
Nov 07 Javascript
php读取sqlite数据库入门实例代码
Jun 25 Javascript
javascript中bind函数的作用实例介绍
Sep 28 Javascript
javascript创建对象的几种模式介绍
May 06 Javascript
ionic js 复选框 与普通的 HTML 复选框到底有没区别
Jun 06 Javascript
jquery实现input框获取焦点的方法
Feb 06 Javascript
AngularJS中ng-class用法实例分析
Jul 06 Javascript
基于JavaScript实现选项卡效果
Jul 21 Javascript
关于ES6箭头函数中的this问题
Feb 27 Javascript
vue element 中的table动态渲染实现(动态表头)
Nov 21 Javascript
Vant+postcss-pxtorem 实现浏览器适配功能
Feb 05 Javascript
jquery中通过父级查找进行定位示例
Jun 28 #Javascript
javascript实现文字图片上下滚动的具体实例
Jun 28 #Javascript
JavaScript操纵窗口的方法小结
Jun 28 #Javascript
网站如何做到完全不需要jQuery也可以满足简单需求
Jun 27 #Javascript
js获取当前日期代码适用于网页头部
Jun 27 #Javascript
jquery仿QQ商城带左右按钮控制焦点图片切换滚动效果
Jun 27 #Javascript
JQUERY实现左侧TIPS滑进滑出效果示例
Jun 27 #Javascript
You might like
PHP程序级守护进程的实现与优化的使用概述
2013/05/02 PHP
php 时间time与日期date之间的使用详解及区别
2016/11/07 PHP
dojo 之基础篇(三)之向服务器发送数据
2007/03/24 Javascript
JavaScript DOM 学习第七章 表单的扩展
2010/02/19 Javascript
jQuery 美元符冲突的解决方法
2010/03/28 Javascript
jquery动态加载图片数据练习代码
2011/08/04 Javascript
关于IE BUG与字符串截取substr的解决办法
2013/04/10 Javascript
浅谈Jquery核心函数
2015/06/18 Javascript
js计算文本框输入的字符数
2015/10/23 Javascript
Js类的静态方法与实例方法区分及jQuery拓展的两种方法
2016/06/03 Javascript
jQuery与JavaScript节点创建方法的对比
2016/11/18 Javascript
headjs实现网站并行加载但顺序执行JS
2016/11/29 Javascript
jQuery实现背景滑动菜单
2016/12/02 Javascript
纯JS焦点图特效实例(可一个页面多用)
2016/12/07 Javascript
jquery uploadify隐藏上传进度的实现方法
2017/02/06 Javascript
详解Vue2.0之去掉组件click事件的native修饰
2017/04/20 Javascript
JS实现简单的天数计算器完整实例
2017/04/28 Javascript
[55:39]DOTA2-DPC中国联赛 正赛 VG vs LBZS BO3 第二场 1月19日
2021/03/11 DOTA
python批量修改文件后缀示例代码分享
2013/12/24 Python
python处理json数据中的中文
2014/03/06 Python
python实现堆栈与队列的方法
2015/01/15 Python
仅用50行Python代码实现一个简单的代理服务器
2015/04/08 Python
python 上下文管理器及自定义原理解析
2019/11/19 Python
SpringBoot实现登录注册常见问题解决方案
2020/03/04 Python
基于Python实现2种反转链表方法代码实例
2020/07/06 Python
python super()函数的基本使用
2020/09/10 Python
彪马荷兰官网:PUMA荷兰
2019/05/08 全球购物
德国受欢迎的旅游和休闲网站:lastminute.de
2019/09/23 全球购物
工作失误检讨书范文大全
2014/01/13 职场文书
中学生自我评价范文
2014/02/08 职场文书
警校毕业生自我评价
2014/04/06 职场文书
综合办公室主任岗位职责
2014/04/13 职场文书
公司员工辞职信范文
2015/05/12 职场文书
太空授课观后感
2015/06/17 职场文书
小学一年级语文教学反思
2016/03/03 职场文书
Winsows11性能如何? win11性能测评多核竟比Win10差了10%
2021/11/21 数码科技