Язык страницы:

Thumbnails: Теория и практика создания миниатюрных изображений

Введение

Интернет позволяет пользователям публиковать собственные графические изображения, например, созданные с помощью компьютера, или фотографии, выполненные цифровыми камерами. Чаще всего эти работы выполнены на высоком художественном уровне и такие файлы значительны по размеру (как геометрически, так и в объеме хранимой информации). Современные серверные технологии позволяют создать уменьшенные копии изображений для их предварительного просмотра.

В англоязычной литературе для обозначения уменьшенных копий оригиналов существуют два термина - preview и thumbnail. Ни одно их не имеет адекватного перевода в русскоязычной литературе кроме более близкого по смыслу термина - миниатюра. В дальнейшем, в данной статье будет использоваться именно это слово и производные от него (с целью исключения повторов в тексте) либо близкие по смыслу выражения.

Обозначения, принятые в статье

Все способы создания миниатюр предполагают выполнение предварительных арифметических операций для вычисления начальной точки копирования фрагмента оригинального изображения, размеров копируемой области. На протяжении данной работы будут использоваться следующие обозначения (выраженные в пикселях):

  • W, H - ширина и высота оригинального изображения, соответственно;
  • X, Y - координаты начальной точки копирования (левого верхнего угла);
  • width, height - ширина и высота миниатюры, соответственно;
  • R, ratio - отношения меньшей стороны к большей стороне прямоугольников оригинала и миниатюры, соответственно;
  • Ww - отношение ширины большого прямоугольника к ширине маленького;
  • Hh - отношение высоты большого прямоугольника к ширине маленького.

Методы создания миниатюр

Основное место использования миниатюр - тематически структурированные коллекции и фото-галереи, где на главных страницах разделов выводятся уменьшенные копии изображений со ссылкой на оригинал. Для более подробного ознакомления с работой пользователь может посмотреть полную версию оригинала.

Размер миниатюры устанавливается администратором фото-галереи и имеет фиксированный размер, соответствующий общему дизайну. В настоящее время существует два наиболее распространенных способа создания миниатюр:

  • пропорционально уменьшенная копия;
  • вырезание некоторого фрагмента оригинала.

Каждый из способов имеет свои достоинства и недостатки. Например, миниатюры, созданные по первому способу позволяют увидеть миниатюрную копию цельного изображения, но могут испортить общий дизайн вследствие различной ориентации изображений (книжная или альбомная). А второй способ не дает полного представления о представленном изображении.

Однако можно выделить еще один, третий способ создания миниатюр, который можно представить как комбинацию первых двух. В данной статье будут рассмотрены все возможные способы.

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

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

Метод максимального сжатия

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

  1. определить большую сторону прямоугольника первоначального изображения;
  2. вычислить отношение R;
  3. вычислить меньшую сторону прямоугольника миниатюры путем умножения отношения R и большей стороны.

На псевдокоде это будет описано так:

if W > H
then
    height = H * width / W
else
    width  = W * height / H
end if

Таким образом, будут определены размеры будущей копии. Это необходимо, для создания уменьшенной копии, которая будет вписана в заданные рамки миниатюры без искажений. Дальнейшие действия заключаются в использовании соответствующих графических средств на стороне сервера по преобразованию изображений. Следующий пример иллюстрирует преобразование, реализованное на PHP (в предположении, что исходное изображение уже загружено в программу - переменная $srcImage, и его размеры получены в $width и $height):


Описание данного метода завершим рисунком, иллюстрирующим данный подход.

Рисунок 1. Метод максимального сжатия

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

Следующий код на PHP иллюстрирует данный подход:


При всем многообразии начальных координат источника копирования автор считает, что источник копии может иметь только девять фиксированных позиций:

  1. центральная;
  2. крайние левая и правая стороны;
  3. крайние верхняя и нижняя границы;
  4. углы прямоугольника.

Соответственно, можно говорить о вертикальном и горизонтальном выравнивании. Алгоритм вычисления координат источника описан на псевдокоде:

if horizontal align = left
then
    X = 0
else if horizontal align = right
    X = W - width
else
    X = (W - width) / 2
end if

if vertical align = top
then
    Y = 0
else if vertical align = bottom
    Y = H - height
else
    Y = (H - height) / 2
end if

Рисунок 2. Фрагмент целого

Метод минимального сжатия

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

Рисунок 3. Метод минимального сжатия

В общем случае, одна из сторон большого прямоугольника должна быть вписана в соответствующую сторону малого. При этом коэффициент сжатия (масштабирования) должен быть минимален. Этого легко добиться сравнивая соотношения соответствующих сторон - большее соотношение определяет сторону, которое будет обрезано при масштабировании.

