Изменение размера анимированного GIF-файла без разрушения анимации

StackOverflow https://stackoverflow.com/questions/718491

Вопрос

Мне нужно изменить размер анимированного файла GIF, не разрушая анимацию.

Как я могу это сделать с помощью PHP?

Это было полезно?

Решение

если у вас есть доступ к imagemagick, вы можете сделать это:

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

это, скорее всего, возможно с плагином imagemagick, если у вас нет доступа к system()

ПРИМЕЧАНИЕ:это может привести к созданию изображения большего размера, хотя и меньшего размера, из-за слияния, которое существенно деоптимизирует изображение.

ОБНОВЛЯТЬ:Если у вас нет доступа к ImageMagick, вы сможете использовать комбинацию следующих шагов для изменения размера анимированного GIF-файла (при условии, что у вас есть доступ к GD):

  1. Определите, является ли изображение анимированным gif: Могу ли я обнаружить анимированные GIF-изображения с помощью php и 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, но это должно быть технически возможно.

Если у вас получится, поделитесь с миром!

Другие советы

Пытаться GDEnhancer (Использовать ImageCraft).Ему нужна только библиотека GD, и она сохраняет анимацию gif.

Вам нужно будет разложить гифку на кадры, миниатюры и собрать заново.

Посмотри на ИзображениеМагия и этот урок.

Пример на http://www.php.net/manual/en/imagick.coalesceimages.php изменит размер вашего gif, сохраняя синхронизацию кадра.То, чего не делает большинство других примеров.

Другие примеры перестроить гифка, а эта позволяет вам изменить рамки изображения.

Я пробовал множество примеров изменения размера анимированных GIF-файлов с помощью PHP-модуля Imagick, но ни один из них мне не помог.Затем, после некоторого времени отладки, наконец, я нашел реальную проблему:анимация пропала при сохранении изображения на диск, $animation->writeImage($file_dst); или$animation->writeImages($file_dst, true);

Я изменил это наfile_put_contents($file_dst, $animation->getImagesBlob());и большинство примеров начали работать сразу.

Надеюсь, это кому-то поможет.

Если у вас установлен ImageMagick, вы можете использовать один вызов convert:

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

Думаю, это у меня в сумке.

Это решение ни в коем случае не является идеальным и здесь и там содержит некоторую грубую силу, но я смог добавить свой сценарий изменения размера изображения на основе GD/PHP с достаточной функциональностью для поддержки анимации.

Решение в значительной степени основано на превосходных бесплатных библиотеках Ласло Жиди. http://www.phpclasses.org/browse/author/283569.html

Вы можете просмотреть быструю демонстрацию и загрузить исходные коды с сайта http://forssto.com/gifexample/ (Прямая ссылка: http://forssto.com/gifexample/gifanimresize.zip )

ИЗВЕСТНЫЕ ВОПРОСЫ:

  • Поддержка прозрачности - это было бы легко добавить к этому решению, но, поскольку у меня нет непосредственной потребности в этом, я останавливаюсь здесь.

  • Частота кадров - По какой -то неизвестной причине класс GifeNcoder не учитывает указанные частоты кадров.Мне нужно будет посмотреть на это позже.

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

Просто создайте 3 имя папки 1.FRAME_OUTPUT 2.IMAGES 3.RESIZED_FRAME_OUTPUT и скачать 2 класса Encoder и Decoder из этой ссылки ниже 1. Download Class "GIFDECODER.CLASS.PHP" http://phpclasses.elib.com/browse/package/3234.html 2. Загрузите класс «GIFEncoder.class.php» с сайта http://phpclasses.betablue.net/browse/package/3163.html

а затем запустите сценарий с именем «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, чтобы увидеть, как работа происходит в этих папках. в этом нет необходимости, но я использую ее, чтобы увидеть функциональность.

Если на вашем сервере нет Imagemagick, вы можете попробовать это:

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

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

Попробуйте, и если вы обнаружите ошибку или захотите предложить некоторые оптимизации и т. д.Вы можете использовать форум класса или оставить комментарий на странице моего сайта.И я отвечу на это как можно скорее.

Все эти ответы, кроме ImageMagick, у меня не сработали.Скрипты в ответах до этого полны ошибок.

Даже установить ImageMagick было сложно, поэтому вот мой опыт.

Вот как установить ImageMagick в Windows 7 и xampp 1.7.4.
Примечание:Выберите 64 бит (для Win7) и при установке оставьте галочку «Добавить в системный путь».

И затем следуйте:http://www.creativearmory.com/tutorials/resize-animated-gifs-with-php-and-imagemagick

Я потратил несколько часов на сценарии в этих постах, а ImageMagick и этот урок были успешны за считанные минуты.

И еще одно замечание:на моем веб-сервере по умолчанию есть ImageMagick, так что я думаю, что на большинстве серверов он тоже есть.

Изменение размера GIF-анимации — это простой одноклассовый инструмент, который сделает свое дело.

Примечание: Он использует временную папку для записи отдельных кадров.Несмотря на то, что кадры маркируются временными метками, вам может потребоваться создать уникальную папку, если вы собираетесь использовать ее на сервере, где несколько пользователей будут одновременно изменять размер GIF-файлов.

Имиджкрафт — это надежная библиотека и расширение PHP GD, которая поддерживает анимацию GIF, редактирует и компонует изображения в несколько слоев и поддерживает водяные знаки.

Я использовал эту функцию:

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

}

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top