canvas进阶之图像处理基础知识

2,878 阅读4分钟

前言

在阅读完 canvas - 基础了解 后,想必大家对 canvas 有了一定的认知,那么接下来,咱们就玩点稍微有意思的东西....

绘制图像

  • drawImage(image,x,y): 将独立的图片绘制在画布中(注意: 图片加载完毕后才能使用canvas进行绘制)
    • 参数x, y:canvas上的坐标
    • 保证图片加载完成
image = new Image();
image.src = "图片地址";
image.onload = function(){
  context.drawImage(image,0,0);
}
  • drawImage(image,x,y,width,height):

    • width, height: 是设置引入图片的高度和宽度,对图片进行缩放处理
    • 如果不传 width、height 参数,按图片原始大小画在canvas上,超出部分被自动裁剪
  • drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh);

    • 规定要使用的图像
    • (可选)图片-开始剪切的 x 坐标位置,
    • (可选)图片-开始剪切的 y 坐标位置,
    • (可选)图片-被剪切图像的宽度。
    • (可选)图片-被剪切图像的高度,
    • 在画布上放置图像的 x 坐标位置,
    • 在画布上放置图像的 y 坐标位置,
    • (可选,伸展或缩小图像)要使用的图像的宽度,
    • (可选,伸展或缩小图像)要使用的图像的高度

图像平铺

  • createPattern(image,type): 并不表示绘制图片,要设置图片是否平铺,还需要用绘制方法进行单独绘制

  • 参数type:表示是否平铺

    • no-repeat(没意义,不平铺,我直接用drawImage,它不香么...
    • repeat
    • repeat-x
    • repeat-y
var image = new Image();
image.src = '1.png';
image.onload = function () {
  var rpt = ctx.createPattern(image, 'repeat');
  ctx.fillStyle = rpt;
  ctx.fillRect(0, 0, drawing.width, drawing.height);
};

裁剪图像

  • 载入图像: drawImage()或createPattern()
  • 切割: clip() - 从原始画布剪切任意形状和尺寸的区域
  • 注意:一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。您也可以在使用 clip() 方法前通过使用 save() 方法对当前画布区域进行保存,并在以后的任意时间对其进行恢复(通过 restore() 方法)

image.png

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
// Draw a rectangle
ctx.rect(50,20,200,120);
ctx.stroke();
// Draw red rectangle
ctx.fillStyle="green";
ctx.fillRect(0,0,150,100);

// 使用 clip
var c=document.getElementById("myCanvas2");
var ctx=c.getContext("2d");
// Clip a rectangular area
ctx.rect(50,20,200,120);
ctx.stroke();
ctx.clip();
// Draw red rectangle after clip()
ctx.fillStyle="green";
ctx.fillRect(0,0,150,100);

离屏 canvas

  • 多个canvas存在时,可以将第二个canvas中的内容加载到第一个canvas上
  • ctx.drawImage(otherCanvas, x, y);

应用

  • 水印: 为图片增加增加一个水印(在后面的 demo 中,会详细讲解水印的编码实现)
    • 为水印单独设置一个 canvas2
    • 然后使用 ctx1.drawImage(canvas2,x,y)-xy表示c2在c1上的位置
  • 放大镜: 为一个图片增加放大镜效果(在后面的 demo 中,会详细讲解放大镜的编码实现)

像素处理

获取图像像素

  • imageDate = context.getImageData(x,y,w,h);

  • imageDate对象:矩形区域的图像数据

    • width、height、data,其中data为图像信息,一维数组
  • R - 红色 (0-255)

  • G - 绿色 (0-255)

  • B - 蓝色 (0-255)

  • A - alpha 通道 (0-255; 0 是透明的,255 是完全可见的)

将图像信息放回到 canvas 中

  • context.putImageData(imageData,dx,dy,dirtyX,dirtyY,dirtyW,dirtyH)
    • imageData 图像信息 一维数组
    • dx、dy 将imageData放在画布中的位置
    • dirtyX,如果设置值了,它会累加到dx上
    • dirtyY,如果设置值了,它会累加到dy上

创建imageData

  • 创建矩形图像
  • context.createImageData(w,h)

举个 🌰

  • 创建一个矩形图像,第一个像素变为红色,第二个像素变为绿色,其他为浅绿色
var c = document.getElementById('myCanvas');
var ctx = c.getContext('2d');
var imgData = ctx.createImageData(100, 100);

// 第一个像素变为红色
imgData.data[0] = 255;
imgData.data[1] = 0;
imgData.data[2] = 0;
imgData.data[3] = 255;

// 第二个像素变为绿色
imgData.data[4] = 0;
imgData.data[5] = 255;
imgData.data[6] = 0;
imgData.data[7] = 255;

for (var i = 8; i < imgData.data.length; i += 4) {
  imgData.data[i + 0] = 0;
  imgData.data[i + 1] = 66;
  imgData.data[i + 2] = 0;
  imgData.data[i + 3] = 77;
}
ctx.putImageData(imgData, 10, 10);

再举个 🌰

image.png

canvas.width = 500;
canvas.height = 500;

var imageData = ctx.createImageData(canvas.width, canvas.height);
var pixelData = imageData.data;

for (var i = 0; i < canvas.height; i++) {
  for (var j = 0; j < canvas.width; j++) {
    var p = i * canvas.width + j;
    pixelData[4 * p + 0] = parseInt(Math.pow(Math.cos(Math.atan2(j - 250, i - 250) / 2), 2) * 255);
    pixelData[4 * p + 1] = parseInt(
      Math.pow(Math.cos(Math.atan2(j - 250, i - 250) / 2 - (2 * Math.acos(-1)) / 3), 2) * 255
    );
    pixelData[4 * p + 2] = parseInt(
      Math.pow(Math.cos(Math.atan2(j - 250, i - 250) / 2 + (2 * Math.acos(-1)) / 3), 2) * 255
    );
    pixelData[4 * p + 3] = 255;
  }
}

ctx.putImageData(imageData, 0, 0, 0, 0, canvas.width, canvas.height);

画布方法

状态方法

  • save(): 保存当前Canvas设置
  • restore(): 还原设置

转换方法:

  • scale(宽的倍数,高的倍数): 设置放大或缩小,应放在绘制之前
  • translate(x,y): 重新映射画布的原点位置(效果就是图像移动位置),应放在绘制之前
  • rotate(要旋转的度数*Math.PI/180): 以画布的原点旋转图像,应放在绘制之前
    • 原点在canvas的左上角

图像处理经典小例子

canvas进阶之图像处理经典小例子