ImageMagick: redraw a text without "-draw" for only outward stroke - imagemagick

I try to create a text image with ImageMagick, where is the stroke expands only outward. I found a solution, where I should use the "-draw" command, but with it I would need the size of my image, but I don't know it in advance.
The command below should be upgrated. Somehow I would need to draw the text again on it, without strokewidth:
convert -background none -fill white -pointsize 100 -stroke red \
-strokewidth 20 label:text stroke.png
#leu's solution almost good, but the positioning of the new text isn't in the good position. My result was that above, and I don't know, where I took a mistake:

My suggestion: combine label:"Some text" with -annotate "Some text". Like this:
#myfont="Arial-Black-Standard"
#myfont="Tahoma"
#offset="-0-0"
#offset="-20-10"
#offset="-30-10"
#offset="-10+10"
myfont="Tahoma"
offset="+10+10"
convert -respect-parentheses \
\( \
-font "${myfont}" \
-pointsize 180 \
-strokewidth 18 \
-fill blue \
-stroke blue \
-background none \
label:"Test text" \
\) \
-gravity center \
-font "${myfont}" \
-pointsize 180 \
-fill white \
-annotate "${offset}" "Test text" \
result${offset}.png
Play with the offset=... variable (also with the point sizes and stroke widths) to get closer to what you want. Here are some of my results:
However, like #MarkSetchell, I do not fully comprehend what you want to achieve. An explanation of what you mean by "outward stroke" that I do understand is missing...

yes: draw the same text onto your pic - maybe by piping output of your command to another convert
convert -background none -fill white -pointsize 100 -stroke red \
-strokewidth 20 label:text png:- \
| convert -fill white -pointsize 100 -stroke none \
-draw 'text 10,82 "text"' - stroke.png
the trick is to correctly place the second string. x-position is half the strokewidth, but y-position seems to be font- and pointsize-dependant. My approach was to first place both strings over each other when strokewidth was set to 0:
convert -background none -fill white -pointsize 100 -stroke red \
-strokewidth 0 label:text png:- \
| convert -fill white -pointsize 100 -stroke none \
-draw 'text 0,72 "text"' - stroke.png
then you have to add half the strokewidth to this y-position as well.
a bit of trial-and-error to get the correct y-position, but it seems to work for any string.
== edit ==
of course, we don't need to do trial-and-error. But instead we can use ImageMagick's power. Just perform the following steps (in this example within Bash):
#!/bin/bash
# read text from command line (or use "Test Text")
text=${1:-"Test Text"}
# strokewidth
sw=20
# pointsize
ps=120
# font
font=Arial
# result file
result="stroke.png"
# do some calc
sw_half=$(expr $sw / 2)
convert -background none -font $font -fill white -pointsize $ps -stroke red -strokewidth $sw label:"$text" $result
convert -background none -font $font -fill white -pointsize $ps -stroke none label:"$text" png:- | composite -geometry +${sw_half}+${sw_half} - $result $result
You can get the list of fonts available on your system by
convert -list font
The idea is the same as above: draw the text twice and draw one onto the other while using an offset of half the strokewidth.
The results all look like the following

Related

Add a tile watermark to a part of the image only

