Specifying a font with the font family using ImageMagick
Asked Answered
G

2

10

Is it possible to render a font using the font family in ImageMagick?

I have tried everything I can think of and nothing seems to work. I have done a lot of searching and I can't seem to find anything that addresses this specific issue.

I am ultimately using PHP, but I have also tried using ImageMagick on the command line with no success. I am using ImageMagick 6.7.6 on linux. Here is what I have done so far.

  • I have tested the fonts that ImageMagick reckognizes using the identify -list font command
  • I have manually created a type.xml file based on the xml files that came installed on my system
  • I have created a type.xml file using this script: imagick_type_gen
  • I have tested with multiple font types: ttf, otf, pfb, ttc

Here is the example output from identify -list font for some fonts I have tested with:

Font: DejaVu-Sans-Book
  family: DejaVu Sans
  style: Normal
  stretch: Normal
  weight: 400
  glyphs: /usr/share/fonts/dejavu/DejaVuSans.ttf

Font: Baskerville-Regular
  family: Baskerville
  style: Normal
  stretch: Normal
  weight: 400
  glyphs: /usr/share/fonts/custom/Baskerville.ttc

Font: Palatino-Roman
  family: Palatino
  style: Normal
  stretch: Normal
  weight: 400
  glyphs: /usr/share/fonts/urw-fonts/p052003l.pfb

Font: Honey-Script-Light
  family: Honey Script
  style: Normal
  stretch: Normal
  weight: 300
  glyphs: /usr/share/fonts/custom/HoneyScript-Light.ttf


If I specify the full font name everything works as expected:

convert -pointsize 32 -font "Honey-Script-Light" label:'Testing' testing.png

Working


However, when I try to use the font family (both listed by identify -list font and listed in type.xml) I get the default system font:

convert -pointsize 32 -family "Honey Script" label:'Testing' testing.png

Not Working


I have also tried specifying all of the font's parameters and it again does not work:

convert -pointsize 32 -stretch Normal -style Normal -weight 300 -family "Honey Script"   label:'Testing' testing.png



When I do a similar process through PHP, it actually returns an error as soon as I try to set the font family of the draw object.

$draw->setFontFamily('Honey Script');

This is the error that gets thrown:

PHP Fatal error:  Uncaught exception 'ImagickDrawException' with message 'Unable to set font family; parameter not found in the list of configured fonts



Just like the command line option, if I specify the full font name, the image is rendered properly.

$draw->setFont('Honey-Script-Light');



From everything I have found about how to configure a font to be used with ImageMagick, the fonts are indeed configured. Why can't I select the fonts based on the font family?

Is this possibly an undocumented bug? Is there something I am missing?

I realize that I could simply specify the full font name and be done with it, but there is a reason specific to my project that make it much better to specify the font family.

Why would specifying the font family be an option if it does not work? This is what ImageMagick says regarding the font family option:

This setting suggests a font family that ImageMagick should try to use for rendering text. If the family can be found it is used; if not, a default font (e.g., "Arial") or a family known to be similar is substituted (e.g., "Courier" might be used if "System" is requested but not found).

Any ideas are very welcome. I am pretty much stuck at this point.


EDIT:
The main reason I would prefer to use font families rather than fully named fonts is because of the input I am processing. I receive files from a third party that need to be processed. These files specify fonts as:

font-family="Honey Script" font-style="Normal" font-stretch="Normal" font-weight="300"

If I had to specify the exact font name based on that information I would need to create a mapping for every possible combination of font family and attributes to the exact font name. That would be very difficult to maintain as hundreds of fonts are added to the system.

It seems to me that there must be a way to get ImageMagick to retrieve the exact font based on all the available details about the font as listed above.

If that is not possible then why would ImageMagick have the option to specify font family at all?

