转自:http://blog.terry39.com/?p=51
对GIF动画进行缩小操作时,需要逐帧的缩小,这里会碰到几个比较麻烦的问题:
1、透明动画的问题
2、帧图片比显示尺寸小,并且有坐标控制的问题,直接缩小会似的动画完全乱掉
针对第一个问题,首先要建立一个透明的目标图片对象
$image = new Imagick();
$image->newImage($width,$height, $color, ‘gif’);
其中 $color = new ImagickPixel(“transparent”); 实际上是建立了一个透明色。
针对第二个问题,一开始我也是循环了GIF中每个图片对象,发现尺寸大小不一样,看API手册里只有 getImageWidth 和getImageHeight 这两个方法是和尺寸有关的,而没有关于获得坐标 position 的方法;只能一个一个的试,最后发现是用 getImagePage 获得的一个数组,里面包含了 width, height, x, y 这4个字段,其中width和height分别是图象的显示尺寸,并非图象的尺寸,而图象的尺寸是用getImageWidth和getImageHeight来获得,可能比图象的显示尺寸小;还有两个数据 x和y 分别是当前图象在显示区域内的坐标;不知道这个 Image Page 如何翻译,也许应该是层的概念;这个时候就可以计算出帧图片正确的显示内容。
原图效果
缩小或切割后
这里给出ImagickResizeImage函数
- <?php
- /**
- * 使用ImageMagick库缩放图片
- *
- * @param string $srcFile 源图片路径
- * @param string $destFile 目标文件路径
- * @param int $new_w 新的宽度
- * @param int $new_h 新的高度
- * @param bool $trim 是否切割图片
- *
- * @version 1.0
- * @update 2007-04-03 23:09
- * @author terry39
- *
- */
- function ImagickResizeImage($srcFile,$destFile,$new_w,$new_h, $trim=false)
- {
- if($new_w <= 0 || $new_h <= 0 || !file_exists($srcFile)) return false;
- $src = new Imagick($srcFile);
- $image_format = strtolower($src->getImageFormat());
- if($image_format != 'jpeg' && $image_format != 'gif' && $image_format != 'png' && $image_format != 'jpg') return false;
- $src_page = $src->getImagePage();
- //如果是 bbsposts 目录里的图片文件,这加入水印
- if(strpos($destFile, 'bbsposts') !== false){
- //先算出最终缩略图的尺寸
- $src_w = $src_page['width'];
- $src_h = $src_page['height'];
- $rate_w = $new_w / $src_w;
- $rate_h = $new_h / $src_h;
- $rate = (!$trim && $rate_w < $rate_h) || ($trim && $rate_w > $rate_h) ? $rate_w : $rate_h;
- $rate = $rate > 1 ? 1 : $rate;
- $thumb_w = round($src_w * $rate);
- $thumb_h = round($src_h * $rate);
- //确定使用对应尺寸的水印图片
- $watermask = true;
- if($thumb_w >= 300 && $thumb_h >= 300){
- $watermaskfile = "images/watermask/1.png";
- }else if($thumb_w >= 100 && $thumb_h >= 100){
- $watermaskfile = "images/watermask/2.png";
- }else{
- $watermask = false;
- $watermaskfile = '';
- }
- if($watermask){
- $water = new Imagick($watermaskfile);
- $water_page = $water->getImagePage();
- $water_w = $water_page['width'];
- $water_h = $water_page['height'];
- }
- }
- //如果是 jpg jpeg gif
- if($image_format != 'gif'){
- $dest = $src;
- if(!$trim){
- $dest->thumbnailImage($new_w, $new_h, true);
- }else{
- $dest->cropthumbnailImage($new_w, $new_h);
- }
- if($watermask) $dest->compositeImage($water, Imagick::COMPOSITE_OVER, $dest->getImageWidth() - $water_w, $dest->getImageHeight() - $water_h);
- $dest->writeImage($destFile);
- $dest->clear();
- //gif需要以帧一帧的处理
- }else{
- $dest = new Imagick();
- $color_transparent = new ImagickPixel("transparent"); //透明色
- foreach($src as $img){
- $page = $img->getImagePage();
- $tmp = new Imagick();
- $tmp->newImage($page['width'], $page['height'], $color_transparent, 'gif');
- $tmp->compositeImage($img, Imagick::COMPOSITE_OVER, $page['x'], $page['y']);
- if(!$trim){
- $tmp->thumbnailImage($new_w, $new_h, true);
- }else{
- $tmp->cropthumbnailImage($new_w, $new_h);
- }
- if($watermask) $tmp->compositeImage($water, Imagick::COMPOSITE_OVER, $tmp->getImageWidth() - $water_w, $tmp->getImageHeight() - $water_h);
- $dest->addImage($tmp);
- $dest->setImagePage($tmp->getImageWidth(), $tmp->getImageHeight(), 0, 0);
- $dest->setImageDelay($img->getImageDelay());
- $dest->setImageDispose($img->getImageDispose());
- }
- $dest->coalesceImages();
- $dest->writeImages($destFile, true);
- $dest->clear();
- }
- }
- ?>