注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

@fc_lamp

关注Web应用解决方案MySql/PHP/Python一盏名为"飞川"的灯~

 
 
 

日志

 
 

PHP图片处理函数 类 (水印图,缩略图)[关于等比例压缩与裁剪压缩][Imagick 扩展处理]  

2012-05-07 17:07:00|  分类: Web技术-Php |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

PHP图片处理函数 类(水印图,缩略图)[关于等比例压缩与裁剪压缩]【Imagick 处理

以下为GD库模式处理:

近来闲来无事,就想到了再把PHP的图片处理函数整来再熟悉熟悉。下面简单的写了一个图片处理类,功能包括:水印,缩略图等。

不过,对于生成缩略图有两种方式:一种是直接按比例来压缩图片,另外一种是先裁剪再压缩的方式。在自己看来等例压缩与裁剪压缩区别就在于:

等例压缩:能保证图片的宽长比例合理,且图片有完整性。但实际大小不保证符合要求。

裁剪压缩:  能保证图片的宽长比例合理,实际大小也能保证。但图片完整性不能保证。 

好了,我们还是直接上代码吧。

image.php

<?php
/**
*
* 图像处理类
* @author FC_LAMP
* @internal功能包含:水印,缩略图
*/
class Img
{
//图片格式
private $exts = array ('jpg', 'jpeg', 'gif', 'bmp', 'png' );

/**
*
*
* @throws Exception
*/
public function __construct()
{
if (! function_exists ( 'gd_info' ))
{
throw new Exception ( '加载GD库失败!' );
}
}

/**
*
* 裁剪压缩(
先裁后压)

* @param $src_img 图片
* @param $save_img 生成后的图片
* @param $option 参数选项,包括: $maxwidth 宽 $maxheight 高
* array('width'=>xx,'height'=>xxx)
* @internal
* 我们一般的压缩图片方法,在图片过长或过宽时生成的图片
* 都会被“压扁”,针对这个应采用先裁剪后按比例压缩的方法
*/
public function thumb_img($src_img, $save_img = '', $option)
{

if (empty ( $option ['width'] ) or empty ( $option ['height'] ))
{
return array ('flag' => False, 'msg' => '原图长度与宽度不能小于0' );
}
$org_ext = $this->is_img ( $src_img );
if (! $org_ext ['flag'])
{
return $org_ext;
}

//如果有保存路径,则确定路径是否正确
if (! empty ( $save_img ))
{
$f = $this->check_dir ( $save_img );
if (! $f ['flag'])
{
return $f;
}
}

//获取出相应的方法
$org_funcs = $this->get_img_funcs ( $org_ext ['msg'] );

//获取原大小
$source = $org_funcs ['create_func'] ( $src_img );
$src_w = imagesx ( $source );
$src_h = imagesy ( $source );

//调整原始图像(保持图片原形状裁剪图像)
$dst_scale = $option ['height'] / $option ['width']; //目标图像长宽比
$src_scale = $src_h / $src_w; // 原图长宽比
if ($src_scale >= $dst_scale)
{ // 过高
$w = intval ( $src_w );
$h = intval ( $dst_scale * $w );

$x = 0;
$y = ($src_h - $h) / 3;
} else
{ // 过宽
$h = intval ( $src_h );
$w = intval ( $h / $dst_scale );

$x = ($src_w - $w) / 2;
$y = 0;
}
// 剪裁
$croped = imagecreatetruecolor ( $w, $h );
imagecopy ( $croped, $source, 0, 0, $x, $y, $src_w, $src_h );

/*

如果这里直接按比例裁剪,如下:

$croped = imagecreatetruecolor ( $option ['width'], $option ['height'] );

imagecopy ( $croped, $source, 0, 0, $x, $y, $src_w, $src_h );再保存输出。

如果直接取间裁剪,如下:

$croped = imagecreatetruecolor ( $option ['width'], $option ['height'] );

   imagecopy ( $croped, $source, 0, 0, ($src_w-$option ['width'])/2, ($src_h-$option ['height'])/2, $src_w, $src_h );再保存输出。

*/

// 缩放
$scale = $option ['width'] / $w;
$target = imagecreatetruecolor ( $option ['width'], $option ['height'] );
$final_w = intval ( $w * $scale );
$final_h = intval ( $h * $scale );
imagecopyresampled ( $target, $croped, 0, 0, 0, 0, $final_w, $final_h, $w, $h );
imagedestroy ( $croped );

//输出(保存)图片
if (! empty ( $save_img ))
{

$org_funcs ['save_func'] ( $target, $save_img );
} else
{
header ( $org_funcs ['header'] );
$org_funcs ['save_func'] ( $target );
}
imagedestroy ( $target );
return array ('flag' => True, 'msg' => '' );
}

/**
*
* 等比例缩放图像
* @param $src_img 原图片
* @param $save_img 需要保存的地方
* @param $option 参数设置 array('width'=>xx,'height'=>xxx)
*
*/
function resize_image($src_img, $save_img = '', $option)
{
$org_ext = $this->is_img ( $src_img );
if (! $org_ext ['flag'])
{
return $org_ext;
}

//如果有保存路径,则确定路径是否正确
if (! empty ( $save_img ))
{
$f = $this->check_dir ( $save_img );
if (! $f ['flag'])
{
return $f;
}
}

//获取出相应的方法
$org_funcs = $this->get_img_funcs ( $org_ext ['msg'] );

//获取原大小
$source = $org_funcs ['create_func'] ( $src_img );
$src_w = imagesx ( $source );
$src_h = imagesy ( $source );

if (($option ['width'] && $src_w > $option ['width']) || ($option ['height'] && $src_h > $option ['height']))
{
if ($option ['width'] && $src_w > $option ['width'])
{
$widthratio = $option ['width'] / $src_w;
$resizewidth_tag = true;
}

if ($option ['height'] && $src_h > $option ['height'])
{
$heightratio = $option ['height'] / $src_h;
$resizeheight_tag = true;
}

if ($resizewidth_tag && $resizeheight_tag)
{
if ($widthratio < $heightratio)
$ratio = $widthratio;
else
$ratio = $heightratio;
}

if ($resizewidth_tag && ! $resizeheight_tag)
$ratio = $widthratio;
if ($resizeheight_tag && ! $resizewidth_tag)
$ratio = $heightratio;

$newwidth = $src_w * $ratio;
$newheight = $src_h * $ratio;

if (function_exists ( "imagecopyresampled" ))
{
$newim = imagecreatetruecolor ( $newwidth, $newheight );
imagecopyresampled ( $newim, $source, 0, 0, 0, 0, $newwidth, $newheight, $src_w, $src_h );
} else
{
$newim = imagecreate ( $newwidth, $newheight );
imagecopyresized ( $newim, $source, 0, 0, 0, 0, $newwidth, $newheight, $src_w, $src_h );
}
}
//输出(保存)图片
if (! empty ( $save_img ))
{

$org_funcs ['save_func'] ( $newim, $save_img );
} else
{
header ( $org_funcs ['header'] );
$org_funcs ['save_func'] ( $newim );
}
imagedestroy ( $newim );
return array ('flag' => True, 'msg' => '' );
}

/**
*
* 生成水印图片
* @param $org_img 原图像
* @param $mark_img 水印标记图像
* @param $save_img 当其目录不存在时,会试着创建目录
* @param array $option 为水印的一些基本设置包含:
* x:水印的水平位置,默认为减去水印图宽度后的值
* y:水印的垂直位置,默认为减去水印图高度后的值
* alpha:alpha值(控制透明度),默认为50
*/
public function water_mark($org_img, $mark_img, $save_img = '', $option = array())
{
//检查图片
$org_ext = $this->is_img ( $org_img );
if (! $org_ext ['flag'])
{
return $org_ext;
}
$mark_ext = $this->is_img ( $mark_img );
if (! $mark_ext ['flag'])
{
return $mark_ext;
}
//如果有保存路径,则确定路径是否正确
if (! empty ( $save_img ))
{
$f = $this->check_dir ( $save_img );
if (! $f ['flag'])
{
return $f;
}
}

//获取相应画布
$org_funcs = $this->get_img_funcs ( $org_ext ['msg'] );
$org_img_im = $org_funcs ['create_func'] ( $org_img );

$mark_funcs = $this->get_img_funcs ( $mark_ext ['msg'] );
$mark_img_im = $mark_funcs ['create_func'] ( $mark_img );

//拷贝水印图片坐标
$mark_img_im_x = 0;
$mark_img_im_y = 0;
//拷贝水印图片高宽
$mark_img_w = imagesx ( $mark_img_im );
$mark_img_h = imagesy ( $mark_img_im );

$org_img_w = imagesx ( $org_img_im );
$org_img_h = imagesx ( $org_img_im );

//合成生成点坐标
$x = $org_img_w - $mark_img_w;
$org_img_im_x = isset ( $option ['x'] ) ? $option ['x'] : $x;
$org_img_im_x = ($org_img_im_x > $org_img_w or $org_img_im_x < 0) ? $x : $org_img_im_x;
$y = $org_img_h - $mark_img_h;
$org_img_im_y = isset ( $option ['y'] ) ? $option ['y'] : $y;
$org_img_im_y = ($org_img_im_y > $org_img_h or $org_img_im_y < 0) ? $y : $org_img_im_y;

//alpha
$alpha = isset ( $option ['alpha'] ) ? $option ['alpha'] : 50;
$alpha = ($alpha > 100 or $alpha < 0) ? 50 : $alpha;

//合并图片
imagecopymerge ( $org_img_im, $mark_img_im, $org_img_im_x, $org_img_im_y, $mark_img_im_x, $mark_img_im_y, $mark_img_w, $mark_img_h, $alpha );

//输出(保存)图片
if (! empty ( $save_img ))
{

$org_funcs ['save_func'] ( $org_img_im, $save_img );
} else
{
header ( $org_funcs ['header'] );
$org_funcs ['save_func'] ( $org_img_im );
}
//销毁画布
imagedestroy ( $org_img_im );
imagedestroy ( $mark_img_im );
return array ('flag' => True, 'msg' => '' );

}

/**
*
* 检查图片
* @param unknown_type $img_path
* @return array('flag'=>true/false,'msg'=>ext/错误信息)
*/
private function is_img($img_path)
{
if (! file_exists ( $img_path ))
{
return array ('flag' => False, 'msg' => "加载图片 $img_path 失败!" );
}
$ext = explode ( '.', $img_path );
$ext = strtolower ( end ( $ext ) );
if (! in_array ( $ext, $this->exts ))
{
return array ('flag' => False, 'msg' => "图片 $img_path 格式不正确!" );
}
return array ('flag' => True, 'msg' => $ext );
}

/**
*
* 返回正确的图片函数
* @param unknown_type $ext
*/
private function get_img_funcs($ext)
{
//选择
switch ($ext)
{
case 'jpg' :
$header = 'Content-Type:image/jpeg';
$createfunc = 'imagecreatefromjpeg';
$savefunc = 'imagejpeg';
break;
case 'jpeg' :
$header = 'Content-Type:image/jpeg';
$createfunc = 'imagecreatefromjpeg';
$savefunc = 'imagejpeg';
break;
case 'gif' :
$header = 'Content-Type:image/gif';
$createfunc = 'imagecreatefromgif';
$savefunc = 'imagegif';
break;
case 'bmp' :
$header = 'Content-Type:image/bmp';
$createfunc = 'imagecreatefrombmp';
$savefunc = 'imagebmp';
break;
default :
$header = 'Content-Type:image/png';
$createfunc = 'imagecreatefrompng';
$savefunc = 'imagepng';
}
return array ('save_func' => $savefunc, 'create_func' => $createfunc, 'header' => $header );
}

/**
*
* 检查并试着创建目录
* @param $save_img
*/
private function check_dir($save_img)
{
$dir = dirname ( $save_img );
if (! is_dir ( $dir ))
{
if (! mkdir ( $dir, 0777, true ))
{
return array ('flag' => False, 'msg' => "图片保存目录 $dir 无法创建!" );
}
}
return array ('flag' => True, 'msg' => '' );
}
}

