ImageMagick convert - Label text over alpha background - imagemagick

I'm trying to place a copyright message on a large batch of PNG images. I'd like to place the message in the bottom-right corner in black text on a semi-transparent white background. Here's my Windows command line script which loops through the images and runs a ImageMagick convert & composite pipeline:
for %%f in (*.png) do (
convert -background "#FFFFFF80" -font verdana -fill black ^
label:" (c) 2015 My Company " miff:- ^
| composite -compress zip -gravity SouthEast ^
-geometry +0+0 - "%%f" "credited\%%f.png" )
The white background with 50% (0x80) opacity is working well, but when the label text renders into the image, there's a horrible grey in the background of the characters. Here is an example by just running the initial convert into a PNG.
Is this a bug or am I missing something important in IM alpha channel management?

Running these commands on OSX with version 6.9.0-0 Q16 x86_64 2014-12-06:
convert -background '#ffffff80' -font verdana \
-size 360 -fill black label:"Hello World" hw1.png
convert -background '#00000080' -font verdana \
-size 360 -fill black label:"Hello World" hw2.png
convert -background '#ff000080' -font verdana \
-size 360 -fill black label:"Hello World" hw3.png
composite hw1.png -geometry +100+10 hw2.png comp12.png
composite hw1.png -geometry +100+10 hw3.png comp13.png
produces the following images:

Related

align text to left with imagemagick

I am using ImageMagick to add text to an image. I used to -gravity Center flag to put the text in the center of the image. But I think this is resulting in the text being center aligned too. I want the text at the center of the image but left aligned. Here is an example of what I'm trying to have:
This is the output I'm getting:
Current output
This is what I want:
This is my requirement
How do I accomplish this? This is my first time using ImageMagick. Please guide me.
Here is one way to do that in Imagemagick 6. I specify the background color, the font color (fill), the font and the pint-size and gravity west (left side). I use label: to create the two lines of text with a new line between them. This creates a text image of the size needed to hold the text. Then I pad the image all around that to the final size with the text image in its center using the same background color.
convert -background black -fill white -font ubuntu -pointsize 28 -gravity west label:"This is line 1 of text\nThis is line 2 of text" -gravity center -extent 400x300 result.png
See
https://imagemagick.org/Usage/text/
https://imagemagick.org/Usage/crop/#extent
ADDITION
If you want to put the text over an existing image, then you do something similar, but in place of the extent, we composite the text image over the background image.
The following is Unix syntax. For Window, remove the backslashes \ before the parentheses.
Input:
convert lena.png \( -background black -fill white -font ubuntu -pointsize 21 -gravity west label:"This is line 1 of text\nThis is line 2 of text" \) -gravity center -compose over -composite result.png
Result:
Or if you do not want the black background, use "none" for the color.
convert lena.png \( -background none -fill white -font ubuntu -pointsize 21 -gravity west label:"This is line 1 of text\nThis is line 2 of text" \) -gravity center -compose over -composite result2.png

Captioning all frames of a gif

I have a simple bash script to caption still images (jpg, png...) but it completely fails when given an animated gif. The error is convert: unable to write pixel cache '/tmp/magick-[random chars]': No space left on device # error/cache.c/WritePixelCachePixels/5854. There are many questions similar to mine, however they use specific coordinates to determine where the text should be placed (at least, I think). My script creates a dynamically sized caption area for the text to be written to. The image is appended to the bottom of the caption area (or the caption area is prepended to the top of the image, however you want to think about it.)
#!/bin/bash
input=$1
caption=$2
output=$3
wd=`convert $input -format "%w" info:`
convert \( -size ${wd}x -background white -gravity north -fill black -font FuturaBT-ExtraBlackCondensed -pointsize $(($wd/17)) \
caption:"$caption" \) \
$input \
-append $output
You can also do this in Imagemagick.
convert anim.gif -coalesce \
-gravity north -background white \
-splice 0x18 -font Arial -pointsize 12 -annotate +0+0 'THIS IS A TEST OF CAPTIONING TEXT' \
-layers Optimize anim3.gif
In Imagemagick you will need to create a text image from your caption and then use -layers composite to apply it to your animation.
Input GIF Animation:
Imagemagick 6 Unix Syntax:
convert \( anim.gif -coalesce \) null: \( -size 100x -background white -gravity north -fill black caption:"THIS IS A TEST OF CAPTIONING TEXT ON AN ANIMATION" \) -compose over -layers composite -layers optimize anim2.gif
For Windows, remove the \s
For Imagemagick 7, change convert to magick.

How to draw a image on top of a shape

