点击按钮出现不同滤镜效果
首先,我们分析滤镜的具体,主要就是对图片的每个具体像素进行处理,先拿到像素,处理后再将像素放回去。
通过getImageData可以拿到图片的imageData,imageData包含3个内容:width,height,data;
width,height指的是图片的宽和高
data指的是图片内部所有信息。
context.getImageData(x, y, w, h),从x,y坐标处爬取图片宽为w,高为h
var imageData = cxta.getImageData(0, 0, canvasa.width, canvasa.height);
var pixelData = imageData.data;
获取图片data,将其存储在pixelData中。
这里有一个问题就是本地图片使用getImageData方法的话会产生一个图片跨域的问题。
解决方法1.使用服务器,将图片放在服务器中;
2.使用火狐浏览器
我们在这个demo中使用了5个滤镜算法
灰度滤镜:计算出图片每个像素点的灰度值
function grey(){
var imageData = cxta.getImageData(0, 0, canvasa.width, canvasa.height);
var pixelData = imageData.data;
for (var i = 0; i < canvasb.width*canvasb.height; i++) {
var r = pixelData[i*4+0]
var g = pixelData[i*4+1]
var b = pixelData[i*4+2]
var grey = r*0.3+g*0.59+b*0.11//图片灰度值
pixelData[i*4+0] = grey
pixelData[i*4+1] = grey
pixelData[i*4+2] = grey
}
cxtb.putImageData(imageData,0, 0, 0, 0, canvasb.width, canvasb.height)
}
黑白滤镜:图片中没有灰色,只有黑与白,灰度值大于255/2,则显示为黑色,否则为白色
function black(){//黑白滤镜即图片中没有灰色
var imageData = cxta.getImageData(0, 0, canvasa.width, canvasa.height);
var pixelData = imageData.data;
for (var i = 0; i < canvasb.width*canvasb.height; i++) {
var r = pixelData[i*4+0]
var g = pixelData[i*4+1]
var b = pixelData[i*4+2]
var grey = r*0.3+g*0.59+b*0.11//图片灰度值
if (grey >255/2) {
v = 255
}
else{
v = 0
}
pixelData[i*4+0] = v
pixelData[i*4+1] = v
pixelData[i*4+2] = v
}
cxtb.putImageData(imageData,0, 0, 0, 0, canvasb.width, canvasb.height)
}
反色滤镜:图片每个像素点的颜色变为原来颜色的255-原
function reverse(){//图片中每个像素的rgb都是255-原
var imageData = cxta.getImageData(0, 0, canvasa.width, canvasa.height);
var pixelData = imageData.data;
for (var i = 0; i < canvasb.width*canvasb.height; i++) {
var r = pixelData[i*4+0]
var g = pixelData[i*4+1]
var b = pixelData[i*4+2]
pixelData[i*4+0] = 255-r
pixelData[i*4+1] = 255-g
pixelData[i*4+2] = 255-b
}
cxtb.putImageData(imageData,0, 0, 0, 0, canvasb.width, canvasb.height)
}
模糊滤镜:计算一个像素点及其周围像素点的平均值
function blur(){//要参考周围的像素
var imageData = cxta.getImageData(0, 0, canvasa.width, canvasa.height);
var pixelData = imageData.data;
//创建作为参考的像素
var tmpImageData = cxta.getImageData(0, 0, canvasa.width, canvasa.height);
var tmpPixelData = tmpImageData.data;
var blurR = 3
var totalnum = (2*blurR+1)*(2*blurR+1)
//此处循环需从1开始,..-1结束,否则在里面的二层循环(dx=-1,dy=-1)就会越界
for (var i = blurR; i < canvasb.height-blurR; i++) {
for (var j = blurR; j < canvasb.width-blurR; j++) {
var totalr = 0,totalg = 0,totalb = 0;
//一个像素点周围的加上自身
for (var dx = -blurR; dx <= blurR; dx++) {
for(var dy = -blurR; dy<=blurR; dy++){
var x = i+dx;
var y = j+dy;
var p = x*canvasb.width+y
totalr += tmpPixelData[p*4+0]
totalg += tmpPixelData[p*4+1]
totalb += tmpPixelData[p*4+2]
}
}
var p = i*canvasb.width+j//每个像素点
pixelData[p*4+0] = totalr/totalnum
pixelData[p*4+1] = totalg/totalnum
pixelData[p*4+2] = totalb/totalnum
}
}
cxtb.putImageData(imageData,0, 0, 0, 0, canvasb.width, canvasb.height)
}
马赛克滤镜:和模糊滤镜类似,只是马赛克滤镜是计算每一块的平均值,在这里,需要计算图片的宽与高来确定方块的边长
如代码中:var size = 25,因为我用的图片是500*375的,25可以整除。
function mosaic(){//要参考周围的像素
var imageData = cxta.getImageData(0, 0, canvasa.width, canvasa.height);
var pixelData = imageData.data;
//创建作为参考的像素
var tmpImageData = cxta.getImageData(0, 0, canvasa.width, canvasa.height);
var tmpPixelData = tmpImageData.data;
var size = 25//马赛克方块的边长
var totalnum = size*size
//此处循环需从1开始,..-1结束,否则在里面的二层循环(dx=-1,dy=-1)就会越界
for (var i = 0; i < canvasb.height; i+=size) {
for (var j = 0; j < canvasb.width; j+=size) {
var totalr = 0,totalg = 0,totalb = 0;
//一个像素点周围的加上自身
for (var dx = 0; dx < size; dx++) {
for(var dy = 0; dy
放置imageData
context.putImageData(imageData, dx, dy, dirtyX, dirtyY, dirtyW, dirtyH)
dx,dy在画布上的初始偏移
总体效果:
所有代码如下:
滤镜练习