if (! empty ( $_FILES ['test'] ['tmp_name'] ))
{
//例子
$img = new Img ();
//原图
$name = explode ( '.', $_FILES ['test'] ['name'] );
$org_img = 'D:/test.' . end ( $name );
move_uploaded_file ( $_FILES ['test'] ['tmp_name'], $org_img );
$option = array ('width' => $_POST ['width'], 'height' => $_POST ['height'] );
if ($_POST ['type'] == 1)
{
$s = $img->resize_image ( $org_img, '', $option );
} else
{
$img->thumb_img ( $org_img, '', $option );
}
unlink ( $org_img );
}



使用方式:

水印

$img = new Img ();
$org_img = 'D:/tt.png';
$mark_img = 'D:/t.png';
//保存水印图片(如果$save_img为空时,将会直接输出图片)
$save_img = 'D:/test99h/testone/sss.png';
//水印设置调节
$option = array ('x' => 50, 'y' => 50, 'alpha' => 80 );
//生成水印图片
$flag = $img->water_mark ( $org_img, $mark_img, $save_img, $option );

当我们调节 $option 参数时,会有相应变化:

1 $option = array ('x' => 0, 'y' => 0, 'alpha' => 50 );

图:PHP图片处理函数 类 (水印图,缩略图)[关于等比例压缩与裁剪压缩] - fc-lamp - fc-lamp的博客

