ImageMagick (or other) for UTF-8 text to image

I'm trying to create many single-character images using convert. The purpose is to provide a plastics specialist with images to print onto keyboard keycaps.

The ImageMagick documentation suggests something like this:

 printf "\u2318" | convert -size 100x100 label:@- -font unifont-Medium command.png


or

 echo ⌘ | convert -size 100x100 label:@- -font unifont-Medium command.png


or

 convert -size 100x100 label:'⌘' -font unifont-Medium command.png


which is supposed to print the place of interest symbol, but it instead produces a question mark.

I have confirmed (using charmap) that the unifont-Medium fontset actually includes this glyph. I know that other fonts on my system can also provide this glyph, because I could see it before installing unifont, but I've not been able to work out what their name is.

I also tried using LaTeX (e.g. TexLive with all the extras and the utf8x package) but none of the special characters are supported.

There are a lot of forum questions about printing chinese characters with imagemagick and other special characters... the following does work for me:

convert -background lightblue -fill blue -pointsize 32 \
label:' é è à ù ç Ö ÿ ‘ ’ “ ” ° ² ³ € x ÷ '    label_i8n.gif


but it just doesn't work for the UTF-8 characters that are actually important to me.

How can I convert arbitrary unicode characters to images?

UPDATE: I gave up, looks like a bug. Instead, I created a bunch of scripts to generate and render SVG, open sourced here: kinesis-dvorak

• I haven't used it in a long time, but I'm positive you could do this with a simple "script-fu" routine for gimp. This may not be so useful to you unless you are familiar w/ gimp and know either scheme, or another language which ports the plug-in (python, perl, tcl, there may be more) -- but I though I'd throw it out there just in case. – goldilocks Apr 8 '14 at 21:08
• The above didn't work for me either. Seems like a bug in imagemagick, no? – slm Apr 9 '14 at 11:54
• Btw. I've made related question : How to combine multiple fonts into one – Grzegorz Wierzowiecki Aug 31 '17 at 18:10

I tried the same commands and got the same results.

$printf "\u2318" | convert -size 100x100 label:@- \ -font unifont-Medium command.png  Changing to the unicode for the letter G works fine though: $ printf "\u0047" | convert -size 100x100 label:@- \
-font unifont-Medium command.png


I would post this question to the ImageMagick Discourse site to see why this is occurring. I can assist if you're unsure how to do this or proceed.

Debugging convert

You can add the -debug annotate switch to see what convert's up to.

$printf "\u2318" | convert -size 100x100 label:@- -font unifont-Medium -pointsize 40 -debug annotate command.png 2014-04-10T09:37:04-04:00 0:00.020 0.010u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 12 2014-04-10T09:37:04-04:00 0:00.020 0.010u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 6.375; height: 14; ascent: 11; descent: -3; max advance: 24; bounds: 0.625,0 6.78125,8; origin: 7,0; pixels per em: 12,12; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.020 0.010u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 12 2014-04-10T09:37:04-04:00 0:00.020 0.010u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 6.375; height: 14; ascent: 11; descent: -3; max advance: 24; bounds: 0.625,0 6.78125,8; origin: 7,0; pixels per em: 12,12; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.020 0.010u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 24 2014-04-10T09:37:04-04:00 0:00.020 0.010u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 12.75; height: 28; ascent: 22; descent: -5; max advance: 48; bounds: 1.25,0 13.5781,18; origin: 15,0; pixels per em: 24,24; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.020 0.010u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 48 2014-04-10T09:37:04-04:00 0:00.020 0.010u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 25.5156; height: 55; ascent: 43; descent: -10; max advance: 96; bounds: 2.48438,0 27.1406,35.5; origin: 29,0; pixels per em: 48,48; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.020 0.010u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 96 2014-04-10T09:37:04-04:00 0:00.020 0.020u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 53.0312; height: 110; ascent: 87; descent: -20; max advance: 192; bounds: 4.96875,0 54.2812,70; origin: 59,0; pixels per em: 96,96; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.020 0.020u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 96 2014-04-10T09:37:04-04:00 0:00.020 0.020u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 53.0312; height: 110; ascent: 87; descent: -20; max advance: 192; bounds: 4.96875,0 54.2812,70; origin: 59,0; pixels per em: 96,96; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.020 0.020u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 95 2014-04-10T09:37:04-04:00 0:00.020 0.020u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 52.0781; height: 109; ascent: 86; descent: -20; max advance: 190; bounds: 4.92188,0 53.7188,70; origin: 58,0; pixels per em: 95,95; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.020 0.020u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 94 2014-04-10T09:37:04-04:00 0:00.020 0.020u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 51.1406; height: 108; ascent: 85; descent: -20; max advance: 188; bounds: 4.85938,0 53.1562,68; origin: 57,0; pixels per em: 94,94; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.020 0.020u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 93 2014-04-10T09:37:04-04:00 0:00.020 0.020u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 51.1875; height: 107; ascent: 84; descent: -20; max advance: 186; bounds: 4.8125,0 52.5781,67; origin: 57,0; pixels per em: 93,93; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.020 0.020u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 92 2014-04-10T09:37:04-04:00 0:00.020 0.020u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 50.2344; height: 106; ascent: 83; descent: -19; max advance: 184; bounds: 4.76562,0 52.0156,67; origin: 56,0; pixels per em: 92,92; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.020 0.020u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 91 2014-04-10T09:37:04-04:00 0:00.030 0.020u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 50.2969; height: 105; ascent: 82; descent: -19; max advance: 182; bounds: 4.70312,0 51.4531,65.4688; origin: 56,0; pixels per em: 91,91; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.030 0.020u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 90 2014-04-10T09:37:04-04:00 0:00.030 0.020u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 49.3438; height: 103; ascent: 81; descent: -19; max advance: 180; bounds: 4.65625,0 50.8906,65.4688; origin: 55,0; pixels per em: 90,90; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.030 0.020u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 89 2014-04-10T09:37:04-04:00 0:00.030 0.020u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 48.3906; height: 102; ascent: 81; descent: -19; max advance: 178; bounds: 4.60938,0 50.3281,64; origin: 54,0; pixels per em: 89,89; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.030 0.020u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 88 2014-04-10T09:37:04-04:00 0:00.030 0.020u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 48.4375; height: 101; ascent: 80; descent: -19; max advance: 176; bounds: 4.5625,0 49.7656,64; origin: 54,0; pixels per em: 88,88; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.030 0.020u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 87 2014-04-10T09:37:04-04:00 0:00.030 0.020u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 47.5; height: 100; ascent: 79; descent: -18; max advance: 174; bounds: 4.5,0 49.1875,63; origin: 53,0; pixels per em: 87,87; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.030 0.020u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 86 2014-04-10T09:37:04-04:00 0:00.030 0.020u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 47.5469; height: 99; ascent: 78; descent: -18; max advance: 172; bounds: 4.45312,0 48.625,63; origin: 53,0; pixels per em: 86,86; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.030 0.020u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 86 2014-04-10T09:37:04-04:00 0:00.030 0.020u 6.7.8 Annotate convert[16619]: annotate.c/GetTypeMetrics/798/Annotate Metrics: text: ⌘; width: 47.5469; height: 99; ascent: 78; descent: -18; max advance: 172; bounds: 4.45312,0 48.625,63; origin: 53,0; pixels per em: 86,86; underline position: -5.0625; underline thickness: 3.35938 2014-04-10T09:37:04-04:00 0:00.030 0.020u 6.7.8 Annotate convert[16619]: annotate.c/RenderFreetype/1220/Annotate Font /usr/share/fonts/msttcorefonts/arialbd.ttf; font-encoding none; text-encoding none; pointsize 86  UPDATE #1 - Debugging further This issue was irking me so I think I've finally figured it out. The issue is the selection of the font, and it not being able to display that particular glyph. 1. First off you can use this command to see which fonts you have available within convert. So let's start there. $ convert -list font | head -8