Usually, I add watermark text on documents with something like this:
convert -size 700x360 xc:none -fill "#00000020" -font "Liberation-Sans-Bold" -pointsize 60 \
-gravity NorthWest -draw "text 0,75 \"${3}\"" \
-gravity SouthEast -draw "text 0,75 \"${3}\"" \
miff:- |\
composite -tile - "${1}" "${2}"
It spreads a tile with text over the whole image.
Now I need to add a watermark that excludes a specific area on the document.
My question is:
How to limit "operating area" only to a specific rectangular image region defined as x,y,width,height?
On the other hand: Is it possible and how to exclude a specific rectangular region and spread my tiles only outside of it?
You can do that as follows in Imagemagick by creating a tiled watermark image of the size you want and then compositing over the background image.
Here I create the tile image (mpr:wm) . Then tile it out with a transparent background using -draw "color 0,0 reset". Then I composite that over the background image at the desired upper left corner (+32+32). This is all done in one convert command line without needing to pipe.
In:
in="mandril3.jpg"
out="mandril3_wm.jpg"
text="Testing"
convert -size 64x64 xc:none -fill black \
-font "candice" -pointsize 14 \
-gravity NorthWest -draw "text 0,5 '$text'" \
-gravity SouthEast -draw "text 0,5 '$text'" \
-write mpr:wm +delete \
-size 128x128 xc:none -tile mpr:wm -draw "color 0,0 reset" \
$in +swap -geometry +32+32 \
-compose over -composite \
$out
Out:

Chain 2 imagemagick commands

I would like to add a logo and some text to an image.
I can achieve this through the following:
// Add logo
composite -geometry +10+20 logo.png input.jpg \
output_with_logo.jpg
// Add text
convert output_with_logo.jpg -font Arial -pointsize 20 \
-draw "fill black text 20,50 'Test'" \
final.jpg
However I'm wondering if I can chain these 2 commands together so I can work from the same source file at once, instead of saving out staged versions of the image.
I've tried:
convert -font Arial -pointsize 20 \
-draw "fill black text 20,50 'Test'" \
-composite -geometry +10+20 input.jpg logo.png \
final.jpg
However this creates 2 "Test" strings on the image
Like this:
convert input.jpg logo.jpg -geometry +10+20 -composite -font Arial -pointsize 20 -draw "fill black text 20,50 'Test'" final.jpg
Rather than use the composite command which won't let you add text, use the convert command and its -composite operator which does the same thing. So, I am saying:
composite A.jpg B.jpg result.jpg = convert A.jpg B.jpg -composite result.jpg
Then, once you have done the compositing, you can add the text afterwards - exactly as you had it.

Image magick padding font

I am trying to put a label with a transparent background on an image, which works, but there is an issue with padding. The text is too close to the top of the transparent background. I wanted to add some padding to it, but I can't seem to get it to work. I know I could probably do it with draw for the background instead, but the length of the label changes all the time. I guess I could estimate the size I need based on character length, but is there a more simple way in image magick?
I tried to search for an option to maybe change line height or something, but just found spacing between words, chars, or lines instead.
Any ideas?
Convert input.jpg -fill white -undercolor 'rgba(0, 0, 0, .75)' -font Helvetica -pointsize 48 -gravity south -annotate +0+35 " Blah blah blah " output.jpg
You could use label to create your label, then splice some extra lines on top, then composite that onto your image. It is a bit ugly but not too complicated.
convert -background 'rgba(0, 0, 0, .75)' \
-fill white -font Helvetica -pointsize 48 \
label:" Blah blah blah " -splice 0x10 \
input.jpg \
+swap -gravity south \
-geometry +0+10 -composite result.jpg
Or you can do it the other way around and preserve the metadata:
convert input.jpg \
\( -background 'rgba(0, 0, 0, .75)' -fill white \
-font Helvetica -pointsize 48 \
label:" Blah blah blah " -splice 0x10 \
\) -gravity south -geometry +0+10 -composite result.jpg
This can also be a solution for adding a padding on all sides of a transparent text image
Use:
-gravity southeast -splice 20x20 -gravity northwest -splice 20x20
This solution works good for me
Without Padding:
convert -background "rgba(0, 255 ,0, 0.7)" \
-font "Lobster-Regular.ttf" -pointsize "60" \
-fill "#FFFFFF" label:"PROMOTE ANYTHING" \
heading.png
With Padding:
convert -background "rgba(0, 255 ,0, 0.7)" \
-font "Lobster-Regular.ttf" -pointsize "60" \
-fill "#FFFFFF" label:"PROMOTE ANYTHING" \
-gravity southeast -splice 20x20 -gravity northwest -splice 20x20 \
heading.png

