canvas图像像素处理- 马赛克/滤镜(一)

一.要注意的问题
在chrome下会发生错误
Uncaught SecurityError: 
Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
大概意思就是发生了跨域操作,也就是指图片的来源和当前的网页来源不同时,造成了跨域。
据说放到服务器上加载就会解决这个问题;我放到了本地的服务器环境可以顺利运行。以后凡是用到getImageData函数的地方,一定要使用此方法进行测试,此处不赘述。

二.知识点:

1.图片的加载:
var img=new Image();
img.src = "timg.jpg";
img.οnlοad=function (){
context.drawImage( image , 0 , 0 );
}
2. getImageData() 从Canvas画板上取得所选区域的像素数据

图片数据读取完成后,首先将图片数据绘制到Canvas画板上,用getImageData函数从画板上取得像素数据。

var imgData=context.getImageData(x,y,width,height);

x,y开始复制的起点坐标 width,height选择区域的长和宽

② ImageData 对象,该对象拷贝了画布指定矩形的像素数据。


最后分析结果:data: 含有ImageData 对象所有的像素,每个像素都存在着四个值的信息,分别是r,g,b,a

 这是一个简单像素处理:var pixelData = imageData.data;
            for(var i=0;i<canvas.width*canvas.height;i++){
                pixelData[4*i+0]=0;
                pixelData[4*i+1]=0;
                // pixelData[4*i+2]=0;
            }

 这是一个简单像素深浅处理:

var pixelData = imageData.data;

            for(var i=0;i<canvas.width*canvas.height;i++){
                var r = pixelData[i*4+0];
                var g = pixelData[i*4+1];
                var b = pixelData[i*4+2];

                var grey = r*0.3+g*0.59+b*0.11;//这个算法是图像学家研究出对RGB深浅的最好值

                pixelData[i*4+0] = grey;
                pixelData[i*4+1] = grey;
                pixelData[i*4+2] = grey;
            }

这是二维数组:遍历每一个像素

 for( var i = 0 ; i < canvas.height ; i ++ )
                for( var j = 0 ; j < canvas.width ; j ++ ){

//遍历第i行第j列的时候对应canvas的位移
                    var p = i*canvas.width + j;
                    //每一个点的像素值
                    pixelData[p*4+0] =
r;
                    pixelData[p*4+1] =
g;
                    pixelData[p*4+2] =
b;

}
}

4.putImageData() 方法函数则表示将所得到的像素数据描画到Canvas画板上形成图形。

context.putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight);

其中imgdata为像素数据,dx、dy是绘制图片的定位坐标值,dirtyXdirtyY是imgdata所要绘制图片的起始位置,dirtyXw、dirtyXh是imgdata所要绘制区域(相对imgdata的dirtyXx和dirtyXy坐标的偏移量)的宽度和高度值。这里面第4个参数以及其后的所有参数都可以省略,如果这些参数都省略了,则表示绘制整个imgdata。

5.getImageData函数从画板上取得像素数据然后通过 putImageData() 将所取得的像素数据画到Canvas画板上
var imgData=ctx.getImageData(10,10,50,50);

整个像素数据画到Canvas画板上:ctx.putImageData(imgData,10,70);

像素数据的一部分画到Canvas画板上:ctx.putImageData(imgData,200,260,50,50,100,100); 

三.特效


<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        .clearfix:after,.zn-clearfix:before{content: ""; visibility: hidden; display: block; height: 0; clear: both; }
        .clearfix{zoom:1;margin: 20px auto; width:1700px;}
    </style>
</head>
<body>
    <div class="clearfix">
        <canvas id="canvasa" width="800" height="560" style="display:block;float:left;border:1px solid #aaa;"></canvas>
        <canvas id="canvasb" width="800" height="560" style="display:block;float:right;border:1px solid #aaa;"></canvas>
    </div>
    <script>
        var canvasa = document.getElementById("canvasa");
        var contexta = canvasa.getContext("2d");

        var canvasb = document.getElementById("canvasb");
        var contextb = canvasb.getContext("2d");

        var image = new Image();

        window.onload = function(){

            image.src = "1.jpg";
            image.onload = function(){

                contexta.drawImage( image , 0 , 0 , canvasa.width , canvasa.height );
            }
        }
        
    </script>
</body>
</html>


(1).如何在图像中简单图像处理

灰度滤镜:


//灰度影响
        function greyEffect(){
            //通过 getImageData() 复制画布上指定矩形的像素数据,然后通过 putImageData() 将图像数据放回画布:
            var imageData = contexta.getImageData(0 , 0 , canvasa.width , canvasa.height);
            var pixelData = imageData.data;
            for(var i=0;i<canvasb.width*canvasb.height;i++){
                var r = pixelData[i*4+0];
                var g = pixelData[i*4+1];
                var b = pixelData[i*4+2];

                var grey = r*0.3+g*0.59+b*0.11;//这个算法是图像学家研究出对RGB深浅的最好值

                pixelData[i*4+0] = grey;
                pixelData[i*4+1] = grey;
                pixelData[i*4+2] = grey;
            }
            contextb.putImageData( imageData , 0 , 0 ,0 , 0 , canvasb.width, canvasb.height);
        }


黑白滤镜:是指图像上只有白色,黑色;也就是rgb(255,255,255),或是rgb(0,0,0)。



