canvas图像处理

一.drawImage()函数

drawImage() 方法在画布上绘制图像、画布或视频。drawImage() 方法也能够绘制图像的某些部分,以及/或者增加或减少图像的尺寸。

三种用法

context.drawImage(img,x,y); 在画布上定位图像。
context.drawImage(img,x,y,width,height);在画布上定位图像,并规定图像的宽度和高度。
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
这里写图片描述

传9个参数时,这个函数的意思是从原图像的sx,sy的位置,剪取sw,sh大小的图像,放到canvas画布中dx,dy的位置,现图像的大小为dw宽,dh高。

注意点:我们直接调用drawImage()函数时,将使用图片的原有尺寸,从指定的位置开始,平铺在canvas画布中。当图片尺寸大于canvas画布时,超出的部分将自动隐藏。

二.中心缩放图片

方法一:在原图像的sx,sy位置,选取canvas.width,canvas.height的图像,放置于canvas画布中。

这里写图片描述
绿颜色的代表原图像,蓝颜色的代表canvas画布。
sx = imageWidth/2 - canvas.width/2;
sy = imageHidth/2 - canvas.height/2;
context.drawImage(image,sx,sy.canvas.width,canvas.height,0,0,canvas.width,canvas.height);
缺点:缩小的时候会出bug。

方法二:每一次都显示整个图像,只不过我们显示整个图像的时候,显示这个图像在左上角的坐标不一样。

这里写图片描述
绿色为canvas画布,蓝色为要显示的图像。
sx,sy为我们要显示的目的图像在左上角的坐标。
sx = canvas.width - imageWidth/2;
sy = canvas.height - imageHeight/2;
context.drawImage(image,dx,dy,imageWidth,iamgeHeight);
当scale>1时,sx,sy为负,从canvas外面进行显示,画布外面的部分自动隐藏达到放大的效果。
当scale<1时,sx,sy为正,从canvas里面进行显示。

源代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body style="background: black;">
<canvas id="canvas" style="border: 1px solid #000; display: block; margin:0 auto">
    您的浏览器不支持canvas画布!
</canvas>
<input type="range" id="scale-range" min="0.5" max="3.0" step="0.01" value="1.0"
       style="display: block; margin: 20px auto; width: 800px;">
<script type="text/javascript">
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");
    var slide = document.getElementById("scale-range");
    var image = new Image();

    window.onload = function () {
        canvas.width = 1152;
        canvas.height = 700;
        var scale = slide.value;
        image.src = "img/img-lg.jpg";
        image.onload = function () {
            //context.drawImage(image,0,0,canvas.width,canvas.height);
            drawImageByScale(scale);
            slide.onmousemove = function () {
                scale = slide.value;
                drawImageByScale(scale);
            }
        }
    };

    function drawImageByScale(scale) {
         var imageWidth = 1152*scale;
         var imageHeight = 700*scale;
         x = canvas.width/2 - imageWidth/2;
         y = canvas.height/2 - imageHeight/2;
         context.clearRect(0,0,canvas.width,canvas.height);
         context.drawImage(image,x,y,imageWidth,imageHeight);
    }
</script>
</body>
</html>

三.离屏canvas(将第二个canvas中的内容加载到第一个canvas上)

1.给图片加水印
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<canvas id="canvas" style="border: 1px solid #000; display: block; margin: 50px auto">
    您的浏览器不支持canvas画布!
</canvas>
<input type="range" id="scale-range" min="0.5" max="3.0" step="0.01" value="1.0"
       style="display: block; margin: 20px auto; width:800px">
<canvas id="watermark-canvas" style="display: none; margin: 0 auto;border: 1px solid #aaa;">
    您的浏览器不支持canvas画布!
</canvas>

<script>
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");
    var slider = document.getElementById("scale-range");

    var watermarkCanvas = document.getElementById("watermark-canvas");
    var watermarkContext = watermarkCanvas.getContext("2d");
    window.onload = function () {
        canvas.width = 1152;
        canvas.height = 768;

        var image = new Image();
        var scale = 1.0;
        image.src = "img/img-lg.jpg";
        image.onload = function () {
            drawImage(image,scale);
            slider.onmousemove = function () {
                scale = slider.value;
                drawImage(image,scale);
            }
        };

        //setup watermark canvas
        watermarkCanvas.width = 600;
        watermarkCanvas.height = 100;
        watermarkContext.font = "bold 50px Arial";
        watermarkContext.lineWidth = 1;
        watermarkContext.fillStyle = "rgba(255,255,255,0.5)";
        watermarkContext.textBaseline = "middle";
        watermarkContext.fillText("==AFeng521web.com==",20,50);
    };

    function drawImage(image,scale) {
        imageWidth = 1152*scale;
        imageHeight = 768*scale;
        x = canvas.width/2 - imageWidth/2;
        y = canvas.height/2 - imageHeight/2;

        context.clearRect(0,0,canvas.width,canvas.height);
        context.drawImage(image,x,y,imageWidth,imageHeight);
        //将第二个画布加到第一个画布的右下角
        context.drawImage(watermarkCanvas,canvas.width - watermarkCanvas.width,
            canvas.height - watermarkCanvas.height)
    }
</script>
</body>
</html>

效果图:
这里写图片描述

2.放大镜

关键点:获取鼠标在canvas中的位置
这里写图片描述

代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body style="background: black">
<canvas id="canvas" style="display: block; margin: 0 auto; border: 1px solid #aaa;">
    您的浏览器不支持canvas!
</canvas>

