Змінення розміру полотна HTML5 (зменшений масштаб) Зображення високої якості?

Я використовую елементи полотна html5 для зміни розміру зображень у моєму браузері. Виявляється, якість дуже низька. Я знайшов це: Вимкніть інтерполяцію при масштабуванні a, але це не сприяє підвищенню якості.

Нижче мій код css та js, а також зображення, масштабоване за допомогою Photoshop і масштабоване в API полотна.

Що мені потрібно зробити, щоб отримати оптимальну якість при масштабуванні зображення в браузері?

Примітка: Я хочу зменшити велике зображення до маленького, змінити колір на полотні та надіслати результат із полотна на сервер.

Змінено розмір зображення за допомогою Photoshop:

javascript

Змінено розмір зображення на полотні:

Я намагався зробити зменшення масштабу більш ніж одним кроком, як було запропоновано в:

Це функція, якою я користувався:

Ось результат, якщо я використовую 2-ступене зменшення розміру:

Ось результат, якщо я використовую 3-ступене зменшення розмірів:

Ось результат, якщо я використовую 4-ступеневий розмір:

Ось результат, якщо я використовую 20-градусний розмір:

Примітка: Виявляється, від 1 до 2 кроків відбувається значне покращення якості зображення, але чим більше кроків ви додаєте до процесу, тим більш нечітким стає зображення.

Чи є спосіб вирішити проблему, завдяки якій зображення стає нечіткішим, чим більше кроків ви додаєте?

Редагувати 2013-10-04: Я спробував алгоритм GameAlchemist. Ось результат порівняно з Photoshop.

14 Відповіді 14

Оскільки ваша проблема полягає в зменшенні масштабу вашого зображення, немає сенсу говорити про інтерполяцію - що стосується створення пікселів -. Справа тут у зменшенні вибірки.

Щоб зменшити вибірку зображення, нам потрібно перетворити кожен квадрат p * p пікселів у вихідному зображенні в один піксель у цільовому зображенні.

З міркувань продуктивності Браузери виконують дуже просту десенсиплінгу: щоб створити менший малюнок, вони просто виберуть ОДИН піксель у джерелі та використають його значення для пункту призначення. який «забуває» деякі деталі та додає шуму.

Проте є виняток з цього: оскільки зменшення дискретизації 2-кратного зображення дуже просте для обчислення (в середньому 4 пікселі для створення одного) і використовується для пікселів сітківки/HiDPI, цей випадок обробляється належним чином - Браузер використовує 4 пікселі для створення один-.

АЛЕ. якщо ви використовуєте кілька разів дворазову дискретизацію, ви зіткнетеся з проблемою, що послідовні помилки округлення додадуть занадто багато шуму.
Що ще гірше, ви не завжди зменшуєте розмір у два рази, а зменшення розміру до найближчого рівня + останнє змінення розміру дуже шумне.

Ви шукаєте ідеальну піксельну дескрипцію, тобто повторну вибірку зображення, яка враховуватиме всі вхідні пікселі - незалежно від масштабу-.
Для цього ми повинні обчислити для кожного вхідного пікселя його внесок в один, два або чотири пікселі призначення, залежно від того, чи масштабована проекція вхідних пікселів знаходиться прямо всередині пікселів призначення, перекриває межу X, межу Y або обидва.
(Тут би була гарна схема, але у мене її немає.)

Ось приклад масштабу полотна проти мого ідеального масштабу пікселя в масштабі 1/3 зомбату.

Зверніть увагу, що зображення може масштабуватися у вашому браузері, і його .jpegized S.O.
Проте ми бачимо, що шуму набагато менше, особливо в траві за вомбатом та гілках праворуч. Шум у хутрі робить його більш контрастним, але схоже, що у нього білі волосся - не схоже на вихідне зображення-.
Правильне зображення є менш привабливим, але остаточно приємним.

Ось код для ідеального зменшення масштабу пікселя:

Це досить жадібно до пам’яті, оскільки для збереження проміжних значень цільового зображення потрібен плаваючий буфер (-> якщо ми підраховуємо полотно результату, то в цьому алгоритмі ми використовуємо пам’ять вихідного зображення в 6 разів).
Це також досить дорого, оскільки кожен вихідний піксель використовується незалежно від розміру призначення, і ми повинні платити за getImageData/putImageDate, також досить повільно.
Але в цьому випадку неможливо пришвидшити обробку кожного вихідного значення, і ситуація не така вже й погана: для мого зображення вомбата 740 * 556 обробка займає від 30 до 40 мс.