<?php
/**
* Image
*
* 提供图片的一些常用处理程序
*$img = new images();
*$img->loadFile("test.gif")->crop(0,0,100,100)->resize(50,50)->waterMark("mark.png", 'left','center')->save("b.gif");
*/
class images {
var $img; //图像标识符
var $info; //保存图片的一些信息
function images($file=null) {
if(!extension_loaded('gd')) {
$this->exceptionFunc("GD库没有加载.");
}
if($file) $this->loadFile($file);
}
function exceptionFunc($msg){
}
function __destruct() {
if(is_resource($this->img)) {
imagedestroy($this->img);
}
}
/*
//返回图片信息
function __call($method, $arg) {
if(substr($method, 0, 3) == 'get') {
$attr = strtolower(substr($method, 3));
if(isset($this->info[$attr]))
return $this->info[$attr];
return null;
}
}
*/
//返回图片资源
function getResource() {
if(isset($this->img))
return $this->img;
return null;
}
// 获取图片信息
function getImgInfo($key=false){
if ($key){
return isset($this->info[$key]) ? $this->info[$key] : null ;
}else {
return $this->info;
}
}
/**
* 保存到文件
*
* @param string $path 文件的绝对路径
*/
function save($path) {
return $this->_output($path);
}
/**
* 将图片输出到浏览器
*
* @param $type 格式
*/
function output($type='gif') {
return $this->_output('stream', $type);
}
/**
* 初始化,创建图像标识符
*
* @param $file 源文件
*/
function loadFile($file) {
if(!file_exists($file)) {
$this->exceptionFunc("指定的文件不存在 => $file");
}
$string = file_get_contents($file);
$key = array('width', 'height', 'type');
$this->info = array_combine($key, array_slice(getimagesize($file), 0, 3));
$this->info['file'] = $file;
$this->img = imagecreatefromstring($string);
return $this;
}
/**
* 图片缩放
*
* @param int $width 目标宽度
* @param int $height 目标高度
* @param boolean $keepScale,是否等比缩放
* @return array $wh 包含缩放后宽度和高度的数组 $wh[0]为宽度,$wh[1]为高度
*/
function resize($width, $height, $keepScale=true) {
$srcw = $this->getWidth();
$srch = $this->getHeight();
if($keepScale) {
//原始宽高比大于目标宽高比,调整高度
if((double)($srcw/$srch) > (double)($width/$height))
{
$height = ceil($srch * $width / $srcw);
}else{
///原始宽高比小于目标宽高比,调整宽度
$width = ceil($srcw * $height / $srch);
}
}
//创建一个透明背景的图像
$newimg = $this->_createAlphaImage($width, $height);
//将原始重新采样复制到透明背景上
imagecopyresampled($newimg, $this->img, 0, 0, 0, 0, $width, $height, $srcw, $srch);
imagedestroy($this->img);
$this->img = $newimg;
$this->info['width'] = $width;
$this->info['height'] = $height;
return $this;
}
/**
* 创建一个透明图片,用于图像复制
*
* @param int $width 宽度
* @param int $height 高度
*/
function _createAlphaImage($width, $height){
$newimg = imagecreatetruecolor($width, $height);
if($this->getType() == 1){ //gif图片
$colorCount = imagecolorstotal($this->img);
imagetruecolortopalette($newimg, true, $colorCount);
imagepalettecopy($newimg,$this->img);
$transparentcolor = imagecolortransparent($this->img);
imagefill($newimg,0,0,$transparentcolor);
imagecolortransparent($newimg,$transparentcolor);
}elseif($this->getType() == 3){ //png图片
imagealphablending($newimg,false);
$col=imagecolorallocatealpha($newimg,255,255,255,127);
imagefilledrectangle($newimg,0,0,$width,$height,$col);
imagealphablending($newimg,true);
}
return $newimg;
}
/**
* 生成缩略图
*
* @param int $width 宽度
* @param int $height 高度
* @param boolean $crop 是否对超出部分进行裁剪,默认为是, 如果不裁剪,则缩图将等比缩放至小于目标尺寸
* @param boolean $center crop时是否在中间裁剪
* @param string $path 要生成的新文件名
*/
function thumbnail($width=128,$height=128, $crop=true, $center=true, $path=null) {
$destw = min($this->getWidth(), $width);
$desth = min($this->getHeight(), $height);
if($crop){
$srcw = $this->getWidth();
$srch = $this->getHeight();
$x = $y = 0;
if((double)($srcw/$srch) > (double)($width/$height))
{
//计算应COPY的宽度
$srcw = ceil($width * $srch/ $height);
//计算起始的x坐标
if($center) $x = ceil(($this->getWidth() - $srcw) / 2);
}else{
//计算应COPY的高度
$srch = ceil($height * $srcw / $width);
//计算起始的y坐标
if($center) $y = ceil(($this->getHeight() - $srch) / 2);
}
//创建一个透明背景的图像
$newimg = $this->_createAlphaImage($width, $height);
//将原始重新采样复制到透明背景上
imagecopyresampled($newimg, $this->img, 0, 0, $x, $y, $width, $height, $srcw, $srch);
imagedestroy($this->img);
$this->img = $newimg;
$this->info['width'] = $width;
$this->info['height'] = $height;
}else{
$this->resize($destw, $desth);
}
if($path) return $this->save($path);
return $this;
}
/**
* 图片裁剪
*
* @param int $x x坐标
* @param int $y y坐标
* @param int $w 裁剪宽度
* @param int $h 裁剪高度
* @return resource 返回裁剪后的图片资源
*/
function crop($x, $y, $w, $h){
$w = min($w, $this->getWidth());
$h = min($h, $this->getHeight());
$newimg = $this->_createAlphaImage($w, $h);
imagecopy($newimg, $this->img, 0, 0, $x, $y, $w, $h);
imagedestroy($this->img);
$this->img = $newimg;
$this->info['width'] = $w;
$this->info['height'] = $h;
return $this;
}
/**
* 对图片进行波纹处理
*
* @param int $grade 弯曲度数,越大图片变形越厉害
* @param string $dir h=水平, v=垂直
*/
function wave($grade=5, $dir="h"){
$w = $this->getWidth();
$h = $this->getHeight();
if($dir=="h"){
for($i=0;$i<$w;$i+=2){
imagecopyresampled($this->img,$this->img, $i-2, sin($i/10)*$grade,$i,0,2,$h,2,$h);
}
}else{
for($i=0;$i<$h;$i+=2){
imagecopyresampled($this->img,$this->img, sin($i/10)*$grade,$i-2,0,$i,$w,2,$w,2);
}
}
return $this;
}
/**
* 给图片加带背景的一行文字
*
* @param string $text 水印文字
* @param string $font 字体文件的路径
* @param $color 文字的颜色 16进制,默认为黑色
* @param int $size 文字的大小
* @param string $path 如果指定则生成图片到$path
* @return 生成的水印图片路径
*/
function textMark($text, $font, $color="#000000", $size=9, $path=null) {
if(!file_exists($font))
$this->exceptionFunc("字体文件不可用 => $font");
//取得图片的高度和宽度
$mwidth = $this->getWidth();
$mheight= $this->getHeight();
$color = $this->_hexColor($color);
$color = imagecolorallocate($this->img, $color['r'], $color['g'], $color['b']);
$black = imagecolorallocate($this->img, 0, 0, 0);
$alpha = imagecolorallocatealpha($this->img, 230, 230, 230, 40);
//填充文字背景
$box = imagettfbbox($size, 0, $font, $text);
//文字补白
$padding = 6;
$textheight = $box[1] - $box[7];
$bgheight = $textheight + $padding * 2;
//文字背景
imagefilledrectangle($this->img, 0, $mheight-$bgheight, $mwidth, $mheight, $alpha);
//小竖条
imagefilledrectangle($this->img, 10, $mheight-$padding-$textheight, 15, $mheight-$padding, $color);
//填充文字
$texty = $mheight - $bgheight/2 + $textheight/2;
imagettftext($this->img, $size, 0, 20, $texty, $color, $font, $text);
if($path) return $this->save($path);
return $this;
}
/**
* 用一张PNG图片给原始图片加水印,水印图片将自动调整到目标图片大小
*
* @param string $png png图片的路径
* @param string $hp 水平位置 left|center|right
* @param string $vp 垂直位置 top|center|bottom
* @param int $pct 水印的透明度 0-100, 0为完全透明,100为完全不透明,只适用于非PNG图片水印
* @param string $path 如果指定则生成图片到$path
* @param
* @return
*/
function waterMark($markImg, $hp='center', $vp='center', $pct=50, $path=null) {
//原图信息
$srcw = $this->getWidth();
$srch = $this->getHeight();
//水印图信息
$mark = new self($markImg);
$markw = $mark->getWidth();
$markh = $mark->getHeight();
//水印图片大于目标图片,调整大小
if($markw > $srcw || $markh > $srch) {
//先将水印图片调整到原始图片大小-10个像素
$mark->resize($srcw-10, $srch-10, true);
$markw = $mark->getWidth();
$markh = $mark->getHeight();
}
//判断水印位置
$arrx = array('left' => 0, 'center' => floor(($srcw - $markw) / 2), 'right' => $srcw - $markw);
$arry = array('top' => 0, 'center' => floor(($srch - $markh) / 2), 'bottom' => $srch - $markh);
$x = isset($arrx[$hp]) ? $arrx[$hp] : $arrx['center'];
$y = isset($arry[$vp]) ? $arry[$vp] : $arry['center'];
//png图片水印
if($mark->getType() == 3){
//打开混色模式
imagealphablending($this->img, true);
imagecopy($this->img, $mark->getResource(), $x, $y, 0, 0, $markw, $markh);
}else{
imagecopymerge($this->img, $mark->getResource(), $x, $y, 0, 0, $markw, $markh, $pct);
}
unset($mark);
if($path) return $this->save($path);
return $this;
}
//返回由16进制组成的颜色索引
function _hexColor($hex) {
$color = hexdec(substr($hex, 1));
return array(
"r" => ($color & 0xFF0000) >> 16,
"g" => ($color & 0xFF00) >> 8,
"b" => $color & 0xFF
);
}
//png的alpha校正
function _pngalpha($format) {
//PNG图像要保持alpha通道
if($format == 'png') {
imagealphablending($this->img, false);
imagesavealpha($this->img, true);
}
}
//输出函数,内部使用
function _output($path, $type=null) {
$toFile = false;
//输出到文件
if($path !='stream') {
if(!is_dir(dirname($path)))
$this->exceptionFunc('指定的路径不可用 =>'.$path);
$type = pathinfo($path, PATHINFO_EXTENSION);
$toFile = true;
}
//png的alpha校正
$this->_pngalpha($type);
if($type == "jpg") $type = "jpeg";
$func = "image".$type;
if(!function_exists($func)) {
$type = 'gif';
$func = 'imagegif';
}
if($toFile) {
call_user_func($func, $this->img, $path);
}
else
{
if(!headers_sent())
header("Content-type:image/".$type);
call_user_func($func, $this->img);
}
return $this;
}
function getWidth() {
if (isset($this->info['width'])) {
return $this->info['width'];
}
return false;
}
function getHeight() {
if (isset($this->info['height'])) {
return $this->info['height'];
}
return false;
}
function getType() {
if (isset($this->info['type'])) {
return $this->info['type'];
}
return false;
}
}
?>