Home  >  Article  >  Web Front-end  >  HTML5 uses canvas to achieve the effect of converting pictures to sketches

HTML5 uses canvas to achieve the effect of converting pictures to sketches

青灯夜游
青灯夜游Original
2018-09-25 17:41:373653browse

This chapter will introduce you to how HTML5 uses canvas to achieve the effect of converting pictures to sketches. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.

Sketch filter principle:
The most basic algorithm is:
1. Decolorization; (Decolorization formula: gray = 0.3 red 0.59 green 0.11 * blue)
2. Copy Color layer, and invert the color;
3. Perform Gaussian blur on the inverted image;
4. Select the color dodge effect in the overlay mode of the blurred image.
Dodging formula: C =MIN(A (A×B)/(255-B),255), where C is the mixing result, A is the pixel after decolorization, and B is the pixel after Gaussian blur .

Let’s take a look at the effect comparison chart first:

HTML5 uses canvas to achieve the effect of converting pictures to sketches

sigma can adjust the effect.

Code example:

<!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>
        <br>
        <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);    
                    //监听文件读取结束后事件    
                    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);

                // 循环计算整个图像每个像素高斯处理之后的值
                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>

The above is all the code for converting images to sketches using canvas. You can compile and debug it yourself.

The above is the detailed content of HTML5 uses canvas to achieve the effect of converting pictures to sketches. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn