Text in a shape
Text in a shape
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.
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.
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: Text in a shape
In theory, yes, from SVG input. See http://www.w3.org/TR/2004/WD-SVG12-20041027/flow.html
snibgo's IM pages: im.snibgo.com
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: Text in a shape
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
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.
I want the text to be inserted inside the shape and follow the edges of the shape.
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: Text in a shape
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
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: Text in a shape
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:
Command:
flow.png:
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>
Code: Select all
inkscape -f flow.svg -e flow.png -y 1
snibgo's IM pages: im.snibgo.com
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: Text in a shape
Yeah, "convert flow.svg flow2.png" works fine, now I've put the Inkscape directory into my path.
Another example:
Where heartWords.svg is:
And the resulting heartWords.png is:
I found the best font-size by trial and error.
Another example:
Code: Select all
convert heartWords.svg -trim heartWords.png
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>
I found the best font-size by trial and error.
snibgo's IM pages: im.snibgo.com
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: Text in a shape
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?
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?
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: Text in a shape
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:
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>
snibgo's IM pages: im.snibgo.com
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: Text in a shape
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:
Potrace needs PNM input.
Commands:
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.
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>
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:
Code: Select all
769.815 (0.0117466)
snibgo's IM pages: im.snibgo.com
Re: Text in a shape
Hi snibgo,snibgo wrote:Yeah, "convert flow.svg flow2.png" works fine, now I've put the Inkscape directory into my path.
Another example:
Where heartWords.svg is:Code: Select all
convert heartWords.svg -trim heartWords.png
And the resulting heartWords.png 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>
I found the best font-size by trial and error.
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
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
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: Text in a shape
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.
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.
snibgo's IM pages: im.snibgo.com
Re: Text in a shape
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?
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?
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: Text in a shape
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.
You could, instead, call inkscape directly.
snibgo's IM pages: im.snibgo.com
Re: Text in a shape
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.
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.