duanping2695 2019-04-16 13:24
浏览 121
已采纳

结合不同长度的GIF

I am trying to combine variable length PNG strips into a single GIF using the PHP GD and imagemagick libraries.

For example:

first strip = 4 frames

second strip = 8 frames

third strip = 9 frames

fourth strip = 12 frames

enter image description here = 36 frames

When combining these into one GIF there has to be enough frames for the longest animation, however the shorter animations do not have enough frames.

Right now, if there's not enough frames I just repeat the first frame, however as you would expect this leads to the animations stalling until they all restart:

combined

The number of frames isn't totally random, however it's not always as clean as the examples. There are sets with a couple with 25 frames and the highest 36, and some with frames of 1, 3, 4, 9, 5, 12, 16, 26, etc.

The reasoning for wanting this is to combine all the strips into one big image that showcases a set of strips (with information about the sets themselves on it).

Is there a way of tackling this that I am missing? Or am I best just trying to double the strips until they're all at the highest frame count and removing a few frames here and there and hope no one notices?

Here's a MCVE that shows what I am doing now:

<?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条回答 默认 最新

  • douxiong2999 2019-04-17 07:52
    关注

    The best solution (but the image can be huge) is to use the lowest common multiple of all the frame counts (72 in this case, so not that much), and repeat each image sequence as many times as necessary (18,9,8,6,2).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100