php使用imagick模块实现图片缩放、裁剪、压缩示例


Posted in PHP onApril 17, 2014

PHP 使用Imagick模块 缩放,裁剪,压缩图片 包括gif图片

缩放 裁剪

/**
  * 图片裁剪
  * 裁剪规则:
  *   1. 高度为空或为零   按宽度缩放 高度自适应
  *   2. 宽度为空或为零  按高度缩放 宽度自适应
  *      3. 宽度,高度到不为空或为零  按宽高比例等比例缩放裁剪  默认从头部居中裁剪
  * @param number $width
  * @param number $height
  */
 public function resize($width=0, $height=0){
  if($width==0 && $height==0){
   return;
  }  $color = '';// 'rgba(255,255,255,1)';
  $size = $this->image->getImagePage ();
  //原始宽高
  $src_width = $size ['width'];
  $src_height = $size ['height'];
  //按宽度缩放 高度自适应
  if($width!=0 && $height==0){
   if($src_width>$width){
    $height = intval($width*$src_height/$src_width);
    if ($this->type == 'gif') {
     $this->_resizeGif($width, $height);
    }else{
     $this->image->thumbnailImage ( $width, $height, true );
    }
   }
   return;
  }
  //按高度缩放 宽度自适应
  if($width==0 && $height!=0){
   if($src_height>$height){
    $width = intval($src_width*$height/$src_height);
    if ($this->type == 'gif') {
     $this->_resizeGif($width, $height);
    }else{
     $this->image->thumbnailImage ( $width, $height, true );
    }
   }
   return;
  }
  //缩放的后的尺寸
  $crop_w = $width;
  $crop_h = $height;
  //缩放后裁剪的位置
  $crop_x = 0;
  $crop_y = 0;
  if(($src_width/$src_height) < ($width/$height)){
   //宽高比例小于目标宽高比例  宽度等比例放大      按目标高度从头部截取
   $crop_h = intval($src_height*$width/$src_width);
   //从顶部裁剪  不用计算 $crop_y
  }else{
   //宽高比例大于目标宽高比例   高度等比例放大      按目标宽度居中裁剪
   $crop_w = intval($src_width*$height/$src_height);
   $crop_x = intval(($crop_w-$width)/2);
  }
  if ($this->type == 'gif') {
   $this->_resizeGif($crop_w, $crop_h, true, $width, $height,$crop_x, $crop_y);
  } else {
   $this->image->thumbnailImage ( $crop_w, $crop_h, true );
   $this->image->cropImage($width, $height,$crop_x, $crop_y);
  }
 }

针对gif图片的处理方法

/**
  * 处理gif图片 需要对每一帧图片处理
  * @param unknown $t_w  缩放宽
  * @param unknown $t_h  缩放高
  * @param string $isCrop  是否裁剪
  * @param number $c_w  裁剪宽
  * @param number $c_h  裁剪高
  * @param number $c_x  裁剪坐标 x
  * @param number $c_y  裁剪坐标 y
  */
 private function _resizeGif($t_w, $t_h, $isCrop=false, $c_w=0, $c_h=0, $c_x=0, $c_y=0){
  $dest = new Imagick();
  $color_transparent = new ImagickPixel("transparent"); //透明色
  foreach($this->image 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']);   $tmp->thumbnailImage ( $t_w, $t_h, true );
   if($isCrop){
    $tmp->cropImage($c_w, $c_h, $c_x, $c_y);
   }
   $dest->addImage($tmp);
   $dest->setImagePage($tmp->getImageWidth(), $tmp->getImageHeight(), 0, 0);
   $dest->setImageDelay($img->getImageDelay());
   $dest->setImageDispose($img->getImageDispose());
  }
  $this->image->destroy ();
  $this->image = $dest;
 }

保存时压缩处理

// 保存到指定路径
 public function save_to($path) {
  //压缩图片质量
  $this->image->setImageFormat('JPEG');
  $this->image->setImageCompression(Imagick::COMPRESSION_JPEG);
  $a = $this->image->getImageCompressionQuality() * 0.60;
  if ($a == 0) {
   $a = 60;
  }
  $this->image->setImageCompressionQuality($a);
  $this->image->stripImage();  if ($this->type == 'gif') {
   $this->image->writeImages ( $path, true );
  } else {
   $this->image->writeImage ( $path );
  }
 }

