簡單的實現了 灰度,黑白,底片,模糊,馬賽克(代碼比較簡單,通過canvas實現的) 感覺挺有意思的,上面解釋很詳細,直接看代碼 ...
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>簡易板美圖秀秀</title> </head> <body> <canvas id="canvas1" width="500" height="500" style="border: 1px red solid;"></canvas> <canvas id="canvas2" width="500" height="500" style="border: 1px solid blue;"></canvas> <button id="huidu">灰度</button> <button id="heibai">黑白</button> <button id="suibian">底片</button> <button id="mohu">模糊</button> <button id="mask">馬賽克</button> </body> <script type="text/javascript"> var context1 = canvas1.getContext("2d"); var context2 = canvas2.getContext("2d"); var img = new Image(); img.src = "img/1.jpg"; img.onload = function() { context1.drawImage(img, 0, 0, canvas1.width, canvas1.height); } //給對應的按鈕設置點擊事件,並將對應的事件進行封裝 huidu.onclick = function() { grayOperation(); } heibai.onclick = function() { heibaiOperation(); } suibian.onclick = function() { suibianOperation(); } mohu.onclick = function() { mohuOperation(); } mask.onclick = function() { maskOperation(); } //灰度處理函數 //讓每一個像素塊裡面的r,g,b值等於r,g,b三個值得平均值 function grayOperation() { //獲取畫布裡面的圖片數據 var imgData = context1.getImageData(0, 0, 500, 500); //獲取所有的像素塊信息,以rgba依次排列. var px = imgData.data; for(var i = 0; i < canvas1.width * canvas1.height; i++) { //因為px裡面存的每一個像素塊都是以rgba依次排列,我們在找到對應的色素每次的i都應該乘4 var r = px[i * 4 + 0]; var g = px[i * 4 + 1]; var b = px[i * 4 + 2]; var avg = (r + g + b) / 3; px[i * 4 + 0] = avg; px[i * 4 + 1] = avg; px[i * 4 + 2] = avg; } // 像素值已經發生改變 // 把改變過的像素信息 繪製到 canvas2上面 context2.putImageData(imgData, 0, 0, 0, 0, 500, 500); } //黑白處理 //如果r,g,b三個值得和大於(255 * 3 / 2),我們就讓這三個值都變成255反之都為零(不懂r,g,b可以百度) function heibaiOperation() { var imgData = context1.getImageData(0, 0, 500, 500); var px = imgData.data; for(var i = 0; i < canvas1.width * canvas1.height; i++) { var r = px[i * 4 + 0]; var g = px[i * 4 + 1]; var b = px[i * 4 + 2]; var sum = r + g + b; var a = 0; if(sum > 255 * 3 / 2) { a = 255; } else { a = 0; } px[i * 4 + 0] = a; px[i * 4 + 1] = a; px[i * 4 + 2] = a; } // 像素值已經發生改變 // 把改變過的像素信息 繪製到 canvas2上面 context2.putImageData(imgData, 0, 0, 0, 0, 500, 500); } //實現底片的效果 //底片效果就是讓r,g,b的每個值都反過來,即讓每一個的值變為(255-本身)的值 function suibianOperation() { var imgData = context1.getImageData(0, 0, 500, 500); var px = imgData.data; for(var i = 0; i < canvas1.width * canvas1.height; i++) { var r = px[i * 4 + 0]; var g = px[i * 4 + 1]; var b = px[i * 4 + 2]; px[i * 4 + 0] = 255 - r; px[i * 4 + 1] = 255 - g; px[i * 4 + 2] = 255 - b; } // 像素值已經發生改變 // 把改變過的像素信息 繪製到 canvas2上面 context2.putImageData(imgData, 0, 0, 0, 0, 500, 500); } //實現模糊的效果 //首先我們要實現模糊就得讓你獲取的每一個色素信息的值(r或g或b)等於周圍一圈的色素信息(r或g或b)值得平均值,模糊的程度取決於你選取的圈的大小(一圈的顏色信息加上自己本身等於9個,同理兩圈就是25個,n圈(2n+1)的平方) function mohuOperation() { //因為我們要修改每一個色素信息,避免讓前一個修改的信息干擾到下一個修改,我們將畫布裡面的數據拷貝兩份,一份用來修改,一份用來獲取色素信息 var imgData1 = context1.getImageData(0, 0, 500, 500); var px1 = imgData1.data; var imgData2 = context1.getImageData(0, 0, 500, 500); var px2 = imgData2.data; //blur 就是我說的 圈的大小 這就表示兩圈(即25個色素信息的平均值) var blur = 2; var blurNumber = (2 * blur + 1) * (2 * blur + 1); //如果和上面一樣直接遍歷所有的像素,我們在獲取周圍的色素信息的值會變得比較困難,在這裡我們使用迴圈嵌套的方法,讓i表示行,j表示列這樣有利於我們獲取周圍的色素信息 //註意:這裡我們的i,j都是從blur開始 for(var i = blur; i < canvas1.height - blur; i++) { for(var j = blur; j < canvas1.width - blur; j++) { var sumR = 0; var sumG = 0; var sumB = 0; //這裡的ii,jj和外面的迴圈一樣,讓ii和jj分別表示行和列,去獲取周圍的元素,這樣有利於維護,如果直接用下標來獲取,會顯得複雜 for(var ii = -blur; ii <= blur; ii++) { for(var jj = -blur; jj <= blur; jj++) { var x = i + ii; var y = j + jj; //根據二維數組坐標換算成一維數組的坐標 //因為px裡面存的色素信息都是以r,g,b,a依次排列,這裡我們用變數p*4來表示每個像素r通道的位置 var p = x * canvas1.width + y; //我們讓sumR,sumG,sumB這三個的值去存儲對應色素的信息 sumR += px1[p * 4 + 0]; sumG += px1[p * 4 + 1]; sumB += px1[p * 4 + 2]; } } //算出這一圈的數據的平均值 var avgR = sumR / blurNumber; var avgG = sumG / blurNumber; var avgB = sumB / blurNumber; //找到我們要修改的點,將我們準備的第二份數據進行修改 var pp = i * canvas1.width + j; px2[pp * 4 + 0] = avgR; px2[pp * 4 + 1] = avgG; px2[pp * 4 + 2] = avgB; } } // 像素值已經發生改變 // 把改變過的像素信息 繪製到 canvas2上面 context2.putImageData(imgData2, 0, 0, 0, 0, 500, 500); } //馬賽克 //馬賽克和模糊的原理基本一致,只是馬賽克是將你獲取的的一圈的所有色素信息都進行修改 function maskOperation() { var imgData1 = context1.getImageData(0, 0, 500, 500); var px1 = imgData1.data; var imgData2 = context1.getImageData(0, 0, 500, 500); var px2 = imgData2.data; var blur = 2; var blurNumber = (2 * blur + 1) * (2 * blur + 1); //註意:和模糊不同的是,我們不能獲取每一個色素信息周圍的周圍信息,如果這樣做的話後面一個點修改的信息會將前一個修改覆蓋,所以 (i += 2 * blur)讓他每次修改的時候跳過這一圈,避免後面的將前面的修改(或得到和模糊一模一樣的效果) for(var i = 1; i < canvas1.height - blur; i += 2 * blur) { for(var j = 1; j < canvas1.width - blur; j += 2 * blur) { var sumR = 0; var sumG = 0; var sumB = 0; for(var ii = -blur; ii <= blur; ii++) { for(var jj = -blur; jj <= blur; jj++) { var x = i + ii; var y = j + jj; //根據二維數組坐標換算成一維數組的坐標 var p = x * canvas1.width + y; sumR += px1[p * 4 + 0]; sumG += px1[p * 4 + 1]; sumB += px1[p * 4 + 2]; } } var avgR = sumR / blurNumber; var avgG = sumG / blurNumber; var avgB = sumB / blurNumber; for(var iii = -blur; iii <= blur; iii++) { for(var jjj = -blur; jjj <= blur; jjj++) { var a = i + iii; var b = j + jjj; var pp = a * canvas1.width + b; px2[pp * 4 + 0] = avgR; px2[pp * 4 + 1] = avgG; px2[pp * 4 + 2] = avgB; } } } } // 像素值已經發生改變 // 把改變過的像素信息 繪製到 canvas2上面 context2.putImageData(imgData2, 0, 0, 0, 0, 500, 500); } </script> </html>
簡單的實現了 灰度,黑白,底片,模糊,馬賽克(代碼比較簡單,通過canvas實現的)
感覺挺有意思的,上面解釋很詳細,直接看代碼