Инфосфера
Генерация превьюшек

Генерация превьюшек

В базе данных Инфосферы хранится несколько тысяч самых разных изображений, которые используются в самых разных частях сайта. Одни картинки открываются по ссылкам, другие картинки используются для превьюшек в списках статей, третьи − для карточек внутри статей, четвёртые − для галерей и мини-галерей. Поэтому созданием уменьшенных копий («превьюшек») изображений Инфосфера занимается сама, автоматически.

Программисту

Рассмотрим простой пример − изображение «Главные герои сериала».

Изображение в оригинальном размере

Превьюшка с шириной 250 пикселов, высота подбирается автоматически:

Ширина 250 пикселов

Превьюшка фиксированного размера, 120×90 пикселов:

120×90 пикселов

Квадратная превьюшка 100×100 пикселов:

100×100 пикселов

Маленькая превьюшка для списка статей, 80×50 пикселов:

80×50 пикселов

Все превьюшки сохраняются в формате PNG-24, чтобы максимально сохранить качество картинки и цветопередачу. Размер файла при этом получается чуть больше, чем для формата JPG (с артефактами), но оно того стоит.

Обратите внимание на два последних примера − 100×100 и 80×50. И там и там соотношение сторон у превьюшки не совпадает с соотношением сторон у исходного изображения, поэтому Инфосфера вынуждена отрезать часть, чтобы сохранить правильные пропорции у картинки. В первом случае приходится обрезать по ширине, и Инфосфера отрезает равные полоски слева и справа, спасая центральную часть изображения. Во втором же случае приходится обрезать по высоте, и Инфосфера отрезает лишь одну полоску снизу, не трогая верхнюю часть изображения. Таким образом, в любом случае сохраняется «центральная верхняя» часть картинки, где обычно и расположено всё самое интересное.

Возможны ситуации, когда такой подход даёт не очень хорошие результаты. Пример − иллюстрация СамуСа «Приятные Воспоминания». Если действовать по стандартному правилу, то на квадратной превьюшке будет виден лишь кусочек головы Лилы. На такой экзотический случай в Инфосфере предусмотрена возможность особого выбора сохраняемой области для отдельных картинок.

Как это работает

Как это работает

Обработка изображений на стороне веб-сервера − относительно долгий и ресурсоёмкий процесс, который желательно выполнять как можно реже. Поэтому все сгенерированные превьюшки сохраняются в отдельном каталоге «cutepics» для повторного использования. Когда движку необходимо отобразить «на экране» очередную превьюшку к какой-либо картинке, он действует по следующему алгоритму:

  • Зная путь к оригинальному изображению и требуемые размеры превьюшки, вычисляет путь к превьюшке.
  • Проверяет, существует ли уже по этому пути файл, т.е. была ли превьюшка уже создана раньше.
  • Если существует − то алгоритм не делает ничего, просто возвращает этот путь.
  • Если же нет − только тогда запускается долгий процесс обработки изображения и сохранения превьюшки в виде файла.

Для лучшего результата учитывается ещё пара хитростей.

Хитрость 1. При вычислении пути к превьюшке никак не учитывается содержимое файла с исходным изображением. Путь вычисляется, исходя лишь из трёх параметров: путь к оригинальному изображению (например, "/images/common/FuturamaTrio.png"), требуемая ширина и требуемая высота. Это позволяет рассчитать путь к превьюшке, не открывая никаких файлов и не читая с диска никаких дополнительных данных, что даёт солидный прирост к быстродействию.

Хитрость 2. Бывают ситуации, когда на сервере одновременно выполняются два одинаковых скрипта (запроса), и оба бросаются генерировать превьюшки к одним и тем же изображениям. Получается нехорошая схема:

  • Скрипт А убедился, что нет превьюшки к картинке N.
  • Скрипт Б убедился, что нет превьюшки к картинке N.
  • Скрипт А начал генерировать превьюшку к картинке N.
  • Скрипт Б начал генерировать превьюшку к картинке N.
    ...
  • Скрипт А закончил генерировать превьюшку, сохранил файл.
  • Скрипт Б закончил генерировать превьюшку, перезаписал тот же самый файл.

