想象一下:从动画GIF中删除帧?

时间:2022-11-22 09:00:58

I am trying to understand how to remove frames from an animated GIF.

我试图了解如何从动画GIF中删除帧。

Currently I am trying this (as a test):

目前我正在尝试这个(作为测试):

$count = 1;
foreach ($_im AS $frame) {
    if ($count > 1) { $frame->removeImage(); }
    $count++;        
}

However this seems to toast everything in the object.

然而,这似乎是对象中的一切。

Suggestions from workmates have been to just create another IM object, and extract a famee into it, etc. That seems extremely messy however.

来自同事的建议只是创建另一个IM对象,然后将其中的一个famee提取出来,等等。但这似乎非常混乱。

2 个解决方案

#1


I've been going through the Imagick documentation for a while, and tried a couple of things... But I didn't manage to do what you want either -- so, we are at least two who can't find out a clean way ^^

我已经浏览了Imagick文档了一段时间,并尝试了几件事......但我没有设法做你想做的事 - 所以,我们至少有两个人找不到了干净的方式^^

Anyway, the only way I managed to remove a frame for an animated GIF image was by creating a new one, containing only the frames I didn't want to remove :-(

无论如何,我设法删除动画GIF图像的帧的唯一方法是创建一个新的,只包含我不想删除的帧:-(


Considering I loaded an image this way :

考虑到我以这种方式加载图像:

// Load the existing image
$image = new Imagick(dirname(__FILE__) . '/animated-gif-source.gif');

(This is an animated gif, with 3 frames ; I want to "remove" the second one).

(这是一个动画gif,有3帧;我想“删除”第二个)。


As I said, only way I found to "remove a frame" is this one :

正如我所说,我发现“删除框架”的方法就是这样:

$new_image = new Imagick();

$i = 1;
foreach ($image as $frame) {
    if ($i===1 || $i===3) {
        // 3 frames ; we keep the first and third one
        // ie, remove the second one
        $new_image->addImage($frame->getImage());
    }
    $i++;
}

So :

  • create a new image
  • 创建一个新的图像

  • iterate over the frames of the orignal one
  • 迭代原始帧的帧

  • if the current frame is one I want to keep, copy it to the new image
  • 如果当前帧是我想保留的帧,则将其复制到新图像


And, in the end, to output the image to the browser :

并且,最后,将图像输出到浏览器:

// To directly output to the browser
header('Content-Type: image/gif');
echo $new_image->getImagesBlob();

Or, to write it to a file :

或者,将其写入文件:

// To write the new image to a file
// Must use writeImages, and not writeImage (multi-frames ! )
$new_image->writeImages(dirname(__FILE__) . '/animated-gif-output.gif', true);

Each one of these outputs only contain the first and third frames ; so, it's working...
But, as you said, it doesn't feel good :-(

这些输出中的每一个仅包含第一帧和第三帧;所以,它的工作......但是,正如你所说,它感觉不舒服:-(


It will probably work just fine for most images, I think ; you might encouter troubles with big images, but animated GIFs are generally not that big... are they ?

我认为它对大多数图像都可能正常工作;你可能会遇到大图像的麻烦,但动画GIF通常不是那么大......是吗?


Other way might be using convert from the command line... But... not that great, and I didn't find a way to just remove a frame with those either :-(

其他方式可能是从命令行使用转换......但是......不是很好,我没有找到一种方法来删除框架与这些:-(

#2


I have only used the command line utilities for IM.

我只使用IM的命令行实用程序。

convert srcImage.gif[0] dstImage.gif

转换srcImage.gif [0] dstImage.gif

Should do the trick unless I forgot an option.

除非我忘了一个选项,否则应该这样做。

[0] referes to the first frame of the animated gif.

[0]引用动画gif的第一帧。

#1


I've been going through the Imagick documentation for a while, and tried a couple of things... But I didn't manage to do what you want either -- so, we are at least two who can't find out a clean way ^^

我已经浏览了Imagick文档了一段时间,并尝试了几件事......但我没有设法做你想做的事 - 所以,我们至少有两个人找不到了干净的方式^^

Anyway, the only way I managed to remove a frame for an animated GIF image was by creating a new one, containing only the frames I didn't want to remove :-(

无论如何,我设法删除动画GIF图像的帧的唯一方法是创建一个新的,只包含我不想删除的帧:-(


Considering I loaded an image this way :

考虑到我以这种方式加载图像:

// Load the existing image
$image = new Imagick(dirname(__FILE__) . '/animated-gif-source.gif');

(This is an animated gif, with 3 frames ; I want to "remove" the second one).

(这是一个动画gif,有3帧;我想“删除”第二个)。


As I said, only way I found to "remove a frame" is this one :

正如我所说,我发现“删除框架”的方法就是这样:

$new_image = new Imagick();

$i = 1;
foreach ($image as $frame) {
    if ($i===1 || $i===3) {
        // 3 frames ; we keep the first and third one
        // ie, remove the second one
        $new_image->addImage($frame->getImage());
    }
    $i++;
}

So :

  • create a new image
  • 创建一个新的图像

  • iterate over the frames of the orignal one
  • 迭代原始帧的帧

  • if the current frame is one I want to keep, copy it to the new image
  • 如果当前帧是我想保留的帧,则将其复制到新图像


And, in the end, to output the image to the browser :

并且,最后,将图像输出到浏览器:

// To directly output to the browser
header('Content-Type: image/gif');
echo $new_image->getImagesBlob();

Or, to write it to a file :

或者,将其写入文件:

// To write the new image to a file
// Must use writeImages, and not writeImage (multi-frames ! )
$new_image->writeImages(dirname(__FILE__) . '/animated-gif-output.gif', true);

Each one of these outputs only contain the first and third frames ; so, it's working...
But, as you said, it doesn't feel good :-(

这些输出中的每一个仅包含第一帧和第三帧;所以,它的工作......但是,正如你所说,它感觉不舒服:-(


It will probably work just fine for most images, I think ; you might encouter troubles with big images, but animated GIFs are generally not that big... are they ?

我认为它对大多数图像都可能正常工作;你可能会遇到大图像的麻烦,但动画GIF通常不是那么大......是吗?


Other way might be using convert from the command line... But... not that great, and I didn't find a way to just remove a frame with those either :-(

其他方式可能是从命令行使用转换......但是......不是很好,我没有找到一种方法来删除框架与这些:-(

#2


I have only used the command line utilities for IM.

我只使用IM的命令行实用程序。

convert srcImage.gif[0] dstImage.gif

转换srcImage.gif [0] dstImage.gif

Should do the trick unless I forgot an option.

除非我忘了一个选项,否则应该这样做。

[0] referes to the first frame of the animated gif.

[0]引用动画gif的第一帧。