//黑白滤镜:是指图像上只有白色,黑色;也就是rgb(255,255,255),或是rgb(0,0,0)。
        function blackEffect(){

            var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );
            var pixelData = imageData.data;
            for( var i = 0 ; i < canvasb.width * canvasb.height ; i ++ ){

                var r = pixelData[i*4+0];
                var g = pixelData[i*4+1];
                var b = pixelData[i*4+2];

                var grey = r*0.3+g*0.59+b*0.11;
                if(grey > 125){
                    pv = 255;
                }
                else{
                    pv = 0;
                }

                pixelData[i*4+0] = pv;
                pixelData[i*4+1] = pv;
                pixelData[i*4+2] = pv;
            }

            contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasa.width , canvasa.height );
        }

反色滤镜:是指图像上的每一个点的RGB值修改为255-原来的值



 //反色滤镜:是指图像上的每一个点的RGB值修改为255-原来的值
        function reverseEffect(){

            var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );
            var pixelData = imageData.data;
            for( var i = 0 ; i < canvasb.width * canvasb.height ; i ++ ){

                var r = pixelData[i*4+0];
                var g = pixelData[i*4+1];
                var b = pixelData[i*4+2];

                pixelData[i*4+0] = 255 - r;
                pixelData[i*4+1] = 255 - g;
                pixelData[i*4+2] = 255 - b;
            }

            contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height );
        }


黑白,反色滤镜的每一个像素修改只需要参照自己当前的像素。


(2).如何在图像中参考一个像素周围的其他像素,进而实现一个图像处理

要注意:要保证周围的像素点不能被算法所修改,所以就不能仅仅使用一个imageData,需要创建一个imageData的拷贝var tmpImageData.

此后就参考tmpImageData,来修改imageData,最终把imageData结果传给putImageData,由此复制在画布上,同时当函数运行putImageData时,tmpImageData也就抛弃了。
模糊滤镜:模糊滤镜则需要参考自己周围的滤镜,图像上的每一个点的RGB值为周围的像素的平均值。


function blurEffect(){
            var tmpImageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );
            var tmpPixelData = tmpImageData.data;

            var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );
            var pixelData = imageData.data;

            var blurR =3;//模糊的半径
            //参考多少个像素点(这个区域是正方形的面积)
            var totalnum = (2*blurR + 1)*(2*blurR + 1);
            //采用二维循环编辑
            for( var i = blurR ; i < canvasb.height - blurR ; i ++ ){
                for( var j = blurR ; j < canvasb.width - blurR ; j ++ ){

                    var totalr = 0 , totalg = 0 , totalb = 0;//来计算周围所有的RGB的总和
                    //一个像素点周围有8个像素点。
                    //二维循环编辑:基于中心点在x,y方向的位移的变化值,循环走了9次,
                    //下面这个就是点周围的点循环+自身(i,j)
                    for( var dx = -blurR ; dx <= blurR ; dx ++ ){
                        for( var dy = -blurR ; dy <= blurR ; dy ++ ){

                            var x = i + dx;
                            var y = j + dy;
                            //周围像素点位移
                            var p = x*canvasb.width + y;
                            //所对应的像素点
                            totalr += tmpPixelData[p*4+0];
                            totalg += tmpPixelData[p*4+1];
                            totalb += tmpPixelData[p*4+2];
                        }
                    }
                    //遍历第i行第j列的时候对应canvas的位移
                    var p = i*canvasb.width + j;
                    //把周围的像素的平均值赋值(i,j)
                    pixelData[p*4+0] = totalr / totalnum;
                    pixelData[p*4+1] = totalg / totalnum;
                    pixelData[p*4+2] = totalb / totalnum;
                }
            }
            contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height );
        }


马赛克滤镜:


马赛克:一块像素的值=这块全部像素平均值

        //马赛克:一块像素的值=这块全部像素平均值
        function mosaicEffect(){
            var tmpImageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );
            var tmpPixelData = tmpImageData.data;

            var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );
            var pixelData = imageData.data;
            //定义为一块的边长是多少(这个图像宽高的整数倍)
            var size = 16;
            var totalnum = size*size;
            for( var i = 0 ; i < canvasb.height ; i += size )
                for( var j = 0 ; j < canvasb.width ; j += size ){
                    //这块是计算每一块全部的像素值--平均值
                    var totalr = 0 , totalg = 0 , totalb = 0;
                    for( var dx = 0 ; dx < size ; dx ++ )
                        for( var dy = 0 ; dy < size ; dy ++ ){

                            var x = i + dx;
                            var y = j + dy;

                            var p = x*canvasb.width + y;
                            totalr += tmpPixelData[p*4+0];
                            totalg += tmpPixelData[p*4+1];
                            totalb += tmpPixelData[p*4+2];
                        }

                    var p = i*canvasb.width+j;
                    var resr = totalr / totalnum;
                    var resg = totalg / totalnum;
                    var resb = totalb / totalnum;

                    //这个快像素的值=它的平均值
                    for( var dx = 0 ; dx < size ; dx ++ )
                        for( var dy = 0 ; dy < size ; dy ++ ){

                            var x = i + dx;
                            var y = j + dy;

                            var p = x*canvasb.width + y;
                            pixelData[p*4+0] = resr;
                            pixelData[p*4+1] = resg;
                            pixelData[p*4+2] = resb;
                        }
            }
            contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width, canvasb.height );
        }



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值