Path: /etc/ImageMagick/type-ghostscript.xml
Font: AvantGarde-Book
family: AvantGarde
style: Normal
stretch: Normal
weight: 400
glyphs: /usr/share/fonts/default/Type1/a010013l.pfb
...


The above shows a sample, every font has lines similar to the above. Incidentally, running this command shows we have several hundred fonts:

$convert -list font | grep Font | wc -l 262  2. Next we're going to go through the task of encoding our character, \u2318 using every font we have. This sounds complicated but is fairly trivial with some well thought out one liners via Bash. $ for i in $(convert -list font | grep Font | awk '{print$2}'); \
do convert -font $i -pointsize 36 label:⌘${i}.gif;done


This snippet will use a for loop to run through each font, running a modified version of your convert command.

3. Now we look through the results. Many of the fonts could not display this particular glyph but several could, which would seem to indicate that it's not necessarily a bug in ImageMagick, but rather a limitation of the fonts themselves. Here's a list of the fonts that I had that could display this glyph.

• DejaVu-Sans-Bold
• DejaVu-Sans-Bold-Oblique
• DejaVu-Sans-Book
• DejaVu-Sans-Condensed-Bold
• DejaVu-Sans-Condensed-Bold-Oblique
• DejaVu-Sans-Condensed
• DejaVu-Sans-Condensed-Oblique
• DejaVu-Sans-Mono-Bold
• DejaVu-Sans-Mono-Bold-Oblique
• DejaVu-Sans-Mono-Book
• DejaVu-Sans-Mono-Oblique
• DejaVu-Sans-Oblique
• DejaVu-Serif-Bold
• DejaVu-Serif-Bold-Italic
• DejaVu-Serif-Book
• DejaVu-Serif-Condensed-Bold
• DejaVu-Serif-Condensed-Bold-Italic
• DejaVu-Serif-Condensed
• DejaVu-Serif-Condensed-Italic
• DejaVu-Serif-Italic
• FreeMono-Regular
• FreeSerif-Regular
• STIX-Math-Regular
• STIX-Regular
• VL-Gothic-regular

I visually went through the entire ~260 resulting .gif files to determine which worked and which didn't. Here's a sample of a few of the ones that worked just so you can see them.

References

• thanks so much for the analysis! I gave up... I've updated the question with the eventual solution, which involved using SVG and inkscape to render the fonts to paths. – fommil Apr 12 '14 at 12:37
• @fommil - seems to be a font issue. See updates. – slm Apr 12 '14 at 15:12
• would be pretty nice to have the final command in the answer (selecting the font) – Boris Däppen Jul 22 '15 at 9:25
• For me adding the option -font DejaVu-Sans-Bold helped for tagging an image with the pirate skull: perl -e 'binmode(STDOUT, ":utf8");print "Skull: \x{2620}";' |convert picture_orig.jpg -background none -fill red -pointsize 90 -font DejaVu-Sans-Bold label:@- -flatten picture_tagged.jpg thanks for your superb help! – Boris Däppen Jul 22 '15 at 9:39
• Thanks @slm ! Your answer contributed to my resolution: unix.stackexchange.com/a/389474/9689 – Grzegorz Wierzowiecki Aug 31 '17 at 18:02