前面给大家带来了操作像素的API,此时此刻,我觉得应该配以小实例来进行进一步的说明和演示,以便给大家带来更宽广的视野和灵感,你们看了我的那么多的文章,应该是懂我的风格,废话不多说,进入正题:

这次给大家带来的是图片的马赛克效果,这种效果你们应该很熟悉了,比如看到一些较污的新闻,关键的地方总是有这万恶的马赛克挡着,咱们今天就来剖析一下这马赛克到底是撒东西,是一个什么原理:

大家看看这张图,这就是马赛克的效果,整个图就是一颗颗很大的像素点构成的,当然这里说的像素点指的不是一像素,而是一个像素点可能是由几个像素或者是十几个像素构成的,像素点越大,图像就约模糊,像素点越小,图片越清晰,什么,你对上图无感?好吧,我们看一下现实生活中你见过的马赛克:

看,左边的大美女,打上马赛克,立马变神秘了,那马赛克纠结是一个什么原理呢?

对比上图的左右两个脸,右边的脸虽然看不清,但还是能看清轮廓的,而且右边的马赛克部分像素点非常大,而左边的呢,几乎看不到像素点,那么左边的是不是就不是由像素点构成的呢?我们把图放大n倍来看看:

上图是截图的马赛克图片的一部分,放大后可以清除的看到,图像是由一个个像素点构成的,可以发现,马赛克的像素颗粒也是由许多的像素点构成的,只是这些颗粒的颜色是一个的,缩小就感觉是一个大的像素颗粒,而偏不的则是一个个小的像素点,各自颜色不一样,才形象非常细腻的图像,由此可见,要想做马赛克效果,只需要将一个区域内的像素的的颜色用里面一个随机的颜色替代,就会使得图像模糊,这样缩小了看就是马赛克效果了,而且这个区域也大,图像越模糊,越小,则图像越清晰!

知道了马赛克的原理,那么我们就可以通过操作像素来制作马赛克效果了,怎么做呢?比如将一整张图做成马赛克效果,那么,如果我们将这张图等分成n份,且每一份随机在这个区域里找一个像素点的颜色,然后将这个区域的颜色都设为这个颜色,全部操作完,马赛克就做完了,哈哈,挺抽象的,那老规矩,跟着我一步一步的做吧:

首先我们在画布上引进来一张图,然后我们建一个函数,用于绘制马赛克(其目的我再说一般,一是图片必须加装完成,才能进行像素操作,二是结构更清晰,便于理解)

var aImg = new Image();
aImg.src = '1.jpg';
aImg.onload = function(){
draw(this);
}
//此函数用于后面的像素操作
function draw(obj){
ctx.drawImage(obj,0,0,400,400);
}

我们将画布的大小设为图片的2倍,右边用于显示马赛克的图

下面就该获取像素了,不清楚的同学可以先去看看前文的API的第5篇,工欲善其事必先利其器

function draw(obj){
ctx.drawImage(obj,0,0,400,400);
var oImg = ctx.getImageData(0,0,400,400);
var w = oImg.width;
var h = oImg.height;
ctx.putImageData(oImg,w,0);
}

在右侧把图片用像素操作复制一个放到右边

一模一样双胞胎,哈哈,接下来就是醉关键的地方了,就是如何将一个区域的像素点用一个颜色替代,我们画一个图来示意一下:

看看上图,图画的很粗糙哈(俗话说图糙理不糙),比如说图片是100*100像素的图,那么原来是由1*1像素的点构成的,现在我们等分成10份,一份的像素点就是10*10,那么这份的像素点在里面随机设置一个颜色,然后同理操作所有的,就成了一个只显示10分之一图像的马赛克了

这里引用我们原来写的获取某一点的颜色的函数和设置某一点的颜色的函数,可以作为通用方法:

function getXY(obj,x,y){
var w = obj.width;
var h = obj.height;
var d = obj.data;
var color = [];
color[0] = obj.data[4*(y*w+x)];
color[1] = obj.data[4*(y*w+x)+1];
color[2] = obj.data[4*(y*w+x)+2];
color[3] = obj.data[4*(y*w+x)+3];
return color;
} function setXY(obj,x,y,color){
var w = obj.width;
var h = obj.height;
var d = obj.data;
obj.data[4*(y*w+x)] = color[0];
obj.data[4*(y*w+x)+1] = color[1];
obj.data[4*(y*w+x)+2] = color[2];
obj.data[4*(y*w+x)+3] = color[3];
}

接下来就是操作像素了,我们在一个新的ImageData上操作

//创建一个新的ImageData对象
var newImg = ctx.createImageData(obj.width,obj.height);
//马赛克的程度,数字越大越模糊
var num = 5;
//等分画布
var stepW = w/num;
var stepH = h/num;
//这里是循环画布的像素点
for(var i=0;i<stepH;i++){
for(var j=0;j<stepW;j++){
//获取一个小方格的随机颜色,这是小方格的随机位置获取的
var color = getXY(oImg,j*num+Math.floor(Math.random()*num),i*num+Math.floor(Math.random()*num));
//这里是循环小方格的像素点,
for(var k=0;k<num;k++){
for(var l=0;l<num;l++){
//设置小方格的颜色
setXY(newImg,j*num+l,i*num+k,color);
}
} }
}

