Source: http://blog.oskoui-oskoui.com/?p=404
One question that you may ask yourself when you work with images is if it is possible to resize an animated GIF and keep the animation. We will see here the different steps to do that in PHP, without using any special library like ImageMagick or something else.
Required libraries
First, to manipulate our image files, we will need the GD library from PHP. If you don’t have it already installed on your server, here is the link which explains how to proceed: click to link to the page.
Here is the animated GIF that we would like to resize:
The following steps explain the process.
Step 1: Extraction of the GIF’s frames
The first step is to extract each frame, each individual image of the GIF, to modify them.
For this, we will use the PHP class GIFDecoder.class.php that is available on the web. This class allows us to retrieve each frame from the GIF and the delay between each frame.
Here is the part of the code which shows how to extract and reduce each frame of the GIF:
$animation ="../gif_upload/animated_image.gif; // link to the file
$gifDecoder = new GIFDecoder ( fread ( fopen ( $animation, "rb" ), filesize ($animation) ) );
$delay = $gifDecoder->GIFGetDelays ( ); // get the delay between each frame
// treatment of the reduced images 225x127
$i = 1;
foreach ( $gifDecoder -> GIFGetFrames ( ) as $frame ) {
fwrite ( fopen ( "resizeGif/tmp_reduced/image$i.gif" , "wb" ), $frame ); // write each frame in a temporary file
$img = "resizeGif/tmp_reduced/image$i.gif"; // File image location
$newfilename = "resizeGif/tmp_reduced/image$i.gif"; // New file name
$w = 225; // new width
$h = 127; // new height
resize($img, $w, $h, $newfilename); // function to reduce the image$i++;
}
Step 2: Reduction of the Frames
The “resize” function used in Step 1 used the GD library, and resizes the image to the given width and height:
function resize($img, $w, $h, $newfilename) {
//Check if GD extension is loaded
if (!extension_loaded('gd') && !extension_loaded('gd2')) {
trigger_error("GD is not loaded", E_USER_WARNING);
return false;
}
//Get Image size info
$imgInfo = getimagesize($img);
switch ($imgInfo[2]) {
case 1: $im = imagecreatefromgif($img); break;
case 2: $im = imagecreatefromjpeg($img); break;
case 3: $im = imagecreatefrompng($img); break;
default: trigger_error('Unsupported filetype!', E_USER_WARNING); break;
}
//If image dimension is smaller, do not resize
if ($imgInfo[0] > $w) {
$nWidth = $w;
$nHeight = $imgInfo[1]*($w/$imgInfo[0]);
}else{
$nWidth = $imgInfo[0];
$nHeight = $imgInfo[1];
}
if ($nHeight > $h) {
$nWidth = $imgInfo[0]*($h/$imgInfo[1]);
$nHeight = $h;
}
$nWidth = round($nWidth);
$nHeight = round($nHeight);
$newImg = imagecreatetruecolor($nWidth, $nHeight);
// Check if this image is PNG or GIF, then set if Transparent
if(($imgInfo[2] == 1) OR ($imgInfo[2]==3)){
imagealphablending($newImg, false);
imagesavealpha($newImg,true);
$transparent = imagecolorallocatealpha($newImg, 255, 255, 255, 127);
imagefilledrectangle($newImg, 0, 0, $nWidth, $nHeight, $transparent);
}
imagecopyresampled($newImg, $im, 0, 0, 0, 0, $nWidth, $nHeight, $imgInfo[0], $imgInfo[1]);
//Generate the file, and rename it to $newfilename
switch ($imgInfo[2]) {
case 1: imagegif($newImg,$newfilename); break;
case 2: imagejpeg($newImg,$newfilename); break;
case 3: imagepng($newImg,$newfilename); break;
default: trigger_error('Failed resize image!', E_USER_WARNING); break;
}
return $newfilename;
}
We now have on the folder “tmp_reduced” the temporary reduced images. The next step will consist of assembling all the frames to construct the new resized GIF image.
Step 3: Fusion of the Frames to Create the New Resized GIF
Now that we have reduced all the frames, the last step will consist of retrieving each reduced frame, and then building the new resized GIF.
For this, we will use the PHP class GIFEncoder.class.php, also available on the web. This class lets us retrieve each frame from the GIF contained in an array and reconstruct the GIF with the same delay between each frame.
//Build a frames array from sources
$i = 1;
if ( $dh = opendir ( "resizeGif/tmp_thumbnail/" ) ) {
while ( false !== ( $dat = readdir ( $dh ) ) ) {
if ( $dat != "." && $dat != ".." ) {
$framesThumb [ ] = "resizeGif/tmp_thumbnail/image$i.gif";
$i++;
}
}
closedir ( $dh );
}
$gifThumb = new GIFEncoder (
$framesThumb,
$delay,
0,
2,
0, 0, 0,
"url"
);
// save the new gif file
$fpThumb = fopen('../gif_upload/thumb_image.gif', 'w');
fwrite($fpThumb, $gifThumb->GetAnimation());
fclose($fpThumb);
The parameters of the GIFEncoder constructor are, in order:
- the images
- the delay time
- the animation are played n times (0 = infinite)
- disposal
- transparent red, green and blue colors
- source type
With the “GetAnimation” function of GIFEncoder, we are now able to construct the new GIF image.
We can now use our resized animated GIF!
Image before resizing: