说明:
由于动态gif是由多张静态图片组成的,所以生成缩略图时要循环遍历每一张图片,对每张图片分别进行resize,最后再合并到一起。
我没深入研究gif图片的格式,以下是根据实际测试得出的一些结论:
(1)可根据gif图片的头部特殊字符串判断是否是动态gif图片(is_animation函数)
(2)动态gif图片第0帧貌似是背景图,可以根据此图得出图片最大宽度和高度,然后得到一个压缩比率,其他帧都以此压缩比率进行压缩。
(3)动态gif图片第1帧貌似是被保留的,用来存储背景图resize后的图片(实际上就是静态缩略图),所以在执行resize操作时要把此帧排除,不然就等于把缩略图又压缩了一次,观察到现象就是一张被resize了两次的很小的缩略图。
(4)MagickWriteImages()只比MagickWriteImage()函数多了一个s,用来把多张图片写到一个图片中(第三个参数必须是true)
(5)MagickResetIterator()和MagickNextImage()可用来实现循环迭代
(6)生成的缩略图会有略微的错位变形
- $magickwand = NewMagickWand();
- MagickReadImage($magickwand, $src);
- $type = MagickGetImageFormat($magickwand);
- $src_w = MagickGetImageWidth($magickwand);
- $src_h = MagickGetImageHeight($magickwand);
- $src = '/data1/cache/src.gif'
- $dst = '/data1/cache/dst.gif';
- $width = 160;
- $height = 120;
- if($type=='GIF'){
- if(is_animation($src))
- {
- scale_GIF($magickwand, $width, $width);
- MagickWriteImages($magickwand, $dst, true);
- DestroyMagickWand($magickwand);
- }
- }
- function is_animation($src)
- {
- $fp=fopen($src, 'rb');
- $p_w_picpath_head = fread($fp,1024);
- fclose($fp);
- return preg_match('/'.chr(0x21).chr(0xff).chr(0x0b).'NETSCAPE2.0/', $p_w_picpath_head) ? true : false;
- }
- function scale_GIF(&$magickwand, $dst_width, $dst_height)
- {
- MagickResetIterator($magickwand);
- $i = 0;
- do{
- $src_w = MagickGetImageWidth($magickwand);
- $src_h = MagickGetImageHeight($magickwand);
- if($i==0)
- {
- $ratio_w = doubleval($src_w) / doubleval($dst_width);
- $ratio_h = doubleval($src_h) / doubleval($dst_height);
- $ratio = $ratio_w > $ratio_h ? $ratio_w : $ratio_h;
- $width = floor( $src_w / $ratio);
- $height = floor( $src_h / $ratio);
- if ($width>=$src_w || $height>=$src_h) { return true; }
- }
- if($i!=1){
- $width = floor( $src_w / $ratio);
- $height = floor( $src_h / $ratio);
- //echo "$i:$src_w,$src_h,$dst_width, $width, $height<br>";
- if($width && $height) {
- $r = MagickResizeImage($magickwand, $width, $height, MW_LanczosFilter, 1.0);
- }
- }
- $i++;
- }while(MagickNextImage($magickwand));
- return true;
- }