Positioning layers - imagemagick

At the moment I'm working on a quite comprehensive (well at least for me) imagemagic task. I want to add some annotations i extract from exif-data and adding an overlay image.
At the moment i'm having the following code:
convert -verbose source.jpg \
-pointsize 32 -fill white -undercolor '#00000070' -gravity NorthWest -annotate +10+10 "some exif data"\
-pointsize 32 -fill white -undercolor '#00000070' -gravity North -annotate +10+10 "more exif data"\
-pointsize 32 -fill white -undercolor '#00000070' -gravity NorthEast -annotate +10+10 "even more exif data"\
-gravity South overlay.png \
-layers flatten \
-quality 95 destination.jpg;
The annotation works fine including the position. But i stuck with the overlay. It seems the the "-gravity South" doesn't work here. It stuck on the upper left corner. What do i have to change to get the overlay to the bottom and centered?
Bonus question: How to get the overlay semitransparent?

You should use -composite rather than -flatten with your convert:
convert -verbose source.jpg \
-pointsize 32 -fill white -undercolor '#00000070' -gravity NorthWest -annotate +10+10 "some exif data"\
-pointsize 32 -fill white -undercolor '#00000070' -gravity North -annotate +10+10 "more exif data"\
-pointsize 32 -fill white -undercolor '#00000070' -gravity NorthEast -annotate +10+10 "even more exif data"\
-gravity South overlay.png -composite \
result.jpg
If you want the overlay semi-transparent, use:
convert -verbose source.jpg \
-pointsize 32 -fill white -undercolor '#00000070' -gravity NorthWest -annotate +10+10 "some exif data"\
-pointsize 32 -fill white -undercolor '#00000070' -gravity North -annotate +10+10 "more exif data"\
-pointsize 32 -fill white -undercolor '#00000070' -gravity NorthEast -annotate +10+10 "even more exif data"\
\( -gravity South overlay.png -channel A -fx "0.5" \) -composite \
result.jpg
By the way, -pointsize, -fill, and -undercolor are "settings", so they remain set until changed, so you don't need to repeat them:
convert -verbose source.jpg -pointsize 32 -fill white -undercolor '#00000070' \
-gravity NorthWest -annotate +10+10 "some exif data"\
-gravity North -annotate +10+10 "more exif data"\
-gravity NorthEast -annotate +10+10 "even more exif data"\
\( -gravity South overlay.png -channel A -fx "0.5" \) -composite \
result.jpg

You need to add overlay with composite not convert.
convert -verbose source.jpg \
-pointsize 32 -fill white -undercolor '#00000070' -gravity NorthWest -annotate +10+10 "some exif data"\
-pointsize 32 -fill white -undercolor '#00000070' -gravity North -annotate +10+10 "more exif data"\
-pointsize 32 -fill white -undercolor '#00000070' -gravity NorthEast -annotate +10+10 "even more exif data"\
-layers flatten \
-quality 95 destination.jpg;
and then:
composite -gravity South overlay.png destination.jpg result.jpg
More on composite here.
Edit: Best way would be to use ImageMagick intermediate save format miff and pipelining. This will save extra steps of read/write from disk.
convert -verbose source.jpg \
-pointsize 32 -fill white -undercolor '#00000070' -gravity NorthWest -annotate +10+10 "some exif data"\
-pointsize 32 -fill white -undercolor '#00000070' -gravity North -annotate +10+10 "more exif data"\
-pointsize 32 -fill white -undercolor '#00000070' -gravity NorthEast -annotate +10+10 "even more exif data"\
-layers flatten \
-quality 95 miff:- | \
composite -gravity South overlay.png miff:- destination.jpg

Related

How to rotate text with imagemagick?

