Високопродуктивна обробка зображень на стороні клієнта
Обробка зображень у браузері зараз є стандартною вимогою. Ви можете створювати фоторедактори, набори інструментів для активів або фільтри доступності. Щоб інтерфейс залишався чуйним, вам потрібна низька затримка.
Просте завдання — інверсія кольорів. Це означає перетворення значень RGB на їхні протилежні (негативні) значення. Якщо використовувати стандартний підхід для зображень 4K, ви зіткнетеся з обмеженнями апаратного забезпечення.
Проблема: Наївна ітерація
Більшість розробників використовують метод getImageData(). Він повертає Uint8ClampedArray. Цей масив зберігає пікселі як канали Red, Green, Blue та Alpha (RGBA).
Стандартний цикл виглядає так:
- Прохід циклом через кожен окремий байт.
- Віднімання кожного значення кольору від 255.
- Пропуск каналу Alpha.
Це працює для малих зображень. Це не спрацьовує для 4K-активів. Зображення 4K має понад 8 мільйонів пікселів. Стандартний цикл виконує понад 33 мільйони окремих операцій запису. Це блокує основний потік (main thread), що спричиняє підторможування браузера та пропуски кадрів.
Рішення: Маніпуляція 32-бітним буфером
Ви можете припинити сприймати пікселі як чотири окремі канали. Замість цього накладіть Uint32Array поверх буфера даних.
Використовуючи 32-бітне представлення, ви групуєте R, G, B та A в одне ціле число. Тепер ваш цикл виконує лише 8,2 мільйона ітерацій замість 33 мільйонів. Ви виконуєте одну операцію на піксель замість чотирьох.
Швидка інверсія кольорів за допомогою побітового XOR
Щоб інвертувати кольори, не чіпаючи Alpha, використовуйте побітовий оператор XOR (^). Використовуйте маску 0x00FFFFFF.
Як це працює:
- Маска націлена лише на біти кольору.
- Біти Alpha залишаються незмінними.
- Процесор обробляє це за один цикл.
Результати:
- 1080p-активи: у 3,8 раза швидше.
- 2K-шаблони: у 4,1 раза швидше.
- 4K-шпалери: у 4,4 раза швидше.
Порада професіонала: Використовуйте Web Workers Якщо ви обробляєте багато файлів високої роздільної здатності, навіть 32-бітні операції можуть сповільнити інтерфейс. Перенесіть логіку у Web Worker. Використовуйте Transferable Objects для передачі буфера. Це дозволить уникнути копіювання даних і звільнить основний потік.
Припиніть використовувати важкі цикли. Використовуйте 32-бітні слова та побітові прапорці для створення легких і швидких конвеєрів обробки зображень.