Получается, что оба скрипта заняты одним и тем же делом и тратят ресурсы сервера впустую. В особенно тяжёлом случае таких скриптов-запросов может быть не два, а больше. Поэтому алгоритм Инфосферы действует чуть хитрее:

  • Вычисляет путь к превьюшке.
  • Убеждается, что по этому пути не существует файла, т.е. превьюшка ещё не была создана.
  • Сразу после этого − создаёт по этому пути фиктивный файл нулевой длины.
  • И лишь после этого приступает к медленному процессу обработки изображения.

В случае одновременной работы двух скриптов, скрипт А убедится, что превьюшки нет, и тут же создаст фиктивную, пустую превьюшку. Скрипт Б, увидев созданный файл, пусть и пустой, уже не приступит к обработке того же самого изображения. Когда скрипт А завершит свою работу, он заменит фиктивный файл настоящей превьюшкой, и посетитель сайта сможет её загрузить и увидеть.

Вычисление пути к превьюшке

Вычисление пути к превьюшке

Последний вопрос, который хотелось бы рассмотреть − это вычисление пути к превьюшке. Задача алгоритма − по известному пути к исходному изображению и требуемым размерам превьюшки (ширина, высота) вычислить строку-путь. Посмотрим ещё раз на пример в начале статьи, и выпишем отдельно исходный путь к «большой» картинке и все сгенерированные пути к превьюшкам:

ПримерПуть
Исходное изображение/images/common/FuturamaTrio.png
Превьюшка с шириной 250 пикселов/images/cutepics/w250/9d945b850914.png
Превьюшка 120×90 пикселов/images/cutepics/120x90/9d945b850914.png
Квадратная превьюшка 100×100 пикселов/images/cutepics/100x100/9d945b850914.png
Маленькая превьюшка 80×50 пикселов/images/cutepics/80x50/9d945b850914.png

Видно, что все конечные пути выглядят одинаково: общий префикс ("/images/cutepics/"), затем имя каталога, означающее размеры превьюшек, затем имя файла, причём у всех превьюшек к одной и той же картинке имена файлов одинаковые (9d945b850914.png).

Имя файла превьюшки − это первые 12 символов от MD5-суммы исходного пути к картинке. Подчёркиваю, именно пути, т.е. строки "/images/common/FuturamaTrio.png", а не содержимого файла. По умолчанию MD5 даёт сумму длиной в 32 символа, но такое длинное имя нам не нужно, поэтому оставляем первые 12. Степень уникальности суммы при этом остаётся более чем достаточной даже для базы в миллиарды изображений.

Наконец, имя каталога, в котором сохраняется файл, вычисляется из требуемых размеров превьюшки. Если указана только ширина, а высота равна 0, то каталог имеет вид "w<ширина>". Если указана только высота, а ширина равна 0, то каталог имеет вид "h<высота>". Если указана и ширина, и высота (обе величины не равны 0), то каталог имеет вид "<ширина>x<высота>". Всё это наглядно видно на примерах выше.

Если из базы данных Инфосферы требуется удалить изображение, то необходимо также удалить и все превьюшки к нему. В этом случае, зная путь к удаляемой картинке, вычисляется лишь имя файла (9d945b850914.png). Алгоритм циклически пробегает по всем подкаталогам каталога "/images/cutepics/", и если в подкаталоге обнаружен файл с таким именем − он удаляется.

Сложные вложенные хешированные пути к файлам, как в движках типа Smarty или MediaWiki, не используются. Все превьюшки одного размера хранятся в пределах одного каталога. Если у вас в базе не миллион изображений, от сложных путей типа "/images/thumbs/0/00/00ab/..." больше мороки, чем пользы.