图像处理

Canvas图像处理完整教程,掌握图像绘制、裁剪、缩放、滤镜等核心功能。Canvas提供了强大的图像处理能力,包括图像绘制、裁剪、缩放和像素操作。

图像绘制方法

drawImage方法有多种调用形式:

语法说明
drawImage(image, x, y)原始尺寸绘制
drawImage(image, x, y, width, height)缩放绘制
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)裁剪绘制

图像源类型

类型说明
HTMLImageElementimg元素
HTMLVideoElementvideo元素
HTMLCanvasElementcanvas元素
ImageBitmap位图对象

加载并绘制图像

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')

const img = new Image()
img.onload = function() {
  // 原始尺寸绘制
  ctx.drawImage(img, 0, 0)
}
img.src = 'image.png'

图像缩放

img.onload = function() {
  // 缩放到指定尺寸
  ctx.drawImage(img, 0, 0, 200, 150)
  
  // 放大
  ctx.drawImage(img, 220, 0, 400, 300)
}

图像裁剪

img.onload = function() {
  // 从源图像(50, 50)位置裁剪100x100区域
  // 绘制到画布(0, 0)位置,尺寸200x200
  ctx.drawImage(img, 50, 50, 100, 100, 0, 0, 200, 200)
}

图像绘制演示

图像绘制示例

图像翻转

// 水平翻转
ctx.save()
ctx.scale(-1, 1)
ctx.drawImage(img, -img.width, 0)
ctx.restore()

// 垂直翻转
ctx.save()
ctx.scale(1, -1)
ctx.drawImage(img, 0, -img.height)
ctx.restore()

图像翻转演示

图像翻转效果

图像旋转

// 旋转图像
ctx.save()
ctx.translate(canvas.width / 2, canvas.height / 2)
ctx.rotate(Math.PI / 4)  // 旋转45度
ctx.drawImage(img, -img.width / 2, -img.height / 2)
ctx.restore()

图像旋转演示

图像旋转效果

createImageBitmap

异步创建ImageBitmap对象,提高性能:

// 从图像创建
const bitmap = await createImageBitmap(img)
ctx.drawImage(bitmap, 0, 0)

// 从Blob创建
const response = await fetch('image.png')
const blob = await response.blob()
const bitmap = await createImageBitmap(blob)
ctx.drawImage(bitmap, 0, 0)

// 裁剪创建
const croppedBitmap = await createImageBitmap(img, 50, 50, 100, 100)
ctx.drawImage(croppedBitmap, 0, 0)

视频帧绘制

const video = document.querySelector('video')

function drawFrame() {
  ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
  requestAnimationFrame(drawFrame)
}

video.addEventListener('play', drawFrame)

视频帧绘制演示

Canvas作为图像源

图像平滑

// 启用图像平滑(默认)
ctx.imageSmoothingEnabled = true
ctx.imageSmoothingQuality = 'high'  // low, medium, high

// 禁用图像平滑(像素化效果)
ctx.imageSmoothingEnabled = false

图像平滑演示

图像平滑对比

注意事项

跨域问题

// 图像需要设置crossOrigin属性
const img = new Image()
img.crossOrigin = 'anonymous'
img.onload = function() {
  ctx.drawImage(img, 0, 0)
}
img.src = 'https://example.com/image.png'

图像加载状态

// 确保图像加载完成
if (img.complete) {
  ctx.drawImage(img, 0, 0)
} else {
  img.onload = function() {
    ctx.drawImage(img, 0, 0)
  }
}

性能优化

// 预加载图像
const images = {}
function preloadImages(sources, callback) {
  let loaded = 0
  const total = Object.keys(sources).length
  
  Object.keys(sources).forEach(key => {
    const img = new Image()
    img.onload = function() {
      images[key] = img
      loaded++
      if (loaded === total) callback()
    }
    img.src = sources[key]
  })
}

内存管理

// ImageBitmap需要手动释放
let bitmap = await createImageBitmap(img)
ctx.drawImage(bitmap, 0, 0)
bitmap.close()  // 释放内存