Клон, размытие, обрезка и композитный анимированный GIF

Я пытаюсь создать анимированные GIF-файлы из видео YouTube для своего веб-сайта, которые будут содержать видеоинформацию, я хочу клонировать каждый кадр, обрезать его, размыть и скомпоновать его в определенном месте, у меня есть анимация изображения, но клонированные разделы это не так, это как будто он клонирует первый кадр, а затем объединяет его во все кадры, я использую следующий код

$img = "{$dir}{$vidInfo->id}.gif";

if( !file_exists($img) ) {
$grabzIt->SetAnimationOptions("https://www.youtube.com/watch?v={$vidInfo->id}", "{$vidInfo->id}", 320, 180, 0, 5, 2, 10, 0, false, '', 100, "UK");
$grabzIt->SaveTo($img);
}

$image = new Imagick($img);

$image = $image->coalesceImages();

foreach( $image as $frame ) {
$blurred = clone $frame;
$blurred->cropImage(360, 180, 241, 60);
$blurred->blurImage(5,3);
$frame->compositeImage($blurred, imagick::COMPOSITE_OVER, 241, 60);

$blurred = clone $frame;
$blurred->cropImage(320, 20, 0, 0);
$blurred->blurImage(5,3);
$frame->compositeImage($blurred, imagick::COMPOSITE_OVER, 0, 0);

$blurred = clone $frame;
$blurred->cropImage(320, 20, 0, 160);
$blurred->blurImage(5,3);
$frame->compositeImage($blurred, imagick::COMPOSITE_OVER, 0, 160);
}

$image = $image->deconstructImages();
$image->writeImages("{$dir}{$vidInfo->id}_final.gif", true);
echo $image->getImagesBlob();

но получается вот так (обратите внимание, что размытые области статичны)

Я не уверен, что еще делать, я нашел несколько примеров, но они не работают для того, что я пытаюсь сделать, я даже пытался

$blurred->clear();
$blurred->destroy();

после каждого кадра, но это тоже не работает.

любая помощь будет высоко ценится, спасибо

2

Решение

Похоже, в реализации foreach в Imagick есть «ошибка» *. Когда вы делаете это:

foreach ($animationImagick as $frameImagick) {
//whatever
}

$frameImagick объект на самом деле не один кадр, это копия всей анимации с внутренним итератором, настроенным на соответствующий кадр для анимации.

Из-за этого, когда вы возвращаетесь к составному изображению «кадра» в исходное изображение, ImageMagick видит, что это изображение с несколькими внутренними изображениями, и снова сбрасывает внутренний итератор. Это приводит к тому, что первый кадр вставляется постоянно.

Явное отделение изображения кадра от набора анимации изображений решает эту проблему. Кроме того, разумно не изменять данные, которые вы перебираете. Этот код делает оба

$image = new Imagick("./SeriouslyBurned.gif");
$image = $image->coalesceImages();
$newImageFrames = [];
$numberImages = $image->getNumberImages();
$outputImage = new Imagick();


foreach ($image as $frame) {
$frame = $frame->getImage();

$blurred = clone $frame;
$blurred->cropImage(360, 180, 241, 60);
$blurred->blurImage(5,3);
$frame->compositeImage($blurred, imagick::COMPOSITE_OVER, 241, 60);

$blurred = clone $frame;
$blurred->cropImage(320, 20, 0, 0);
$blurred->blurImage(5,3);
$frame->compositeImage($blurred, imagick::COMPOSITE_OVER, 0, 0);

$blurred = clone $frame;
$blurred->cropImage(320, 20, 0, 160);
$blurred->blurImage(5,3);
$frame->compositeImage($blurred, imagick::COMPOSITE_OVER, 0, 160);

$outputImage->addImage($frame);
}

$outputImage->setImageFormat('gif');
$outputImage->writeImages("output_file.gif", true);

* Это, вероятно, технически не ошибка … так как код выполняет то, что ему было сказано. Это просто не то, что кто-то действительно хочет ….

2

Другие решения

Других решений пока нет …