I have a long image source pic and I want to add text to every subimage, but when add text to the book, I failed, the final image and code:
convert src.jpg -gravity north -pointsize 53 -fill white -annotate +0+520 "I love you,don't leave me " -annotate +0+1146 "Do not be a programmer,ok?" -annotate +0+1772 "fuck u!" -annotate +0+3024 "too simple " -draw 'translate 340,3340 rotate 21 text 0,0 "Javascript Action"' final.jpg
Can any one help? Thanks
For your example, you should use -annotate for all the text placements and rotations in Imagemagick rather than using -draw for the last one. This will keep your last text from going off the image. Try this:
convert src.jpg -gravity north -pointsize 53 -fill white -annotate +0+520 "I love you,don't leave me " -annotate +0+1146 "Do not be a programmer,ok?" -annotate +0+1772 "xxxx x" -annotate +0+3024 "too simple " -gravity north -annotate 21x21+0+3340 "Javascript Action" final1.jpg
See https://imagemagick.org/script/command-line-options.php#annotate
Please do not use vulgarisms in examples.
If you want to have text wrap, then you need to use caption: to create a new image with transparent background for each text. Then composite the new text image onto your background image at the desired locations. You can control when it wraps, by the -size Wx argument. Here I use the full width of your image, that is, -size 1000x.
convert src.jpg \
-pointsize 53 -background none -fill white -size 1000x \
\( -gravity center caption:"I love you,don't leave me" \) -gravity north -geometry +0+420 -compose over -composite \
\( -gravity center caption:"Do not be a programmer,ok?" \) -gravity north -geometry +0+1046 -compose over -composite \
\( -gravity center caption:"xxxx x" \) -gravity north -geometry +0+1672 -compose over -composite \
\( -gravity center caption:"too simple" \) -gravity north -geometry +0+2924 -compose over -composite \
\( -gravity center caption:"Javascript Action" -rotate 21 \) -gravity north -geometry +0+3240 -compose over -composite \
final2.jpg
Or to make it wrap earlier than the width of the your image, I set -size 500x
convert src.jpg \
-pointsize 53 -background none -fill white -size 500x \
\( -gravity center caption:"I love you,don't leave me" \) -gravity north -geometry +0+420 -compose over -composite \
\( -gravity center caption:"Do not be a programmer,ok?" \) -gravity north -geometry +0+1046 -compose over -composite \
\( -gravity center caption:"xxxx x" \) -gravity north -geometry +0+1672 -compose over -composite \
\( -gravity center caption:"too simple" \) -gravity north -geometry +0+2924 -compose over -composite \
\( -gravity center caption:"Javascript Action" -rotate 21 \) -gravity north -geometry +0+3240 -compose over -composite \
final3.jpg
See
https://imagemagick.org/Usage/text/#caption
https://imagemagick.org/Usage/layers/#convert
ADDITION:
To blur the text, just add -blur after caption:
convert src.jpg \
-pointsize 53 -background none -fill white -size 500x \
\( -gravity center caption:"I love you,don't leave me" -blur 0x3 \) -gravity north -geometry +0+420 -compose over -composite \
\( -gravity center caption:"Do not be a programmer,ok?" -blur 0x3 \) -gravity north -geometry +0+1046 -compose over -composite \
\( -gravity center caption:"xxxx x" -blur 0x3 \) -gravity north -geometry +0+1672 -compose over -composite \
\( -gravity center caption:"too simple" -blur 0x3 \) -gravity north -geometry +0+2924 -compose over -composite \
\( -gravity center caption:"Javascript Action" -blur 0x3 -rotate 21 \) -gravity north -geometry +0+3240 -compose over -composite \
final4.jpg

Using Imagemagick to add 2 text strings with drop shadow to a background