How to shade text using imagemagick?

I am wondering how to add a shaded copyright text at the bottom of a jpeg. Currently I simply use:
convert input.jpg -font /usr/share/fonts/truetype/pointfree/pointfree.ttf -pointsize 15 -fill white -gravity SouthEast -strokewidth 3 -annotate +0+5 " #blabla.com " "output.jpg"
The problem with this is that when the background is light the text disappears.
I am aware that I could add a flag like
-undercolor '#00000080'
but I find this rather obtrusive, so looking for a better solution that make text's visiblily more independent of the background color. Note: image sizes are different so I can not hardcode the text's coordination.
Try this:
convert input.jpg -font /usr/share/fonts/truetype/pointfree/pointfree.ttf -pointsize 15 -gravity SouthEast -strokewidth 3 -fill black -annotate +2+7 " #blabla.com "-fill white -annotate +0+5 " #blabla.com " "output.jpg"
There was a post on the imagemagick forum from amember which took into consideration the colour under the text and produced a white or black watermark to suite. I was looking for it the otherday and could not find it. It was a batch script from memory.
I had to add the comment here as I was getting some message I did not understand about notifications when trying to add a comment.
Sorry I missed out a space here " #blabla.com "-fill should be " #blabla.com " -fill The command line is very long and would be easier to work with if you split it onto different lines.
Ok, finally I found a good batch solution:
for FILE in *.jpg; do convert $FILE -gravity southeast -stroke '#000C' -strokewidth 2 -annotate 0 'blabla.com' -stroke none -fill white -annotate 0 'blabla.com' $FILE; done

Overlaying an image's filename using ImageMagick (or similar)

I know ImageMagick's annotate command can superimpose some text over an image, but can it use the image's filename as this text? I would've assumed so, but can't seem to find direct documentation that confirms this.
No doubt some combination of parameters can manage this, or is there a better way of doing this in a script?
Eric L.'s answer is correct -- +1 from me for it! -- but -annotate doesn't give you much control over the appearance of the text.
If you look for prettyness, then rather go for something that uses -composite. You can use an IM command to construct an overlay image first (which uses a semi-transparent background) and then overlay it over the original image.
Here is an example how to do it with -composite instead of -annotate, using a scripted approach that processes every PNG file in the current directory. This one even automatically adapts the font size and fits it into the available "width * 90%" -- it is a Bash script (see comments for Win equivalent):
for img in *.png; do
width=$(identify -format %W ${img})
width=$(( ${width} * 9 / 10 ))
convert \
-background '#0008' \
-gravity center \
-fill white \
-size ${width}x100 \
caption:"${img}" \
"${img}" \
+swap \
-gravity south \
-composite \
"with-caption-${img}"
done
An example illustration for one original and the respective output are below:
!
Here is a command that uses -annotate, trying to set a few things beyond the default parameters:
for img in so#12231624-right.png; do
convert \
"${img}" \
-fill red \
-undercolor '#0008' \
-pointsize 24 \
-gravity south \
-annotate +0+5 "${img}" \
"with-annotate-${img}"
done
It's a very old entry but I find it each time I search for this topic, and it doesn't work (for me at least). Here something that works for me:
convert input.jpg -gravity South -annotate 0 '%f' output.jpg
Hope this helps someone...
You can also use mogrify to add text to bunch of images at once.
mogrify -gravity South -annotate 0 '%f' -pointsize 24 -fill white *.png
This will overwrite existing images, so make sure you have a backup before you execute this.
Building on Steve Czetty's solution, it looks like you can set the text size and color of the annotation, using -pointsize and -fill, respectively.
Here's an example:
convert input.jpg -gravity south -pointsize 24 -fill yellow -annotate 0 '%f' output.jpg
Obviously, you can change the text size from 24 points to something else, as well the color, from 'yellow' to some other color, as per your preference.

Resources