Asked  7 Months ago    Answers:  5   Viewed   34 times

I need to resize an animated GIF file without destroying the animation.

How can I do it using PHP?

 Answers

92

if you have imagemagick access, you can do this:

system("convert big.gif -coalesce coalesce.gif");
system("convert -size 200x100 coalesce.gif -resize 200x10 small.gif");

this is most likely possible with the imagemagick plugin if you don't have system() access

NOTE: this may create a larger filesize though a smaller dimensions image due to coalescing essentially deoptimizing the image.

UPDATE: If you don't have ImageMagick access, you should be able to use a combination of the following steps to resize an animated gif (assuming you have GD access):

  1. Detect if the image is an animated gif: Can I detect animated gifs using php and gd? (top answer)
  2. Split the animated gif into individual frames: http://www.phpclasses.org/package/3234-PHP-Split-GIF-animations-into-multiple-images.html
  3. Resize the individual frames: http://www.akemapa.com/2008/07/10/php-gd-resize-transparent-image-png-gif/
  4. Recomposite the frames into an animated gif again: http://www.phpclasses.org/package/3163-PHP-Generate-GIF-animations-from-a-set-of-GIF-images.html

This is definitely much more intensive than the ImageMagick route, but it should be technically possible.

If you get it working, please share with the world!

Wednesday, March 31, 2021
 
cegfault
answered 7 Months ago
100

It's not possible using the standard GD functions that come pre-packed with PHP.

There is a class on phpclasses.org for this. I have never used it myself, but it's used by a lot of other packages.

Alternatively, if you have access to ImageMagick from PHP, using either the MagickWand library or the command line, use it. With ImageMagick, it's no problem.

  • ImageMagick v6 Animation basics (from the IM manual)

  • Creating an Animated GIF image

Wednesday, March 31, 2021
 
freeMagee
answered 7 Months ago
100

I can suggest combination of imagemagick and ffmpeg

do this to extract each frame as png/jpeg

$magick> convert 'images.gif[0]' image.png

Do this to convert images to movie sequence

ffmpeg -f image2 -i image%d.jpg video.mpg

More help on commands

http://www.imagemagick.org/script/command-line-processing.php

http://www.catswhocode.com/blog/19-ffmpeg-commands-for-all-needs

http://electron.mit.edu/~gsteele/ffmpeg/

Monday, August 9, 2021
 
Adam Rackis
answered 2 Months ago
20

I don't have 2 animated GIFs of the same length, so I'll just use two copies of this one:

enter image description here

Let's look at the frames in there, with this:

identify 1.gif
1.gif[0] GIF 500x339 500x339+0+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[1] GIF 449x339 500x339+51+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[2] GIF 449x339 500x339+51+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[3] GIF 449x339 500x339+51+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[4] GIF 448x339 500x339+52+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[5] GIF 449x339 500x339+51+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[6] GIF 448x339 500x339+52+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[7] GIF 448x339 500x339+52+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[8] GIF 448x339 500x339+52+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[9] GIF 448x339 500x339+52+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[10] GIF 448x339 500x339+52+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[11] GIF 500x339 500x339+0+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[12] GIF 500x339 500x339+0+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[13] GIF 500x339 500x339+0+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[14] GIF 500x339 500x339+0+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[15] GIF 448x339 500x339+52+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[16] GIF 500x339 500x339+0+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[17] GIF 500x339 500x339+0+0 8-bit sRGB 32c 508KB 0.000u 0:00.000

Mmmm, 18 frames with different sizes, that means we need to use -coalesce to rebuild partial frames into full ones.

Let's copy that and make 2.gif

cp 1.gif 2.gif

Now we can split the two gifs into their component frames, like this:

convert 1.gif -coalesce a-%04d.gif     # split frames of 1.gif into a-0001.gif, a-0002.gif etc
convert 2.gif -coalesce b-%04d.gif     # split frames of 2.gif into b-0001.gif, b-0002.gif etc

Now let's join the individual frames side-by-side:

for f in a-*.gif; do convert $f ${f/a/b} +append $f; done

Note that ${f/a/b} is a bash-ism meaning "take the value of f and replace the letter 'a' with 'b'".

And put them back together again:

convert -loop 0 -delay 20 a-*.gif result.gif

That looks longer, and harder, than it is because I tried to explain it all, but it looks like this really:

convert 1.gif -coalesce a-%04d.gif                         # separate frames of 1.gif
convert 2.gif -coalesce b-%04d.gif                         # separate frames of 2.gif
for f in a-*.gif; do convert $f ${f/a/b} +append $f; done  # append frames side-by-side
convert -loop 0 -delay 20 a-*.gif result.gif               # rejoin frames

enter image description here

Note that this conceptual code, not production quality. It doesn't remove the temporary files it creates, nor does it carry the inter-frame time forward from the original GIFs. If you want to get the original frame rate you could get them like this and save them into an array and feed the delays back into the re-animation command at the end:

identify -format "%f[%s] %Tn" 1.gif
1.gif[0] 8
1.gif[1] 8
1.gif[2] 8
1.gif[3] 8
1.gif[4] 8
1.gif[5] 8
1.gif[6] 8
1.gif[7] 8
1.gif[8] 8
1.gif[9] 8
1.gif[10] 11
1.gif[11] 11
1.gif[12] 11
1.gif[13] 11
1.gif[14] 11
1.gif[15] 11
1.gif[16] 11
1.gif[17] 26

Also, you may want a spacer between the two animations, say 10 pixels, which you can do by replacing the convert command inside the for loop with this one:

convert $f -size 10x xc:none ${f/a/b} +append $f

enter image description here

Tuesday, August 10, 2021
 
Pratap Vhatkar
answered 2 Months ago
51

The solution uses a tool called LICEcap, a screen capture utility for Windows and Mac. Steps are following:

  1. Download LICEcap and install it. Now, if you start this program, it will have a rather unusual shape, just a thin frame, and everything inside the frame will be transparent: Enter image description here

  2. Go to the window with your D3.js animation and prepare everything so that you could start animation at some point. Let's say we want to record this example from d3js.org: Enter image description here

  3. Now start LICEcap and position it over the area you want to have in your animated GIF file: Enter image description here

  4. Make sure that you enter at least 20 FPS in the bottom left edit box, otherwise the recording will be low quality. Press record. A dialog will first appear, and you choose here whether you want your GIF file to be in an infinite loop, or just repeated once, or any number of times. Also an interesting option is to add some visual clues for mouse clicks. Choose also filename, and press Save. Enter image description here

  5. Now you do whatever you have to do to trigger animations. I pressed buttons Grouped and Stacked several times. After I decided it's enough, I pressed Stop. The resulting file is: Enter image description here

That's it!

Tuesday, August 10, 2021
 
Manse
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :