Мне нужно изменить размер анимированного GIF-файла без разрушения анимации.
Как я могу это сделать с помощью PHP?
если у вас есть доступ к imagemagick, вы можете сделать это:
system("convert big.gif -coalesce coalesce.gif"); system("convert -size 200x100 coalesce.gif -resize 200x10 small.gif");
это, скорее всего, возможно с плагином imagemagick, если у вас нет доступа к системе ()
ПРИМЕЧАНИЕ. Это может создать больший размер файла, хотя изображение меньших размеров связано с совместным сглаживанием изображения.
ОБНОВЛЕНИЕ. Если у вас нет доступа к ImageMagick, вы можете использовать комбинацию следующих шагов для изменения размера анимированного gif (при условии, что у вас есть GD-доступ):
Это определенно намного более интенсивный, чем маршрут ImageMagick, но это должно быть технически возможно.
Если вы заработаете, пожалуйста, поделитесь с миром!
Попробуйте GDEnhancer (используйте ImageCraft ). Ему нужна только библиотека GD, и она поддерживает gif-анимацию
Вам нужно разложить gif на фреймы, миниатюру и повторно собрать.
Взгляните на ImageMagick: http://php.net/imagick и этот учебник: http://www.phpro.org/examples/Thumbnail-From-Animated-GIF.html
Я пробовал множество примеров изменения анимированных GIF-файлов с помощью модуля PHP Imagick, но ни один из них не работал для меня. Затем, после некоторого времени отладки, я обнаружил актуальную проблему: анимация была потеряна при сохранении образа на диск, с помощью $animation->writeImage($file_dst);
или $animation->writeImages($file_dst, true);
Я изменил его на file_put_contents($file_dst, $animation->getImagesBlob());
и большинство примеров начали работать немедленно.
Надеюсь, это поможет кому-то.
В примере на http://www.php.net/manual/en/imagick.coalesceimages.php будет изменяться размер вашего gif, сохраняя при этом временные рамки. Что-то большинство других примеров не делают.
Другие примеры перестраивают gif, в то время как это позволяет вам изменять рамки изображения.
Если у вас установлен ImageMagick, вы можете использовать один вызов для convert
:
system("convert big.gif -coalesce -repage 0x0 -resize 200x100 -layers Optimize small.gif");
Кажется, у меня это в сумке.
Это решение отнюдь не идеально и содержит какую-то грубую силу здесь и там, но я смог добавить свой сценарий изменения размера изображения на основе 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 из моего набора тестов, у которого были какие-то разные кадры, и эта анимация не работала правильно. Еще одна отладка для этого.
просто имя файла creat 3 1.frame_output 2.images 3.resized_frame_output и загрузите 2 класса кодировщика и декодера из этой ниже ссылки 1.Загрузить класс «GIFDecoder.class.php» из http://phpclasses.elib.com/browse/package /3234.html класс 2.Download «GIFEncoder.class.php» из http://phpclasses.betablue.net/browse/package/3163.html
а затем запустите имя сценария как «resize_animator.php», создайте файл html для загрузки и дайте наслаждаться сценарию.
..save этот сценарий как ….. 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>"; } ?>
в<?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 Animation Resizer – это простой одноклассный инструмент, который будет делать трюк.
Примечание. Для записи отдельных кадров используется временная папка. Хотя это временные метки кадров, вам может понадобиться создать уникальную папку, если вы собираетесь использовать ее на сервере, где несколько пользователей будут изменять размер GIF одновременно.
Imagecraft – это надежная библиотека 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);
}