合并不同长度的GIF

时间:2019-04-16 13:24:21

标签: php imagemagick php-gd

我正在尝试使用PHP GD和imagemagick库将可变长度的PNG条带组合到单个GIF中。

例如:

first strip = 4帧

second strip = 8帧

third strip = 9帧

fourth strip = 12帧

enter image description here = 36帧

当将它们组合成一个GIF时,必须有足够的帧才能显示最长的动画,但是较短的动画则没有足够的帧。

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

combined

帧数不是完全随机的,但是并不总是像示例中那样干净。有些组合有一对,每对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");

1 个答案:

答案 0 :(得分:3)

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