Публікація

Стиснення зображень на клієнті

Занотовую бібліотеку, яка робить стиснення зображень на клієнті

У мене час від часу виникає задача зберігати зображення в S3/R2, проте сховище не резинове, а потік зображень доволі великий. Одне з рішень – стискати зображення на бекенді, проте я мало бачу інформації про стискання зображень на клієнті, хоча це в браузері є таке API, як Canvas, котре може робити масштабування. Пошук дав результат, я знайшов бібліотеку browser-image-compression яка робить стискання в браузері клієнта. Розберемо опції.

Набір опцій наступний:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const options: Options = { 
  maxSizeMB: number,            // максимальний обʼєм зображення в мегобайтах (за замовчуванням: Number.POSITIVE_INFINITY)
  maxWidthOrHeight: number,     // максимальна довжина та висота зображення (за замовчуванням: undefined)
                                // проте автоматично зображення скейлиться до максимально возможного розміру Canvas браузера.
                                // Перевірте максимальні значення Canvas.
  onProgress: Function,         // опційно, функція, яка отримує аргумент та передає прогрес зжимання (percentage, від 0 до 100) 
  useWebWorker: boolean,        // опційно, використовувати многопоточність завдяки воркеру, резервно масштабування робиться в головному потоці (default: true)
  libURL: string,               // опційно, посилання на JS файл бібліотеки для імпортування веб-воркера (за замовчуванням: https://cdn.jsdelivr.net/npm/browser-image-compression/dist/browser-image-compression.js)
  preserveExif: boolean,        // опційно, чи потрібно зберігати Exif метадані для JPEG  наприклад, Camera model, Focal length, та подібне (за замовчуванням: false)

  signal: AbortSignal,          // опційно, сигнал для відміни сжимання

  // наступні опції для продвинутих користувачів
  maxIteration: number,         // опційно, максимальна кількість кроків для зжимання зображення (за замовчуваням: 10)
  exifOrientation: number,      // опційно, дивіться https://stackoverflow.com/a/32490603/10395024
  fileType: string,             // опційно, переписати fileType наприклад, 'image/jpeg', 'image/png' (за замовчуванням: file.type)
  initialQuality: number,       // опційно, початкова якість, число між 0 та 1 (за замовчуванням: 1)
  alwaysKeepResolution: boolean // опційно, тільки зменшити якість, завжди зберігати оригінальні ширину та довжину (за замовчуванням: false)
}

Опцій достатньо, щоб перетворити 6 Мб зображення на 600 Кб. Працює доволі швидко, щоб вбудувати в процес перед завантаженням на сервер (можно в моменті додавання зображення). Користувач може і не помітити різниці по часу завантаження. Я ще додав правило по якому зображення до 1 Мб взагалі не обробляються, обробляються тільки ті, що більше 1 Мб.

Значно покращився UX, бо користувачу тепер не треба шукати інструмент для зменшення зображення – він вже вбудований в процес, S3/R2 сховиже тепер не заповнюється занадто швидко, а сервер не виконує зайвої роботи, по мережі передаються не мегобайти, а кілобайти. Виглядає як оптимальне рішення. Єдиний ймовірний недолік, що всеж таки ми зберегаємо не оригінальне зображення, а його зтиснуту версію. Якщо потрібен оригінал – таке рішення не підійде.

Публікація захищена ліцензією CC BY 4.0 .

© jmas. Деякі права захищено.

Powered by Jekyll with Chirpy theme