47

我需要在不破坏动画的情况下调整动画 GIF 文件的大小。

我怎样才能使用 PHP 做到这一点?

4

13 回答 13

65

如果你有 imagemagick 访问权限,你可以这样做:

system("convert big.gif -coalesce coalesce.gif");
system("convert -size 200x100 coalesce.gif -resize 200x10 small.gif");

如果您没有 system() 访问权限,这很可能使用 imagemagick 插件

注意:这可能会通过较小尺寸的图像创建较大的文件大小,因为合并本质上会取消优化图像。

更新: 如果您没有 ImageMagick 访问权限,您应该能够使用以下步骤的组合来调整动画 gif 的大小(假设您有 GD 访问权限):

  1. 检测图像是否为动画 gif:我可以使用 php 和 gd 检测动画 gif 吗?(最佳答案)
  2. 将动画 gif 拆分为单独的帧:http ://www.phpclasses.org/package/3234-PHP-Split-GIF-animations-into-multiple-images.html
  3. 调整各个帧的大小:http ://www.akemapa.com/2008/07/10/php-gd-resize-transparent-image-png-gif/
  4. 再次将帧重新合成为动画 gif:http ://www.phpclasses.org/package/3163-PHP-Generate-GIF-animations-from-a-set-of-GIF-images.html

这绝对比 ImageMagick 路线密集得多,但在技术上应该是可行的。

如果你得到它的工作,请与世界分享!

于 2009-04-05T07:09:13.897 回答
12

试试GDEnhancer(使用ImageCraft)。它只需要GD库,它保留了gif动画

于 2013-08-28T09:26:36.923 回答
11

您需要将 gif 分解为帧、缩略图并重新组合。

看看ImageMagick本教程

于 2009-04-05T07:08:20.373 回答
6

我尝试了许多使用 Imagick PHP 模块调整动画 GIF 大小的示例,但没有一个对我有用。然后经过一段时间的调试,我终于发现了实际问题:动画在将图像保存到磁盘时丢失了,$animation->writeImage($file_dst);或者 $animation->writeImages($file_dst, true);

我已将其更改为 file_put_contents($file_dst, $animation->getImagesBlob()); 大多数示例立即开始工作。

希望它可以帮助某人。

于 2013-03-13T17:55:55.823 回答
4

http://www.php.net/manual/en/imagick.coalesceimages.php上的示例将调整您的 gif 大小,同时保留您的帧时间。大多数其他示例都没有这样做。

其他示例重建gif,而此示例允许您修改图像的帧。

于 2012-02-22T06:20:41.023 回答
3

如果您安装了 ImageMagick,那么您可以使用一次调用convert

system("convert big.gif -coalesce -repage 0x0 -resize 200x100 -layers Optimize small.gif");
于 2015-04-20T13:34:18.417 回答
2

我想我已经把这个放在包里了。

这个解决方案绝不是完美的,并且到处都包含一些蛮力,但我能够在我的基于 GD / PHP 的图像调整大小脚本中附加足够的功能来支持动画。

该解决方案很大程度上基于 László Zsidi 的优秀免费软件库 - http://www.phpclasses.org/browse/author/283569.html

您可以查看一个快速演示并从http://forssto.com/gifexample/下载源代码(直接链接: http: //forssto.com/gifexample/gifanimresize.zip

已知的问题:

  • 透明度支持 - 这很容易附加到此解决方案中,但由于我没有立即需要它,所以我停在这里。

  • 帧速率 - 由于某些未知原因,GifEncoder 类未能考虑指定的帧速率。我稍后需要调查一下。

  • 我确实从我的一组测试中找到了一个 gif 文件,其中不知何故有不同大小的帧,并且动画无法正常工作。然后还有一些调试要做。

于 2011-03-22T13:52:07.777 回答
1

只需创建 3 个文件夹名称 1.frame_output 2.images 3.resized_frame_output 并从以下链接下载 2 个编码器和解码器类 1.从http://phpclasses.elib.com/browse/package下载类“GIFDecoder.class.php” /3234.html 2.从http://phpclasses.betablue.net/browse/package/3163.html 下载类“GIFEncoder.class.php”

然后运行脚本名称为“resize_animator.php”,创建一个上传html文件并享受脚本。

..将此脚本另存为.....index.php.......

