Мне нужно изменить размер анимированного файла GIF, не разрушая анимацию.
Как я могу сделать это с помощью PHP?
Мне нужно изменить размер анимированного файла 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):
Это определенно намного интенсивнее, чем маршрут ImageMagick, но это должно быть технически возможно.
Если у вас получится, поделитесь с миром!
Попробуйте GDEnhancer (используйте ImageCraft). Нужна только библиотека GD, и она сохраняет анимацию gif.
Вам нужно будет разложить гифку на кадры, миниатюру и собрать заново.
Взгляните на ImageMagick и этого руководства.
Я пробовал множество примеров изменения размера анимированных 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 с достаточной функциональностью для поддержки анимации.
Решение в значительной степени основано на превосходных бесплатных библиотеках Ласло Зсиди — 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 класса кодировщика и декодера по этой ссылке ниже 1. Загрузите класс «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-файлов.
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);
}