Работа с phpThumb



Не многие задумывались, что вместе с MODX Revolution поставляется и phpThumb. Это, фактически, единственная и самая крутая библиотека для работы с изображениями на PHP.

В MODX принято работать с ней через сниппет phpThumbOf, однако у него есть существенные недостатки, например серьёзные тормоза и странное кэширование. Поэтому, верным способом будет работа с библиотекой напрямую.

При разработке "Файлохранилища" мне пришлось покопаться в том, как устроен phpThumb и как он интегрирован в MODX, в результате чего появился универсальный рецепт использования этой библиотеки для генерации изображений.

Заодно решил известную проблему с генерацией уменьшенной копии, с обрезкой из левой верхней части картинки.

Запуск phpThumb

Предлагаю универсальный скрипт, который может запускаться как снаружи MODX, так и в качестве сниппета.
<?php
if (!isset($modx)) {
	define('MODX_API_MODE', true);
	require 'index.php';	// Если запускаем снаружи - тут надо указать путь к файлу в корне сайта

	$modx->getService('error','error.modError');
	$modx->setLogLevel(modX::LOG_LEVEL_ERROR);
	$modx->setLogTarget('FILE');
}

$src = MODX_BASE_PATH.'img.jpg';	// Исходник
$dst = MODX_BASE_PATH.'img_thumb.jpg';	// Уменьшенная копия

$params = array(
	'w' => 300	,		// Ширина
	'h' => 176,		// Высота
	'bg' => 'ffffff',		// Фон
	'q' => 95,			// Качество в %
	'zc' => 'TL',		// Обрезка, TL - это Top Left, есть еще C - center, BR - Bootom Right  и т.д.
	'f' => 'jpg',		// Формат изображения
);

// Подключаем обёртку MODX, которая выставит системные настройки в класс phpThumb
$phpThumb = $modx->getService('modphpthumb','modPhpThumb', MODX_CORE_PATH . 'model/phpthumb/', array());

// Указываем исходник
$phpThumb->setSourceFilename($src);

// Выставляем параметры
foreach ($params as $k => $v) {
	$phpThumb->setParameter($k, $v);
}

// Генерируем уменьшенную копию
if ($phpThumb->GenerateThumbnail()) {
	// Выводим готовое изображение сразу на экран
	//return $phpThumb->OutputThumbnail();
	
	// Или сохраняем в файл
	if (!$phpThumb->renderToFile($dst)) {
		$modx->log(modX::LOG_LEVEL_ERROR, 'Could not save rendered image to'.$dst);
	}
}
else {
	// Если возникла ошибка - пишем лог работы в журнал MODX
	$modx->log(modX::LOG_LEVEL_ERROR, print_r($phpThumb->debugmessages, 1));
}
Этот скрипт прекрасно работает, обрезает и уменьшает изображения за исключением одного момента — обрезка идёт всегда по центру рисунка. Причем, зависит это не от phpThumb, а от сервера.

ImageMagick

phpThumb сам не умеет конвертировать изображения, он запускает один из модулей PHP: phpGD2 или ImageMagick.

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

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

Устанавливаем его на сервер, настроенный по этой заметке:
sudo apt-get install imagemagick php5-imagick
Перезапускаем php5-fpm:
sudo service php5-fpm restart
Смотрим в phpinfo(), что ImageMagick подключен.

Проверяем работу скрипта и ничего не меняется!

А дело в том, что на моём сервере (и многих других) отключены функции exec, system, shell_exec и passthru, через которые phpThumb пытается выяснить версию установленного ImageMagick, а потом и запустить его на конвертацию.

