18

I was surprised today to find apparently how difficult it is to go from a webp animation to gif animation. My GIMP 2.8.22 and ImageMagick 7.0.7-21 on linux 4.14.13-1-ARCH don't seem to support the format, and the only tool available in repos seem to be libwebp 0.4.1 which includes a decode tool that lets you extract individual frames to some image formats, none of them being gif (It's a licensing problem maybe?)

Anyway, I used the following script:

#!/bin/bash

DELAY=${DELAY:-10}
LOOP=${LOOP:-0}
r=`realpath $1`
d=`dirname $r`
pushd $d > /dev/null
f=`basename $r`
n=`webpinfo -summary $f | grep frames | sed -e 's/.* \([0-9]*\)$/\1/'`
pfx=`echo -n $f | sed -e 's/^\(.*\).webp$/\1/'`
if [ -z $pfx ]; then
    pfx=$f
fi

echo "converting $n frames from $f 
working dir $d
file stem '$pfx'"

for ((i=0; i<$n; i++)); do
    webpmux -get frame $i $f -o $pfx.$i.webp
    dwebp $pfx.$i.webp -o $pfx.$i.png
done

convert $pfx.*.png -delay $DELAY -loop $LOOP $pfx.gif
rm $pfx.[0-9]*.png $pfx.[0-9]*.webp
popd > /dev/null

Which creates a gif animation from the extracted frames of the file supplied in the first argument.

I tried it on this file and the resulting file was kind of artifacty. Is it proper form to post in this forum for suggestions of improvement of the procedure/invocations?

And: If there are custom tools for this conversion, please share your knowledge! :)

5
  • 1
    This seems like a question better suited for Code Review (still not off topic!)
    – Stan Strum
    Jan 26, 2018 at 17:13
  • 3
    I would think keep it here because *nix users wondering about this conversion would have a better change finding it here and thus benefit from the discussion?
    – lash
    Jan 26, 2018 at 17:29
  • I have the same question as you, and I was happy to find this (+1). You have two answers, but you have not accepted either of them. Did the answers not work, did you solve it yourself, lose interest & move on or what...? I don't mean to be nosey, just trying to avoid putting time into this if it doesn't work.
    – Seamus
    May 30, 2020 at 10:20
  • The best technique I've found so far is here: stackoverflow.com/questions/59977561/…
    – NateT
    Jun 12, 2020 at 21:39
  • Gimp 2.10.20 supports conversion. see this link on youtube. youtube.com/watch?v=6T3mp0EoxBA
    – George
    Jul 10, 2020 at 10:44

4 Answers 4

13

Running into the same issue myself, I found that using Python and its Pillow library might be the easiest way. Just import it, let it load the image file, and directly save it again with appropriate options.

from PIL import Image
im = Image.open('your_file.webp')
im.save('your_file.gif', 'gif', save_all=True, optimize=True, background=0)

Tested with Python3.8 and Pillow 8.0.1. You might have to install or upgrade the library first, using e.g. python3 -m pip install --user --upgrade Pillow

All on one line to batch convert all *.webp files in the current folder to *.gif with the same name:

for f in *.webp;do echo "$f";python3 -c "from PIL import Image;Image.open('$f').save('${f%.webp}.gif','gif',save_all=True,optimize=True,background=0)";done

Note: This answer was inspired by Stack Overflow.

3
8

Your script works just fine, but you need to zero pad your individual frame names; otherwise it creates the gif with frames in a jumbled order. I fixed that and tried it on a few giphy webp animations (including your example) and the output is what you'd expect.

Below is just your script with two changes. First, an altered for loop to zero pad those frame filenames. Second, I added another webpinfo check to grab the frame duration and use that (if > 0) for DELAY (naively assuming that people aren't using variable frame durations):

#!/bin/bash

DELAY=${DELAY:-10}
LOOP=${LOOP:-0}
r=`realpath $1`
d=`dirname $r`
pushd $d > /dev/null
f=`basename $r`
n=`webpinfo -summary $f | grep frames | sed -e 's/.* \([0-9]*\)$/\1/'`
dur=`webpinfo -summary $f | grep Duration | head -1 |  sed -e 's/.* \([0-9]*\)$/\1/'`

if (( $dur > 0 )); then
    DELAY = dur
fi

pfx=`echo -n $f | sed -e 's/^\(.*\).webp$/\1/'`
if [ -z $pfx ]; then
    pfx=$f
fi

echo "converting $n frames from $f 
working dir $d
file stem '$pfx'"

for i in $(seq -f "%05g" 1 $n)
do
    webpmux -get frame $i $f -o $pfx.$i.webp
    dwebp $pfx.$i.webp -o $pfx.$i.png
done

convert $pfx.*.png -delay $DELAY -loop $LOOP $pfx.gif
rm $pfx.[0-9]*.png $pfx.[0-9]*.webp
popd > /dev/null
7

I would have used ffmpeg for this task. Have a look at this thread which should give you good results.

I tried with the mp4 of the gif from giphy and obtained this gif below as a result, which looks pretty good in my opinion!

mkdir frames
ffmpeg -i giphy.mp4 -vf scale=320:-1:flags=lanczos,fps=10 frames/ffout%03d.png
convert -loop 0 frames/ffout*.png output.gif

enter image description here

3
  • 4
    I have the same problem as the OP - I need to convert animated webp-to-gif. I would like to use ffmpeg & was drawn to your answer. But I must be missing something. You appear to be converting from mp4-to-gif. If you could enlighten me, I'd appreciate it.
    – Seamus
    May 30, 2020 at 10:16
  • 1
    I indeed converted mp4-to-gif (as it is possible to download mp4 from giphy). For webp-to-gif, you need to extract frames first (you can use the method described in this answer) using anim_dump then use ffmpeg to convert it back to a mp4 video (eg. using ffmpeg -framerate 25 -i dump_%04d.tiff output.mp4)
    – MRousse
    Jun 5, 2020 at 14:42
  • 5
0

The bulk of your script can be replaced using the anim_dump binary, which is included in libwebp along with webpmux, dwebp, etc.

#!/bin/bash

f="/path/to/my.webp"
mkdir $f.frames
anim_dump -folder $f.frames  $f
convert $f.frames/*.png -delay 10 -loop 0 $f.gif
/bin/rm -fr $f.frames

Not the answer you're looking for? Browse other questions tagged or ask your own question.