ImagickService.php

<?php
/**
 * 图片处理服务类
 * 使用php扩展服务Imagick实现
 * ImageMagick 官网地址 [url]http:www.imagemagick.org/script/index.php[/url]  
 * 
 * @author weiguang3
 * @since 20140403
 */
class ImagickService {
 private $image = null;
 private $type = null;
 // 构造函数
 public function __construct() {
 }
 // 析构函数
 public function __destruct() {
  if ($this->image !== null)
   $this->image->destroy ();
 }
 public function init(){
 }
 // 载入图像
 public function open($path) {
  $this->image = new Imagick ( $path );
  if ($this->image) {
   $this->type = strtolower ( $this->image->getImageFormat () );
  }
  return $this->image;
 }
 /**
  * 图片裁剪
  * 裁剪规则:
  *   1. 高度为空或为零   按宽度缩放 高度自适应
  *   2. 宽度为空或为零  按高度缩放 宽度自适应
  *      3. 宽度,高度到不为空或为零  按宽高比例等比例缩放裁剪  默认从头部居中裁剪
  * @param number $width
  * @param number $height
  */
 public function resize($width=0, $height=0){
  if($width==0 && $height==0){
   return;
  }
  $color = '';// 'rgba(255,255,255,1)';
  $size = $this->image->getImagePage ();
  //原始宽高
  $src_width = $size ['width'];
  $src_height = $size ['height'];
  //按宽度缩放 高度自适应
  if($width!=0 && $height==0){
   if($src_width>$width){
    $height = intval($width*$src_height/$src_width);
    if ($this->type == 'gif') {
     $this->_resizeGif($width, $height);
    }else{
     $this->image->thumbnailImage ( $width, $height, true );
    }
   }
   return;
  }
  //按高度缩放 宽度自适应
  if($width==0 && $height!=0){
   if($src_height>$height){
    $width = intval($src_width*$height/$src_height);
    if ($this->type == 'gif') {
     $this->_resizeGif($width, $height);
    }else{
     $this->image->thumbnailImage ( $width, $height, true );
    }
   }
   return;
  }
  //缩放的后的尺寸
  $crop_w = $width;
  $crop_h = $height;
  //缩放后裁剪的位置
  $crop_x = 0;
  $crop_y = 0;
  if(($src_width/$src_height) < ($width/$height)){
   //宽高比例小于目标宽高比例  宽度等比例放大      按目标高度从头部截取
   $crop_h = intval($src_height*$width/$src_width);
   //从顶部裁剪  不用计算 $crop_y
  }else{
   //宽高比例大于目标宽高比例   高度等比例放大      按目标宽度居中裁剪
   $crop_w = intval($src_width*$height/$src_height);
   $crop_x = intval(($crop_w-$width)/2);
  }
  if ($this->type == 'gif') {
   $this->_resizeGif($crop_w, $crop_h, true, $width, $height,$crop_x, $crop_y);
  } else {
   $this->image->thumbnailImage ( $crop_w, $crop_h, true );
   $this->image->cropImage($width, $height,$crop_x, $crop_y);
  }
 }
 /**
  * 处理gif图片 需要对每一帧图片处理
  * @param unknown $t_w  缩放宽
  * @param unknown $t_h  缩放高
  * @param string $isCrop  是否裁剪
  * @param number $c_w  裁剪宽
  * @param number $c_h  裁剪高
  * @param number $c_x  裁剪坐标 x
  * @param number $c_y  裁剪坐标 y
  */
 private function _resizeGif($t_w, $t_h, $isCrop=false, $c_w=0, $c_h=0, $c_x=0, $c_y=0){
  $dest = new Imagick();
  $color_transparent = new ImagickPixel("transparent"); //透明色
  foreach($this->image 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']);
   $tmp->thumbnailImage ( $t_w, $t_h, true );
   if($isCrop){
    $tmp->cropImage($c_w, $c_h, $c_x, $c_y);
   }
   $dest->addImage($tmp);
   $dest->setImagePage($tmp->getImageWidth(), $tmp->getImageHeight(), 0, 0);
   $dest->setImageDelay($img->getImageDelay());
   $dest->setImageDispose($img->getImageDispose());
  }
  $this->image->destroy ();
  $this->image = $dest;
 }
 
