Search code examples
bashimagemagickanimated-gif

imagemagick convert individual frame delay in gif


I have a directory full of images I want to turn into a gif.

Each file name follows this pattern: <zero_padded_index>_<delay_in_milliseconds>.gif

Example: 00001_1432.gif

I can create the gif animation with imagemagick: convert -loop 0 -delay 10 *.gif out.gif

The problem is, I want each frame to have a different delay based on the second digit in it's name.

convert -delay 0 -loop 0 *.gif output.gif

for gif in *.gif; do

    name=${gif%.gif}
    index=$(echo ${name%-*} | sed 's/0*//')
    delay=${name#*-}

    # 1. convert milliseconds to w/e imagemagick -delay uses.
    # 2. update the frame at the correct index.

done;

Do I incrementally build up the gif? Or go back and change them after the fact? My imagemagick chops are not up to par.


Solution

  • So If I was approaching this problem i'd do the following ( If I understand correctly )

    Given the following files:

    [root@dev7 ~]# ls -lta so/
    total 728
    drwxr-xr-x   2 root root   4096 Aug 13 18:35 .
    dr-xr-x---. 17 root root   4096 Aug 13 18:35 ..
    -rw-r--r--   1 root root  18933 Aug 13 18:23 00007_1432.gif
    -rw-r--r--   1 root root  18594 Aug 13 18:23 00006_1432.gif
    -rw-r--r--   1 root root  18984 Aug 13 18:23 00005_1432.gif
    -rw-r--r--   1 root root  19601 Aug 13 18:23 00004_1444.gif
    -rw-r--r--   1 root root  19408 Aug 13 18:23 00003_1432.gif
    -rw-r--r--   1 root root  18632 Aug 13 18:23 00002_1552.gif
    -rw-r--r--   1 root root  20104 Aug 13 18:23 00001_1432.gif
    [root@dev7 ~]# 
    

    My script would look like this:

    #!/bin/bash -x
    
    # directory of the individual gifs
    _dir=/root/so/
    
    # get gifs and make sure your sort them in order
    gifs=$(find $_dir -name *.gif|sort|xargs)
    
    # this is going to be the imagemagick command
    _CONVERT="convert "
    
    # make sure the list of gifs look correct
    echo $gifs
    
    for gif in $gifs; do
    
        # full path of each gif
        full_path=$gif
    
        # get just the name of the gif ( originally I was going to use this if everything was happing within the same directory )
        name=$(echo ${gif##*/})
        #echo -e "\n$name"
    
        # Get the index
        index=$(echo ${gif##*/} | cut -d\_ -f1)
        #echo -e "\n$index"
    
        # Get the delay of the current image
        delay=$(echo ${gif##*/} | cut -d\_ -f2| sed "s,.gif,,")
        # echo -e "\n$delay"
    
        # add correct delay options to current gif, append to existing command
       _CONVERT="${_CONVERT} -delay $delay $gif " 
    
    done;
    
    # add the outpt of where you're going to put your gif
    _CONVERT="${_CONVERT} -loop 0 -layers Optimize /root/so/stackoverflow.gif"
    
    # show full command
    echo "Convert cmd: $_CONVERT"
    
    # run it, then go get your image
    eval $_CONVERT
    

    Example of the command that gets generated:

    Convert cmd: convert  -delay 1432 /root/so/00001_1432.gif  -delay 1552 /root/so/00002_1552.gif  -delay 1432 /root/so/00003_1432.gif  -delay 1444 /root/so/00004_1444.gif  -delay 1432 /root/so/00005_1432.gif  -delay 1432 /root/so/00006_1432.gif  -delay 1432 /root/so/00007_1432.gif  -layers Optimize /root/so/stackoverflow.gif
    

    Hope this is what you're looking for.