Graiae answered 14/5, 2012 at 3:26 Comment(3)
I've always thought font family is just a way of specifying the first font of a family. So, for the font "Honey Script", the actual font selected would be the first Honey Script font that is listed when you do a font listing with convert list. That said, I notice some SVG files I'm working with from Inkscape do indeed only have a family specified in text elements. Inkscape does seem to select a sensible font from that family, so it might be worth doing some research on how its renderer (Pango) does it?Trencher
I'm not even getting the first font in the family. I've also tried fonts where there is only a single font in the family. I might look into how other programs do it, but that still doesn't explain why ImageMagick does not. I have not been able to find a configuration for ImageMagick using the Imagick PECL extension that lets me specify any font family without throwing an exception.Graiae
It looks pretty definitive that this doesn't work. Personally, I would write a conversion routine that takes a family, style, weight etc and tries to auto-determine the font required. A small list of exceptions can deal with the awkward cases, and where no defaults are listed, the first in the list should be chosen. I suspect this is one of the things that has to be tried to see if it would be appropriate - but shouldn't take too long to write.Trencher
G
5

Here is method that outputs as image(into browser) all available Imagick fonts

 public function test_fonts(){
    //load background
    $im = new Imagick();
    $im->newimage(800, 10000, 'lightgray');
    $y = 10;
    $i = 1;
    foreach($im->queryFonts() as $font){
        $insert_image = new Imagick();
        $insert_image->newImage(600, 30, 'whitesmoke');
        $insert_image->setImageFormat("png");
        $draw = new ImagickDraw();
        $draw->setFont($font);
        $draw->setFontSize(25);
        $draw->setFillColor(new ImagickPixel('black'));
        $draw->setgravity(imagick::GRAVITY_NORTH);
        $insert_image->annotateImage($draw, 0, 0, 0, $i . '.' .  $font );
        $im->compositeImage( $insert_image,  $insert_image->getImageCompose(),100, $y);
        $y += 30;
        $i++;
    }
    $im->setImageFormat('jpg');
    header('Content-Type: image/jpg');
    echo $im;

}

You should see something like this: enter image description here

Gravelblind answered 6/11, 2014 at 9:34 Comment(1)
Thanks, but that doesn't really help with my issue. I need to be able to specify a font based on the font family rather than the font name. The font names are different in different platforms, such as windows and linux. That makes a cross platform script difficult to manage. I have yet to find an answer to this question, which makes me think that no answer exists. I really don't understand why those functions even exist if they do not work.Graiae
L
2

This is due to how font families work; for instance, the "Arial" font family comprises specific font definitions for bold, italic, underlines, etc. You must be specific when choosing a font to use in your images.

I'm guessing that if you really wanted to, you could do the following:

  1. Take the font family name, replace spaces with dashes
  2. If that works, great!
  3. If not, append -Regular to the end and try again

But you shouldn't do anything programmatic with font family unless you're forced to ;-)

My source of imagick knowledge mostly comes from this guy: http://valokuva.org/?cat=1

Loritalorn answered 14/5, 2012 at 3:39 Comment(7)
But if I specify the exact style, stretch, and weight along with the font family, shouldn't ImageMagick be able to determine exactly what font to use?Graiae
Probably because stretch, style and weight can be applied to any font; it still requires a specific font.Tamarah
Unfortunately it's not that simple for many fonts. Fonts use different terminologies and conventions for naming weight, style and stretch. Some need spaces replaced with dashes and some need spaces removed. Here are some other examples of fonts that don't map at well all, Younglove ES -> Young-Love-ES-Regular, JaneAusten -> JaneAusten-NoSecret, Footlight MTight -> Footlight-MT-Light-Regular, Trebuchet -> TrebuchetMS, Scriptina - Alternates -> ScriptinaAlternates, Retsyn -> RetsynDilated. I'm sure there are plenty others that have non-standard mappings.Graiae
Why would ImageMagick have an option to specify font family if there is no circumstance it can be used?Graiae
@Graiae You make a good point. I've tried looking for this online, but there are not many useful posts about it either :( so I've bumped up your question to see if anyone else knows what's the rationale.Tamarah
Yeah, I looked as well. I found surprising little. Most of the suggestions were like yours, just don't use the font family. There are cases where that would work fine, but I have an automated process that needs to handle a great deal of fonts.Graiae
Thanks for the link. I hadn't found that. I'll look into it.Graiae

© 2022 - 2024 — McMap. All rights reserved.