Обработка изображений Canvas 2D: Принципы и практика пиксельных операций на стороне браузера

技术架构

Canvas в обработке изображений

Браузер предлагает три пути обработки изображений:

Подход Производительность Гибкость Лучше всего для
CSS-фильтр Высокая (GPU) Низкая (предустановленные фильтры) Простые визуальные эффекты
Canvas 2D Средняя Высокая (пиксельный уровень) Сжатие, обрезка, конвертация форматов
WebGL Наивысшая Высокая (требуются шейдеры) Сложные фильтры, обработка в реальном времени

Инструменты изображений ToolsKu (сжатие, обрезка, конвертация форматов, водяной знак) все построены на Canvas 2D API.


Базовый процесс обработки

// 1. Load image
const img = new Image();
img.src = URL.createObjectURL(file);
await img.decode();

// 2. Create Canvas and draw
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d')!;
ctx.drawImage(img, 0, 0);

// 3. Export to target format
const blob = await new Promise<Blob>((resolve) =>
  canvas.toBlob(resolve, 'image/webp', 0.85) // quality 85%
);

Как работает сжатие изображений

Сжатие Canvas — это по сути перекодирование:

Original PNG (2MB, lossless)
     ↓ drawImage to Canvas
     ↓ toBlob('image/jpeg', 0.8)
Compressed JPEG (400KB, lossy 80% quality)
Формат Сжатие Типичное соотношение Прозрачность
JPEG С потерями DCT 60-80%
WebP С потерями/без потерь 70-90%
PNG Без потерь DEFLATE 10-30%
AVIF С потерями/без потерь 80-95%

Инструмент сжатия изображений ToolsKu поддерживает пакетное сжатие WebP/JPEG. Качество по умолчанию 85% балансирует размер файла и визуальное качество.


Пиксельные операции

Управляйте пикселями RGBA напрямую через ImageData:

const imageData = ctx.getImageData(0, 0, width, height);
const data = imageData.data; // Uint8ClampedArray, 4 bytes = 1 pixel

for (let i = 0; i < data.length; i += 4) {
  // Grayscale
  const avg = (data[i] + data[i+1] + data[i+2]) / 3;
  data[i] = data[i+1] = data[i+2] = avg;
}

ctx.putImageData(imageData, 0, 0);

Оптимизация производительности с OffscreenCanvas

Операции Canvas в главном потоке блокируют UI. OffscreenCanvas может работать в Worker:

// worker.ts
const offscreen = new OffscreenCanvas(width, height);
const ctx = offscreen.getContext('2d')!;
ctx.drawImage(imageBitmap, 0, 0);
const blob = await offscreen.convertToBlob({ type: 'image/webp', quality: 0.85 });
postMessage({ blob }, [blob]); // Transferable

При пакетной обработке 50 изображений OffscreenCanvas + Worker снижает блокировку главного потока с 10с до 0.


Частые вопросы

Почему изображение выглядит размытым после сжатия?

Сжатие с потерями JPEG/WebP отбрасывает высокочастотные детали. Повысьте параметр качества (0.9+) или используйте режим без потерь PNG/WebP.

Есть ли ограничения на размер Canvas?

Большинство браузеров ограничивают один край Canvas до 16384px, с общей площадью около 268MP. Превышение требует мозаичной обработки.

Как обрабатывать ориентацию EXIF?

Фотографии с телефонов могут содержать EXIF Orientation. Считайте EXIF и поверните Canvas перед отрисовкой, иначе изображение будет отображаться повёрнутым. Конвертер форматов изображений ToolsKu обрабатывает EXIF автоматически.


Заключение

Canvas 2D — стандартный подход для обработки изображений на стороне браузера. Понимание конвейера кодирования drawImage → toBlob, пиксельных операций ImageData и выноса в Worker с OffscreenCanvas является основой для создания высокопроизводительных инструментов работы с изображениями.

Попробуйте эти локальные браузерные инструменты — регистрация не требуется →

#Canvas#图像处理#WebGL#像素操作#性能