这几天需要处理图片的问题,发现gd库生成的gif缩略图,全部成了静态的了。如何解决这个问题呢?

解决方案 »

  1.   

    gif应该不可以。
    感觉可以将每一帧都读出来然后全部重新缩略,然后重新生成?
    gif的没弄过。
      

  2.   

    gif是无法生成缩略图的,因为它是一帧一帧的,缩略后就会失去动画的效果的
      

  3.   


    你话未免过于绝对吧?使用im库就可以,我只是不确定GD库是否可以。在这里向大家求证,竟然一个个懒得回答
      

  4.   

    如同一楼所说的,楼主可以先将其每一帧处理后在生成,上次我也在弄个这个问题,有两个类
    分别是解码GIFDecoder.class.php和编码GIFEncoder.class.php的楼主自己研究下 http://code.h2ero.cn/code/classes/gif.zip
      

  5.   

    要保持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_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
    ?>
      

  6.   

    囧~~   那个是别人写的类,先解码提取每一帧,然后再对每一帧处理,处理了将这些帧重新生成gif,im是挺简单不过要安装扩展,
      

  7.   

    这儿有个演示,解码gif为帧,添加新帧,然后再生成gif;
    http://code.h2ero.cn/temp/gifs/decode_a_gif.php
    楼主那两个类你没有下来看看~~~   
    呜呜呜呜~~~~~
      

  8.   

    这个处理效率还是比较高,反正貌似比使用im简单点点,当初自己弄这个问题最后还是没有用im处理,
      

  9.   

    下来试过了。有个麻烦的问题,楼上用过的朋友能否解决?就是分离出来的帧,使用GIFEncoder合并后,动画中有几个帧出现严重的画质问。但使用imagick合并那些帧就不会有这种现象。可见GIFEncoder的合并算法似乎存在问题。
    http://u.115.com/file/t5a016496b#gifmerge.zip里面test.gif是原图。testXX.gif是分离的各帧。
      

  10.   


    那个问题是存在,不过后来又有人写了个,就是在那个GIFEncoder的基础上面修改了下,基本上解决了,你看我生成的那个都没有画质问题,
    当时看别人的demo基本上是无损的,我在弄几张随机生成的大图给你看看,
      

  11.   

    楼上的这儿,无损的,我觉得比较简单,不过对gif的文件编码不懂,
    http://code.h2ero.cn/temp/gifs/gif.php
      

  12.   

    这儿那个别人修改过的
    GIFEncoder
    http://code.h2ero.cn/code/classes/gif.zip
      

  13.   

    你下我的文件去试试看好吗?我用的就是这个包,但某些gif就是合并后差异明显。我分析过,提取每一帧没问题。但吧提取出来的帧重新合并就变化了。不是说总是这样,我也试过有些gif合并后,起码肉眼看不出毛病。但我上面包里面给的gif文件,提取、合并就是有问题。但我用imagick合并是没问题(码肉眼看问题)。
      

  14.   

    toh2ero我csdn的空间不能批准加好友,加QQ35513767聊吧,谢谢
      

  15.   

    GIFEncoder存在的问题已经找出来了,稍后代码整理好考虑与大家分享!
      

  16.   

    暂时没有找到支持5.3.x的imagick扩展:(
      

  17.   


    找就有了,正在使用php5.3.2