2$option = array ('x' => 50, 'y' => 50, 'alpha' => 80 );

图:PHP图片处理函数 类 (水印图,缩略图)[关于等比例压缩与裁剪压缩] - fc-lamp - fc-lamp的博客

3 如果你不设置$option 参数,将会采用默认值:

图:PHP图片处理函数 类 (水印图,缩略图)[关于等比例压缩与裁剪压缩] - fc-lamp - fc-lamp的博客


如果要纯文字式的水印,可以参看这里:http://www.php.net/manual/zh/image.examples.merged-watermark.php

比例图

//例子
$img = new Img ();
$org_img = 'D:/tt.png';
//压缩图片(100*100)
$option = array ('width' => 100, 'height' => 100 );

//$save_img为空时,将会直接输出图像到浏览器

$save_img = 'D:/test99h/testone/sss_thumb.png';
$flag = $img->thumb_img ( $org_img, $save_img, $option );


图像:PHP图片处理函数 类 (水印图,缩略图)[关于等比例压缩与裁剪压缩] - fc-lamp - fc-lamp的博客

调节$option的大小值:

$option = array ('width' => 200, 'height' => 200);

图像:PHP图片处理函数 类 (水印图,缩略图)[关于等比例压缩与裁剪压缩] - fc-lamp - fc-lamp的博客