<html>
<body>
<table width="500" border="0" align="center" cellpadding="0" cellspacing="1" bgcolor="#CCCCCC">
<tr>
<form action="resize_animator.php" method="post" enctype="multipart/form-data" >
<td>
<table width="100%" border="0" cellpadding="3" cellspacing="1" bgcolor="#FFFFFF">
<tr>
<td align="center"><font face="Tahoma">SELECT ANIMATED FILE</font> 
<input type="file" name="uploadfile" size="20" accept="image/gif"/>
</td>
</tr>
<tr>
<td align="center"><input type="submit" name="Submit" value="PROCESS ANIMATION" /></td>
</tr>
</table>
</td>
</form>
</tr>
</table>
</body>
</html>

......................将此脚本保存为resize_animator.php............

   <?php

   require "GIFDecoder.class.php";
   include "GIFEncoder.class.php";
   $file_name= $_FILES['uploadfile']['name'];
   $file_ext = substr($file_name, -4);
   $file_size=($_FILES["uploadfile"]["size"] /1024 );
   if($file_ext=='.gif')
    {
 if($file_size > 0 && $file_size < 2000 )
  {
    session_start ( );
        $uploaded_file = $_FILES['uploadfile']['tmp_name'];
        $fp=file_get_contents($uploaded_file);

        if ( $fp )
            {
                $_SESSION['delays'] = Array ( );
                $gif = new GIFDecoder ( $fp );
                $arr = $gif->GIFGetFrames ( );
                $_SESSION [ 'delays' ] = $gif -> GIFGetDelays ( );

                for ( $i = 0; $i < count ( $arr ); $i++ )
                {
                        fwrite ( fopen ( ( $i < 10 ? "frame_output/$i$i_frame.gif" : "frame_output/$i_frame.gif" ), "wb" ), $arr [ $i ] );
                }
          }

        function resize_frames($newwidth,$newheight)
            {
                    $dir=opendir("frame_output/");
                    $i=0;
                    while($imgfile=readdir($dir))
                    {
                         if ($imgfile != "." && $imgfile!="..")
                             {
                                        $imgarray[$i]=$imgfile;
                                        $uploadedfile = "frame_output/".$imgarray[$i];
                                        $src = imagecreatefromgif($uploadedfile);
                                        list($width,$height)=getimagesize($uploadedfile);
                                        $tmp=imagecreatetruecolor($newwidth,$newheight);
                                        imagecopyresampled($tmp,$src,0,0,0,0,$newwidth,$newheight,$width,$height);
                                        $filename = "resized_frame_output/".$imgarray[$i];
                                        imagegif($tmp,$filename,100);
                                        imagedestroy($src);
                                        imagedestroy($tmp);
                                        $i++;
                            }
                    }
                    closedir($dir);

                if ( $dh = opendir ( "resized_frame_output/" ) )
                {
                    while ( false !== ( $dat = readdir ( $dh ) ) )
                    {
                        if ( $dat != "." && $dat != ".." )
                        {
                            $frames [ ] = "resized_frame_output/$dat";
                        }
                    }
                    closedir ( $dh );
                }

            $gif = new GIFEncoder   ( $frames,$_SESSION [ 'delays' ],0, 2, 0, 0, 0,"url" );
            $data = $gif->GetAnimation ( );

            $x='x';
            $y='_';
            $uploaded_file_name= $_FILES['uploadfile']['name'];
            $actual_file_name = substr($uploaded_file_name, 0, -4);
            $file_extention = substr($uploaded_file_name, -4);
            $new_name=$actual_file_name.$y.$newwidth.$x.$newheight.$file_extention ;

            //$output_image_name=$newwidth.$x.$newheight;
            fwrite ( fopen ( "images/$new_name", "wb" ), $data );
            //remove resized frames from folder
            //sleep for 1 second
            // usleep(2000000);
            $dir = 'resized_frame_output/';
            foreach(glob($dir.'*.*') as $v)
                {
                 unlink($v);
                }
        }  // end of function resize_frames


            $gif = new GIFEncoder   ( $frames,$_SESSION [ 'delays' ],0, 2, 0, 0, 0,"url" );
            $data = $gif->GetAnimation ( );

            $x='x';
            $y='_';
            $z='_p';
            $uploaded_file_name= $_FILES['uploadfile']['name'];
            $actual_file_name = substr($uploaded_file_name, 0, -4);
            $file_extention = substr($uploaded_file_name, -4);
            $new_name=$actual_file_name.$y.$newwidth.$x.$newheight.$z.$file_extention ;

            //$output_image_name=$newwidth.$x.$newheight;
            fwrite ( fopen ( "images/$new_name", "wb" ), $data );
            //remove resized frames from folder
            //sleep for 1 second
             //usleep(2000000);
            $dir = 'resized_frame_output/';
            foreach(glob($dir.'*.*') as $v)
                {
                 unlink($v);
                }
        }  // end of function resize_frames

            resize_frames(110,110);
            resize_frames(120,160);
            resize_frames(120,80);
            resize_frames(128,96);
            resize_frames(128,128);
            resize_frames(208,208);
            resize_frames(208,320);

            session_destroy();

            //usleep(200000);

            //remove resized frames from folder
            $dir = 'frame_output/';
            foreach(glob($dir.'*.*') as $v)
                {
                 unlink($v);
                }
      echo "<center><h1>Your Animation processing is compleated.</h1></center>";
      echo "<center><h2><a href=\"index.php\">BACK TO UPLOAD PAGE</h2></center>";
  }  //end of file size checker
