Page 1 of 2
Text in a shape
Posted: 2013-11-03T07:43:06-07:00
by badabou
Hello,
Does the program imagemagick can put text in a form (eg a black and white mask) ?
I made a sketch to explain what I mean :
Thank you for your answers.
Re: Text in a shape
Posted: 2013-11-03T08:56:52-07:00
by snibgo
Re: Text in a shape
Posted: 2013-11-03T11:32:56-07:00
by fmw42
I cropped out your images.
Code: Select all
convert mask.png \( text.png -negate \) \( -clone 0 -negate \) -gravity center -compose over -composite text_in_heart.png
Re: Text in a shape
Posted: 2013-11-04T02:08:22-07:00
by badabou
This is not quite what I want to do.
I want the text to be inserted inside the shape and follow the edges of the shape.
Re: Text in a shape
Posted: 2013-11-04T10:45:35-07:00
by fmw42
You will need to write your text over the heart image in a way that conforms to the shape of the heart. That will require you to use for example PANGO and trial and error. See
http://www.imagemagick.org/Usage/text/#pango
Re: Text in a shape
Posted: 2013-11-04T11:07:22-07:00
by snibgo
The job is easily done with SVG, using inkscape for the rasterization. For example, here is an SVG file with a simpler path. I use Inkscape directly. Doubtless it could be done by using IM to call Inkscape.
flow.svg:
Code: Select all
<svg xmlns:svg="http://www.w3.org/2000/svg" version="1.2"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 300 310">
<title>Basic textflow</title>
<rect x="0" y="0" width="100%" height="100%" fill="yellow" fill-opacity="0"/>
<flowRoot font-size="16" >
<flowRegion fill="none" fill-opacity="0" stroke-opacity="1" stroke="red">
<path d="M90,40L40,270L260,270L210,40z"/>
</flowRegion>
<flowPara fill="blue" fill-opacity="1" stroke-opacity="1" stroke="red">
The job is easily done with SVG, using inkscape for the rasterization. For example, here is an SVG file with a simpler path. I use Inkscape directly. Doubtless it could be done by using IM to call Inkscape.
</flowPara>
</flowRoot>
<path d="M90,40L40,270L260,270L210,40z" fill="none" fill-opacity="0" stroke-opacity="1" stroke="red" stroke-width="2"/>
</svg>
Command:
Code: Select all
inkscape -f flow.svg -e flow.png -y 1
flow.png:
Re: Text in a shape
Posted: 2013-11-04T20:07:23-07:00
by snibgo
Yeah, "convert flow.svg flow2.png" works fine, now I've put the Inkscape directory into my path.
Another example:
Code: Select all
convert heartWords.svg -trim heartWords.png
Where heartWords.svg is:
Code: Select all
<svg xmlns:svg="http://www.w3.org/2000/svg" version="1.2"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 744 1052">
<title>Basic textflow</title>
<rect x="0" y="0" width="100%" height="100%" fill="yellow" fill-opacity="0"/>
<path d="m 300,169.50504 c 0,0 -111.53096,-11.5113 -114.28571,140 -1.42858,78.57143 116.42857,275.28572 223.65747,328.46079 107.22895,-54.68207 225.08605,-251.39636 223.65755,-329.96779 -2.7548,-151.5113 -114.2858,-140 -114.2858,-140 0,0 -105.7142,5.71429 -109.37175,117.89636 C 405.71428,175.21933 300,169.50504 300,169.50504 z"
fill="black" fill-opacity="1" stroke-opacity="0" stroke="red" stroke-width="2"/>
<flowRoot font-size="33" text-anchor="middle" >
<flowRegion>
<path d="m 300,169.50504 c 0,0 -111.53096,-11.5113 -114.28571,140 -1.42858,78.57143 116.42857,275.28572 223.65747,328.46079 107.22895,-54.68207 225.08605,-251.39636 223.65755,-329.96779 -2.7548,-151.5113 -114.2858,-140 -114.2858,-140 0,0 -105.7142,5.71429 -109.37175,117.89636 C 405.71428,175.21933 300,169.50504 300,169.50504 z"
/>
</flowRegion>
<flowPara fill="white" fill-opacity="1" stroke-opacity="0" stroke="red">The job is easily done with SVG, using inkscape for the rasterization. For example, here is an SVG file with a heart path. I can use Inkscape directly, or by using IM to call Inkscape.</flowPara>
</flowRoot>
</svg>
And the resulting heartWords.png is:
I found the best font-size by trial and error.
Re: Text in a shape
Posted: 2013-11-04T20:22:38-07:00
by fmw42
pretty neat!
how did you create the heart shape and get it vectorized?
One option would be to get a binary heart image, get its boundary (edge) and vectorize with autotrace, something like at
http://www.imagemagick.org/Usage/transform/#edge_vector, but starting with the edge image.
Did you do something like that or just create it by hand?
Re: Text in a shape
Posted: 2013-11-04T22:01:22-07:00
by snibgo
I just created it by hand in Inkscape. A heart shape, roughly symmetrical, with four points on the curve and eight control points. I wrote the result to an SVG file, and copied the path from there to my own file.
The result works, but I don't much like the solution, so I then simplified it.
A heart needs only two points on the curve, with four control points, two of which coincide. In Inkscape, I edited the points, then used a text editor to remove the fractional values and ensure it was exactly symmetrical. I also reorganised my SVG file so the path needs to be specified once even though it is used twice (once for the black shape, and once as a path in which to fit the text). So here is a simpler version:
Code: Select all
<svg xmlns:svg="http://www.w3.org/2000/svg" version="1.2"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 900 650">
<title>Text in a heart</title>
<defs>
<path id="heartPath"
d="M 434,638
C 868,183 434,72 434,287
434,72 0,183 434,638
z"
/>
</defs>
<use xlink:href="#heartPath"
fill="black" stroke="none"
fill-opacity="1" stroke-opacity="0" />
<flowRoot font-size="30" text-anchor="middle" >
<flowRegion>
<use xlink:href="#heartPath" />
</flowRegion>
<flowPara fill="white" fill-opacity="1"
stroke-opacity="0">The job is easily done with SVG,
using Inkscape for the rasterization.
For example, here is an SVG file with a heart path.
I can use Inkscape directly, or call Inkscape via IM.</flowPara>
</flowRoot>
</svg>
Re: Text in a shape
Posted: 2013-11-05T08:34:44-07:00
by snibgo
Just for fun, we can define the heart-shape in SVG, rasterise that in IM (delegating to Inkscape), vectorise the result with Potrace, rasterise that, and compare the two raster images.
heart0.svg:
Code: Select all
<svg xmlns:svg="http://www.w3.org/2000/svg" version="1.2"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="900.000000pt" height="650.000000pt" viewBox="0 0 900 650">
<title>Text in a heart</title>
<defs>
<path id="heartPath"
d="M 434,638
C 868,183 434,72 434,287
434,72 0,183 434,638
z"
/>
</defs>
<use xlink:href="#heartPath"
fill="black" stroke="none"
fill-opacity="1" stroke-opacity="0" />
</svg>
Potrace needs PNM input.
Commands:
Code: Select all
convert -verbose -density 72 -depth 16 heart0.svg h0.pnm
c:\potrace\potrace.exe -s -o h1.svg h0.pnm
convert -verbose -density 72 -depth 16 h1.svg h1.pnm
compare -metric RMSE h0.pnm h1.pnm NULL:
The difference is ...
... which is okay, and just visible. Potrace reports 18 points on the curve, rather than the elegant 2 that are actually needed.
Re: Text in a shape
Posted: 2013-11-05T11:52:19-07:00
by badabou
snibgo wrote:Yeah, "convert flow.svg flow2.png" works fine, now I've put the Inkscape directory into my path.
Another example:
Code: Select all
convert heartWords.svg -trim heartWords.png
Where heartWords.svg is:
Code: Select all
<svg xmlns:svg="http://www.w3.org/2000/svg" version="1.2"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 744 1052">
<title>Basic textflow</title>
<rect x="0" y="0" width="100%" height="100%" fill="yellow" fill-opacity="0"/>
<path d="m 300,169.50504 c 0,0 -111.53096,-11.5113 -114.28571,140 -1.42858,78.57143 116.42857,275.28572 223.65747,328.46079 107.22895,-54.68207 225.08605,-251.39636 223.65755,-329.96779 -2.7548,-151.5113 -114.2858,-140 -114.2858,-140 0,0 -105.7142,5.71429 -109.37175,117.89636 C 405.71428,175.21933 300,169.50504 300,169.50504 z"
fill="black" fill-opacity="1" stroke-opacity="0" stroke="red" stroke-width="2"/>
<flowRoot font-size="33" text-anchor="middle" >
<flowRegion>
<path d="m 300,169.50504 c 0,0 -111.53096,-11.5113 -114.28571,140 -1.42858,78.57143 116.42857,275.28572 223.65747,328.46079 107.22895,-54.68207 225.08605,-251.39636 223.65755,-329.96779 -2.7548,-151.5113 -114.2858,-140 -114.2858,-140 0,0 -105.7142,5.71429 -109.37175,117.89636 C 405.71428,175.21933 300,169.50504 300,169.50504 z"
/>
</flowRegion>
<flowPara fill="white" fill-opacity="1" stroke-opacity="0" stroke="red">The job is easily done with SVG, using inkscape for the rasterization. For example, here is an SVG file with a heart path. I can use Inkscape directly, or by using IM to call Inkscape.</flowPara>
</flowRoot>
</svg>
And the resulting heartWords.png is:
I found the best font-size by trial and error.
Hi snibgo,
Thank you so much for your examples, it's almost exactly what I want to do.
I did the test with your svg file :
Code: Select all
convert heartWords.svg -trim heartWords.png
but I is not the same result (the text is not displayed):
My imagemagick version :
Code: Select all
# convert -version
Version: ImageMagick 6.5.9-2 2010-02-03 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2010 ImageMagick Studio LLC
Features: OpenMP
I have another question: Is it possible that the text size is adjusted automatically according to the number of characters depending on the space available in the vector form (as with the "caption" option imagemagick program)?
Re: Text in a shape
Posted: 2013-11-05T18:34:02-07:00
by snibgo
My tests were on IM v6.8.7-0, Inkscape 0.48 (the current version), on Windows 7.
Your version of IM is very old. I suggest you upgrade. What version of Inkscape are you on? That's more likely to make a difference. Is the Inkscape directory on your path? What happens when you run the Inkscape command?
A script could be written that could guess the best font-size, based on the proportion of the heart within the rectangle, and automated trial-and-error. But it wouldn't be easy. I can't see a simple test for the text being clipped.
Re: Text in a shape
Posted: 2013-11-06T00:52:18-07:00
by badabou
My imagemagick version is old because when I update it, I have compatibility problems with php-imagick library (version 2.3.0) and all my scripts are written with it.
There's something I do not understand: In your second example, you seem not to use Inkscape to create the heart in PNG. So I simply used imagemagick "convert -trim heartWords.svg heartWords.png" with your heartWords.svg file, is it a mistake?
Re: Text in a shape
Posted: 2013-11-06T01:11:54-07:00
by snibgo
My tests were done with the directory containing inkscape.exe on my PATH variable. This means that ImageMagick will use Inkscape to rasterise the SVG.
You could, instead, call inkscape directly.
Re: Text in a shape
Posted: 2013-11-06T04:42:41-07:00
by badabou
It's good it works perfectly.
I must now find a way to adjust the text size in the vector shape.
I do not know how to know if the text out of the vector shape or not. If I knew that I could do more tests and derive the best font size.