Consider the scenario:
- you have multiple images in different sizes
- you need to add text annotations to all the image such that the text is in a consistent x/y position
- you need to the annotations to be the same size when varoius images are displayed to fit
One solution is to scale all images to a common size and then create our annotation with fixed point size. Whilst this works this is a bit of a hack.
The better solution is to use a font size (and location placement) that is proportional to the size of the image.Great, but trying to perform the calculations for each image in an image editor is cumbersome, time consuming and annoying. But there is another way with ImageMagick - this works on linux and will just need minor tailoring for your platform
Firstly, we will need to determine:
- the font we want to use, if you want to install a new font from google fonts
Note that ImageMagick may not see a different name of your font so verify its name.$ cp font*.ttf ~/.local/share/fonts $ fc-cache -f -v $ fc-list
$ magick -list font ... Font: Oxanium-Bold family: Oxanium glyphs: ~/.local/share/fonts/Oxanium-Bold.ttf Font: Oxanium-ExtraBold family: Oxanium glyphs: ~/.local/share/fonts/Oxanium-ExtraBold.ttf Font: Oxanium-ExtraLight family: Oxanium glyphs: ~/.local/share/fonts/Oxanium-ExtraLight.ttf Font: Oxanium-Light family: Oxanium glyphs: ~/.local/share/fonts/Oxanium-Light.ttf ... - determine the relative position and size of the text, lets say offset 5% from far left and 10% from top
$ for i in in.jpg; do \ magick "$i" \ -fill white -font Oxanium-Regular \ -pointsize "%[fx:w*0.035]" \ -gravity northwest \ -annotate "+%[fx:w*0.05]+%[fx:h*0.10]" \ "$(exiftool -s3 -p '$LensID @ f/$Aperture' "$i")" \ "out-$i" done


And with browser scaled to 75% width, we can see that the text is the same relative size and at the position


Above, we are specifying (via
-pointsize "%[fx:w*0.035]") an arbituary text size that works well enough for my usecase. If we want a true proportional text occupancy width (say 50% of width), we have to do something like:$ for i in in.jpg; do \
IM_TEXT="$(exiftool -s3 -p '$LensID @ f/$Aperture' "$i")"
IM_LEN=${#IM_TEXT}
# IM_CROP="-gravity center -crop 2000x800+0+0 +repage"
# IM_STROKE="-stroke black -strokewidth 2"
magick "$i" \
${IM_CROP} \
-fill white ${IM_STROKE} -font Oxanium-Regular \
-pointsize "%[fx:(w*0.5)/(${IM_LEN}*0.6)]" \
-gravity northwest \
-annotate "+%[fx:w*0.05]+%[fx:h*0.10]" \
"${IM_TEXT}\n%wx%h" \
"out-$i"
done
Another useful and time saving trick is that sometimes you need to crop out centre sections of the image ahead of annotating. This can also be easily achieved by using the
-gravity center -crop ... - using ImageMagick's usual command, you may specify this as absolutes (-crop 2000x800+0+0) or as percentages (-crop 50%x+0+0) etc.
No comments:
Post a Comment