Генератор ASCII-артів на HTML5

html5
Доброго часу доби, шановні хаброжителі.

У цій статті я розповім про те, як за допомогою HTML5 можна зробити простенький додаток, який генеруватиме ASCII-арти на основі звичайних зображень. Стаття орієнтована тих, хто тільки починає своє знайомство з такою чудовою технологією, як HTML5, яким є і я. Фахівці навряд чи знайдуть собі щось нове.

Справа була ввечері, робити не було чого

Копався я нещодавно в інтернеті в пошуках шпалер і натрапив на одне цікаве зображення (1.1 мб). І мене "зачепила" ідея малювати зображення різнобарвними літерами. Порившись в інтернеті, дізнався, що це називається ASCII-art. Ну і звичайно ж перша думка: "А запилю як я додаток, щоб мої улюблені шпалери таким чином намалювало!" Сказано - зроблено. Є час, є бажання чому б не спробувати.

Було вирішено реалізовувати програму в браузері. Я давно дивився на HTML5 і облизувався, але всі руки не доходили погратися. А що? Технологія модна, перспективна, чому б не спробувати? Та й проект не складний, для вивчення чогось нового — саме те. На цьому й зупинився.

Постановка задачі

Додаток повинен відповідати таким вимогам:

  • наявність двох способів завантаження вихідного зображення: через поле вибору файлу та перетягуванням у спеціальну область (далі називатимемо «область прийому»);
  • відсутність складних налаштувань. Тільки найнеобхідніше: колір фону, текст і розмір шрифту;
  • можливість обробки зображень із прозорим фоном;
  • робота повинна відбуватися лише у браузері, без звернень до сервера та без перезавантаження сторінки.
Зрозуміло, що питання підтримки старих браузерів не постає.

Для початку, накидаємоhtml-розмітку. Сторінка програми ділиться на три логічні частини:

Завантаження вихідного зображення

Спочатку розберемо спосіб завантаження вихідного зображення. Для того, щоб отримати доступ до вибраного користувачем файлу, без відправки його вона сервер використовується клас FileReader. Його метод readAsDataURL() повертає вміст файлу як схеми data:URL. Ну що ж, спробуймо.

Тепер ми маємо вихідне зображення у вигляді data:URL. Що з нею можна зробити? Його можна використовувати як значення атрибута src для зображення. Тому давайте покажемо користувачеві вихідне зображення.

Ось так набагато наочніше. Тепер найголовніше: необхідно обробити це зображення.

Ми не будемо зберігати налаштування кожного разу, коли користувач змінює їх. Натомість ми вважаємо їх лише один раз, безпосередньо перед обробкою зображення.

Тепер перейдемо безпосередньо до створення нашого арту.

Обробка зображення

Весь процес можна розбити на кілька етапів:

  1. отримання даних про вихідне зображення. А точніше, нам потрібен колір кожного пікселя;
  2. розрахунок розмірів символів, за допомогою яких формуватиметься арт;
  3. розрахунок кольору кожного символу та його кольору;
  4. безпосередньо генерація арту;
  5. уявлення арту як зображення, що користувач міг зберегти плід своїх старань.

Отримання даних про вихідне зображення

Для того, щоб дізнатися кольори пікселів вихідного зображення, необхідно створити канву та нанести зображення на неї. Спочатку додамо канву на сторінку:

Тепер поставимо їй такі самі розміри, як і у вихідного зображення і нанесемо це зображення на неї. А потім отримаємо інформацію про канву, а як наслідок— про вихідне зображення.

Метод getImageData() повертає інформацію про канву. Поле data містить опис кожного пікселя саме те, що нам треба.

Тепер ми маємо необхідну інформацію. Ось тільки представлена ​​вона не в найкращій формі. Це одновимірний масив, де перші чотири елементи описують перший піксель (rgba), елементи з п'ятого по восьму - другий піксель і т.д. до кінця. Як із таким працювати, я слабо уявляю. Тому давайте наведемо цю купу чисел у людський вигляд.

Тепер ми маємо двовимірний масив, де кожен піксель представлений об'єктом. З ним і працюватимемо далі.

Розрахунок розмірів символу

Як отримати точний розмір символу? Чи не розмір шрифту, а область, яку символ займає на екрані? Щоб не морочитися, просто створимо тимчасовий span з цим символом і заміряємо його розмір.

Уважний читач, швидше за все, помітив, що враховується не вся висота символу, а лише 80%. Це зроблено тому, що видима частина букви займає не всю висоту, що відводиться їй. Через це на підсумковому зображенні з'являються порожні горизонтальні лінії між рядками. Особливо вони помітні, якщо літери великого розміру. Я пристрілявся, так що при різних розмірах шрифту відстань між рядками була мінімальною — вийшло 80%. Так і залишимо.

Розрахунок положення та кольору символів

Тепер необхідно скласти "карту символів" - список, що містить інформацію про кожен символ, з яких формуватиметься підсумкове зображення. Необхідно знати координати символу та його колір.

Як колір символу будемо використовувати колір пікселя, що знаходиться в центрі області вихідного зображення, що займає цей символ. Ну або поряд з ним, у випадку області з непарною кількістю пікселів по одній ізсторін.

Також визначимо функцію, яка повертатиме черговий символ із введеного користувачем тексту. А при досягненні кінця починати спочатку.

Генерація арту

Тепер у нас є все, що потрібно: список позицій та кольорів символів, з яких формуватимемо зображення та функцію, яка ці символи повертатиме. Давайте вже згенеруємо наш арт.

Чудово! Наш арт готовий. Залишилося лише показати його користувачеві.