Мініатюри на PHP Сайт Романа Парпалака

Статтю написано для інтернет-видання Hostinfo.ru.

Під час розробки та обслуговування сайтів часто виникає необхідність створення мініатюр — зменшених копій зображень. У тексті сторінки замість великої картинки можна помістити таку копію, яка є посиланням на вихідний файл. Робота фотоальбомів та галерей зображень, менеджерів файлів у CMS немислима без автоматичного створення мініатюр. Ми розберемо скрипт, що генерує подібні мініатюри, і на його прикладі познайомимося з деякими можливостями PHP для роботи із зображеннями.

PHP обробляє зображення за допомогою бібліотеки GD. Майже на всіх хостингових майданчиках цю бібліотеку встановлено. Якщо раптом вам не пощастило, зверніться до технічної підтримки вашого хостингу. У нашому скрипті використовуватимемо функції, що з'явилися в бібліотеці GD версії 2.0.1.

Спочатку визначимо вимоги, яким відповідатиме генератор мініатюр. Він повинен створювати зменшені копії зображень, збережених у форматах GIF, JPEG та PNG. Якщо вихідне зображення мало прозорість, мініатюра повинна зберігати прозорість. Також не слід нехтувати безпекою та швидкодією.

Ми визначились із тим, чого хочемо. Тепер можна розпочинати програмування. Вихідний файл і розміри кінцевої картинки передаватимемо через URL:

Для вказівки розміру мініатюри передбачимо два способи. Можна встановити параметр max_size , тоді розміри зображення на виході будуть пропорційні вихідним, але зміняться так, що його можна буде вписати в квадрат розміром max_size*max_size . Можна також задавати розмір зображення на виході безпосередньо у параметрах width і height (за відсутності однієї з них картинка буде стиснута пропорційно).

Домовимося, що скрипт будегенерувати мініатюри для файлів, розташованих у кореневій директорії веб-сервера або піддиректоріях. Для запобігання несанкціонованому доступу до інших файлів умовимося, що параметр file URL задає шлях до файлу від кореневої директорії і починається зі знака '/' .

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

Для початку отримаємо інформацію про вихідне зображення:

Функція getimagesize повертає масив $image_info , що містить значення деяких характеристик зображення:

  • $image_info[0] і $image_info[1] — це ширина та висота зображення,
  • $image_info[2] — константа виду IMAGETYPE_XXX , яка визначає формат файлу (наприклад, IMAGETYPE_GIF або IMAGETYPE_JPEG ),
  • $image_info[3] — рядок 'height="yyy" w ', призначений для вставки в тег
  • $image_info['mime'] — mime-тип, який відповідає файлу.

Залежно від mime-типу ми будемо викликати свою функцію для відкриття та завантаження зображення: imagecreatefromGIF, imagecreatefromJPEG або imagecreatefromPNG.

Тепер потрібно визначити розмір мініатюри, якщо вони не задані явно.

Функція imagecreatetruecolor створює повнокольорове зображення вказаного у параметрах розміру та повертає його ідентифікатор. imagealphablending дозволяє вибрати один із двох способів роботи з альфа-каналом. Якщо другий параметр цієї функції встановлений у true, то при малюванні напівпрозорим кольором нове зображення частково накладається на старе. Якщо ж він встановлений у false, відбувається повне заміщення пікселів вихідного зображення на пікселі нового. Зрозуміло, що нам потрібний саме другий режим. Функція imagesavealpha необхідна для того, щоб при виклику функції imagePNG альфа-канал був збережений у результуюче зображення.

Оскільки хочемо зберегти прозорість вихідного зображення, мініатюру доводиться зберігати у форматі PNG. Функція imagePNG виводить у браузер зображення із зазначеним ідентифікатором.

На цьому роботу над скриптом можна було б завершити. Справді, зібравши наведений вище код в один файл (при цьому текст функції необхідно помістити на самому початку) і розмістивши в кінці оператори

ми матимемо працездатний скрипт.

Слід зазначити, що функція header встановлює заголовки відповіді сервера, і в цьому випадку вона вказує на тип (картинка PNG) даних, що повертаються. Заголовок Content-Type, як і будь-які заголовки, необхідно встановлювати до операцій виведення. Однак при роботі з графікою встановлювати цей заголовок потрібно якомога нижче, оскільки повідомлення про помилки, що з'являються після встановлення Content-Type: image/png не виводитимуться у браузер.

Подивимося на написаний код. Щоразу при зверненні до сторінки з мініатюрами сервер створює їх заново, що з великої відвідуваності сайту призведе до значної навантаження на сервер. Звичайним виходом у цій ситуації є кешування - збереження результатів роботи скрипта у файли.

Кешування динамічної інформації має сенс, якщо вона оновлюється значно рідше, ніж відбуваються звернення до сторінки, де вона відображається. Є ситуації, коли не потрібно кешувати картинку, що генерується нальотом. Наприклад, лічильник відвідувань, який для кожного завантаження сторінки повинен показувати, очевидно, різні значення. Однак у більшості випадків зображення, для яких створюються мініатюри, змінюються порівняно рідко, у таких випадках кешування виправдане.

Розглянемо, як зробити кешування мініатюр. Ми зберігатимемо їх у файли з іменами, що є md5-хешами іменфайлів з вихідними зображеннями, наприклад, у папку img_cache у кореневій директорії веб-сервера.

Визначимо час зміни файлу із кешем, якщо він існує.

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

Наша функція make_thumbnail відразу надсилає мініатюру браузеру. Однак попередньо потрібно зберегти мініатюру до кешу. Тому ми не повинні викликати функцію make_thumbnail безпосередньо, так як це зробили вище. Потрібно перехопити виведення за допомогою буферизації. Після виконання ділянки коду між ob_start і ob_end_clean у змінній $thumbnail будуть утримуватися дані, які функція imagePNG збиралася відправити браузеру, а змінної $thumb_size — розмір даних.

Варто зазначити, що в директорії img_cache залишатимуться зменшені копії віддалених картинок. Тому за масштабної зміни структури сайту кеш потрібно очищати вручну.

Залишилося встановити заголовки та відправити мініатюру браузеру.

Тепер потрібно зібрати ділянки коду в один файл, наприклад preview.php (розмістивши функцію make_thumbnail на початку) і помістити його в кореневу директорію веб-сервера. Там же потрібно створити директорію img_cache та встановити права доступу до неї у 777. Все готово!

Нехай зображення pict.jpg лежить у директорії images, тобто його можна вставити на сторінку за допомогою коду . Тоді код, що містить мініатюру, набуде вигляду

мініатюри
.

Зрозуміло, у цьому скрипті можна реалізувати інші можливості. У статті було закладено основу, а іншезалежить від вашої фантазії.