Мне нужно изменить размер анимированного GIF файла без разрушения анимации.
Как это сделать с помощью PHP?
Мне нужно изменить размер анимированного GIF файла без разрушения анимации.
Как это сделать с помощью PHP?
Если у вас есть доступ к imagemagick, вы можете сделать это:
system("convert big.gif -coalesce coalesce.gif");
system("convert -size 200x100 coalesce.gif -resize 200x10 small.gif");
это, скорее всего, возможно с плагином imagemagick, если у вас нет доступа к системе()
ПРИМЕЧАНИЕ. Это может создать больший размер файла, хотя изображение меньших размеров из-за коалесценции, существенно деоптимизирующей изображение.
UPDATE: Если у вас нет доступа к 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 файлов с помощью модуля Imagick PHP, но ни один из них не работал у меня.
Затем, после некоторого времени отладки, я обнаружил фактическую проблему: анимация была потеряна при сохранении образа на диск, $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 script с достаточной функциональностью для поддержки анимации.
Решение в значительной степени основано на превосходных бесплатных библиотеках 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.Загрузить класс "GIFEncoder.class.php" из http://phpclasses.betablue.net/browse/package/3163.html
а затем запустите имя script как "resize_animator.php", создайте файл html для загрузки и дайте наслаждаться script.
.. Сохраните этот script как..... 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>
........................ сохранить и этот script как 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>";
}
?>
....................... LETS ENJOY............
раскомментируйте функцию usleep, чтобы увидеть, как работа происходит в этих папках. Не обязательно, но я использую ее для просмотра функциональности.
Все ответы, кроме 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, поэтому я думаю, что на большинстве серверов есть он.
Если у вас нет Imagemagick на вашем сервере, вы можете попробовать следующее:
http://www.phpclasses.org/package/7353-PHP-Resize-animations-in-files-of-the-GIF-format.html
Класс изменяет размер анимации GIF с помощью GD. Сначала анализирует кадры, а затем изменяет их размеры, после чего он снова компилирует их в один файл без потери времени задержки, методов удаления, таблиц цветов и т.д.
Попробуйте, если вы обнаружите ошибку или хотите предложить некоторые оптимизации и т.д., вы можете использовать форум класса или оставить комментарий на странице своего веб-сайта. И я отвечу на это как можно скорее.
GIF Animation Resizer - это простой одноклассный инструмент, который сделает трюк.
Примечание.. Он использует временную папку для записи отдельных кадров. Несмотря на то, что это временные метки для фреймов, вам может потребоваться создать уникальную папку, если вы собираетесь использовать ее на сервере, где несколько пользователей будут изменять размер GIF одновременно.
Imagecraft является надежной библиотекой и расширением GD PHP, которая поддерживает 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);
}