- PVSM.RU - https://www.pvsm.ru -

Наложение текста и картинок на изображение с помощью библиотек MagickWand и GD

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);

В результате этих двух способов получилось следующее:

image

Время выполнения схоже. В первом случае скачет от 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);

В результате этих двух способов получилось следующее:

image

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

По скорости способы идентичны. Время сильно скачет. Для мелких изображений составляет 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); //Очищаем память

image

2. Генерация текста средствами GD

$color = imagecolorallocatealpha($new_image, 0, 0, 0, 60); //Устанавливаем черный цвет с прозрачностью 60%
imagettftext($new_image, 10, 90, $w-7, $h-12, $color, 'copyright.ttf', '© Копирайт'); //Создаем текстовую строку и размещаем на исходном изображении

image

Время работы в первом случае составило от 0,2 до 0,7 мс в зависимости от размера изображения, во втором — на 30% дольше.

Признаться, сам удивился, когда увидел, что GD работает чуть ли не в 1000 раз быстрее. Правда, замерял именно алгоритм обработки изображения, без открытий, сохранений и конвертаций в другой формат. Так же не учитывал объем занимаемой памяти, поэтому данные мало подходят для практического применения. Замер производительности целых функций с разными типами файлов показал, что на мелких файлах GD работает до 10 раз быстрее. Наиболее распространенные размеры (3–8 мегапикселей) библиотеки обрабатывают с одинаковой скоростью (справедливо только для моего хостинга [1]). MagickWand (ImageMagic) любят за лучшее качество масштабирования. Опять же это справедливо только для сложных фотографий. Четкие контуры MW слишком размывает

image image

Интересно, что вес такого png-изображения (справа) получился 1,2 КБ против 6 КБ у GD. А все от того, что GD не догадался поменять палитру на 8-битную.

Так что проверяйте скорость на своем хостинге [1] (я тестировал на МакХосте), выбирайте качество исходя из ваших нужд и после этого отдавайте предпочтение той или иной библиотеке, а лучше подкиньте монетку ;-)

Бонус

Немного о настройках качества

В 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

Источник [2]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/kopirajt/20512

Ссылки в тексте:

[1] хостинга: https://www.reg.ru/?rlink=reflink-717

[2] Источник: http://habrahabr.ru/post/159209/