Generating timer animations

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
wsdookadr
Posts: 2
Joined: 2016-05-11T02:45:04-07:00
Authentication code: 1151

Generating timer animations

Post by wsdookadr »

Hi,

I wrote a script that generates timer animations. So just an animation displaying the time in HH:MM:SS format, with some labels beneath to indicate hours/minutes/seconds.

The main idea in the script is to cache all possible two-digit combinations (with padding), and then reusing those to form MM:SS and then finally HH:MM:SS with the labels underneath.

It's written in Bash and is meant to be run on Linux.

Some more information (I'll add more soon):
- 1h of final frames is 15MB, so a full day would be 360MB
- generating one MM:SS frame takes 17ms
- generating one HH:MM:SS frame takes 149ms
- generating the timer animation with 60 frames takes 3 seconds

I thought it would be interesting to share it here.
One interesting question that I was wondering about would be how to make this faster.

Any suggestions are welcome

Code: Select all

#!/bin/bash
#
# This script generates timers.
#
DIM="300x200"
generate_cached_groups() {
    rm -rf cached
    mkdir cached
    for g in $(seq -w 0 99); do
        convert -background black -font /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc -fill white -size x60 -density 192 label:"$g" \
        cached/$g.png
    done
}

#
# generate MM:SS frames 
#
generate_frames_MS() {
    rm -rf cached_MS
    mkdir cached_MS
    for M in $(seq -w 0 59); do
        for S in $(seq -w 0 59); do
            convert \
              -size $DIM xc:None \
              -background None \
              \( cached/$M.png -geometry +0+0 \) -composite \
              \( cached/$S.png -geometry +70+0 \) -composite \
            cached_MS/$M\_$S.png
        done
    done
}

generate_frames_HMS() {
    rm -rf cached_HMS
    mkdir cached_HMS
    SNIPPET_TEXT="-background transparent -font /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc -fill white -size x25 -density 192"
    for H in $(seq -f "%02g" 0 0); do
        for M in $(seq -f "%02g" 0 59); do
            for S in $(seq -f "%02g" 0 59); do
                convert \
                  -size $DIM xc:None \
                  -background None \
                  \( cached/$H.png -geometry +0+0 \) -composite \
                  \( cached_MS/$M\_$S.png -geometry +70+0 \) -composite \
                  \( $SNIPPET_TEXT -geometry +0+60 label:"hours" \) -composite \
                  \( $SNIPPET_TEXT -geometry +70+60 label:"minutes" \) -composite \
                  \( $SNIPPET_TEXT -geometry +140+60 label:"seconds" \) -composite \
                cached_HMS/$H\_$M\_$S.png
            done
        done
    done
}

assemble_gif() {
    START="00_01_00"
    END="00_02_00"
    FRAMES=$(ls cached_HMS/ | sort | START=$START END=$END perl -ne 'print "cached_HMS/$_" if $_ ge $ENV{START} && $_ le $ENV{END}')
    convert -delay 100 $FRAMES -loop 0 timer.gif
}

echo "" > generate.log
echo `date +"%Y-%m-%d %H:%M:%S"`" Generating cached groups" | tee -a generate.log
generate_cached_groups
echo `date +"%Y-%m-%d %H:%M:%S"`" Generating frames MS" | tee -a generate.log
generate_frames_MS
echo `date +"%Y-%m-%d %H:%M:%S"`" Generating frames HMS" | tee -a generate.log
generate_frames_HMS
echo `date +"%Y-%m-%d %H:%M:%S"`" Assembling the gif" | tee -a generate.log
assemble_gif
echo `date +"%Y-%m-%d %H:%M:%S"`" Done" | tee -a generate.log



Here's also the resulting timer:

Image

User avatar
fmw42
Posts: 26269
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Generating timer animations

Post by fmw42 »

You can trade storage space vs compression speed. PNG is a bit slow. You could try saving as uncompressed TIFF (or zip or lzw compressed) or as PGM from NetPBM or even MIFF.

Check the output and possibly add -type grayscale to ensure it is 8-bit per pixel rather than 24-bit.

Post Reply