<canvas id="offCanvas" style="display: none;">

</canvas>
<script>
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");

    var offCanvas = document.getElementById("offCanvas");
    var offContext = offCanvas.getContext("2d");

    var image = new Image();
    var isMouseDown = false;
    var scale;
    window.onload = function () {
        canvas.width = 1152;
        canvas.height = 768;
        image.src = "img/img-lg.jpg";
        image.onload = function () {
            offCanvas.width = image.width;
            offCanvas.height = image.height;
            scale = offCanvas.width / canvas.width;

            context.drawImage(image,0,0,canvas.width,canvas.height);
            offContext.drawImage(image,0,0);
        }
    };
    function windowToCanvas(x,y) {
        var bbox = canvas.getBoundingClientRect();
        return {
            x:x-bbox.left,
            y:y-bbox.top
        }
    }
    canvas.onmousedown = function (e) {
        e.preventDefault();
        isMouseDown = true;
        point = windowToCanvas(e.clientX,e.clientY);
        console.log(point.x,point.y);
        drawCanvasWithMagnifier(true,point)
    };
    canvas.onmouseup = function(e){
        e.preventDefault();
        isMouseDown = false;
        drawCanvasWithMagnifier( false );
    };

    canvas.onmouseout = function(e){
        e.preventDefault();
        isMouseDown = false;
        drawCanvasWithMagnifier( false );
    };

    canvas.onmousemove = function(e){
        e.preventDefault();
        if( isMouseDown == true ){
            point = windowToCanvas( e.clientX , e.clientY );
            console.log( point.x , point.y );
            drawCanvasWithMagnifier( true , point );
        }
    };
    function drawCanvasWithMagnifier(isShowMagnifier,point) {
        context.clearRect(0,0,canvas.width,canvas.height);
        context.drawImage(image,0,0,canvas.width,canvas.height);
        if(isShowMagnifier == true) {
            drawMagnifier(point);
        }
    }
    function drawMagnifier(point) {
        var mr = 200;
        var imageLG_cx = point.x *scale;
        var imageLG_cy = point.y *scale;

        var sx = imageLG_cx - mr;
        var sy = imageLG_cy - mr;
        var dx = point.x - mr;
        var dy = point.y - mr;

        context.save();
        context.lineWidth = 10;
        context.strokeStyle = "#069";

        context.beginPath();
        context.arc(point.x,point.y,mr,0,Math.PI*2,false);
        context.stroke();
        context.clip();
        context.drawImage(offCanvas,sx,sy,2*mr,2*mr,dx,dy,2*mr,2*mr);
        context.restore();
    }
</script>

</body>
</html>

效果图:
这里写图片描述

三.滤镜

1.getImageData(x,y,w,h);

x 开始复制的左上角位置的 x 坐标。
y 开始复制的左上角位置的 y 坐标。
width 将要复制的矩形区域的宽度。
height 将要复制的矩形区域的高度。
ImageData = context.getImageData(x,y,w,h);
返回ImageData对象,该对象拷贝了画布指定矩形区域的像素数据,width和height。
这里写图片描述
data属性返回一个 Uint8ClampedArray,它可以被使用作为查看初始像素数据。每个像素用4个1bytes值(按照红,绿,蓝和透明值的顺序; 这就是”RGBA”格式) 来代表。每个颜色值部份用0至255来代表。每个部份被分配到一个在数组内连续的索引,左上角像素的红色部份在数组的索引0位置。像素从左到右被处理,然后往下,遍历整个数组。
Uint8ClampedArray 包含高度 × 宽度 × 4 bytes数据,索引值从0到(高度×宽度×4)-1。

2.putImageData()方法去对场景进行像素数据的写入。

context.putImageData(imageData,dx,dy,dirtyX,dirtyY,dirtyW,dirtyH);
这里写图片描述

注意点:离整个canvas的左端为dx+dirtyX;离整个canvas的上端为dy+dirtyY;

3.滤镜制作思想:将原图像中的像素数据通过getImageData(x,y,w,h)得到,然后再通过图像算法进行修改,最后将修改的像素信息通过putImageData()添加进canvas画布中。

代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div style="margin: 20px auto; width:1700px">
        <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>
    <div style="clear: both;"></div>
    <div style="text-align: center; margin-top: 50px; font-size: 20px">
        <a href="javascript:greyEffect()">Grey Effect</a>
        <a href="javascript:blackEffect()">Black and White Effect</a>
        <a href="javascript:reverseEffect()">Reverse Effect</a>
        <a href="javascript:blurEffect()">Blur Effect</a>
        <a href="javascript:mosaicEffect()">Mosaic Effect</a>
    </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 = "img/autumn.jpg";
            image.onload = function () {
                contexta.drawImage(image,0,0,canvasa.width,canvasa.height);
            }
        };

        function greyEffect() {
            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;
                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);
            //context.putImageData();
        }

        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);
        }

        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);
        }

        function blurEffect() {
            var tempImageData = contexta.getImageData(0,0,canvasa.width,canvasa.height);
            var tempPixelData = tempImageData.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;
                    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 += tempPixelData[p*4+0];
                            totalg += tempPixelData[p*4+1];
                            totalb += tempPixelData[p*4+2];
                        }
                    }
                    var p = i*canvasb.width + 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 )

        }
    </script>
</body>
</html>

本教程主要是根据慕课网刘宇波老师的Canvas玩转图像处理视频教程总结而来。在此特别感谢刘老师的无私奉献。

课程链接

https://www.imooc.com/learn/476

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值