• 技术文章 >web前端 >H5教程

    html5利用canvas实现图片转素描效果

    青灯夜游青灯夜游2018-09-25 17:41:37原创1872
    本章给大家介绍html5如何利用canvas实现图片转素描效果。有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所帮助。

    素描滤镜原理:
    最基础的算法就是:
    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为高斯模糊后的像素点。

    先看看效果对比图:

    1.png

    sigma可以调节效果。

    代码实例:

    <!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>

    上面就是canvas实现图片转素描效果的全部代码,大家可以自己动手编译调试。

    以上就是html5利用canvas实现图片转素描效果的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:如何使用HTML5+css3实现粒子效果文字动画特效(附完整代码) 下一篇:如何使用HTML5实现地理位置的获取
    PHP编程就业班

    相关文章推荐

    • Javascript HTML5 Canvas实现的一个画板_javascript技巧• javascript html5 canvas实现可拖动省份的中国地图_javascript技巧• JavaScript+html5 canvas实现图片破碎重组动画特效_javascript技巧• JavaScript+html5 canvas实现本地截图教程_javascript技巧

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网