Ww = W / width
Hh = H / height
if Ww > Hh
then
    W = width * Hh
    X = ...
else
    H = height * Ww
    Y = ...
end if

Здесь используется алгоритм вычисления начальных координат источника фрагмента, идентичный описанному ранее алгоритму.

Так как одна из сторон большего прямоугольника будет полностью вписана в соответствующую сторону меньшего, а другая - обрезана, то здесь тоже можно говорить о выравнивании - или вертикальном, или горизонтальном.

Пропорциональное сжатие в процентах

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

  1. в проектах, где жестко заданы размеры исходного изображения (фиксированная ширина и/или фиксированная высота);
  2. при преобразовании очень больших изображений, когда создание миниатюры в один проход может привести к переполнению памяти.

При этом следует иметь в виду, что пропорции относятся к соответствующим сторонам исходного изображения и результирующего.

Иллюстрация создания миниатюр на PHP

В этом разделе будет подробно рассмотрен реализованный на PHP в рамках объектно-ориентированного похода модуль Thumbnail на основе описанного алгоритма.

Основным публичным методом является метод output(). В своей работе он использует результат работы метода render(), определяет приемник для вывода изображения (браузер или файл на сервере):


Обязательный аргумент функции - имя файла исходного изображения. По умолчанию, метод выводит результирующее изображение в браузер. Если будет указан второй аргумент - имя выходного файла, будет создан файл. Третий, аргумент метода, ассоциативный массив, содержит необязательные параметры обработки изображений. По умолчанию, используются собственные установки - методом максимального сжатия создается миниатюра в формате PNG размером 150х150 пикселей.

Логика класса по созданию миниатюр реализована в методе render(), который загружает файл изображения в память, определяет размеры исходного изображения, рассчитывает размеры будущей миниатюрной копии, создает новое изображение и возвращает ссылку на него в случае успешного выполнения. При этом данный метод использует вспомогательные методы для загрузки объекта и расчета необходимых переменных:


Данный метод учитывает особенности работы PHP с графическими изображениями - при отсутствии функций библиотеки GD для работы с изображениями высокого качества imagecreatetruecolor и imagecopyresampled используются их менее качественные аналоги imagecreate и imagecopyresized.

Опции обработки изображения

При необходимости, можно указать аргумент $options (ассоциативный массив параметров - третий аргумент метода output() и второй - метода render()) для реализации собственной обработки изображений. Для этого необходимо лишь указать требуемые опции

  1. width - ширина миниатюры в пикселях (целое положительное число, по умолчанию 150);
  2. height - высота миниатюры в пикселях (целое положительное число, по умолчанию 150);
  3. method - метод обработки - максимальное/минимальное сжатие, вырезание фрагмента целого(целое число, по умолчанию максимальное сжатие);
  4. percent - масштабирование в процентах от оригинала (положительное вещественное число на интервале от 0 до 1, по умолчанию 0);
  5. halign - вертикальное выравнивание (допустимые значения 0 - по центру, < 0 - выравнивание по верхнему краю, > 0 - выравнивание по нижнему краю, по умолчанию - 0);
  6. valign - горизонтальное выравнивание (допустимые значения 0 - по центру, < 0 - выравнивание влево, > 0 - выравнивание вправо, по умолчанию - 0);
  7. type - тип выводимого изображения (IMAGETYPE_PNG или IMAGETYPE_JPEG, по умолчанию - IMAGETYPE_PNG).

Обработка ошибок

Никто не застрахован от ошибок, поэтому модуль реализует минимальную обработку типовых ошибок (неверный формат входных данных, невозможность инициализации графического формата) посредством генерации пользовательских сообщений встроенной функцией user_error.

Ошибки передачи некорректных опций отсутствуют. По мнению автора, эти ошибки должны обрабатываться и корректироваться на уровне приложения до передачи их в модуль.

Вспомогательные методы

Эти методы необходимы для загрузки изображения и расчета координат и размеров области копирования исходного и результирующего изображений.

Методы загрузки изображения из файла - основное их назначение определить источник изображения (файл, строка или образ изображения в памяти)


Метод расчета координат и размеров области копирования исходного и результирующего изображений


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

Предопределенные константы класса

В модуле предопределено несколько констант для управления методом создания миниатюр и выравнивания изображений


Примеры использования

Пример 1. Простое создание миниатюры в браузер

include_once 'includes/Thumbnail.php';

$filename = 'files/image.jpg';
Thumbnail::output($filename);

Пример 2. Простое создание миниатюры в файл

include_once 'includes/Thumbnail.php';

$input_file = 'files/image.jpg';
$output_file = 'files/thumb.jpg';
Thumbnail::output($input_file, $output_file);

