Обработка изображений 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 является основой для создания высокопроизводительных инструментов работы с изображениями.
Попробуйте эти локальные браузерные инструменты — регистрация не требуется →