Понять это можно, если поглядеть в лог работы:
[2013-01-27 10:50:30] (ERROR @ /test.php) Array
(
    [0] => phpThumb() v1.7.9-200712090829 in file "phpthumb.class.php" on line 216
    [1] => setSourceFilename(/var/www/static/www/img.jpg) set $this->sourceFilename to "/var/www/mysite/www/img.jpg" in file "phpthumb.class.php" on line 243
    [2] =>   file_exists() = 0 in file "phpthumb.class.php" on line 1101
    [3] => is_executable() = 0 in file "phpthumb.class.php" on line 1102
    [4] => ImageMagickThumbnailToGD() aborting because cannot find convert in $this->config_imagemagick_path (), and `which convert` returned () in file "phpthumb.class.php" on line 1131
    [5] => $AvailableImageOutputFormats = array(text;ico;bmp;wbmp;gif;png;jpeg) in file "phpthumb.class.php" on line 884
ImageMagickThumbnailToGD() aborting выглядит нехорошо, правда?

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

Результат работы phpThumb с параметром zc = TL:
  • Модуль phpGD2
  • Модуль ImageMagick
Не забывайте, что всегда можно проверить, какой способ используется в логе $phpThumb->debugmessages.
27 января 2013, 11:00    Василий Наумкин   G+  
17    10165 0

Комментарии (17)

  1. СикретНаме 31 января 2013, 12:58 # 0
    1. Я так понимаю, что на обычном виртуальном сервере функцию не включить?
    2. ThumbOf иThumb чем существенно различаются, что-то не нашёл в Рунете?
    1. Василий Наумкин 31 января 2013, 13:13 # 0
      Надо смотреть на хостинг, далеко не везде их вообще отключают.

      phpThumb — библиотека для работы с изображениями.
      phpThumbOf — сниппет MODX для ресайза и кэша изображений с помощью phpThumb.
    2. Александр Котлов 07 февраля 2013, 15:30 # 0
      Скрипт очень приятный и удобный. Но есть пичаль, про которую я уже как-то тему создавал, но еще тут на всякий случай спрошу. Ни скрипт ни phpthumbof хочет сохранять миниатюру с ошибкой —
      (ERROR @ /index.php) Could not save rendered image to/hosting2/bikes/public_html/images/MY13_HP_road_report_v1.thumb.jpg
      Права на каталог 777, и все идеи куда копать у меня кончились(

      Файл создается, но пустой.
      1. Василий Наумкин 07 февраля 2013, 15:33 # 0
        А если туда же попробовать file_put_contents()?

        100% с парвами что-то.
      2. Александр Котлов 07 февраля 2013, 15:49 # 0
        Туда же тоже не хочет(

        Придется хостинг менять.
        1. Василий Наумкин 07 февраля 2013, 15:58 # 0
          Задай вопрос в поддержку, что за нафиг?

          Если что, хостинги тут.
        2. Александр Котлов 07 февраля 2013, 16:12 # 0
          Спасибо за ссылку, но переду на hoster.by — у меня там с десяток сайтов разных хостится и ни разу никакаих проблем. А с остальными хостингами в зоне бай — постоянные и всегда в самый не подходящий момент. Так что ну его нафиг. Не картинки так еще что-нибудь потом вылезет.

          Есть еще Active.by — вообще отдельная история, там стоит хоститься только если ты любишь латексные костюмы, боль и удары плетки — отличным дополнением станет) Кстати, там в антихостинг его можно смело добавлять — медленный, с отвратительной панелью, корявой поддержкой и страшными глюками с половиной компонентов и особенно с картинками.
          1. Andrei Kulazhenko 07 февраля 2013, 16:43 # 0
            Лично у меня проблем с Active.by особенных никогда не было. Единственное, что я делаю, прописываю в htaccess следующие правила:

            #active.by instructions
            php_flag eaccelerator.enable 0
            php_flag eaccelerator.optimizer 0
            SetEnv force-response-1.0 1
            SetEnv downgrade-1.0 1
            + у Active отличная техподдержка, чего я, при всем желании и уважении, не могу сказать о саппорте тутбаевского hoster.by. Хотя у hoster.by — вполне вменяемый и нормальный рабочий виртуальный хостинг. В общем, это вопрос личного выбора. Но active.by я бы точно не заносил в черный список.
            1. Александр Котлов 07 февраля 2013, 17:37 # 0
              Может конечно мне одному так не повезло)
              1. Александр Котлов 07 февраля 2013, 17:49 # 0
                Тем не менее, полгода назад имело место — частично не работающая основная панель управления active.by (в частности что касается переноса домена). Панель управления хостингом — ipsmanager, крайне мне не удобный. Поддержка тупила.
                1. Жуковский Антон 07 февраля 2013, 19:36 # 0
                  Мне, выходит, повезло. За год ни разу не обращался в поддержку. С проблемой картинок тоже столкнулся, но быстро нашел на modx.com совет отключить eaccelerator. Админка Revo, кстати, просто летает.
                  Жуткую панель управления обновили. Так что буду продлевать еще на год и купил подписку на activecloud.ru (то же самое, только в РФ), чтобы перенести российские сайты. Дополнительный плюс — партнерка, для РФ можно 50% стоимости компенсировать. SSH опять же бесплатный.
                  1. Василий Наумкин 07 февраля 2013, 20:47 # 0
                    Linode платит $ 20 за каждого реферала, который пользуется их услугами 3 месяца.

                    Ну это я так, к слову.
                2. Владимир 11 июля 2013, 23:39 # 0
                  Доброго дня! Василий, ведь у тебя размещены сайты в том числе на Timeweb (сайт о фитнесе, как я помню ты упоминал его в данном блоге ).
                  На хостинге Таймвеб судя по php info:
                  imagick module enabled
                  imagick module version 3.0.1
                  imagick classes Imagick, ImagickDraw, ImagickPixel, ImagickPixelIterator
                  ImageMagick version ImageMagick 6.6.1-2 2010-07-06 Q16 www.imagemagick.org
                  Т.е. должно все работать без проблем? Не сталкивался с работой ImageMagick именно на Timeweb?
                  Спасибо.
                  PS Вот то же решение предлагается www.darkstardesign.com/resources/phpthumbsup и то же для ресайза ImageMagick используется.
                  1. Володя 12 июля 2013, 00:27 # 0
                    у меня помню проблема была на timeweb заставить обрабатывать картинки через GD2. Так что на timeweb Imagick работает… все нормально
                    1. Василий Наумкин 12 июля 2013, 03:14 # 0
                      Не сталкивался.

                      Если там есть ImageMagick, и доступ к нему из консоли — всё должно работать нормально.
                    2. Boris Akimenko 12 июля 2013, 16:26 # 0
                      Василий, для меня очень актуальна тема генерации PNG c прозрачным фоном в минишоп-2.
                      На хостинге можно штатными средствами подключить imagic (отметить чекбокс :) ).
                      Что и как нужно изменить в настройках, чтобы генерились PNG с прозрачным фоном? Исходные изображения, разумеется, тоже с прозрачным фоном загружаю.
                      Спасибо!
                      1. Илья Уткин 01 марта 2017, 14:06 # 0
                        Для тех, кто не хочет включать эти опасные функции, нашёл небольшой костыль. Нужно в файле core/model/phpthumb/phpthumb.class.php в методе ImageMagickVersion поменять последнюю строчку (у меня это 1499 строчка файла) на слудующее:

                        return '6.4.9'; //$versionstring[intval($returnRAW)];

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