canva實踐小實例 —— 馬賽克效果

前面給你們帶來了操做像素的API,此時此刻,我以爲應該配以小實例來進行進一步的說明和演示,以便給你們帶來更寬廣的視野和靈感,大家看了個人那麼多的文章,應該是懂個人風格,廢話很少說,進入正題:canvas

此次給你們帶來的是圖片的馬賽克效果,這種效果大家應該很熟悉了,好比看到一些較污的新聞,關鍵的地方老是有這萬惡的馬賽克擋着,我們今天就來剖析一下這馬賽克究竟是撒東西,是一個什麼原理:dom

你們看看這張圖,這就是馬賽克的效果,整個圖就是一顆顆很大的像素點構成的,固然這裏說的像素點指的不是一像素,而是一個像素點多是由幾個像素或者是十幾個像素構成的,像素點越大,圖像就約模糊,像素點越小,圖片越清晰,什麼,你對上圖無感?好吧,咱們看一下現實生活中你見過的馬賽克:函數

看,左邊的大美女,打上馬賽克,立馬變神祕了,那馬賽克糾結是一個什麼原理呢?學習

對比上圖的左右兩個臉,右邊的臉雖然看不清,但仍是能看清輪廓的,並且右邊的馬賽克部分像素點很是大,而左邊的呢,幾乎看不到像素點,那麼左邊的是否是就不是由像素點構成的呢?咱們把圖放大n倍來看看:this

上圖是截圖的馬賽克圖片的一部分,放大後能夠清除的看到,圖像是由一個個像素點構成的,能夠發現,馬賽克的像素顆粒也是由許多的像素點構成的,只是這些顆粒的顏色是一個的,縮小就感受是一個大的像素顆粒,而偏不的則是一個個小的像素點,各自顏色不同,才形象很是細膩的圖像,因而可知,要想作馬賽克效果,只須要將一個區域內的像素的的顏色用裏面一個隨機的顏色替代,就會使得圖像模糊,這樣縮小了看就是馬賽克效果了,並且這個區域也大,圖像越模糊,越小,則圖像越清晰!spa

 

知道了馬賽克的原理,那麼咱們就能夠經過操做像素來製做馬賽克效果了,怎麼作呢?好比將一整張圖作成馬賽克效果,那麼,若是咱們將這張圖等分紅n份,且每一份隨機在這個區域裏找一個像素點的顏色,而後將這個區域的顏色都設爲這個顏色,所有操做完,馬賽克就作完了,哈哈,挺抽象的,那老規矩,跟着我一步一步的作吧:3d

首先咱們在畫布上引進來一張圖,而後咱們建一個函數,用於繪製馬賽克(其目的我再說通常,一是圖片必須加裝完成,才能進行像素操做,二是結構更清晰,便於理解)code

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篇,工欲善其事必先利其器blog

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圖片局部馬賽克效果

今天就講到這裏,後面要是有時間,在給幾個例子給你們學習一下!

相關文章
相關標籤/搜索