Как центрировать подписи в PerlMagick?

Используя ImageMagick в командной строке, я могу сказать

convert -background '#0000' -fill white -stroke black -strokewidth 3 -gravity center -pointsize 78 -size 568x1000 caption:'Lorem ipsum etc etc' -trim +repage out.png

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

use strict;
use warnings;
use Image::Magick;

my $im = new Image::Magick;
my $e = $im->Set(
        background => '#0000',
        fill => 'white',
        stroke => 'black',
        strokewidth => 3,
        gravity => 'center',
        pointsize => 78,
        size => '586x1000',
);
die $e if $e;

$e = $im->Read("caption:Lorem ipsum etc etc");
die $e if $e;

$e = $im->Trim();
die $e if $e;

$e = $im->Set(page=>'0x0+0+0'); # +repage
die $e if $e;

$e = $im->Write('out.png');
die $e if $e;

И это работает точно так же, за исключением того, что результирующий текст не центрируется.

Документации по PerlMagick почти не существует. Я основал этот синтаксис «прочитать заголовок» на некоторых примерах MagicWand, где утверждается, что это приведет к выравниванию текста по центру. Очевидно, что-то другое для PerlMagick.

Итак, вопрос: как я могу заставить PerlMagick уважать гравитацию в этом случае? Как с помощью PerlMagick получить многострочный, центрированный и переносимый по словам текст? Обратите внимание, что для этого требуется, чтобы я использовал подпись, а не аннотировал или рисовал. Я бы предпочел избегать ручного построчного центрирования, но я бы рассмотрел это.

В качестве альтернативы, если у кого-то есть пример переноса слов с пропорциональными шрифтами и Annotate, это сработает для меня.

РЕДАКТИРОВАТЬ: обратите внимание, что опция -caption для поляроида, хотя и разделяет реализацию с тем, что я делаю, не совпадает с подписью: псевдоизображение. Я бы все равно принял ответ, используя polaroid и -caption, если вывод точно соответствует тому, что дано приведенным выше примером команды convert.

РЕДАКТИРОВАТЬ 2: вот более минимальный пример проблемы.

use strict;
use warnings;
use Image::Magick;

my $im = new Image::Magick;
my $e = $im->SetAttribute(
        background => '#0000',
        pointsize=>12,
        size => '100x100',
        gravity => 'center',
);
die $e if $e;
$e = $im->ReadImage('caption:The quick brown fox jumps over the lazy dog.');
die $e if $e;
$e = $im->Write('out.png');
die $e if $e;

Ожидаемый результат: текст выравнивается по центру.

Фактический результат: текст выровнен по левому краю.

Фактический результат должен быть идентичен выводу этой команды:

convert -background '#0000' -size 100x100  -pointsize 12 -gravity center caption:'The quick brown fox jumps over the lazy dog.' out.png

Глядя на источник perlmagick, я не вижу ничего, что должно было бы перехватывать конкретный вызов SetAttribute, поэтому я не понимаю, почему гравитация игнорируется. Как я могу заставить гравитацию не игнорироваться для этого? Или, как еще я могу сделать перенос слов и центрированный текст с таким выводом?


person sorpigal    schedule 14.10.2010    source источник
comment
Не пробовал это, но мне интересно, есть ли здесь что-то, что можно использовать повторно. code.google.com/p/image-boxmodel/source/browse/trunk/lib/Image/   -  person bob.faist    schedule 26.10.2010
comment
Я попробую это через несколько часов, когда буду дома с работы. Мой возможный обходной путь заключался в том, чтобы PerlMagick неоднократно выполнял нецентрированный рендеринг с разными размерами точек, пока результирующее изображение не соответствовало размеру моего блока. Затем я вызываю конвертировать через system() и выполняю окончательный рендеринг. Однако он использует во много раз больше мощности процессора, чем настоящее нативное решение, поэтому я все еще пытаюсь, но, по крайней мере, у меня есть кое-что, на что я могу опереться.   -  person sorpigal    schedule 26.10.2010


Ответы (3)


Версия: ImageMagick 6.5.7-8

Ближе, но все еще не по центру по горизонтали, только по вертикали. Как-то закончились идеи...

#!/usr/bin/perl

use strict;
use warnings;
use Image::Magick;

my $t = Image::Magick->new();
my $b = Image::Magick->new();
$t->SetAttribute(pointsize=>12, size => '100x50', background=>'transparent');
$b->SetAttribute(size => '100x100');
$t->ReadImage('caption:The quick brown fox jumps over the lazy dog.');
$b->ReadImage('xc:transparent');
$b->Composite(image => $t, gravity=>'center', compose=>'over');
$b->Write('out.png');