Пример 3. Использование собственных параметров (JPEG, 200х200 пикселей)

include_once 'includes/Thumbnail.php';

$filename = 'files/image.jpg';
$options = array(
    'width'  => 200,
    'height' => 200,
    'type'   => IMAGETYPE_JPEG,
);
Thumbnail::output($filename, null, $options);

По умолчанию, из любого изображения создается маленькое изображение в формате PNG. Указывая явно тип можно изменить формат графического потока (в примере - JPEG). Для вывода в браузер второй аргумент установлен в значение null.

Пример 4. Каскадное создание миниатюры из очень большого изображения


Последний пример стоит разобрать более подробно.

Вначале из исходного изображения вырезается центральный прямоугольник, стороны которого составляют ровно половину оригинала (50%). Затем, за второй проход из полученного промежуточного изображения создается обычная уменьшенная копия (стандартные размеры 150х150 пикселей). После этого полученное окончательное изображение отображается в браузере.

Заключение

Хотя задача создания миниатюр не самая сложная задача, решаемая разработчиками интернет-приложений, тем не менее, она не всегда решается на должном уровне и в полном объеме. В настоящей статье были разобраны все варианты создания миниатюр, кратко рассмотрены особенности работы с изображениями в PHP.

Методы загрузки и создания реализуют работу с изображениями только в форматах PNG и JPEG. Однако модуль расширяем, и добавить отсутствующую функциональность будет достаточно легко.

Как ни странно, но в богатой коллекции PEAR нет полноценных классов или методов для работы с миниатюрами, хотя существуют пакеты, реализующие отдельные методы обработки изображений (обрезки, масштабирования, поворота и т.д.) Однако описанный модуль может быть с легкостью интегрирован.

Исходные коды и демонстрационные файлы представлены в архиве на googlecode. На странице sourceforge старая (слегка подправленная) копия статьи со ссылками на примеры.

Благодарности

Автор искренне признателен Илье Лебедеву за реальную помощь в публикации данной статьи.


  • Закладки и социальные сети
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на del.icio.us
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Digg
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Furl
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Reddit
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Ask
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на BlinkList
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на blogmarks
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Google
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Ma.gnolia
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Netscape
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на ppnow
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Rojo
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Shadows
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Simpy
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Socializer
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Spurl
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на StumbleUpon
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Tailrank
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Technorati
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Live Bookmarks
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Wists
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Yahoo! Myweb
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на BobrDobr
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Memori
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Faves
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Favorites
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Facebook
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Newsvine
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Yahoo! Bookmarks
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Twitter
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на myAOL
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Slashdot
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Fark
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на RawSugar
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на LinkaGoGo
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Mister Wong
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Wink
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на BackFlip
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Diigo
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Segnalo
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Netvouz
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на DropJack
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на Feed Me Links
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на funP
  • Сохранить "Thumbnails: Теория и практика создания миниатюрных изображений" на HEMiDEMi

Дискуссия

, 2008/10/03 06:33

очень плохое качество сжатия.

как исправить?

, 2008/10/03 21:06

Возможно Ваша версия PHP не поддерживает функцию imagecopyresampled. Возможно надо производить сжатие поэтапно. Возможно Вы пытаетесь сжать очень большое изображение.

Уточните, пожалуйста - Что значит плохое качество?

, 2008/11/06 15:36

2 метод на мой взгляд не очень хорош. На практике столкнулся с тем, что пользователи зачастую грузят изображения с размерами порядка 3000 на 4000 px. А превью нам надо получить 50х50. В итоге на изображении вообще не поймёшь ничего.

Я использую третий метод с небольшим (на мой взгляд) улучшением - для вертикально ориентированных изображений я помещаю вырезаемую область чуть выше (так, чтобы сверху оставалось 1/3 удаляемого, а снизу - 2/3) - обычно значимая часть изображения находится ближе к верху.

Другой способ вычисления размеров изображения - вырезание квадрата (или прямоугольника) из случайного места. Но чтобы было, откуда вырезать, изображение уменьшяется до размеров больших, чем превью, раза в три.

Например, есть картинка 1000 на 10000 px, нужно случайное превью 50х50 px. Уменьшаем исходное изображение так, чтобы меньшая сторона его стала 50*3=150px, а большая соответственно 1500. И из этой области уже случайно вырезаем нужный нам квадратик. Так мы будем уверены, что на нём будет что-то осмысленное.

, 2008/11/07 14:09

Хорошее замечание. Согласен с Вами, что очень большие изображения дадут трудноразличимые мелкие картинки. Попробуйте каскадный метод:

  • уменьшить в половину или втрое;
  • из полученного вырезать половину;
  • полученное уменьшить до 50х50.

