【问题标题】:Resize animated GIF file without destroying animation在不破坏动画的情况下调整动画 GIF 文件的大小
【发布时间】:2010-10-17 15:18:32
【问题描述】:

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

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

【问题讨论】:

    标签: php image imagemagick animated-gif


    【解决方案1】:

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

    看看ImageMagickthis tutorial

    【讨论】:

      【解决方案2】:

      尝试GDEnhancer(使用ImageCraft)。只需要GD库,保存gif动画

      【讨论】:

      • 谢谢。它可以与 PHP 5.2 一起使用吗?在网站上它说 5.4+,这对于大多数环境(包括我在这种情况下的目标环境)来说都是非常先进的。否则看起来很棒!
      • 唉,GDEnhancer 网站已经死了。
      • @TechNyquist 现在 GDEnhacer 已被弃用,请改用 github.com/coldume/imagecraft
      【解决方案3】:

      我用过这个功能:

      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);
      

      }

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

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

          system("convert big.gif -coalesce -repage 0x0 -resize 200x100 -layers Optimize small.gif");
          

          【讨论】:

            【解决方案6】:

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

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

            【讨论】:

              【解决方案7】:

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

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

              希望它对某人有所帮助。

              【讨论】:

              • 太棒了!!这拯救了我的一天!谢谢安东尼。使用 writeImages 时,旧版本的 Imagick 有问题,但使用您的方法可以正常工作,完全没有问题! :)
              • 这在 writeImages() 会剥离动画时起到了作用。
              【解决方案8】:

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

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

              这里是 Windows 7 和 xampp 1.7.4 上的 how to install ImageMagick
              注意:选择 64 位(对于 win7),安装时请选中“添加到系统路径”选项.

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

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

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

              【讨论】:

                【解决方案9】:

                如果你有 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:Can I detect animated gifs using php and gd?(最佳答案)
                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 路线密集得多,但在技术上应该是可行的。

                如果你成功了,请与全世界分享!

                【讨论】:

                • 抱歉,我无权访问 imagemagic。还有其他解决方案吗?
                • 发布了一个更新,其中包含使用 GD 和第三方类的多个步骤来实现这一点(理论上)。
                • 我想我只是在实践中得到了理论:forssto.com/gifexample
                • 非常感谢@TommiForsström!
                • @JeremyStanley 的方法非常正确。可以看完整教程here
                【解决方案10】:

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

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

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

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

                【讨论】:

                  【解决方案11】:

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

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

                  【讨论】:

                  • imagick 最擅长复杂的图像处理。 PHP 确实知道一些技巧。
                  • 这就是我最终寻求的解决方案,我尝试了其他解决方案,但速度非常慢。确保您的主机上安装了 Imagick(如今这并不罕见)并使用它。
                  【解决方案12】:

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

                  这个解决方案绝不是完美的,并且到处都包含一些蛮力,但我能够在我的基于 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 文件 以某种方式有不同的测试 其中的大小帧和动画 无法正常工作。还有一些 然后进行调试。

                  【讨论】:

                  • 你好。谢谢。我试过你的解决方案。我修改了源以从字符串中读取图像(如果您有兴趣,请告诉我),但结果是 WAAAY 变慢了。我终于意识到 Imagick 可以在主机上使用并改用它。
                  【解决方案13】:

                  只需创建 3 个文件夹名称 1.frame_output 2.images 3.resized_frame_output 并从以下链接下载 2 个编码器和解码器类 1.从http://phpclasses.elib.com/browse/package/3234.html下载类“GIFDecoder.class.php” 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 功能以查看这些文件夹中发生的工作。这不是必需的,但我使用它来查看功能。

                  【讨论】:

                    猜你喜欢
                    • 2018-04-18
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-02-23
                    • 2012-04-16
                    • 2011-08-09
                    • 2011-08-31
                    • 1970-01-01
                    • 2011-11-01
                    相关资源
                    最近更新 更多