整理所有的代码就是:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d"); var aImg = new Image();
aImg.src = '1.jpg';
aImg.onload = function(){
draw(this); } function draw(obj){
ctx.drawImage(obj,0,0,400,400);
var oImg = ctx.getImageData(0,0,400,400);
var w = oImg.width;
var h = oImg.height;
//创建一个新的ImageData对象
var newImg = ctx.createImageData(obj.width,obj.height);
//马赛克的程度,数字越大越模糊
var num = 5;
//等分画布
var stepW = w/num;
var stepH = h/num;
//这里是循环画布的像素点
for(var i=0;i<stepH;i++){
for(var j=0;j<stepW;j++){
//获取一个小方格的随机颜色,这是小方格的随机位置获取的
var color = getXY(oImg,j*num+Math.floor(Math.random()*num),i*num+Math.floor(Math.random()*num));
//这里是循环小方格的像素点,
for(var k=0;k<num;k++){
for(var l=0;l<num;l++){
//设置小方格的颜色
setXY(newImg,j*num+l,i*num+k,color);
}
} }
}
ctx.putImageData(newImg,w,0);
} function getXY(obj,x,y){
var w = obj.width;
var h = obj.height;
var d = obj.data;
var color = [];
color[0] = obj.data[4*(y*w+x)];
color[1] = obj.data[4*(y*w+x)+1];
color[2] = obj.data[4*(y*w+x)+2];
color[3] = obj.data[4*(y*w+x)+3];
return color;
} function setXY(obj,x,y,color){
var w = obj.width;
var h = obj.height;
var d = obj.data;
obj.data[4*(y*w+x)] = color[0];
obj.data[4*(y*w+x)+1] = color[1];
obj.data[4*(y*w+x)+2] = color[2];
obj.data[4*(y*w+x)+3] = color[3];
}

得到的效果:

为了显得好看一点,我们只是取了一个比较小的值,现在五分之一的像素点,如果是十分之一,得到是就是这样的,值在num的地方修改:

具体效果看这里——canvas马赛克效果

这是整张图做成马赛克,能不能跟上面的美女一样,做成局部的马赛克呢?其实也很简单,我们起初获取的是整张图的像素,现在我们只获取局部我们想要的部分的像素就可以了:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d"); var aImg = new Image();
aImg.src = '1.jpg';
aImg.onload = function(){
draw(this); } function draw(obj){
//绘制第一张图
ctx.drawImage(obj,0,0,400,400);
//绘制第二张图,用作对比
ctx.drawImage(obj,400,0,400,400);
//获取坐边图像的局部坐标的部分像素(左图位置在258,为方便演示,这里设成和马赛克显示位置一样的坐标)
var oImg = ctx.getImageData(650,60,50,50); var w = oImg.width;
var h = oImg.height;
//马赛克的程度,数字越大越模糊
var num = 10;
//等分画布
var stepW = w/num;
var stepH = h/num;
//这里是循环画布的像素点
for(var i=0;i<stepH;i++){
for(var j=0;j<stepW;j++){
//获取一个小方格的随机颜色,这是小方格的随机位置获取的
var color = getXY(oImg,j*num+Math.floor(Math.random()*num),i*num+Math.floor(Math.random()*num));
//这里是循环小方格的像素点,
for(var k=0;k<num;k++){
for(var l=0;l<num;l++){
//设置小方格的颜色
setXY(oImg,j*num+l,i*num+k,color);
}
} }
}
ctx.putImageData(oImg,650,60);
} function getXY(obj,x,y){
var w = obj.width;
var h = obj.height;
var d = obj.data;
var color = [];
color[0] = obj.data[4*(y*w+x)];
color[1] = obj.data[4*(y*w+x)+1];
color[2] = obj.data[4*(y*w+x)+2];
color[3] = obj.data[4*(y*w+x)+3];
return color;
} function setXY(obj,x,y,color){
var w = obj.width;
var h = obj.height;
var d = obj.data;
obj.data[4*(y*w+x)] = color[0];
obj.data[4*(y*w+x)+1] = color[1];
obj.data[4*(y*w+x)+2] = color[2];
obj.data[4*(y*w+x)+3] = color[3];
}

是不是跟刚开始的那个美女很像了,可能有的同学注意到,我有时候创建了一个新的ImageData对象,有的时候没有,那到底什么时候需要创建新的ImageData对象,什么时候不需要呢?原则上说,如果你操作的像素不在原图上,则需要新创建一个ImageData对象,但是也不是绝对的,你在原图上操作像素,也是可以创建一个新的ImageData对象的,具体还是看需要!

上面的局部马赛克效果看这里——canvas图片局部马赛克效果

今天就讲到这里,后面要是有时间,在给几个例子给大家学习一下!

