Page 1 of 1

how to speed up convert with label?

Posted: 2015-05-20T06:36:46-07:00
by Albert25
I'm generating pictures with text on a neutral background, to convert to video. Originally, I used something like this:

Code: Select all

time for i in `seq 0 50 `; do \
  convert -background "#666666" -fill "#99CCFF" -font "$font" \
    -size 1920x1080 -gravity center -pointsize $((1080/8)) \
    label:"image $i" $(printf "test-%06d.png" $i); \
done
It takes 31 seconds for the 51 pictures. (on a 6 years old laptop ...)

I then tried tiff. It is much faster ( 8.7 seconds), but the files are over 400 times bigger (16'598K vs 39K).

Adding compression to tiff slows it down, and the files are still much bigger. I tried lzw and zip. With lzw, time went up 25% (10.7 seconds) for a size of 260K. Zip made small files (40K, not much bigger than .png), but time was 16.6 seconds.

Are there any tricks to speed up this image generation? In reality, I'm not generating 50 images, but thousands, so both speed and size do make quite a difference.

Thanks for any suggestions.

(ImageMagick 6.6.9-7 2014-03-06 Q16 on Ubuntu 12.04LTS)

Re: how to speed up convert with label?

Posted: 2015-05-20T19:20:48-07:00
by snibgo
The printf is redundant. The output filename can be simply:

Code: Select all

test-%06d.png
For every image, you are re-starting convert, re-reading the font file so on. It may be quicker to run one long command. "+write" each image, then "-delete" it, and make the next one. So the command would be something like:

Code: Select all

convert -background "#666666" -fill "#99CCFF" -font "$font" \
    -size 1920x1080 -gravity center -pointsize $((1080/8)) \
    label:"image 0" +write test-000000.png -delete \
    label:"image 1" +write test-000001.png -delete \
    label:"image 2" +write test-000002.png -delete \
    label:"image 3" +write test-000003.png -delete \
:     :    :    :
    label:"image 99" +write test-000099.png -delete \
    NULL:

Re: how to speed up convert with label?

Posted: 2015-05-27T05:56:18-07:00
by Albert25
In case anyone is interested, here is what I found after playing with it for a while. The different image formats give very different speed results.

* PNG is very slow, but makes the smallest files
* TIFF uncompressed is fast, but makes huge files
* TIFF compressed slows down proportionally to the compression
* JPEG is fast and makes small files, but of course not exactly identical

For my needs, I settled on JPEG with -quality 100%. For perfect quality, select the TIFF compromise which suits you between speed and file size.

Some statistics produced with this code, which I ran several times ( and averaged the results ):

Code: Select all

time for i in `seq 1 100`; do \
  convert -background "#666666" -fill "#99CCFF" -font "$font" \
    -size 1920x1080 -gravity center -pointsize $((1080/8)) \
    label:"image $i" \
    png:- > /dev/null; \
done
* 100 PNG : 41 sec. (35K files)
* 100 JPEG : 9 sec. (62K) adding "-quality 100%"
* 100 TIFF uncompressed : 8 sec. (but 16.6 MB!)
* 100 TIFF ZIP : 20 sec. (40K) adding "-compress zip"
* 100 TIFF LZW : 16 sec. (255K) adding "-compress lzw"
* 100 TIFF RLE : 13 sec. (8 MB) adding "-compress rle"

I also tried to reduce the depth of the TIFF with "-depth 8", but it almost tripled the time, while only reducing the huge size by half. And "-depth 16", which is the default, actually triggered some extra calcuations, increasing the time by 50% for no reason. So avoid "-depth" if speed matters.

Apart from that, I also tried snibgo's suggestion of stuffing all the iterations into a single convert call. It did gain some more speed (5-20%) for the faster converts, but it makes the code much more complex and hard to read a week later. And on the slow .png convert, it made hardly a difference. Anyway, in case someone wants to try this version, this is what I tested:

Code: Select all

cat <<END1 > run
convert -background "#666666" -fill "#99CCFF" -font "$font" \\
    -size 1920x1080 -gravity center -pointsize $((1080/8)) \\
END1
for i in `seq 1 100`; do cat <<END2 >> run
    label:"image $i" +write "$(printf test-y-%06d.png $i)" +delete \\
END2
done
echo "null: null:" >> run
chmod +x run
time ./run

Re: how to speed up convert with label?

Posted: 2015-05-27T06:20:35-07:00
by snibgo
Speed of writing PNG depends on the type of image, and the "-quality" setting. PNG is always lossless compression, so "-quality" affects speed and size but not actual pixels. For photographs, I find that "-quality 21" is about twice as fast as no quality setting.

Re: how to speed up convert with label?

Posted: 2015-05-27T06:55:58-07:00
by Albert25
Nice tip about -quality. I wasn't aware of that, and indeed, "-quality 21" makes .png creation twice as fast as the default.

Re: how to speed up convert with label?

Posted: 2015-05-27T11:44:03-07:00
by snibgo
For a photograph, a test of all 100 qualities (0 to 99) show the ?8 series eg "-quality 18" is about 3 times as fast as "-quality 21", and only 10% larger.

Your mileage may vary.

Re: how to speed up convert with label?

Posted: 2015-05-27T12:43:34-07:00
by Albert25
Well, it looks like there is no simple rule to remember and use when needed. For my label test, -quality 18 is almost two times slower than -quality 21. So apparently, it must depend on the image content. But it's good to know that this is worth experimenting with before starting a convert of thousands of images.

Re: how to speed up convert with label?

Posted: 2015-05-27T13:04:07-07:00
by snibgo
Yes, image content makes a difference.

Quite possibly, one rule is good for photographs that tend to be "noisy", and another rule is good for images with flat colours plus a little anti-aliasing.