I am trying to place 2 annotated texts onto a background in different locations and give the text font shadow. A single text works fine, but when I add the second, it blurs the background and the rest of the image.
Here is the image results: https://imgur.com/a/VW09KIy
The first command works as expected:
convert ~/.backgrounds/White.jpg -font Bitter -pointsize 72 -annotate +130+170 'Anthony' -blur 0x4 -fill white -annotate +125+165 'Anthony' font_shadow_fuzzy.jpg
The second messes everything up and I need to know how I fix it.
convert ~/.backgrounds/White.jpg -font Bitter -pointsize 72 -annotate +130+170 'Anthony' -blur 0x4 -fill white -annotate +125+165 'Anthony' -annotate +230+270 'Anthony' -blur 0x4 -fill white -annotate +225+265 'Anthony' font_shadow_fuzzy.jpg
The problem you are having with your Imagemagick command is that the second -blur affects the first text. So you need to separate the processing for each text and put it on a transparent background. Then flatten the two results onto a white background.
The following works for me with Imagemagick 6.9.10.9 Q16 Mac OSX Sierra:
convert \
\( -size 600x400 xc:none -font ubuntu -pointsize 72 -fill black -annotate +130+170 'Anthony' -blur 0x4 -fill white -annotate +125+165 'Anthony' \) \
\( -size 600x400 xc:none -font ubuntu -pointsize 72 -fill black -annotate +230+270 'Anthony' -blur 0x4 -fill white -annotate +225+265 'Anthony' \) \
-background white -flatten \
font_shadow_fuzzy.jpg
Uploading does not seem to be working at this time, so here is a link to the result:
http://www.fmwconcepts.com/misc_tests/font_shadow_fuzzy.jpg
You did not say how big your white background image was. So if I assume it is 600x400, then I will create one and modify the command. You could use any other background, but need to know how big it is for the transparent background to your text.
convert -size 600x400 xc:white white.jpg
convert white.jpg \
\( -size 600x400 xc:none -font ubuntu -pointsize 72 -fill black -annotate +130+170 'Anthony' -blur 0x4 -fill white -annotate +125+165 'Anthony' \) \
\( -size 600x400 xc:none -font ubuntu -pointsize 72 -fill black -annotate +230+270 'Anthony' -blur 0x4 -fill white -annotate +225+265 'Anthony' \) \
-flatten \
font_shadow_fuzzy2.jpg
Or, for any arbitrary background that is larger than where you want to place your text, you can find the dimensions and do the processing as follows:
infile="white.jpg"
dim=`convert "$infile" -format "%wx%h" info:`
convert "$infile" \
\( -size $dim xc:none -font ubuntu -pointsize 72 -fill black -annotate +130+170 'Anthony' -blur 0x4 -fill white -annotate +125+165 'Anthony' \) \
\( -size $dim xc:none -font ubuntu -pointsize 72 -fill black -annotate +230+270 'Anthony' -blur 0x4 -fill white -annotate +225+265 'Anthony' \) \
-flatten \
font_shadow_fuzzy3.jpg
One other way to do this is to make two small text images with your shadow as separate images on a white background. The black blurred text would have and offset of +5+5 and the white unblurred text would have offsets of +0+0. Do this for both images, then composite them onto your background white image at the desired offsets using -geometry for the offsets.

ImageMagick: inter-line spacing with captions creates cutoff's

I'm using the following command to create a caption. But I want to control the interline spacing as well. When I set the value to negative (to get the lines closer to eachother), the first line gets it's capital letters cut off. I tried added a "border", but that just adds a border - doesn't add "padding". Is there a way to add "padding"?
convert templates/input.pdf -font test.ttf
-size 1245x283! -background red -fill white -gravity northwest
-interline-spacing -25
caption:"Interline-Spacing NOT WORKING\r\nwith Captions"
-geometry +129+129 -composite output/temp.png
In ImageMagick, you can set the -gravity center, then use -trim +repage, if you want to remove excess around the text and then add any amount of border back using -border or -extent if you know the desired output size.
Try this using unix syntax:
convert \( -size 2115x560 xc:skyblue \) \( -size 1245x283! -background red -fill white -gravity center -font arial -interline-spacing -25 caption:"Interline-Spacing NOT WORKING\r\nwith Captions" -trim +repage -background red -extent 1245x283! \) -gravity northwest -geometry +129+129 -composite temp.png
or this in Windows:
convert ( -size 2115x560 xc:skyblue ) ( -size 1245x283! -background red -fill white -gravity center -font arial -interline-spacing -25 caption:"Interline-Spacing NOT WORKING\r\nwith Captions" -trim +repage -background red -extent 1245x283! ) -gravity northwest -geometry +129+129 -composite temp.png
If you want the white text left justified, then use -gravity west before -extent and -gravity west before the caption:
convert \( -size 2115x560 xc:skyblue \) \( -size 1245x283! -background red -fill white -gravity west -font arial -interline-spacing -25 caption:"Interline-Spacing NOT WORKING\r\nwith Captions" -trim +repage -background red -gravity west -extent 1245x283! \) -gravity northwest -geometry +129+129 -composite temp2.png
Replace your input image in place of my -size 2115x560 xc:skyblue and your font for mine.
I would guess the interline spacing is from the base line of the text up. Lower letters will protrude below the base line. I suppose it is more of a "line height"
The obvious solution is to either increase the spacing to allow for capital letters or do not use capital letters.
A setting of -15 seems to work for what you are doing.

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

Create text mask using ImageMagick

I need to create an image from some background and text, like:
I try
convert -size 320x100 xc:transparent \
-font Arial -pointsize 72 -tile "bg.jpg" \
-annotate +28+68 'Some text' clear.png
but this does not work.
Use the following command:
magick -gravity center input.jpg ( +clone -threshold 101% -fill white -font berlin-sans-fb-bold -pointsize 124 -draw "text 0,0 Hello" ) -alpha off -compose copyopacity -composite -trim output.png

Resources