水印与压缩图


$img = new Img ();
//原图
$org_img = 'D:/tt.png';
//水印标记图
$mark_img = 'D:/t.png';
//保存水印图片
$save_img = 'D:/test99h/testone/sss.png';
//水印设置调节
$option = array ('x' => 50, 'y' => 50, 'alpha' => 60 );
//生成水印图片
$flag = $img->water_mark ( $org_img, $mark_img, $save_img, $option );
//压缩水印图片
$option = array ('width' => 200, 'height' => 200 );
//保存压缩图
$save_img2 = 'D:/test99h/testone/sss2_thumb.png';
$flag = $img->thumb_img ( $save_img, $save_img2, $option ); //等比例压缩类似

图像:PHP图片处理函数 类 (水印图,缩略图)[关于等比例压缩与裁剪压缩] - fc-lamp - fc-lamp的博客

在压缩生成的水印图像时,压缩后生成的图像格式应与原图像,水印图像一致。不然,会出现一些未知错误。

另注:图片压缩原理非本人所创。


Imagick 扩展处理】模式:

实际上在PHP中自带了更好的图片处理模式,Imagick !

API 接口:http://uk3.php.net/manual/zh/book.imagick.php

比如缩略图处理:http://uk3.php.net/manual/zh/imagick.thumbnailimage.php

<?php
$im = new \Imagick();
$img = dirname(__FILE__).'/2.jpg';
$im->readImage($img);
$im->thumbnailImage(300,350);
#$im->writeImage('./2_.jpg');
header('Content-Type:image/jpg');
echo $im->getImageBlob();

但是此扩展还没有在php捆绑,所以需要单独安装。

dll的下载安装参照官网即可:http://uk3.php.net/manual/zh/imagick.installation.php

imagick 可要官网上下载:http://www.imagemagick.org/script/binary-releases.php


imagick提供了更好、性能更佳的图片处理方式。






  评论这张
 
阅读(1360)| 评论(1)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017