MagickWand — одна из библиотек, осуществляющих доступ к пакету программ ImageMagic, для работы с изображениями в PHP. Рассмотрим особенности наложения текста и графики в ней. Говорят, что ImageMagic очень быстрый и дает результат лучшего качества (но не так распространен как GD). За одно проверим это.
Общий код скрипта будет таким:
$new_image = NewMagickWand(); //Создаем экземпляр MagickWand
MagickReadImage($new_image, 'image.png'); //Загружаем в него исходное изображение
$w = MagickGetImageWidth($new_image); //Узнаем его размеры
$h = MagickGetImageHeight($new_image);
/* --- Обработка изображения --- */
MagickSetImageFormat($new_image, 'jpeg');
MagickWriteImage($new_image, 'newimage.jpeg'); //Сохраняем результат
//
ClearMagickWand($new_image); //Удаляем и выгружаем полученное изображение из памяти
DestroyMagickWand($new_image);
Теперь рассмотрим подробнее код обработки изображения. Для примера, наложим текстовый копирайт на фотографию. Это можно сделать несколькими способами:
1. Наложим заранее подготовленное полупрозрачное изображение копирайта с помощью MagickCompositeImage
$watermark = NewMagickWand();
MagickReadImage($watermark, 'copyright.png'); //Загружаем изображение копирайта
$wc = MagickGetImageWidth($watermark);
$hc = MagickGetImageHeight($watermark);
MagickCompositeImage($new_image, $watermark, MW_OverCompositeOp, $w-$wc, $h-$hc); //Накладываем копирайт на исходное изображение
ClearMagickWand($watermark); //Удаляем и выгружаем копирайт из памяти
DestroyMagickWand($watermark);
2. Наложим заранее подготовленное полупрозрачное изображение копирайта с помощью DrawComposite
$watermark = NewMagickWand();
MagickReadImage($watermark, 'copyright.png');
$watermark_drawing = NewDrawingWand(); //Создаем экземпляр DrawingWand для рисунков
DrawSetGravity($watermark_drawing, MW_SouthEastGravity); //Устанавливаем его расположение в правом нижнем углу
DrawComposite($watermark_drawing, MW_OverCompositeOp, 0, 0, 0, 0, $watermark); //Загружаем в него копирайт
MagickDrawImage($new_image, $watermark_drawing); //Объединяем рисунок с исходным изображением
ClearMagickWand($watermark);
DestroyMagickWand($watermark);
ClearDrawingWand($watermark_drawing);
DestroyDrawingWand($watermark_drawing);
В результате этих двух способов получилось следующее:
Время выполнения схоже. В первом случае скачет от 20 до 400мс. Возьмем абстрактное среднее значение 200мс. Во втором случае практически не зависит от величины изображения и других факторов и составило 160мс.
3. Сгенерируем текст копирайта и наложим с помощью MagickAnnotateImage
//Настраиваем текстовое поле
$watermark_drawing = NewDrawingWand();
DrawSetFont($watermark_drawing, 'copyright.ttf');
DrawSetFontSize($watermark_drawing, 12);
DrawSetGravity($watermark_drawing, MW_NorthWestGravity);
//Задаем его цвет
$pixel_wand = NewPixelWand();
PixelSetColor($pixel_wand, 'black');
PixelSetOpacity($pixel_wand, 0.6);
DrawSetFillColor($watermark_drawing, $pixel_wand);
//Создаем и размещаем на исходном изображении текстовую строку
MagickAnnotateImage($new_image, $watermark_drawing, $w-15, $h-8, -90,'© Копирайт');
ClearDrawingWand($watermark_drawing);
DestroyDrawingWand($watermark_drawing);
4. Тоже самое, но с помощью DrawAnnotation
$watermark_drawing = NewDrawingWand();
DrawSetFont($watermark_drawing, 'copyright.ttf');
DrawSetFontSize($watermark_drawing, 12);
DrawSetGravity($watermark_drawing, MW_NorthWestGravity);
DrawRotate($watermark_drawing, -90);
$pixel_wand = NewPixelWand();
PixelSetColor($pixel_wand, 'black');
PixelSetOpacity($pixel_wand, 0.6);
DrawSetFillColor($watermark_drawing, $pixel_wand);
DrawAnnotation($watermark_drawing, 8-$h, $w-15, '© Копирайт'); //Определяем размещение и текст строки.
//Обратите внимание, что после поворота на 90° координаты смещения так же «перевернулись», в отличие от предыдущего варианта
MagickDrawImage($new_image, $watermark_drawing);
ClearDrawingWand($watermark_drawing);
DestroyDrawingWand($watermark_drawing);
В результате этих двух способов получилось следующее:
Надпись немного четче, но это скорее свидетельствует, о том, что фотошоп слишком размыл текст в файле-исходнике для первых способов.
По скорости способы идентичны. Время сильно скачет. Для мелких изображений составляет 20мс и доходит до 300мс в 2560×1600. Возьмем среднее значение 150. Опять же абстрактно.
Вывод: Для вставки копирайта с помощью MagickWand лучше всего подойдет способ с DrawComposite. Он универсален (можно вставлять не только текст) и работает предсказуемое время. Исходное изображение для него можно подготовить 3 или 4 способом.
GD Graphics Library с большой вероятностью стоит на любом сервере. В ней то же самое можно сделать так:
list($w, $h) = getimagesize('image.png'); //Узнаем размер исходного изображения
$new_image = imagecreatefrompng('image.png'); //Загружаем исходное изображение
/* --- Обработка изображения --- */
imagejpeg($new_image, 'newimage.jpeg') //Сохраняем
imagedestroy($new_image);
1. С помощью подготовленного изображения
list($cw, $ch) = getimagesize('copyright.png');
$watermark = imagecreatefrompng('copyright.png');
imagecopy($new_image, $watermark, $w-$cw, $h-$ch, 0, 0, $cw, $ch); //Накладываем копирайт
imagedestroy($watermark); //Очищаем память
2. Генерация текста средствами GD
$color = imagecolorallocatealpha($new_image, 0, 0, 0, 60); //Устанавливаем черный цвет с прозрачностью 60%
imagettftext($new_image, 10, 90, $w-7, $h-12, $color, 'copyright.ttf', '© Копирайт'); //Создаем текстовую строку и размещаем на исходном изображении
Время работы в первом случае составило от 0,2 до 0,7 мс в зависимости от размера изображения, во втором — на 30% дольше.
Признаться, сам удивился, когда увидел, что GD работает чуть ли не в 1000 раз быстрее. Правда, замерял именно алгоритм обработки изображения, без открытий, сохранений и конвертаций в другой формат. Так же не учитывал объем занимаемой памяти, поэтому данные мало подходят для практического применения. Замер производительности целых функций с разными типами файлов показал, что на мелких файлах GD работает до 10 раз быстрее. Наиболее распространенные размеры (3–8 мегапикселей) библиотеки обрабатывают с одинаковой скоростью (справедливо только для моего
Интересно, что вес такого png-изображения (справа) получился 1,2 КБ против 6 КБ у GD. А все от того, что GD не догадался поменять палитру на 8-битную.
Так что проверяйте скорость на своем
Бонус
Немного о настройках качества
В MagickWand настройки качества задаются перед сохранением
MagickSetImageCompressionQuality($new_image, $quality);
MagickSetImageFormat($new_image, 'jpeg');
MagickWriteImage($new_image, 'newimage.jpeg'); //Сохраняем результат
Здесь $quality степнь сжатия от 0–100 для jpeg и 0–80 для png. На gif не влияет.
для jpeg:
0, null — сжатие по умолчанию ~85
1..100 — градация от ужасного качества до идеального
для png, т. к. это формат без потери качества, влияет только на вес картинки и, соответственно, время ее обработки сервером:
0, null — сжатие по умолчанию самое высокое (в этом случае вес картинки минимален)
1..80 — градация от плохого до хорошего сжатия (но наибольшее сжатие при 0)
Еще в MagickWand можно указать вид компрессии, но в случае с jpeg, png, gif он ни на что не влияет.
MagickSetImageCompression($image, MW_JPEGCompression);
В GD качество настраивается в сохраняющих функциях
imagejpeg($new_image, 'newimage.jpeg', $quality)
imagepng($new_image, 'newimage.png', $quality)
imagegif($new_image, 'newimage.gif') //gif так же обделили
Здесь $quality степнь сжатия от 0–100 для jpeg и 0–9 для png.
Для jpeg:
null — сжатие по умолчанию 75
0..100 — градация от ужасного качества до идеального. Практически совпадает с MagickWand
для png:
null — сжатие по умолчанию 0 (плохое сжатие)
0..9 — градация от плохого до наилучшего сжатия. При значение 9 вес картинки получается примерно такой как при 0 в MagickWand
Автор: tamtakoe