GD库是否不能将处理后的gif图片,保持动态效果? 这几天需要处理图片的问题,发现gd库生成的gif缩略图,全部成了静态的了。如何解决这个问题呢? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 gif应该不可以。感觉可以将每一帧都读出来然后全部重新缩略,然后重新生成?gif的没弄过。 gif是无法生成缩略图的,因为它是一帧一帧的,缩略后就会失去动画的效果的 你话未免过于绝对吧?使用im库就可以,我只是不确定GD库是否可以。在这里向大家求证,竟然一个个懒得回答 如同一楼所说的,楼主可以先将其每一帧处理后在生成,上次我也在弄个这个问题,有两个类分别是解码GIFDecoder.class.php和编码GIFEncoder.class.php的楼主自己研究下 http://code.h2ero.cn/code/classes/gif.zip 要保持GIF上传后的动画效果,可以考虑使用 PHP ImageMagick MagickWand 无变形缩略图程序 发布一个采用php下ImageMagick的扩展库,MagickWand缩略图程序,以前发过一个GD2的处理程序,图片处理后的效果还可以接受,不过没有MagickWand处理的效果好,在生成的缩略图比较大时,比如有一张照片 2296X1528px的大照片,裁剪为宽度800以内的,使用MagickWand足足耗时10多秒,不知道是不是算法有问题,不过同样的算法采用GD2实现的处理起来非常快速,基本上为1秒多,总之呢,先发布第一版本了,以后再完善,MagickWand最大的好处是支持Gif动画缩放,缩小后保持动画,还有bmp图像处理。调用方法也很简单,本来打算不用类的,不过后来还是觉得类封装一下方便代码书写。但是最后再封装成函数调用比较方便。由原来的四种缩放裁剪模式修改为三种,去除第一种不常用的模式,原GD2库的缩放程序在这里:http://hi.baidu.com/smallchicken/blog/item/3549007716bb4713b151b913.html <?php/*** 基于MagickWand的图片缩略图程序, php magick thumb* Author: smallchicken* E-mail: [email protected]* Version: 1.0* 用法:直接调用 magick_thumb函数,传入参数:* magick_thumb($src_image_dir.$src_image,$dst_thumb_dir.$dst_image,100,100,1);* $src_file : 原文件路径 , $dst_file :保存文件路径 , $dst_width :生成文件宽 , $dst_height:生成文件高,$mode=1 裁剪方式* GIF动画缩略到不大于传入的高宽值,并且保留动画效果,GIF非动画格式和其他格式一样处理。* 参数 $mode 说明:* $mode=1 :生成固定高宽的图像,图片缩放后铺满,为了铺满,会有部分图像裁剪掉。* $mode=2 :生成固定高宽的图像,图片缩放后不一定铺满,但保留全部图像信息,即不裁剪,添加补白。* $mode=3 :生成图像高宽不大于给定高宽,并且以缩放后的实际大小保持。**/function magick_thumb($src_file,$dst_file,$dst_width,$dst_height,$mode=1) {$mp = new MagickProcess($src_file);return $mp->MagickThumb($dst_file,$dst_width,$dst_height,$mode);}class MagickProcess {var $src_mw;var $src_file;var $src_width;var $src_height;var $src_ext;var $src_format;var $is_img;function MagickProcess($src_file) {$this->src_file = $src_file;$this->src_mw = NewMagickWand();$this->is_img=MagickReadImage($this->src_mw,$src_file);if(!$this->is_img) return;$this->format = MagickGetImageFormat($this->src_mw);$this->src_width =MagickGetImageWidth($this->src_mw);$this->src_height =MagickGetImageHeight($this->src_mw);}function IsAnimation() {$fp=fopen($this->src_file, 'rb');$image_head = fread($fp,1024);fclose($fp);return preg_match("/".chr(0x21).chr(0xff).chr(0x0b).'NETSCAPE2.0'."/",$image_head) ? true : false;}function MagickThumb($dst_file,$dst_width,$dst_height,$mode=1) {if(!$this->is_img) return false;$src_width = $this->src_width;$src_height= $this->src_height;$ratio_w=1.0 * $dst_width / $src_width;$ratio_h=1.0 * $dst_height / $src_height;$ratio=1.0;if(strtolower($this->format)=='gif') {if ($this->IsAnimation()) {$this->ResizeGif($dst_file, $dst_width, $dst_height);return;}}switch($mode) {case 1: // 生成固定高宽,超过的裁剪掉if($ratio_w < 1 && $ratio_h < 1) { // 都缩小$ratio = $ratio_w < $ratio_h ? $ratio_h : $ratio_w;$crop_width = (int)($dst_width / $ratio);$crop_height = (int)($dst_height / $ratio);$crop_x = (int) ($src_width-$crop_width)/2 ;$crop_y = (int) ($src_height-$crop_height)/2 ;MagickCropImage($this->src_mw, $crop_width, $crop_height, $crop_x, $crop_y);$this->ResizeImage($this->src_mw, $dst_width, $dst_height);$this->SaveImage($this->src_mw, $dst_file);}elseif($ratio_w > 1 && $ratio_h > 1) {$dst_mkwd=NewMagickWand();MagickNewImage($dst_mkwd,$dst_width,$dst_height,'#FFFFFF');$dst_x = (int) abs($dst_width - $src_width) / 2 ;$dst_y = (int) abs($dst_height -$src_height) / 2;MagickCompositeImage($dst_mkwd ,$this->src_mw, MW_OverCompositeOp, $dst_x, $dst_y ) ; // 合并图像,拷贝到目标图像的x,y坐标点$this->SaveImage($dst_mkwd, $dst_file);DestroyMagickWand($this->src_mw);}else {// 一边长,一边短,先裁去长的边。$crop_x=$crop_y=0;$crop_width = min($src_width , $dst_width);$crop_height = min($src_height, $dst_height);$crop_x = (int) ($src_width-$crop_width)/2 ;$crop_y = (int) ($src_height-$crop_height)/2 ;MagickCropImage($this->src_mw, $crop_width, $crop_height, $crop_x, $crop_y);$dst_mkwd=NewMagickWand();MagickNewImage($dst_mkwd,$dst_width,$dst_height,'#FFFFFF');$dst_x = (int) ($dst_width-$crop_width)/2 ;$dst_y = (int) ($dst_height-$crop_height)/2 ;MagickCompositeImage($dst_mkwd ,$this->src_mw, MW_OverCompositeOp, $dst_x, $dst_y ) ; // 合并图像,拷贝到目标图像的x,y坐标点$this->SaveImage($dst_mkwd, $dst_file);DestroyMagickWand($this->src_mw);}break;case 2: // 生成固定高宽,保留全部信息,只缩放,不裁剪if($ratio_w > 1 && $ratio_h > 1) {$dst_mkwd=NewMagickWand();MagickNewImage($dst_mkwd,$dst_width,$dst_height,'#FFFFFF');$dst_x = (int) abs($dst_width - $src_width) / 2 ;$dst_y = (int) abs($dst_height -$src_height) / 2;MagickCompositeImage($dst_mkwd ,$this->src_mw, MW_OverCompositeOp, $dst_x, $dst_y ) ;$this->SaveImage($dst_mkwd, $dst_file);DestroyMagickWand($this->src_mw);}else {$ratio = $ratio_w > $ratio_h ? $ratio_h : $ratio_w;$tmp_w = (int)($src_width * $ratio);$tmp_h = (int)($src_height * $ratio);$this->ResizeImage($this->src_mw, $tmp_w, $tmp_h);$dst_mkwd=NewMagickWand();MagickNewImage($dst_mkwd,$dst_width,$dst_height,'#FFFFFF');$dst_x = (int) abs($tmp_w - $dst_width) / 2 ;$dst_y = (int) abs($tmp_h - $dst_height) / 2;MagickCompositeImage($dst_mkwd ,$this->src_mw, MW_OverCompositeOp, $dst_x, $dst_y ) ;$this->SaveImage($dst_mkwd, $dst_file);DestroyMagickWand($this->src_mw);}break;case 3: // 超过缩放,不超过直接存图。if($ratio_w > 1 && $ratio_h > 1) {$this->SaveImage($this->src_mw, $dst_file);}else {$ratio = $ratio_w > $ratio_h ? $ratio_h : $ratio_w;$tmp_w = (int)($src_width * $ratio);$tmp_h = (int)($src_height * $ratio);$this->ResizeImage($this->src_mw, $tmp_w, $tmp_h);$this->SaveImage($this->src_mw, $dst_file);}break;}return true;}function ResizeGif($dst_file,$dst_width, $dst_height) {MagickResetIterator($this->src_mw);do {$iw = MagickGetImageWidth($this->src_mw);$ih = MagickGetImageHeight($this->src_mw);$iratio=1.0;$iratio_w = doubleval($iw) / doubleval($dst_width);$iratio_h = doubleval($ih) / doubleval($dst_height);$iratio = $iratio_w > $iratio_h ? $iratio_w : $iratio_h;$tmp_w = floor( $iw / $iratio);$tmp_h = floor( $ih / $iratio);$this->ResizeImage($this->src_mw, $tmp_w, $tmp_h);} while(MagickNextImage($this->src_mw));$this->SaveImage($this->src_mw, $dst_file);}function ResizeImage($mgk, $dst_width, $dst_height) {MagickResizeImage( $mgk, $dst_width, $dst_height, MW_LanczosFilter, 1.0);//MagickSampleImage($mw, $dst_width, $dst_height); // Resize的效果好于Sample//MagickScaleImage($mw, $dst_width, $dst_height);/**MW_PointFilter MW_BoxFilterMW_TriangleFilter MW_HermiteFilterMW_HanningFilter MW_HammingFilterMW_BlackmanFilter MW_GaussianFilterMW_QuadraticFilter MW_CubicFilterMW_CatromFilter MW_MitchellFilterMW_LanczosFilter MW_BesselFilterMW_SincFilter*/}function SaveImage($mgk,$dst_file) {MagickSetFormat($mgk, $this->format);MagickWriteImages($mgk, $dst_file, MagickTrue);DestroyMagickWand($mgk);unset($mgk);}}// end class?> 囧~~ 那个是别人写的类,先解码提取每一帧,然后再对每一帧处理,处理了将这些帧重新生成gif,im是挺简单不过要安装扩展, 这儿有个演示,解码gif为帧,添加新帧,然后再生成gif;http://code.h2ero.cn/temp/gifs/decode_a_gif.php楼主那两个类你没有下来看看~~~ 呜呜呜呜~~~~~ 这个处理效率还是比较高,反正貌似比使用im简单点点,当初自己弄这个问题最后还是没有用im处理, 下来试过了。有个麻烦的问题,楼上用过的朋友能否解决?就是分离出来的帧,使用GIFEncoder合并后,动画中有几个帧出现严重的画质问。但使用imagick合并那些帧就不会有这种现象。可见GIFEncoder的合并算法似乎存在问题。http://u.115.com/file/t5a016496b#gifmerge.zip里面test.gif是原图。testXX.gif是分离的各帧。 那个问题是存在,不过后来又有人写了个,就是在那个GIFEncoder的基础上面修改了下,基本上解决了,你看我生成的那个都没有画质问题,当时看别人的demo基本上是无损的,我在弄几张随机生成的大图给你看看, 楼上的这儿,无损的,我觉得比较简单,不过对gif的文件编码不懂,http://code.h2ero.cn/temp/gifs/gif.php 这儿那个别人修改过的GIFEncoderhttp://code.h2ero.cn/code/classes/gif.zip 你下我的文件去试试看好吗?我用的就是这个包,但某些gif就是合并后差异明显。我分析过,提取每一帧没问题。但吧提取出来的帧重新合并就变化了。不是说总是这样,我也试过有些gif合并后,起码肉眼看不出毛病。但我上面包里面给的gif文件,提取、合并就是有问题。但我用imagick合并是没问题(码肉眼看问题)。 toh2ero我csdn的空间不能批准加好友,加QQ35513767聊吧,谢谢 GIFEncoder存在的问题已经找出来了,稍后代码整理好考虑与大家分享! 暂时没有找到支持5.3.x的imagick扩展:( 找就有了,正在使用php5.3.2 一些PHP资料,很罕见!要的来拿! PDO 新手问题 想在国外做一个类似猪八戒的威客的网站,不知成本如何? 请问UCenter Home的页面文件在哪啊 获得三级联动值问题.还需要插入数据库,请问大虾怎么解决这个 那位大哥帮我找下js的教程,最好是视频的! Mysql 建库问题 shopex会员问题 帮忙看看下面的sql报错 PHP如何比较变量的大小 求搜索引擎动态摘要的算法,最好有代码 php上传下载如何优化500人并发执行
感觉可以将每一帧都读出来然后全部重新缩略,然后重新生成?
gif的没弄过。
你话未免过于绝对吧?使用im库就可以,我只是不确定GD库是否可以。在这里向大家求证,竟然一个个懒得回答
分别是解码GIFDecoder.class.php和编码GIFEncoder.class.php的楼主自己研究下 http://code.h2ero.cn/code/classes/gif.zip
发布一个采用php下ImageMagick的扩展库,MagickWand缩略图程序,以前发过一个GD2的处理程序,图片处理后的效果还可以接受,不过没有MagickWand处理的效果好,在生成的缩略图比较大时,比如有一张照片 2296X1528px的大照片,裁剪为宽度800以内的,使用MagickWand足足耗时10多秒,不知道是不是算法有问题,不过同样的算法采用GD2实现的处理起来非常快速,基本上为1秒多,总之呢,先发布第一版本了,以后再完善,MagickWand最大的好处是支持Gif动画缩放,缩小后保持动画,还有bmp图像处理。调用方法也很简单,本来打算不用类的,不过后来还是觉得类封装一下方便代码书写。但是最后再封装成函数调用比较方便。
由原来的四种缩放裁剪模式修改为三种,去除第一种不常用的模式,
原GD2库的缩放程序在这里:
http://hi.baidu.com/smallchicken/blog/item/3549007716bb4713b151b913.html
<?php
/**
* 基于MagickWand的图片缩略图程序, php magick thumb
* Author: smallchicken
* E-mail: [email protected]
* Version: 1.0
* 用法:直接调用 magick_thumb函数,传入参数:
* magick_thumb($src_image_dir.$src_image,$dst_thumb_dir.$dst_image,100,100,1);
* $src_file : 原文件路径 , $dst_file :保存文件路径 , $dst_width :生成文件宽 , $dst_height:生成文件高,$mode=1 裁剪方式
* GIF动画缩略到不大于传入的高宽值,并且保留动画效果,GIF非动画格式和其他格式一样处理。
* 参数 $mode 说明:
* $mode=1 :生成固定高宽的图像,图片缩放后铺满,为了铺满,会有部分图像裁剪掉。
* $mode=2 :生成固定高宽的图像,图片缩放后不一定铺满,但保留全部图像信息,即不裁剪,添加补白。
* $mode=3 :生成图像高宽不大于给定高宽,并且以缩放后的实际大小保持。
*
*/
function magick_thumb($src_file,$dst_file,$dst_width,$dst_height,$mode=1) {
$mp = new MagickProcess($src_file);
return $mp->MagickThumb($dst_file,$dst_width,$dst_height,$mode);
}class MagickProcess {
var $src_mw;
var $src_file;
var $src_width;
var $src_height;
var $src_ext;
var $src_format;
var $is_img;
function MagickProcess($src_file) {
$this->src_file = $src_file;
$this->src_mw = NewMagickWand();
$this->is_img=MagickReadImage($this->src_mw,$src_file);
if(!$this->is_img) return;
$this->format = MagickGetImageFormat($this->src_mw);
$this->src_width =MagickGetImageWidth($this->src_mw);
$this->src_height =MagickGetImageHeight($this->src_mw);
}
function IsAnimation() {
$fp=fopen($this->src_file, 'rb');
$image_head = fread($fp,1024);
fclose($fp);
return preg_match("/".chr(0x21).chr(0xff).chr(0x0b).'NETSCAPE2.0'."/",$image_head) ? true : false;
}
function MagickThumb($dst_file,$dst_width,$dst_height,$mode=1) {
if(!$this->is_img) return false;
$src_width = $this->src_width;
$src_height= $this->src_height;
$ratio_w=1.0 * $dst_width / $src_width;
$ratio_h=1.0 * $dst_height / $src_height;
$ratio=1.0;
if(strtolower($this->format)=='gif') {
if ($this->IsAnimation()) {
$this->ResizeGif($dst_file, $dst_width, $dst_height);return;
}
}
switch($mode) {
case 1: // 生成固定高宽,超过的裁剪掉
if($ratio_w < 1 && $ratio_h < 1) { // 都缩小
$ratio = $ratio_w < $ratio_h ? $ratio_h : $ratio_w;
$crop_width = (int)($dst_width / $ratio);
$crop_height = (int)($dst_height / $ratio);
$crop_x = (int) ($src_width-$crop_width)/2 ;
$crop_y = (int) ($src_height-$crop_height)/2 ;
MagickCropImage($this->src_mw, $crop_width, $crop_height, $crop_x, $crop_y);
$this->ResizeImage($this->src_mw, $dst_width, $dst_height);
$this->SaveImage($this->src_mw, $dst_file);
}elseif($ratio_w > 1 && $ratio_h > 1) {
$dst_mkwd=NewMagickWand();
MagickNewImage($dst_mkwd,$dst_width,$dst_height,'#FFFFFF');
$dst_x = (int) abs($dst_width - $src_width) / 2 ;
$dst_y = (int) abs($dst_height -$src_height) / 2;
MagickCompositeImage($dst_mkwd ,$this->src_mw, MW_OverCompositeOp, $dst_x, $dst_y ) ; // 合并图像,拷贝到目标图像的x,y坐标点
$this->SaveImage($dst_mkwd, $dst_file);
DestroyMagickWand($this->src_mw);
}else {
// 一边长,一边短,先裁去长的边。
$crop_x=$crop_y=0;
$crop_width = min($src_width , $dst_width);
$crop_height = min($src_height, $dst_height);
$crop_x = (int) ($src_width-$crop_width)/2 ;
$crop_y = (int) ($src_height-$crop_height)/2 ;MagickCropImage($this->src_mw, $crop_width, $crop_height, $crop_x, $crop_y);
$dst_mkwd=NewMagickWand();
MagickNewImage($dst_mkwd,$dst_width,$dst_height,'#FFFFFF');$dst_x = (int) ($dst_width-$crop_width)/2 ;
$dst_y = (int) ($dst_height-$crop_height)/2 ;
MagickCompositeImage($dst_mkwd ,$this->src_mw, MW_OverCompositeOp, $dst_x, $dst_y ) ; // 合并图像,拷贝到目标图像的x,y坐标点
$this->SaveImage($dst_mkwd, $dst_file);
DestroyMagickWand($this->src_mw);
}
break;
case 2: // 生成固定高宽,保留全部信息,只缩放,不裁剪
if($ratio_w > 1 && $ratio_h > 1) {
$dst_mkwd=NewMagickWand();
MagickNewImage($dst_mkwd,$dst_width,$dst_height,'#FFFFFF');
$dst_x = (int) abs($dst_width - $src_width) / 2 ;
$dst_y = (int) abs($dst_height -$src_height) / 2;
MagickCompositeImage($dst_mkwd ,$this->src_mw, MW_OverCompositeOp, $dst_x, $dst_y ) ;
$this->SaveImage($dst_mkwd, $dst_file);
DestroyMagickWand($this->src_mw);
}else {
$ratio = $ratio_w > $ratio_h ? $ratio_h : $ratio_w;
$tmp_w = (int)($src_width * $ratio);
$tmp_h = (int)($src_height * $ratio);
$this->ResizeImage($this->src_mw, $tmp_w, $tmp_h);
$dst_mkwd=NewMagickWand();
MagickNewImage($dst_mkwd,$dst_width,$dst_height,'#FFFFFF');
$dst_x = (int) abs($tmp_w - $dst_width) / 2 ;
$dst_y = (int) abs($tmp_h - $dst_height) / 2;
MagickCompositeImage($dst_mkwd ,$this->src_mw, MW_OverCompositeOp, $dst_x, $dst_y ) ;
$this->SaveImage($dst_mkwd, $dst_file);
DestroyMagickWand($this->src_mw);
}
break;
case 3: // 超过缩放,不超过直接存图。
if($ratio_w > 1 && $ratio_h > 1) {
$this->SaveImage($this->src_mw, $dst_file);
}else {
$ratio = $ratio_w > $ratio_h ? $ratio_h : $ratio_w;
$tmp_w = (int)($src_width * $ratio);
$tmp_h = (int)($src_height * $ratio);
$this->ResizeImage($this->src_mw, $tmp_w, $tmp_h);
$this->SaveImage($this->src_mw, $dst_file);
}
break;
}
return true;
}
function ResizeGif($dst_file,$dst_width, $dst_height) {
MagickResetIterator($this->src_mw);
do {
$iw = MagickGetImageWidth($this->src_mw);
$ih = MagickGetImageHeight($this->src_mw);
$iratio=1.0;
$iratio_w = doubleval($iw) / doubleval($dst_width);
$iratio_h = doubleval($ih) / doubleval($dst_height);
$iratio = $iratio_w > $iratio_h ? $iratio_w : $iratio_h;
$tmp_w = floor( $iw / $iratio);
$tmp_h = floor( $ih / $iratio);
$this->ResizeImage($this->src_mw, $tmp_w, $tmp_h);
} while(MagickNextImage($this->src_mw));
$this->SaveImage($this->src_mw, $dst_file);
}function ResizeImage($mgk, $dst_width, $dst_height) {
MagickResizeImage( $mgk, $dst_width, $dst_height, MW_LanczosFilter, 1.0);
//MagickSampleImage($mw, $dst_width, $dst_height); // Resize的效果好于Sample
//MagickScaleImage($mw, $dst_width, $dst_height);
/*
*
MW_PointFilter MW_BoxFilter
MW_TriangleFilter MW_HermiteFilter
MW_HanningFilter MW_HammingFilter
MW_BlackmanFilter MW_GaussianFilter
MW_QuadraticFilter MW_CubicFilter
MW_CatromFilter MW_MitchellFilter
MW_LanczosFilter MW_BesselFilter
MW_SincFilter
*/
}
function SaveImage($mgk,$dst_file) {
MagickSetFormat($mgk, $this->format);
MagickWriteImages($mgk, $dst_file, MagickTrue);
DestroyMagickWand($mgk);
unset($mgk);
}
}// end class
?>
http://code.h2ero.cn/temp/gifs/decode_a_gif.php
楼主那两个类你没有下来看看~~~
呜呜呜呜~~~~~
http://u.115.com/file/t5a016496b#gifmerge.zip里面test.gif是原图。testXX.gif是分离的各帧。
那个问题是存在,不过后来又有人写了个,就是在那个GIFEncoder的基础上面修改了下,基本上解决了,你看我生成的那个都没有画质问题,
当时看别人的demo基本上是无损的,我在弄几张随机生成的大图给你看看,
http://code.h2ero.cn/temp/gifs/gif.php
GIFEncoder
http://code.h2ero.cn/code/classes/gif.zip
找就有了,正在使用php5.3.2