 /**
  * 更改图像大小 
  *  $fit: 适应大小方式 
  *   'force': 把图片强制变形成 $width X $height 大小 
  *   'scale': 按比例在安全框 $width X $height 内缩放图片, 输出缩放后图像大小 不完全等于 $width X $height 
  *   'scale_fill': 按比例在安全框 $width X $height 内缩放图片,安全框内没有像素的地方填充色, 
  *    使用此参数时可设置背景填充色 $bg_color = array(255,255,255)(红,绿,蓝, 透明度) 
  *    透明度(0不透明-127完全透明)) 其它: 智能模能 缩放图像并载取图像的中间部分 $width X $height 像素大小 
  *  $fit = 'force','scale','scale_fill' 时: 输出完整图像 
  *  $fit = 图像方位值 时, 输出指定位置部分图像 字母与图像的对应关系如下: 
  *   north_west north north_east 
  *   west center east 
  *   south_west south south_east
  */
 public function resize_to($width = 100, $height = 100, $fit = 'center', $fill_color = array(255,255,255,0)) {
  switch ($fit) {
   case 'force' :
    if ($this->type == 'gif') {
     $image = $this->image;
     $canvas = new Imagick ();
     $images = $image->coalesceImages ();
     foreach ( $images as $frame ) {
      $img = new Imagick ();
      $img->readImageBlob ( $frame );
      $img->thumbnailImage ( $width, $height, false );
      $canvas->addImage ( $img );
      $canvas->setImageDelay ( $img->getImageDelay () );
     }
     $image->destroy ();
     $this->image = $canvas;
    } else {
     $this->image->thumbnailImage ( $width, $height, false );
    }
    break;
   case 'scale' :
    if ($this->type == 'gif') {
     $image = $this->image;
     $images = $image->coalesceImages ();
     $canvas = new Imagick ();
     foreach ( $images as $frame ) {
      $img = new Imagick ();
      $img->readImageBlob ( $frame );
      $img->thumbnailImage ( $width, $height, true );
      $canvas->addImage ( $img );
      $canvas->setImageDelay ( $img->getImageDelay () );
     }
     $image->destroy ();
     $this->image = $canvas;
    } else {
     $this->image->thumbnailImage ( $width, $height, true );
    }
    break;
   case 'scale_fill' :
    $size = $this->image->getImagePage ();
    $src_width = $size ['width'];
    $src_height = $size ['height'];
    $x = 0;
    $y = 0;
    $dst_width = $width;
    $dst_height = $height;
    if ($src_width * $height > $src_height * $width) {
     $dst_height = intval ( $width * $src_height / $src_width );
     $y = intval ( ($height - $dst_height) / 2 );
    } else {
     $dst_width = intval ( $height * $src_width / $src_height );
     $x = intval ( ($width - $dst_width) / 2 );
    }
    $image = $this->image;
    $canvas = new Imagick ();
    $color = 'rgba(' . $fill_color [0] . ',' . $fill_color [1] . ',' . $fill_color [2] . ',' . $fill_color [3] . ')';
    if ($this->type == 'gif') {
     $images = $image->coalesceImages ();
     foreach ( $images as $frame ) {
      $frame->thumbnailImage ( $width, $height, true );
      $draw = new ImagickDraw ();
      $draw->composite ( $frame->getImageCompose (), $x, $y, $dst_width, $dst_height, $frame );
      $img = new Imagick ();
      $img->newImage ( $width, $height, $color, 'gif' );
      $img->drawImage ( $draw );
      $canvas->addImage ( $img );
      $canvas->setImageDelay ( $img->getImageDelay () );
      $canvas->setImagePage ( $width, $height, 0, 0 );
     }
    } else {
     $image->thumbnailImage ( $width, $height, true );
     $draw = new ImagickDraw ();
     $draw->composite ( $image->getImageCompose (), $x, $y, $dst_width, $dst_height, $image );
     $canvas->newImage ( $width, $height, $color, $this->get_type () );
     $canvas->drawImage ( $draw );
     $canvas->setImagePage ( $width, $height, 0, 0 );
    }
    $image->destroy ();
    $this->image = $canvas;
    break;
   default :
    $size = $this->image->getImagePage ();
    $src_width = $size ['width'];
    $src_height = $size ['height'];
    $crop_x = 0;
    $crop_y = 0;
    $crop_w = $src_width;
    $crop_h = $src_height;
    if ($src_width * $height > $src_height * $width) {
     $crop_w = intval ( $src_height * $width / $height );
    } else {
     $crop_h = intval ( $src_width * $height / $width );
    }
    switch ($fit) {
     case 'north_west' :
      $crop_x = 0;
      $crop_y = 0;
      break;
     case 'north' :
      $crop_x = intval ( ($src_width - $crop_w) / 2 );
      $crop_y = 0;
      break;
     case 'north_east' :
      $crop_x = $src_width - $crop_w;
      $crop_y = 0;
      break;
     case 'west' :
      $crop_x = 0;
      $crop_y = intval ( ($src_height - $crop_h) / 2 );
      break;
     case 'center' :
      $crop_x = intval ( ($src_width - $crop_w) / 2 );
      $crop_y = intval ( ($src_height - $crop_h) / 2 );
      break;
     case 'east' :
      $crop_x = $src_width - $crop_w;
      $crop_y = intval ( ($src_height - $crop_h) / 2 );
      break;
     case 'south_west' :
      $crop_x = 0;
      $crop_y = $src_height - $crop_h;
      break;
     case 'south' :
      $crop_x = intval ( ($src_width - $crop_w) / 2 );
      $crop_y = $src_height - $crop_h;
      break;
     case 'south_east' :
      $crop_x = $src_width - $crop_w;
      $crop_y = $src_height - $crop_h;
      break;
     default :
      $crop_x = intval ( ($src_width - $crop_w) / 2 );
      $crop_y = intval ( ($src_height - $crop_h) / 2 );
    }
    $image = $this->image;
    $canvas = new Imagick ();
    if ($this->type == 'gif') {
     $images = $image->coalesceImages ();
     foreach ( $images as $frame ) {
      $img = new Imagick ();
      $img->readImageBlob ( $frame );
      $img->cropImage ( $crop_w, $crop_h, $crop_x, $crop_y );
      $img->thumbnailImage ( $width, $height, true );
      $canvas->addImage ( $img );
      $canvas->setImageDelay ( $img->getImageDelay () );
      $canvas->setImagePage ( $width, $height, 0, 0 );
     }
    } else {
     $image->cropImage ( $crop_w, $crop_h, $crop_x, $crop_y );
     $image->thumbnailImage ( $width, $height, true );
     $canvas->addImage ( $image );
     $canvas->setImagePage ( $width, $height, 0, 0 );
    }
    $image->destroy ();
    $this->image = $canvas;
  }
 }
 // 添加水印图片
 public function add_watermark($path, $x = 0, $y = 0) {
  $watermark = new Imagick ( $path );
  $draw = new ImagickDraw ();
  $draw->composite ( $watermark->getImageCompose (), $x, $y, $watermark->getImageWidth (), $watermark->getimageheight (), $watermark );
  if ($this->type == 'gif') {
   $image = $this->image;
   $canvas = new Imagick ();
   $images = $image->coalesceImages ();
   foreach ( $image as $frame ) {
    $img = new Imagick ();
    $img->readImageBlob ( $frame );
    $img->drawImage ( $draw );
    $canvas->addImage ( $img );
    $canvas->setImageDelay ( $img->getImageDelay () );
   }
   $image->destroy ();
   $this->image = $canvas;
  } else {
   $this->image->drawImage ( $draw );
  }
 }
 // 添加水印文字
 public function add_text($text, $x = 0, $y = 0, $angle = 0, $style = array()) {
  $draw = new ImagickDraw ();
  if (isset ( $style ['font'] ))
   $draw->setFont ( $style ['font'] );
  if (isset ( $style ['font_size'] ))
   $draw->setFontSize ( $style ['font_size'] );
  if (isset ( $style ['fill_color'] ))
   $draw->setFillColor ( $style ['fill_color'] );
  if (isset ( $style ['under_color'] ))
   $draw->setTextUnderColor ( $style ['under_color'] );
  if ($this->type == 'gif') {
   foreach ( $this->image as $frame ) {
    $frame->annotateImage ( $draw, $x, $y, $angle, $text );
   }
  } else {
   $this->image->annotateImage ( $draw, $x, $y, $angle, $text );
  }
 }
 // 保存到指定路径
 public function save_to($path) {
  //压缩图片质量
  $this->image->setImageFormat('JPEG');
  $this->image->setImageCompression(Imagick::COMPRESSION_JPEG);
  $a = $this->image->getImageCompressionQuality() * 0.60;
  if ($a == 0) {
   $a = 60;
  }
  $this->image->setImageCompressionQuality($a);
  $this->image->stripImage();
  if ($this->type == 'gif') {
   $this->image->writeImages ( $path, true );
  } else {
   $this->image->writeImage ( $path );
  }
 }
 // 输出图像
 public function output($header = true) {
  if ($header)
   header ( 'Content-type: ' . $this->type );
  echo $this->image->getImagesBlob ();
 }
 public function get_width() {
  $size = $this->image->getImagePage ();
  return $size ['width'];
 }
 public function get_height() {
  $size = $this->image->getImagePage ();
  return $size ['height'];
 }
 // 设置图像类型, 默认与源类型一致
 public function set_type($type = 'png') {
  $this->type = $type;
  $this->image->setImageFormat ( $type );
 }
 // 获取源图像类型
 public function get_type() {
  return $this->type;
 }
 public function get_file_size(){
  if($this->image){
   return 0;//$this->image->getImageLength(); getImageLength not find
  }else{
   return 0;
  }
 }
 public function get_file_type(){
  if($this->image){
   return $this->image->getimagemimetype();
  }else{
   return 0;
  }
 }
 public function get_sha1(){
  if($this->image){
   return sha1($this->image->__tostring());
  }else{
   return '';
  }
 }
 // 当前对象是否为图片
 public function is_image() {
  if ($this->image)
   return true;
  else
   return false;
 }
 /*
  * 添加一个边框 $width: 左右边框宽度 $height: 上下边框宽度 $color: 颜色: RGB 颜色 'rgb(255,0,0)' 或 16进制颜色 '#FF0000' 或颜色单词 'white'/'red'...
  */
 public function border($width, $height, $color = 'rgb(220, 220, 220)') {
  $color = new ImagickPixel ();
  $color->setColor ( $color );
  $this->image->borderImage ( $color, $width, $height );
 }
 public function blur($radius, $sigma) {
  $this->image->blurImage ( $radius, $sigma );
 } // 模糊
 public function gaussian_blur($radius, $sigma) {
  $this->image->gaussianBlurImage ( $radius, $sigma );
 } // 高斯模糊
 public function motion_blur($radius, $sigma, $angle) {
  $this->image->motionBlurImage ( $radius, $sigma, $angle );
 } // 运动模糊
 public function radial_blur($radius) {
  $this->image->radialBlurImage ( $radius );
 } // 径向模糊
 public function add_noise($type = null) {
  $this->image->addNoiseImage ( $type == null ? imagick::NOISE_IMPULSE : $type );
 } // 添加噪点
 public function level($black_point, $gamma, $white_point) {
  $this->image->levelImage ( $black_point, $gamma, $white_point );
 } // 调整色阶
 public function modulate($brightness, $saturation, $hue) {
  $this->image->modulateImage ( $brightness, $saturation, $hue );
 } // 调整亮度、饱和度、色调
 public function charcoal($radius, $sigma) {
  $this->image->charcoalImage ( $radius, $sigma );
 } // 素描
 public function oil_paint($radius) {
  $this->image->oilPaintImage ( $radius );
 } // 油画效果
 public function flop() {
  $this->image->flopImage ();
 } // 水平翻转
 public function flip() {
  $this->image->flipImage ();
 } // 垂直翻转
}
PHP 相关文章推荐
JpGraph php柱状图使用介绍
Aug 23 PHP
php中防止恶意刷新页面的代码小结
Oct 31 PHP
PHP_Cooikes不同页面无法传递的解决方法
Mar 07 PHP
jQuery+PHP发布的内容进行无刷新分页(Fckeditor)
Oct 22 PHP
使用php从身份证号中获取一系列线索(星座、生肖、生日等)
May 11 PHP
php 在字符串指定位置插入新字符的简单实现
Jun 28 PHP
详谈PHP程序Laravel 5框架的优化技巧
Jul 18 PHP
PHP对象链式操作实现原理分析
Oct 09 PHP
phpcms的分类名称和类别名称的调用
Jan 05 PHP
PHP简单计算两个时间差的方法示例
Jun 20 PHP
PHP JWT初识及其简单示例
Oct 10 PHP
PHP实现二维数组(或多维数组)转换成一维数组的常见方法总结
Dec 04 PHP
php实现的漂亮分页方法
Apr 17 #PHP
codeigniter中测试通过的分页类示例
Apr 17 #PHP
php生成静态页面的简单示例
Apr 17 #PHP
php文件服务实现虚拟挂载其他目录示例
Apr 17 #PHP
php实现12306余票查询、价格查询示例
Apr 17 #PHP
PHP5.5在windows安装使用memcached服务端的方法
Apr 16 #PHP
纯PHP生成的一个树叶图片画图例子
Apr 16 #PHP
You might like
改写ThinkPHP的U方法使其路由下分页正常
2014/07/02 PHP
PHP制作3D扇形统计图以及对图片进行缩放操作实例
2014/10/23 PHP
PHP实现合并discuz用户
2015/08/05 PHP
PHP+redis实现的限制抢购防止商品超发功能详解
2019/09/19 PHP
在textarea中显示html页面的javascript代码
2007/04/20 Javascript
Javascript创建Silverlight Plugin以及自定义nonSilverlight和lowSilverlight样式
2010/06/28 Javascript
用JQuery实现表格隔行变色和突出显示当前行的代码
2012/02/10 Javascript
javascript针对DOM的应用分析(三)
2012/04/15 Javascript
jquery实现树形二级菜单实例代码
2013/11/20 Javascript
JavaScript判断访问的来源是手机还是电脑,用的哪种浏览器
2013/12/12 Javascript
JavaScript indexOf方法入门实例(计算指定字符在字符串中首次出现的位置)
2014/10/17 Javascript
纯JavaScript实现的兼容各浏览器的添加和移除事件封装
2015/03/28 Javascript
js实现添加可信站点、修改activex安全设置,禁用弹出窗口阻止程序
2016/08/17 Javascript
JavaScript中transform实现数字翻页效果
2017/03/08 Javascript
bootstrap表单按回车会自动刷新页面的解决办法
2017/03/08 Javascript
vue webuploader 文件上传组件开发
2017/09/23 Javascript
Angular Material Icon使用详解
2018/11/07 Javascript
vue控制多行文字展开收起的实现示例
2019/10/11 Javascript
微信小程序获取公众号文章列表及显示文章的示例代码
2020/03/10 Javascript
[01:07:21]NAVI vs VG Supermajor 败者组 BO3 第二场 6.5
2018/06/06 DOTA
在Django中限制已登录用户的访问的方法
2015/07/23 Python
Python字典及字典基本操作方法详解
2018/01/30 Python
不知道这5种下划线的含义,你就不算真的会Python!
2018/10/09 Python
python3字符串操作总结
2019/07/24 Python
PyCharm 无法 import pandas 程序卡住的解决方式
2020/03/09 Python
JupyterNotebook 输出窗口的显示效果调整方法
2020/04/13 Python
Python数组拼接np.concatenate实现过程
2020/04/18 Python
CSS3 选择器 伪类选择器介绍
2012/01/21 HTML / CSS
Java中实现多态的机制
2015/08/09 面试题
业务员岗位职责范本
2013/12/15 职场文书
社团文化节邀请函
2014/01/10 职场文书
新年晚会主持词
2014/03/24 职场文书
写给妈妈的感谢信
2015/01/22 职场文书
学校捐书活动总结
2015/05/08 职场文书
追悼会悼词大全
2015/06/23 职场文书
Go 自定义package包设置与导入操作
2021/05/06 Golang