How to extract frames of an animated GIF with PHP

2019-01-14 04:21发布

问题:

I search for a long time how to extract frames from an animated GIF with PHP... unfortunaly I just found how to get their duration...

I really need to extract the GIF frames and their duration to apply some resize, rotate, etc, on each and then to regenerate the GIF with edited frames !

I don't want to use any software, external library (like ImageMagick), just PHP: in fact I need to allow my class http://phpimageworkshop.com/ to work with animated GIF.

If you have any idea, I'm listening you ^^ !

回答1:

I spent my day creating a class based on this one to achieve what I wanted using only PHP!

You can find it here: https://github.com/Sybio/GifFrameExtractor

Thanks for your answers!



回答2:

Well, I don't really recommend doing it this way, but here's an option. Animated gifs are actually just a number of gifs concatenated together by a separator, "\x00\x21\xF9\x04". Knowing that, you simply pull the image into PHP as a string, run an explode, and loop through the array running your transformation. The code could look something like this.

$image_string = file_get_contents($image_path);

$images = explode("\x00\x21\xF9\x04", $image_string);

foreach( $images as $image ) {
  // apply transformation
}

$new_gif = implode("\x00\x21\xF9\x04", $images);

I'm not 100% sure of the specifics of re-concatenating, the image, but here's the wikipedia page regarding the file format of animated GIFs.



回答3:

I am the author of https://github.com/stil/gif-endec library, which is significantly faster (about 2.5 times) at decoding GIFs than Sybio/GifFrameExtractor library from accepted answer. It has also less memory usage, because it allows you to process one frame after another at decode time, without loading everything to memory at once.

Small code example:

<?php
require __DIR__ . '/../vendor/autoload.php';

use GIFEndec\Events\FrameDecodedEvent;
use GIFEndec\IO\FileStream;
use GIFEndec\Decoder;

/**
 * Open GIF as FileStream
 */
$gifStream = new FileStream("path/to/animation.gif");

/**
 * Create Decoder instance from MemoryStream
 */
$gifDecoder = new Decoder($gifStream);

/**
 * Run decoder. Pass callback function to process decoded Frames when they're ready.
 */
$gifDecoder->decode(function (FrameDecodedEvent $event) {
    /**
     * Write frame images to directory
     */
    $event->decodedFrame->getStream()->copyContentsToFile(
        __DIR__ . "/frames/frame{$event->frameIndex}.gif"
    );
});


回答4:

I don't want to use any software, external library (like ImageMagick)

Well, good luck with that, because 90% of the functionality the Zend Engine exports to the PHP runtime comes from libraries.

If you have any idea, I'm listening you ^^ !

Parse the binary data in the GIF format. You could use unpack(), among other things.