PHP

Делаем быстрые и красивые превьюшки

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


Сравнение способов создания превьюшек

Для тестов была взята фотография размером 3468 х 2736 пикселов, глубина цветности 24 бита. Цель - разными способами сделать из нее превьюшку размером 200 x 150 пикселов и сохранить результат в файл JPG с наилучшим качеством. Тестовые фрагменты кода максимально облегчены, все размеры и названия файлов захардкодены прямо в исходники. Время выполнения тестов и объем занятой памяти соответствуют моему ноутбуку, эти значения приведены только для сравнения, так что не удивляйтесь, если ваши цифры будут отличаться.

Самый быстрый способ создать превьюшку с изменением размера изображения - функция PHP imageCopyResized. Тестовый код приведен ниже, результат можно посмотреть на первой картинке. Хоть скорость и максимальная, но результат оставляет желать лучшего: превьюшка получилась зернистой. Размер файла превьюшки получился около 39 килобайт.
$im=imageCreateFromJPEG('image.jpg');
$tn=imageCreatetrueColor(200,150);
 
// Изменить размер исходного изображения до размера превьюшки
imageCopyResized($tn,$im,0,0,0,0,200,150,3468,2736);
imageDestroy($im);
 
// Сохранить результат в файл
imageJPEG($tn,'resized.jpg',100);
imageDestroy($tn);

Использование функции PHPimageCopyResampled дает на выходе самый красивый результат, превьюшка сглаженная, никаких выбивающихся пикселов и артефактов. Но какой ценой это было достигнуто! Изменение размера изображения и его обработка заняли более 3 секунд. Размер файла превьюшки получился минимальный - около 31 килобайта. Тестовый код приведен ниже.
$im=imageCreateFromJPEG('image.jpg');
$tn=imageCreatetrueColor(200,150);
 
// Изменить размер исходного изображения до размера превьюшки
imageCopyResampled($tn,$im,0,0,0,0,200,150,3468,2736);
imageDestroy($im);
 
// Сохранить результат в файл
imageJPEG($tn,'resampled.jpg',100);
imageDestroy($tn);

Теперь попробуем хитрый комбинированный способ, который объединяет в себе оба вышеописанных способа. Хитрость заключается в том, чтобы сперва быстро изменить размер первоначальной картинки функцией imageCopyResized до такого размера, когда изображение еще не будет сильно деформировано, а затем выполнить доводку полученного промежуточного изображения до размера превьюшки функцией imageCopyResampled. Результат однозначно радует: скорость выполнения кода приближена к первому примеру, а качество полученного изображения почти аналогично второму. Можете сравнить второй и третий примеры на картинке. Оставшаяся небольшая зернистость наоборот идет на пользу, создавая некоторый эффект резкости. Размер файла превьюшки получился около 33 килобайт, то есть опять же максимально приближено к изображению лучшего качества. Но на создание промежуточного изображения тратится дополнительная память, поэтому не забывайте в реальном приложении вовремя освобождать ненужные ресурсы.
$im=imageCreateFromJPEG('image.jpg');
$ds=imageCreatetrueColor(600,450);
 
// Изменить размер исходного изображения до промежуточного
imageCopyResized($ds,$im,0,0,0,0,600,450,3468,2736);
imageDestroy($im);
 
$tn=imageCreatetrueColor(200,150);
// Изменить размер промежуточного изображения до размера превьюшки
imageCopyResampled($tn,$ds,0,0,0,0,200,150,600,450);
imageDestroy($ds);
 
// Сохранить результат в файл
imageJPEG($tn,'combined.jpg',100);
imageDestroy($tn);

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

К чему это я все затеял? Да просто опробовал еще одну возможность оптимизации. В галерее домашней странички Васи Пупкина разница между 3 и 0.6 секундами погоды не сделает, а в высоконагруженных проектах, и особенно если требуется создавать изображения "на лету", любой выигрыш во времени будет ощутим.
Теги:
imageCopyResized, imageCopyResampled, превью
Добавлено: 14 Сентября 2013 10:10:05 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...