素描濾鏡原理:
最基礎的算法就是:
1、去色;(去色公式:gray = 0.3 red + 0.59 green + 0.11 * blue)
2、復制去色圖層,并且反色;
3、對反色圖像進行高斯模糊;
4、模糊后的圖像疊加模式選擇顏色減淡效果。
減淡公式:C =MIN( A +(A×B)/(255-B),255),其中C為混合結果,A為去色后的像素點,B為高斯模糊后的像素點。
先看看效果對比圖:

sigma可以調(diào)節(jié)效果。
代碼實例:
!DOCTYPE html html head meta charset= UTF-8 title /title /head body div id= controls input type= file name= id= imgs value= / br / !-- input type= range name= id= range_radius value= 10 oninput= changeRadius() / radius: span id= value_radius 1 /span br / -- input type= range name= id= range_sigma value= 40 oninput= changeSigma() / sigma: span id= value_sigma 0.8 /span br / a href= download= canvas_love.png id= save_href 下載 /a /div canvas id= canvas1 width= height= /canvas canvas id= canvas2 width= height= /canvas script type= text/javascript var eleImg = document.getElementById( imgs var eleRadius = document.getElementById( range_radius var eleSigma = document.getElementById( range_sigma var valueRadius = document.getElementById( value_radius var valueSigma = document.getElementById( value_sigma var svaeHref = document.getElementById( save_href var imgSrc = img/2.jpg var radius = 1; var sigma = 0.8; eleImg.addEventListener( input ,function (e) { var fileObj = e.currentTarget.files[0] if (window.FileReader) { var reader = new FileReader(); reader.readAsDataURL(fileObj); //監(jiān)聽文件讀取結束后事件 reader.onloadend = function (e) { imgSrc = e.target.result; //e.target.result就是最后的路徑地址 sketch() var butSave = document.getElementById( save function changeRadius() { valueRadius.innerText = eleRadius.value/10; radius = eleRadius.value/10; sketch() function changeSigma() { valueSigma.innerText = eleSigma.value/50; sigma = eleSigma.value/50; sketch() var canvas1 = document.querySelector( #canvas1 var cxt1 = canvas1.getContext( 2d var canvas = document.querySelector( #canvas2 var cxt = canvas.getContext( 2d function sketch() { cxt1.clearRect(0,0,canvas1.width,canvas1.height); cxt.clearRect(0,0,canvas.width,canvas.height); var img = new Image(); img.src = imgSrc; img.onload = function () { canvas1.width = 600; canvas1.height = (img.height/img.width)*600; cxt1.drawImage(img, 0, 0, canvas1.width, canvas1.height); canvas.width = 600; canvas.height = (img.height/img.width)*600; cxt.drawImage(img, 0, 0, canvas.width, canvas.height); var imageData = cxt.getImageData(0, 0, canvas.width, canvas.height); //對于 ImageData 對象中的每個像素,都存在著四方面的信息,即 RGBA 值 var imageData_length = imageData.data.length/4;// var originData = JSON.parse(JSON.stringify(imageData)) // 解析之后進行算法運算 var originData = []; for (var i = 0; i imageData_length; i++) { var red = imageData.data[i*4]; var green = imageData.data[i*4 + 1]; var blue = imageData.data[i*4 + 2]; var gray = 0.3 * red + 0.59 * green + 0.11 * blue;//去色 originData.push(gray) originData.push(gray) originData.push(gray) originData.push(imageData.data[i * 4 + 3]) var anti_data = 255 - gray;//取反 imageData.data[i * 4] = anti_data; imageData.data[i * 4 + 1] = anti_data; imageData.data[i * 4 + 2] = anti_data; imageData = gaussBlur(imageData, radius, sigma)//高斯模糊 for (var i = 0; i imageData_length; i++) { var dodge_data = Math.min((originData[i*4] + (originData[i*4]*imageData.data[i * 4])/(255-imageData.data[i * 4])), 255)//減淡 imageData.data[i * 4] = dodge_data; imageData.data[i * 4 + 1] = dodge_data; imageData.data[i * 4 + 2] = dodge_data; console.log(imageData) cxt.putImageData(imageData, 0, 0); var tempSrc = canvas.toDataURL( image/png svaeHref.href=tempSrc; sketch() function gaussBlur(imgData, radius, sigma) { var pixes = imgData.data, width = imgData.width, height = imgData.height; radius = radius || 5; sigma = sigma || radius / 3; var gaussEdge = radius * 2 + 1; // 高斯矩陣的邊長 var gaussMatrix = [], gaussSum = 0, a = 1 / (2 * sigma * sigma * Math.PI), b = -a * Math.PI; for (var i=-radius; i =radius; i++) { for (var j=-radius; j =radius; j++) { var gxy = a * Math.exp((i * i + j * j) * b); gaussMatrix.push(gxy); gaussSum += gxy; // 得到高斯矩陣的和,用來歸一化 var gaussNum = (radius + 1) * (radius + 1); for (var i=0; i gaussNum; i++) { gaussMatrix[i] = gaussMatrix[i] / gaussSum; // 除gaussSum是歸一化 //console.log(gaussMatrix); // 循環(huán)計算整個圖像每個像素高斯處理之后的值 for (var x=0; x width;x++) { for (var y=0; y height; y++) { var r = 0, g = 0, b = 0; //console.log(1); // 計算每個點的高斯處理之后的值 for (var i=-radius; i =radius; i++) { // 處理邊緣 var m = handleEdge(i, x, width); for (var j=-radius; j =radius; j++) { // 處理邊緣 var mm = handleEdge(j, y, height); var currentPixId = (mm * width + m) * 4; var jj = j + radius; var ii = i + radius; r += pixes[currentPixId] * gaussMatrix[jj * gaussEdge + ii]; g += pixes[currentPixId + 1] * gaussMatrix[jj * gaussEdge + ii]; b += pixes[currentPixId + 2] * gaussMatrix[jj * gaussEdge + ii]; var pixId = (y * width + x) * 4; pixes[pixId] = ~~r; pixes[pixId + 1] = ~~g; pixes[pixId + 2] = ~~b; imgData.data = pixes; return imgData; function handleEdge(i, x, w) { var m = x + i; if (m 0) { m = -m; } else if (m = w) { m = w + i - x; return m; /script /body /html
上面就是canvas實現(xiàn)圖片轉素描效果的全部代碼,大家可以自己動手編譯調(diào)試。
以上就是html5利用canvas實現(xiàn)圖片轉素描效果的詳細內(nèi)容,其它編程語言
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。
新聞熱點
疑難解答