组合不同长度的 GIF

Combine different length GIFs

我正在尝试使用 PHP GD 和 imagemagick 库将可变长度的 PNG 片段组合成单个 GIF。

例如:

= 4 帧

= 8 帧

= 9 帧

= 12 帧

= 36 帧

当将这些组合成一个 GIF 时,最长的动画必须有足够的帧,但是较短的动画没有足够的帧。

现在,如果没有足够的帧,我只是重复第一帧,但是正如您所预料的那样,这会导致动画停顿,直到它们全部重新启动:

帧数并非完全随机,但并不总是像示例中那样干净。有情侣25帧最高36帧的,也有1、3、4、9、5、12、16、26等帧的

想要这样做的原因是将所有条带组合成一个大图像,展示一组条带(上面有关于集合本身的信息)。

有没有办法解决我所缺少的这个问题?还是我最好只是尝试将条带加倍,直到它们都达到最高帧数,然后在这里和那里删除一些帧,希望没有人注意到?

这是一个显示我现在正在做的 MCVE:

<?php
$pngStrips = [
    "happy" => "https://i.stack.imgur.com/oq3Ex.png",
    "shocked" => "https://i.stack.imgur.com/AeoEs.png",
    "mk" => "https://i.stack.imgur.com/Ka6ho.png",
    "dance" => "https://i.stack.imgur.com/lZan3.png",
    "bored" => "https://i.stack.imgur.com/JiIN9.png"
];

$height = 130 * ceil(count($pngStrips) / 6);
$width = 150 * count($pngStrips);

// Set up the showase background gif (simplified to blank white for MCVE)
$background = imagecreatetruecolor($width, $height);
imagealphablending($background, true);
imagefill($background, 0, 0, imagecolorallocatealpha($background, 255, 255, 255, 0));

// Download from external source and split into frames and resize
$highestFrames = 0;
foreach($pngStrips as $name => $URL){    
    file_put_contents("./mcve/" . $name . ".png", file_get_contents($URL));

    $dim = getimagesize("./mcve/" . $name . ".png");

    exec("convert -crop " . $dim[1] . "x" . $dim[1] . " ./mcve/" . $name . ".png ./mcve/" . $name . "_frame_%02d.png");
    exec("convert ./mcve/" . $name . "_frame_*.png -thumbnail 90x90^ -gravity center -extent 90x90 ./mcve/" . $name . "_frame_%02d_resized.png");

    $frames = $dim[0] / $dim[1];

    if($frames > $highestFrames) $highestFrames = $frames;
}

// Every frame of the main gif
for($i = 0; $i < $highestFrames; $i++ ){
    $xcoord = 20;
    $ycoord = 5;
    $count = 1;

    // Make a new frame
    $frame = imagecrop($background, array('x'=>0,'y'=>0,'width'=>imagesx($background),'height'=>imagesy($background)));

    // Add the appropriate frame to this frame of the main gif
    foreach($pngStrips as $name => $URL) {
        $frameFile = "./mcve/" . $name . "_frame_" . sprintf("%02d", $i) . "_resized.png";
        if(!file_exists($frameFile)){
            $frameFile = "./mcve/" . $name . "_frame_00_resized.png";
        }

        $powerImage = imagecreatefrompng($frameFile);

        imagecopymerge($frame, $powerImage, $xcoord, $ycoord, 0, 0, 90, 90, 100);

        $xcoord += 145;

        if($count % 6 == 0){
            $xcoord = 20;
            $ycoord += 130;
        }
        $count++;
    }

    // Save frame
    imagepng($frame, "./mcve/final_frame_" . sprintf("%02d", $i) . ".png");
}

// Into 1 big gif
exec("convert -loop 0 ./mcve/final_frame_*.png ./mcve/final.gif");

header('Content-Type: image/gif');
echo file_get_contents("./mcve/final.gif");

最好的解决方案(但图像可能很大)是使用所有帧数的最小公倍数(在本例中为 72,所以不是那么多),并根据需要重复每个图像序列多次(18,9,8,6,2).