Хотя примерно тоже самое делаете и Вы.

Вообще существует черновик второй версии, как статьи так и библиотеки (маленький класс вырос до целой библиотеки, только GD). Но необходимо время на шлифовку. Веб-разработка в настоящее время - хобби. А на хобби времени не хватает.

, 2008/12/05 12:33

Возник вопрос. В моем случае мне необходимо в обязательном порядке получить миниатюру строго заданного размера, поскольку на экран она выдается еще и с указанными в html параметрами width и height. Таким образом, если размер полученной миниатюры отличается от заданных, на экране она все равно изуродуется, даже если само изображение будет пропорциональным. Для себя ввел следующие принципы: 1.Произвожу первичное сравнение размеров изображения с заданными. 2.Вычисляю Ww и Hh. 3. Нахожу «коэффициент ужаса» -параметр, равный отношению max(Ww, Hh)/min(Ww, Hh). На мой взгляд этот параметр определяет степень несоответствия исходного и заданного изображений. Если этот коэффициент превышает 1.25 ,считаю, что без обрезки на экране в моем случае начнется ужас. 4. В этом случае перехожу к предварительной обрезке исходного изображения. Для этого умножаю заданные размеры на min(Ww, Hh). То есть фактически определяю рамку, одна из сторон которой надежно впишется в исходное изображение. Теперь эта рамка должна встать по центру и обрезать исходное изображение. 5.Обрезанный вариант уменьшаю обычным путем и сохраняю в файл. Так, на мой взгляд, должно получиться более-менее приемлемое решение проблемы.

Теперь вопрос: как можно с помощью библиотеки произвести предварительную обрезку исходного изображения по заданной рамке, центрировав ее относительно исходного изображения. Пожалуйста, если можно-код. В общем смысле я и сам понимаю:) Спасибо! Извините за туповатый вопрос.

, http://rapvokzal.com, 2009/01/25 13:02

Очень огорчило что ссылка http://phpmrtgadmin.sourceforge.net/download/demo/thumbnail/ не работает.

, 2009/01/27 15:53

Видимо на sourceforge запретили просмотр каталога. Изменил заключение статьи - добавил правильную ссылку на рабочие примеры и ссылку на архив.

, 2009/01/28 07:26

Всё равно ссылка не работает…

, 2009/01/28 08:41

поправил еще раз

, 2009/01/29 05:25

Спасибо большое! Скачалось :)

, 2009/04/03 10:14

Мне пришлось заняться созданием миниатюрной галлереи. Начал с того, что открыл справочник функций, попытался реализовать всё сам. Когда не вышло, нашёл вашу библиотеку и попытался воспользоваться написанным вами объектом. В обоих случаях происходит одно и то же. Картинка попадает на экран, при некоторых изменениях, но почему-то в виде текста побайтно (видна служебная информация файла jpg, а далее видимо коды пикселей, перекодированных в символы). В первозданном виде ошибка вылетает на 185й строке, не проходя условия функции !headers_sent(). Подскажите пожалуйста, как решить эту проблемму и с чего начинать. Видимо код модуля нельзя считать недействующим, поэтому проблемма в чём-то другом (возможно настройки сервера или совместимость версий).

, 2009/04/03 11:54

Библиотека корректно обработала отправку данных клиенту. Скорее всего Ваш скрипт уже отправил некие данные. Проверьте свои скрипты - возможно где-то присутствует пустая строка или пробел в начале. Удалите их - они препятствуют нормальному выводу картинки. Убедитесь, что Ваш скрипт не производит редирект, например header('Location: …');.

, 2009/05/05 17:05

В фотопечати есть такой термин - кадрирование. Это как раз то, чем мы тут занимаемся. Есть два варианта кадрирования - «кадр целиком» и «кадр в обрез». В первом случае (мы говорим о горизонтальных изображениях) это Ваш «метод максимального сжатия», во втором - некое подобие «фрагмент целого». В фотопечати в первом случае берется высота фотографии, пропорционально сжимается относительно этой высоты и засовывается в изображение необходимого формата (10х15 и тд). Во втором случае - за основу берется ширина фотографии и уменьшается пропорционально - соответственно при превышении необходимых на эскизе размеров фотография обрезается снизу и сверху.

, 2010/02/02 15:41

В связи с актуальностью материала перенес архив на гулокод http://code.google.com/p/php-funs/downloads/list. Демоверсия на sourceforge http://phpmrtgadmin.sourceforge.net/download/demo/thumbnail/theory.html.

articles/thumbnails.txt · Последние изменения: 2010/02/02 15:20 От Ildar Shaimordanov
GNU Free Documentation License 1.2 www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0