2010-10-14 6 views
3

En utilisant ImageMagick sur la ligne de commande que je peux direComment puis-je centrer les légendes dans PerlMagick?

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

Et produire la sortie que je cherche. Ce que j'aimerais faire, c'est la même chose, mais dans PerlMagick, pour ne pas avoir à lire et à écrire des fichiers pendant que j'effectue d'autres étapes. Voici ce que j'ai jusqu'à maintenant

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; 

Et cela fonctionne exactement de la même manière, sauf que le texte résultant n'est pas centré.

La documentation sur PerlMagick est presque inexistante. J'ai basé cette syntaxe de «légende de lecture» sur certains exemples de MagicWand, où l'on prétend que cela entraînera un texte centré. Clairement, quelque chose est différent pour PerlMagick. Donc, la question: Comment puis-je faire en sorte que PerlMagick respecte la gravité dans ce cas? Comment obtenir un texte multiligne, centré et enveloppé de mots via PerlMagick? Notez que cela nécessite que j'utilise une légende et ne pas annoter ou dessiner. Je préférerais éviter le centrage manuel par ligne, mais je le considérerais. Alternativement, si quelqu'un a un échantillon de faire un emballage de mots et avec des polices proportionnelles et Annoter, alors cela fonctionnerait pour moi.

EDIT: Veuillez noter que l'option -caption de polaroid, bien qu'elle partage l'implémentation avec ce que je fais, n'est pas la même que la légende: pseudo-image. J'accepterais toujours une réponse en utilisant polaroid et -caption si la sortie correspond étroitement à ce qui est donné par l'exemple de commande convert ci-dessus.

EDIT 2: Voici un exemple plus minimal du problème.

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; 

Résultat attendu: Le texte est centré.

Résultat actuel: Le texte est justifié à gauche.

Résultat réel doit être identique à la sortie de cette commande:

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

De la recherche à la source de perlmagick je ne vois rien qui devrait être Intercepter un appel SetAttribute particulier, donc je ne vois pas pourquoi la gravité est être ignoré. Comment puis-je faire en sorte que la gravité ne soit pas ignorée pour cela? Ou, comment puis-je faire du texte enveloppé et centré avec ce type de sortie?

+1

ai pas essayé mais je me demande s'il y a quelque chose qui peut être réutilisé. http://code.google.com/p/image-boxmodel/source/browse/trunk/lib/Image/BoxModel/Backend/IM.pm?r=28#95 –

+0

Je vais essayer cela dans quelques heures quand je rentre du travail. Mon éventuelle solution de contournement consistait à faire PerlMagick effectuer le rendu non-centré à plusieurs reprises à différents points jusqu'à ce que l'image résultante soit dans ma taille de boîte. J'appelle ensuite pour convertir via system() et le faire effectuer le rendu final. Il utilise plusieurs fois la puissance du processeur d'une vraie solution native, donc j'essaie toujours, mais au moins j'ai quelque chose sur lequel je peux me rabattre. – Sorpigal

Répondre

1

Version: ImageMagick 6.5.7-8

Closer, mais ne centre pas encore horizontalement, juste à la verticale. Kinda à court d'idées ...

#!/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'); 

alt text

+0

Mon exemple original m'amène aussi loin. Voici le problème: Dans Magick.xs lors de l'analyse de l'option "gravité" il y a une boucle comme ceci: 'for (; image; image = image-> next) image-> gravité = (MagickGravity) sp;' (notez que l'exact les noms de variables peuvent être un peu éloignés car cela vient de la mémoire). Donc, comme vous le voyez, il définit la gravité pour chaque image. Mais, il n'y a pas d'image à ce moment (l'image est NULL) et quand ReadImage crée une image * new * il n'a évidemment pas cette valeur de gravité. C'est ce que j'ai appris en regardant la source imagemagick hier. – Sorpigal

+0

Je devrais peut-être mentionner que lorsque vous lisez la légende: type d'image, il rend immédiatement le texte avec quelles options sont disponibles et ne semble pas attendre par exemple. une étape composite. C'est la raison pour laquelle "gravity" ne fonctionne pas comme vous l'avez utilisé ici: le texte est déjà rendu à gauche. – Sorpigal

+0

Semble que les deux convertissent sur la ligne de commande et l'API C pour cela aller par le système de baguette, ce qui est différent et fait ce que vous attendez. Il semble étrangement aussi que ReadCAPTIONImage de caption.c n'est jamais frappé si vous exécutez convert (1) ce qui est un peu mystifiant (je travaille encore sur celui-là). – Sorpigal

0

Cela fonctionne sur Ubuntu 10.04 pour moi. Je ne vois que la documentation pour "légende" travaillant avec l'effet "polaroid".

#!/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; 

alt text

+0

Un bon exemple de code pour PerlMagick ici: http://www.imagemagick.org/source/examples.pl –

+0

Veuillez poster vos versions exactes de imagemagick et de perlmagick. Vous pouvez trouver des exemples de légendes utilisées comme ceci ici: http://www.imagemagick.org/Usage/text/#caption (s'il vous plaît noter que polaroid utilise -caption, alors que c'est la légende pseudo-image :) Aussi s'il vous plaît noter que je vais utiliser ceci pour appliquer du texte au-dessus d'une image existante qui * ne doit pas * avoir l'effet polaroid appliqué. – Sorpigal

+0

En outre, l'image obtenue avec cette technique n'est pas suffisante. Cette étape particulière devrait aboutir à une image avec un arrière-plan transparent qui est précisément assez grand pour contenir le texte rendu (exactement comme les résultats si vous exécutez la version de ligne de commande donnée ci-dessus). – Sorpigal

2

Comment l'utilisation Annoter()?

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

alt text

+0

Ce n'est pas un mot enveloppé. Essayez d'ajouter plus de texte jusqu'à ce que l'empaquetage soit requis, ou faites la taille de 568 pixels comme dans mon exemple original, et voyez ce qui se passe. Pour info, d'après les documents imagemagick, vous ne pouvez pas envelopper de mots avec Annoter ou Dessiner, seule légende. – Sorpigal

+0

Une réponse impliquant Annoter ou Dessiner doit inclure du code pour découper la chaîne d'entrée et l'enrouler le cas échéant, en prenant en compte la police proportionnelle. C'est possible (QueryFontMetrics) mais difficile, surtout si vous avez aussi besoin de "mieux s'adapter" dans une boîte prédéfinie tout en minimisant le nombre de lignes de texte et en maximisant la taille de la police comme je le fais. – Sorpigal

Questions connexes