альтернативный текст

person bob.faist    schedule 22.10.2010
comment
Мой оригинальный пример также заводит меня так далеко. Вот проблема: в Magick.xs при анализе параметра гравитации есть такой цикл: for( ; image ; image = image->next ) image->gravity = (MagickGravity)sp; (обратите внимание, что точные имена переменных могут немного отличаться, так как это из памяти). Итак, как вы видите, он устанавливает гравитацию для каждого изображения. Но в это время изображения нет (изображение имеет значение NULL), и когда ReadImage создает новое изображение, оно, очевидно, не имеет этого значения гравитации. Это то, что я узнал вчера, глядя на источник imagemagick. - person sorpigal; 22.10.2010
comment
Возможно, я должен упомянуть, что когда вы читаете заголовок: тип изображения, он сразу же отображает текст с доступными параметрами и, похоже, не ждет, например. составной шаг. Вот почему гравитация не работает так, как вы использовали ее здесь: текст уже выровнен по левому краю. - person sorpigal; 22.10.2010
comment
Кажется, что и преобразование в командной строке, и API C для этого идут через систему палочки, которая отличается и фактически делает то, что вы ожидаете. Странно также кажется, что ReadCAPTIONImage caption.c никогда не срабатывает, если вы используете convert(1), что немного загадочно (я все еще работаю над этим). - person sorpigal; 22.10.2010
comment
Я голосую и принимаю это, хотя это не совсем решение. В ходе моего расследования я обнаружил, что на самом деле не существует собственного решения из-за недостатков PerlMagick. Вы подошли настолько близко, насколько это возможно, оставаясь с чистым решением PerlMagick (и не исправляя сначала imagemagick). - person sorpigal; 26.10.2010

Как насчет использования Annotate()?

use strict;
use warnings;
use Image::Magick;

my $im = Image::Magick->new();
$im->Set(size => "1000x568");
$im->ReadImage('xc:black');
$im->Annotate(text => "Lorem ipsum etc etc",
              gravity => "Center",
              fill => 'white',
              stroke => 'black',
              strokewidth => 3,
              pointsize => 78);
$im->Write('myout.png');

альтернативный текст

person bob.faist    schedule 21.10.2010
comment
Это не перенос слов. Попробуйте добавить больше текста, пока не потребуется обтекание, или сделайте размер 568 пикселей в ширину, как в моем исходном примере, и посмотрите, что получится. К вашему сведению, согласно документам imagemagick, вы не можете использовать перенос слов с помощью Annotate или Draw, только заголовок. - person sorpigal; 21.10.2010
comment
Ответ, включающий Annotate или Draw, должен включать код для разделения входной строки и переноса, где это необходимо, с учетом пропорционального шрифта. Это возможно (QueryFontMetrics), но сложно, особенно если вам также необходимо наилучшим образом вписаться в предопределенное поле, минимизировав количество строк текста и увеличив размер шрифта, как это делаю я. - person sorpigal; 21.10.2010

Это работает на Ubuntu 10.04 для меня. Я вижу документацию только для «заголовка», работающего с эффектом «поляроид».

#!/usr/bin/perl

use strict;
use warnings;
use Image::Magick;

my $im = new Image::Magick;
$im->Set(size => '586x1000');

my $e = $im->ReadImage('xc:black');

$im->Polaroid(
        fill => 'white',
        stroke => 'black',
        strokewidth => 3,
        gravity => 'center',
        pointsize => 78,
        caption => "Lorem ipsum etc etc"
);

$e = $im->Trim();
die $e if $e;

$e = $im->Set(page=>'0x0+0+0'); # +repage
die $e if $e;

$e = $im->Write('out.png');
die $e if $e;

альтернативный текст

person bob.faist    schedule 21.10.2010
comment
Хороший пример кода для PerlMagick здесь: imagemagick.org/source/examples.pl - person bob.faist; 21.10.2010
comment
Пожалуйста, опубликуйте свои точные версии imagemagick и perlmagick. Примеры использования подписи можно найти здесь: imagemagick.org/Usage/text/# подпись (обратите внимание, что polaroid использует -caption, тогда как это подпись псевдо-изображения:) Также обратите внимание, что я собираюсь использовать это, чтобы наложить текст поверх существующего изображения, которое не должно применить эффект полароид. - person sorpigal; 21.10.2010
comment
Кроме того, полученное вами изображение с использованием этой техники недостаточно. Этот конкретный шаг должен привести к изображению с прозрачным фоном, которое достаточно велико, чтобы вместить визуализированный текст (в точности как результаты, если вы запустите версию командной строки, указанную выше). - person sorpigal; 21.10.2010