canva实践小实例 —— 马赛克效果
前面给大家带来了操作像素的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实践小实例 —— 马赛克效果的更多相关文章
- canvas实践小实例二  —— 扇形
		
俗话说:发图不留种,菊花万人捅!我这里想延伸一下:教学不给例,说你是傻逼!哎呀,还挺押韵,嘻嘻,开个玩笑! 我们都讲了四期API的知识了,估计大家看的也是枯燥的很啊,前面的小实例也是太简单,简直不解渴 ...
 - canvas实践小实例一  ——  画板工具
		
前面讲了一部分的canvasAPI的基础知识,光看API的介绍确实是很无趣乏味,需要一点可以激发内心的激情的东西来激励自己来学习,于是就了伴随canvasAPI学习的小实例,这样通过API的知识,结合 ...
 - javascript小实例,拖拽应用(一)
		
前面我们将了一下拖拽的基本思想,理论是有了,那实践呢,可以运用到什么地方呢?下面就给大家带来一个用拖拽思想写的一个小实例,供大家参考,大致效果看下图: 就是这样一个简单的一个拖拽条,你可以把它理解为滚 ...
 - CSS应用内容补充及小实例
		
一.clear 清除浮动 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...
 - 怎么用EDIUS实现跟踪马赛克效果
		
我们经常会在一些新闻的视频中看到一些马赛克,这些马赛克一般都是保护人物的隐私权,肖像权什么的.我们时常也会看到即使人物位置发生了变化,被遮挡的地方依旧还是被遮挡住,一点也不用担心因为人物运动而使马赛克 ...
 - JavaScript小实例:拖拽应用(二)
		
经常在网站别人的网站的注册页中看到一个拖拽验证的效果,就是它的验证码刚开始不出来,而是有一个拖拽的条,你必须将这个拖拽条拖到底,验证码才出来,说了感觉跟没说一样,你还是不理解,好吧,我给个图你看看: ...
 - javascript小实例,编写一个方法,实现从n-m个数中随机选出一个整数
		
别怪我是一个闷葫芦,没那么多花哨的语言,废话不多说,先说说小实例的要求: 编写一个方法,实现从n-m个数中随机选出一个整数,要求:传递的参数不足两个或者不是有效数字,返回[0-1]之间的随机数,需要解 ...
 - javascript小实例,实现99乘法表及隔行变色
		
人生短暂,废话不多说,直奔主题! 这个小实例的要求: 实现在页面中输出99乘法表.(要求:以每三行为一组,实现隔行变色(颜色为白,红,黄(也可自己定义)),鼠标滑过每一行,行背景颜色变为蓝色,鼠标离开 ...
 - django Form 表单  总结与小实例
		
开头寄语: 这几天一直在看Django的form表单验证,然后想对于这几天要有个总结. 首先,先来看一下找到的一个form表单验证的流程: 验证过程 流程详解1. 函数full_clean()依次调用 ...
 
随机推荐
- Java基础-四大特性理解(抽象、封装、继承、多态)
			
抽象: 象就是有点模糊的意思,还没确定好的意思. 就比方要定义一个方法和类.但还没确定怎么去实现它的具体一点的子方法,那我就可以用抽象类或接口.具体怎么用,要做什么,我不用关心,由使用的人自己去定义去 ...
 - bootstrap table简洁扁平的表格
			
使用方法 1.在html页面的head标签中引入Bootstrap库(假如你的项目还没使用)和bootstrap-table.css. <link rel="stylesheet&qu ...
 - Yii2登陆添加验证码
			
models中 LoginForm.php public $verifyCode; public function rules() { return [ …… ['verifyCode', 'capt ...
 - 9.Android之日期对话框DatePicker控件学习
			
设置日期对话框在手机经常用到,今天来学习下. 首先设置好布局文件:如图 xml对应代码 <?xml version="1.0" encoding="utf-8&qu ...
 - POJ2676Sudoku(类似于八皇后)
			
Sudoku Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 16444 Accepted: 8035 Special ...
 - [Angularjs]ng-show和ng-hide
			
写在前面 上篇文章介绍了ng-select和ng-options指令的使用,这篇文章继续指令的学习,本篇文章讲学习ng-show和ng-hide指令. 系列文章 [Angularjs]ng-selec ...
 - Python socket编程之一:
			
soket 编程步骤 # -*- coding: utf-8 -*- ################################################################# ...
 - wifi共享小工具
			
MainForm.cs: using System;using System.Collections.Generic;using System.ComponentModel;using System. ...
 - TFS2008解除独占式锁定文件命令(转载)
			
使用场景:如果项目团队成员A对项目某个文件以独占式方式签出,恰好那天该成员A没有来上班而成员需要对此文件进入修改并check in,这时需要先把A对该文件的锁定解除.没有IDE可以使用,只能使用下面的 ...
 - 获取window窗口大小
			
窗口大小 跨浏览器确定一个窗口的大小不是一件简单的事.IE9+.Firefox.Safari.Opera和Chrome均为此提供了4个属性:innerWidth.innerHeight.outerWi ...