else
 {
      echo "<center><h2>You Upload a unfit size image .Upload a file within 2000 KB</h2></center>";
      echo "<center><h2><a href=\"index.php\">BACK TO UPLOAD PAGE</h2></center>";
 }
   } //end of file extention checker
  else
  {
   echo "<center><h2>Uplaod a gif file!</h2></center>";
   echo "<center><h2><a href=\"index.php\">BACK TO UPLOAD PAGE</h2></center>";
  }
  ?>

..........让我们享受............

取消注释 usleep 功能以查看这些文件夹中发生的工作。这不是必需的,但我使用它来查看功能。

于 2009-04-07T10:35:00.297 回答
1

除了通过 ImageMagick 之外的所有答案都对我不起作用。在此之前的答案中的脚本都充满了错误。

即使安装 ImageMagick 也很难管理,所以这是我的经验。

以下是如何在 Windows 7 和 xampp 1.7.4 上安装 ImageMagick。
注意:选择 64 位(对于 win7),安装时请勾选“添加到系统路径”选项。

然后按照: http ://www.creativearmory.com/tutorials/resize-animated-gifs-with-php-and-imagemagick

在这篇文章中,我在脚本上浪费了几个小时,而 ImageMagick 和本教程在几分钟内就成功了。

还有一点需要注意:我的网络服务器默认有 ImageMagick,所以我猜大多数服务器也有它。

于 2011-09-23T22:00:30.247 回答
1

如果您的服务器中没有 Imagemagick,您可能想试试这个:

http://www.phpclasses.org/package/7353-PHP-Resize-animations-in-files-of-the-GIF-format.html

该课程正在使用 GD 调整 GIF 动画的大小。首先解析帧,然后调整它们的大小,然后再次将它们编译成单个文件,而不会丢失其延迟时间、处理方法、颜色表等。

尝试一下,如果您发现错误或想要提出一些优化建议等,您可以使用课程论坛或在我网站的页面上发表评论。我会尽快回答。

于 2012-03-11T18:53:08.350 回答
1

GIF Animation Resizer是一个简单的一类工具,可以解决问题。

注意:它使用一个临时文件夹来写出单独的帧。虽然它会为帧添加时间戳,但如果您打算在多个用户将同时调整 GIF 大小的服务器上使用它,则可能需要创建一个唯一文件夹。

于 2015-02-27T22:45:48.620 回答
0

Imagecraft是一个可靠的 PHP GD 库和扩展,可以保存 GIF 动画,在多个图层中编辑和合成图像,并支持水印。

于 2017-01-20T05:23:11.833 回答
0

我使用了这个功能:

function gifResize($file_origin,$file_dest,$percent){       
   $crop_w = 0;
   $crop_h = 0;
   $crop_x = 0;
   $crop_y = 0;
   $image = new Imagick($file_origin);
   $originalWidth = $image->getImageWidth();
   $originalHeight = $image->getImageHeight();
   $size_w = ($originalWidth*$percent)/100;
   $size_h = ($originalHeight*$percent)/100;
   if(($size_w-$originalWidth)>($size_h-$originalHeight)){
       $s = $size_h/$originalHeight;
       $size_w = round($originalWidth*$s);
       $size_h = round($originalHeight*$s);
   }else{
       $s = $size_w/$originalWidth;
       $size_w = round($originalWidth*$s);
       $size_h = round($originalHeight*$s);
   }       
   $image = $image->coalesceImages();

   foreach ($image as $frame) {
       $frame->cropImage($crop_w, $crop_h, $crop_x, $crop_y);
       $frame->thumbnailImage($size_h, $size_w);
       $frame->setImagePage($size_h, $size_w, 0, 0);
   }
   $imageContent = $image->getImagesBlob();
   $fp = fopen($file_dest,'w');
   fwrite($fp,$imageContent);
   fclose($fp);

}

于 2017-05-09T11:19:52.933 回答