• 简易版美图秀秀


    <!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实现的)

    感觉挺有意思的,上面解释很详细,直接看代码

  • 相关阅读:
    Linux运维就业技术指导(九)期末架构考核
    Linux运维就业技术指导(八):期中架构考核
    Linux就业技术指导(七):游戏类运维重点流程解析
    Linux就业技术指导(五):Linux运维核心管理命令详解
    Linux就业技术指导(六):天津IDC机房项目实践
    Linux就业技术指导(四):企业CDN缓存加速原理解密
    Linux就业技术指导(三):IDC机房解密
    Linux就业技术指导(一):简历撰写及面试筹备要领
    Linux就业技术指导(二):简历项目经验示例
    Python运维开发基础10-函数基础
  • 原文地址:https://www.cnblogs.com/wangziye/p/6013738.html
Copyright © 2020-2023  润新知