canva实践小实例 —— 马赛克效果的更多相关文章

  1. canvas实践小实例二 —— 扇形

    俗话说:发图不留种,菊花万人捅!我这里想延伸一下:教学不给例,说你是傻逼!哎呀,还挺押韵,嘻嘻,开个玩笑! 我们都讲了四期API的知识了,估计大家看的也是枯燥的很啊,前面的小实例也是太简单,简直不解渴 ...

  2. canvas实践小实例一 —— 画板工具

    前面讲了一部分的canvasAPI的基础知识,光看API的介绍确实是很无趣乏味,需要一点可以激发内心的激情的东西来激励自己来学习,于是就了伴随canvasAPI学习的小实例,这样通过API的知识,结合 ...

  3. javascript小实例,拖拽应用(一)

    前面我们将了一下拖拽的基本思想,理论是有了,那实践呢,可以运用到什么地方呢?下面就给大家带来一个用拖拽思想写的一个小实例,供大家参考,大致效果看下图: 就是这样一个简单的一个拖拽条,你可以把它理解为滚 ...

  4. CSS应用内容补充及小实例

    一.clear 清除浮动 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...

  5. 怎么用EDIUS实现跟踪马赛克效果

    我们经常会在一些新闻的视频中看到一些马赛克,这些马赛克一般都是保护人物的隐私权,肖像权什么的.我们时常也会看到即使人物位置发生了变化,被遮挡的地方依旧还是被遮挡住,一点也不用担心因为人物运动而使马赛克 ...

  6. JavaScript小实例:拖拽应用(二)

    经常在网站别人的网站的注册页中看到一个拖拽验证的效果,就是它的验证码刚开始不出来,而是有一个拖拽的条,你必须将这个拖拽条拖到底,验证码才出来,说了感觉跟没说一样,你还是不理解,好吧,我给个图你看看: ...

  7. javascript小实例,编写一个方法,实现从n-m个数中随机选出一个整数

    别怪我是一个闷葫芦,没那么多花哨的语言,废话不多说,先说说小实例的要求: 编写一个方法,实现从n-m个数中随机选出一个整数,要求:传递的参数不足两个或者不是有效数字,返回[0-1]之间的随机数,需要解 ...

  8. javascript小实例,实现99乘法表及隔行变色

    人生短暂,废话不多说,直奔主题! 这个小实例的要求: 实现在页面中输出99乘法表.(要求:以每三行为一组,实现隔行变色(颜色为白,红,黄(也可自己定义)),鼠标滑过每一行,行背景颜色变为蓝色,鼠标离开 ...

  9. django Form 表单 总结与小实例

    开头寄语: 这几天一直在看Django的form表单验证,然后想对于这几天要有个总结. 首先,先来看一下找到的一个form表单验证的流程: 验证过程 流程详解1. 函数full_clean()依次调用 ...

随机推荐

  1. [Asp.net mvc] 在Asp.net mvc 中使用MiniProfiler

    MiniProfiler是Stack Overflow团队设计的一款性能分析的小程序.可以对一个页面本身,及该页面通过直接引用.Ajax.Iframe形式访问的其它页面进行监控,监控内容包括数据库内容 ...

  2. 【Gym 100712A】Who Is The Winner?

    题 题意 解题数目越多越排前,解题数目相同罚时越少越排前,求排第一的队伍名字. 分析 用结构体排序. 代码 #include<cstdio> #include<algorithm&g ...

  3. groovy–流程控制

    在本篇文章中,我们将介绍逻辑分支,循环,以及如何从if-else以及try-catch代码块中返回值. if – elseGroovy 支持Java传统的if-else语法: def x = fals ...

  4. appium-车友会欢迎界面向右滑动4次点击‘立即体验’进入首屏

    代码如下: driver.swipe(610, 2452, 658, 2452, 200) 只是示例滑动1页,可以使用循环,下一页比上一页x坐标大48

  5. POJ3267 The Cow Lexicon(DP+删词)

    The Cow Lexicon Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9041   Accepted: 4293 D ...

  6. 三角形变形记之纯css实现的分布导航条效果

    三角形变形记,用纯css实现的分布导航条效果 <style type="text/css"> ul,li { list-style-type:none; font-si ...

  7. centos6.4yum搭建lamp环境

    1.配置防火墙,开启80端口.3306端口vi /etc/sysconfig/iptables-A INPUT -m state --state NEW -m tcp -p tcp --dport 8 ...

  8. 微信公开课发布微信官方教程:教你用好微信JS-SDK接口

    微信公众平台开放JS-SDK(微信内网页开发工具包),说明文档已经有相关使用方法和示例了,很多同学觉得不是很直观,为此微信公开课发布微信官方教程:教你用好微信JS-SDK接口. 1.分享类接口:支持获 ...

  9. Windows主机里利用VMware安装Linux(CentOS)虚拟机,Host-only连接上网方式详解

    关于Host-only指的是主机与虚拟机之间的互联,因此虚拟机是不能连网的,若需要连网则需要使用NAT模式: Host-only模式实现联网得考虑如下配置过程: 附:VMware虚拟机三种网络模式(B ...

  10. Internet信息服务找不到

    最近我的电脑也出现了Internet信息服务找不到的情况,在网络上查了很多方法都没一个正确的,后面通过下面的方法我成功了,故此我把这个经历也分享给大家,希望能够帮到您. 控制面板里“->添加/删 ...