Simplified example:
I do create a cirlce like following:
magick convert -size 256x256 xc:none -fill #FFFFFF -draw "circle 128,128 256,128" +profile "icc" out.png
And I do convert a given image like following:
magick convert in.png -background none -gravity center -resize 181x181 +profile "icc" out.png
Question:
In my examples above I do have following "core" functions:
-size 256x256 xc:none -fill #FFFFFF -draw "circle 128,128 256,128" +profile "icc"
in.png -background none -gravity center -extent 181x181 +profile "icc"
How can I combine those images WITHOUT saving the first one to a temporary file? I want to create a 256x256 output image, draw the circle to this image and then draw the converted input image on top of the circle (centered).
My current solution
Create 2 different images and combine them like following:
magick convert -composite -gravity Center out1.png out2.png out.png
EDIT - FULL EXAMPLE
PS Script looks like following:
$in = ".\in.png"
$out1 = ".\tmp1.png"
$out2 = ".\tmp2.png"
$out = ".\out.png"
// 1) create circle image
magick convert -size 256x256 xc:none -fill #FFFFFF -draw "circle 128,128 256,128" +profile "icc" PNG32:$out1
// 2) convert input image
magick convert $in -background none -gravity center -resize 181x181 +profile "icc" -colorspace Gray -fill "#E91FCB" -colorize 50 PNG32:$out2
// 3) combine circle + converted image
magick convert -composite -gravity Center $out1 $out2 PNG32:$out
// 4) delete temp. images
Remove-Item $out1
Remove-Item $out2
Input Image:
Output Image (not visible, but it has the white circle as background + a transparent background otherwise):
You can use parenthesised processing like this:
magick -size 256x256 xc:none -fill white -draw "circle 128,128 256,128" \( in.png -background none -gravity center -resize 181x181 -colorspace Gray -fill "#E91FCB" -colorize 50 \) -composite result.png
On Windows, omit the \ before parentheses.

Composite not transferring color in imagemagick7 vs imagemagick6

I build my app store icons using imagemagick. The process has been working for years with imagemagick6. The final step in the icon building proceed is to composite a blue square with white text and a rounded white rectangle. When I upgraded to imagemagick7, the final step produced a rounded black icon with white text. Here's the code in my shell script:
# build a file with the two text lines centered with different, large point sizes for each
# then resize to the proper width
convert\
-gravity center\
-background transparent\
-fill white\
-font ArialB\
-pointsize ${TEXTSIZE} label:"${TEXT}"\
-pointsize ${TEXT2SIZE} label:"${TEXT2}"\
-append\
-resize $TEXTWIDTH\
tmpText.png
# build a background image with a radial gradient
convert\
-gravity center\
-size ${ICONSIZE}x${ICONSIZE} radial-gradient:"rgb(0,50,255)"-"rgb(0,0,127)"\
tmpBase.png
# combine the two
composite\
-gravity center\
tmpText.png tmpBase.png $FILENAME
In imagemagick7 the final two files tmpText.png and tmpBase.png look correct, but the output does not. I tried several variations of the compositing step to no avail. I finally downgraded back to imagemagick6, and things started working again, but that's not a long-term solution. Any ideas?
With ImageMagick 7, replace convert with magick. Also replace composite with magick composite.
So for IM 6:
convert\
-gravity center\
-background transparent\
-fill white\
-font ArialB\
-pointsize 24 label:"Testing1"\
-pointsize 24 label:"Testing2"\
-append\
-resize 200% \
tmpText.png
# build a background image with a radial gradient
convert\
-gravity center\
-size 500x500 radial-gradient:"rgb(0,50,255)"-"rgb(0,0,127)"\
tmpBase.png
# combine the two
composite\
-gravity center\
tmpText.png tmpBase.png fred_test6.png
I get:
And for IM 7
magick\
-gravity center\
-background transparent\
-fill white\
-font ArialB\
-pointsize 24 label:"Testing1"\
-pointsize 24 label:"Testing2"\
-append\
-resize 200% \
tmpText.png
# build a background image with a radial gradient
magick\
-gravity center\
-size 500x500 radial-gradient:"rgb(0,50,255)"-"rgb(0,0,127)"\
tmpBase.png
# combine the two
magick composite\
-gravity center\
tmpText.png tmpBase.png fred_test7.png
I get:

Get geometry of text on an image

I'd like to draw a text onto an image in a way like this:
convert -quality 100 -font Oswald-Regular -pointsize 515 -fill black -draw "text 1339.0,1099 'some text'" /tmp/ascript.png /tmp/ascript.png
and I need to know the dimensions of the text with the above parameters (size, font, text). How can I get that?
I tried something like this:
convert -size 5000x1500 xc:lightblue -font Oswald-Regular -pointsize 515 -fill none -undercolor white -annotate +20+100 'some text' -trim info:
but it's giving false result:
xc:lightblue XC 1834x250 5000x1500+19+0 16-bit sRGB 0.010u 0:00.000
.
What is the proper way (or a working way) to get the dimension of a drawn image based on this 3 parameters (font, size, text)?
I'm not strictly binded to ImageMagick, it can be any command line tool for the Linux shell, however, the text will be drawn by convert.
There are a couple simple ways to get the dimensions using ImageMagick with commands like this...
convert -size 5000x1500 xc:lightblue -font Oswald-Regular -pointsize 515 \
-fill none -undercolor white -annotate +20+100 'some text' \
-format "%[#]\n" info:
That uses the FX escape "%#" as the formatting string for the "info:" output. It will show IM's calculation of the after-trim width, height, horizontal offset, and vertical offset like "WxH+X+Y".
This similar command just gives the width and height of the trimmed text...
convert -size 5000x1500 xc:lightblue -font Oswald-Regular -pointsize 515 \
-fill none -undercolor white -annotate +20+100 'some text' \
-trim +repage -format "%[w]x%[h]\n" info:
That will trim the text, reset the paging geometry with "+repage", then output a string showing "WxH".
––– Edited to Add –––
I tried your image with_text.png with these commands. The output immediately follows each command...
convert with_text.png -format "%[#]\n" info:
1807x389+512+115
convert with_text.png -trim +repage -format "%[w]x%[h]\n" info:
1807x389
Those were tested with IMv6.8.9-9 on ubuntu bash on Windows 10. If you use that actual image and those commands, I'm not sure why you would get different results.

Resources