Search code examples
unixtextimagemagickpng

Generate a PNG from a long text, with constraints


My need is to be able to generate a transparent PNG of a quite long text (let's say 3000 characters) in less than one second.

My constraints :

  • text has to autowrap according to the width of the .png and the size of the font
  • a 3000 characters text is generated in less than 1s
  • converter can handle any .ttf font
  • converter can handle custom font pointsize, custom density, font color, line spacing, characters kerning
  • transparent background
  • has to work on Unix

I tried with Imagemagick with 'caption' feature, as in :

convert -background transparent -font /home/user/fonts/Arial.ttf -density 72 -pointsize 24 -kerning 0 -interline-spacing 0 -size 500x caption:'My very long text ...' output.png

It works like a charm for small texts, but a 3000 characters text will generate in 16s and I could not find a way to optimize it. I tried every '-quality' option from 0 to 100, without any success.

For example, 791 characters at quality 15 took 3.45s. It's roughly the same time from quality 0 to quality 100.

convert -background transparent -font Arial.ttf -density 72 -pointsize 24 -size 500x caption:"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec malesuada lorem ante, ut venenatis leo venenatis vitae. Phasellus imperdiet volutpat egestas. Nunc lobortis nunc ante, sagittis sagittis ex aliquet sed. Maecenas tempus velit eu leo cursus aliquam. Donec vel purus eget massa lacinia gravida vel vitae elit. Aliquam volutpat ex non purus aliquam, vel faucibus sem molestie. Quisque tincidunt, nulla sed fermentum condimentum, mauris arcu euismod nibh, nec lobortis tortor lorem id quam. Ut pretium lacinia risus id pretium. Suspendisse sit amet dolor ac odio convallis pulvinar vitae ac erat. Nam non congue tellus. Nulla laoreet at justo eget convallis. Phasellus rutrum turpis sed neque vulputate pharetra. Mauris fringilla tincidunt dui, in scelerisque urna sagittis sit amet." -quality 15 /tmp/test.png
quality 15 : 3.4526860713959 s

It tried GraphicksMagick (as mentionned in this thread Slow font rendering in ImageMagick), but I could not make it compile with --with-ttf option even though freefont2 is installed on my server). I dropped here.

I also tried to generate a small .svg containing my text and convert it to .png with rsvg tool. It is really faster, but does not meet my constraint of autowrapping (it would require another piece of code to make the wrap itself, which I do not want).

I have a reduced timeframe to find a solution, so I cannot test every other possible way myself (try another way to optimize IM ? node.js with text2png or node-canvas ? a small java app ? ...).

Has anyone had this kind of constraints and could gently provide a hint on a working solution ?


Version of ImageMagick

Version: ImageMagick 6.8.9-9 Q16 x86_64 2018-11-11 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2014 ImageMagick Studio LLC
Features: DPC Modules OpenMP
Delegates: bzlib cairo djvu fftw fontconfig freetype jbig jng jpeg lcms lqr ltdl lzma openexr pangocairo png rsvg tiff wmf x xml zlib

Version of GraphicksMagick tested

GraphicsMagick 1.3.31 2018-11-17 Q8 http://www.GraphicsMagick.org/
Copyright (C) 2002-2018 GraphicsMagick Group.

Solution

  • I tried with libvips on this modest 2015 laptop running Ubuntu. You should be able to find vips in your package manager (libvips-tools on Debian, for example):

    $ time vips text x.png "$(cat lorem.txt)" --width 500 --rgba
    real    0m0.084s
    user    0m0.062s
    sys 0m0.022s
    

    Generating:

    enter image description here

    Where:

    $ wc lorem.txt 
      9  429 2975 lorem.txt
    

    So 2975 characters of text in 0.1s.

    The text operator has a lot of options, so it should meet your constraints.