Istrel
Istrel

Reputation: 2588

Merge two gifs one after another, preserving last frame of the first gif as background for second one

I need to merge two ( subsequently many ) gifs with transparent backgrounds. The last frame of the first gif should remain visible when the second one is playing. That is, the second gif should complement, continue the first one. As a result I want to get a continuous graph.

Examples of gifs: gif_1.gif gif_2.gif

I get this result when I simply merge them:

convert gif_1.gif gif_2.gif out.gif

out.gif

As you can see, the second gif overwrites the previous one. But I want to get a continuous graph.

Upvotes: 1

Views: 389

Answers (1)

Mark Setchell
Mark Setchell

Reputation: 207425

I might come up with a better version, but for the moment, I get this:

#!/bin/bash

{
   magick 1.gif -coalesce -write miff:- -delete 0--2 bg.gif
   magick 2.gif[0] bg.gif -compose srcover -composite miff:-
   nFrames=$(magick identify 2.gif | wc -l)
   for ((frame=1;frame<$nFrames;frame++)) ; do
     magick 2.gif -coalesce -swap 0,$frame -delete 1--1 bg.gif -compose srcover -composite miff:-
   done
} | magick miff:- result.gif

enter image description here


By way of explanation...

The whole thing is a pair of bash commands, piped together with |, i.e:

command1 | command2

The first command is actually a compound command inside {...}, i.e.:

{ command1A; command1B; command1C; } | command2

The thing being piped through is a MIFF which is a Magick Image File Format that is capable of holding multiple images - multiple GIF frames in this case.

So, you could read it like this:

{ send a MIFF; send a MIFF; send a MIFF; } | assemble MIFFs

The first magick command separates out the frames of the first GIF, sends them down the pipe and deletes all but the last frame which it saves as the background for the frames of the second GIF.

The second magick command extracts the first frame of the second GIF, composites it over the background and sends it down the pipe as a MIFF.

The next command counts the frames in the second GIF and then iterates over them. For each frame in the second GIF, I move that frame to position zero and then delete all other frames, leaving me with just the selected frame and then composite it over the background and send the result down the pipe.

The final magick command at the end gathers all the frames it has been sent and rebuilds it back into a single sequence.

Upvotes: 2

Related Questions