Комбинировать разную длину гифки - PullRequest
2 голосов
/ 16 апреля 2019

Я пытаюсь объединить полосы PNG переменной длины в один GIF с использованием библиотек PHP GD и imagemagick.

Например:

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 Ответ

3 голосов
/ 17 апреля 2019

Лучшее решение (но изображение может быть огромным) состоит в том, чтобы использовать наименьшее общее кратное из всех подсчетов кадров (в данном случае 72, но не так много) и повторять каждую последовательность изображений столько раз, сколько необходимо (18 , 9,8,6,2).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...