PHP代码-图片处理类Image.php

/** 此类使用方法
include 'Image.php';
$image = new Image(); //构建 Image对象

$image->loadImage("images/1.png"); //载入图片文件

$rgb = new RGB(255, 255, 255); //颜色类

if ($image->isLoad()) {

//以下步骤部分无依赖关系,只需loadImage成功后,就可根据实际应用灵活的组合使用,最后执行图片另存即可。
//1:水印功能
//在当前图片上添加水印,指定透明度 40
//PS:会根据水印图片的尺寸,自动在目标图片上进行水平和垂直方向平铺。
//$image->waterMark("waterMark2.gif",40);
//2:缩略图片到指定大小。
//PS:此方法将强制限定长宽比,不足的部分填充背景色。
$image->thumb(140,140,$rgb);
//3:裁剪获取部分图片
//PS:如果指定了背景色 rgb,则超出的部分自动使用 背景色填充。否则自动忽略超出部分。
//$image->cutImage(-50,-20,100,100,$rgb);//由于x,y坐标为负数,且指定了背景色,所以生成图片左上角部分为背景色。
//$image->cutImage(0,0,100,100,$rgb); //从 (0,0)开始,裁剪 width=100,height=100部分。
//$image->cutImage(50,50,400,300);//虽然 width,height超出了原图,但指定了背景色,所以超过原图部分被忽略。
//4:裁剪去掉图片的外边框。默认去掉上/下/左/右 四个方向的边框补足部分。
//$image->shearedEdge();
//$image->shearedEdge($rgb);//如果能确定边框颜色,建议指定此参数。否则程序需要自己计算外边框颜色,这将耗费更多执行时间
//5:转换灰度模式
//$image->gamma();
//6:高斯模糊
//$image->gaussPart(20,150,200,100,100); //高斯模糊图像区域
//$image->gauss(15); //高斯模糊整张图像区域(使用分块法,避免大尺寸内存申请失败)
//7:图片等比列缩小
//PS:如果高和宽有一个为0,则图片缩小比例以不为0的比例为准。如果高和宽都不为0,则图片取缩放比例小的那个
//$image->equalRatioThumb(0,512);
//最后保存图片到指定目录文件
$image->saveImage("images/", '2.png');
//$image->outPutImage();//直接输出到页面
}
*/

//使用UTF-8
/**
* Module: Image Class Module v1.2
*
* author: leaf
* email:yuyuyezi@vip.qq.com
* time: 2012-02-16 14:55
* last_modify-time: 2012-04-19 14:47
* copyright: All Free
*
* functions:
* 1.thumb *
* 2.water mark
* 3.cutPart size
* 4.format convert
* 5.cut border *
* 6.gamma(new)
* 7.gaussPart(new)
* 8.gauss (new)
*/
/*
1、本空间源码部分原创,部分为网络分享。原创部分源码可以任意使用,但作者保留个人版权。 2、大多数情况下,代码已经作者有限的检测和调试,但这不代表代码中一定就不包含错误。您可以自己选择将其用于其它用途,但因此造成的任何后果都与作者无责。
3、如果发现错误,或有更好的建议,请先系作者:yuyuyezi@vip.qq.com。(QQ:910657702)
4、转载请注明出处,以便跟踪其它用户的bug提交。举手之劳,方便大家,谢谢合作!
此代码的详细的使用方法及示例,请访问作者空间。http://hi.baidu.com/zhangshe
*/
//import('leaf.image.RGB'); //导入RGB类
//require_once "RGB.class.php";//导入RGB类

define('SAMPLE_DENSITY', 30); //像素点采样精度(每个指定像素采样比对一次)数值越大越精细,但处理也会更耗时
define('CM_LEVAL', 20); //颜色匹配级别 color match leval(0-255)
define('CMT_LEVAL', 0.9); //匹配次数级别 count match leval(0.1-1)

define('RED_INDEX', 0); //颜色索引
define('GREEN_INDEX', 1); //颜色索引
define('BLUE_INDEX', 2); //颜色索引

define('GAUSS_BLOCK_SIZE', 100); //Gauss模糊处理块边大小,一次读取块越小,占用内存越小,同时块数会增加
define('SUPORT_MIME', "JPG,PNG,GIF"); //支持的文件类型
define('JPEG_SAVE_QUALITY', 80); //JPEG图片保存的质量(0-100)
//RGB Class
class RGB {

private $red = 0; //红绿蓝索引
private $green = 0;
private $blue = 0;

/**
* __construct
*
* @param mix $rgb
*/
function __construct($rgb = null) {
$args_array = func_get_args();

if (func_num_args() == 1) {
$this->setValue($rgb);
} else if (func_num_args() == 3) {
$this->setRed($args_array[0]);
$this->setGreen($args_array[1]);
$this->setBlue($args_array[2]);
}
}

/**
* 设置值
*
* @param mix $rgb
*/
function setValue($rgb) {
if ($rgb == null) {
$this->red = 0;
$this->green = 0;
$this->blue = 0;
} else if (is_array($rgb) && count($rgb) >= 3) {
if (isset($rgb['red']) && isset($rgb['green']) && isset($rgb['blue'])) {
$this->setRed($rgb['red']);
$this->setGreen($rgb['green']);
$this->setBlue($rgb['blue']);
} elseif (isset($rgb[0]) && isset($rgb[1]) && isset($rgb[2])) {
$this->setRed($rgb[0]);
$this->setGreen($rgb[1]);
$this->setBlue($rgb[2]);
} else {
exit('unable rgb setValue source');
}
} else if (is_object($rgb) && get_class($rgb) == 'RGB') {
$this->setRed($rgb->getRed());
$this->setGreen($rgb->getGreen());
$this->setBlue($rgb->getBlue());
} else {
print_r($rgb);
exit('unable rgb setValue source');
}
}

/**
* __destruct
*
*/
function __destruct() {
//do nothing.
}

/**
* 设置颜色索引
*
* @param int $red
* @return int 返回设置的颜色索引
*/
function setRed($red) {
$this->red = abs(intval($red));
if ($this->red > 255) {
$this->red = 255;
}
return $this->red;
}

/**
* 设置颜色索引
*
* @param int $red
* @return int 返回设置的颜色索引
*/
function setGreen($green) {
$this->green = abs(intval($green));
if ($this->green > 255) {
$this->green = 255;
}
return $this->red;
}

/**
* 设置颜色索引
*
* @param int $red
* @return int 返回设置的颜色索引
*/
function setBlue($blue) {
$this->blue = abs(intval($blue));
if ($this->blue > 255) {
$this->blue = 255;
}
return true;
}

/**
* 获取颜色索引
*
* @return int 颜色索引
*/
function getRed() {
return $this->red;
}

/**
* 获取颜色索引
*
* @return int 颜色索引
*/
function getGreen() {
return $this->green;
}

/**
* 获取颜色索引
*
* @return int 颜色索引
*/
function getBlue() {
return $this->blue;
}

/**
* debug
*
*/
function debug() {
$result = array();
$result['red'] = $this->red;
$result['green'] = $this->green;
$result['blue'] = $this->blue;
print_r($result);
}

/**
* 转换灰度模式的 RGB
*
*/
function Gamma() {

$red = $this->red;
$green = $this->green;
$blue = $this->blue;
//灰度计算方法:
//sRGB IEC61966-2.1 [gamma=2.20](Adobe PS目前使用此方法)
//测试纯红色灰度:126
//Gray = (R^2.2 * 0.2126 + G^2.2 * 0.7152 + B^2.2 * 0.0722)^(1/2.2)
$gray_leval = pow((pow($red, 2.2) * 0.2126 + pow($green, 2.2) * 0.7152 + pow($blue, 2.2) * 0.0722), (1 / 2.2));

//Adobe RGB (1998) [gamma=2.20]
//测试纯红色灰度:146
//Gray = (R^2.2 * 0.2973 + G^2.2 * 0.6274 + B^2.2 * 0.0753)^(1/2.2)
//$gray_leval = pow((pow($red,2.2) * 0.2973 + pow($green,2.2) * 0.6274 + pow($blue,2.2) * 0.0753),(1/2.2));
//Apple RGB [gamma=1.80]
//测试纯红色灰度:116
//Gray = (R^1.8 * 0.2446 + G^1.8 * 0.6720 + B^1.8 * 0.0833)^(1/1.8)
//$gray_leval = pow((pow($red,1.8) * 0.2446 + pow($green,1.8) * 0.6720 + pow($blue,1.8) * 0.0833),(1/1.8));
//ColorMatch RGB [gamma=1.8]
//测试纯红色灰度:124
//Gray = (R^1.8 * 0.2750 + G^1.8 * 0.6581 + B^1.8 * 0.0670)^(1/1.8)
//$gray_leval = pow((pow($red,1.8) * 0.2750 + pow($green,1.8) * 0.6581 + pow($blue,1.8) * 0.0670),(1/1.8));
//KODAK DC Series Digital Camera [gamma=2.2]
//测试纯红色灰度:128
//Gray = (R^2.2 * 0.2229 + G^2.2 * 0.7175 + B^2.2 * 0.0595)^(1/2.2)
//$gray_leval = pow((pow($red,2.2) * 0.2229 + pow($green,2.2) * 0.7175 + pow($blue,2.2) * 0.0595),(1/2.2));

$this->setRed($gray_leval);
$this->setGreen($gray_leval);
$this->setBlue($gray_leval);
}

/**
* 颜色的模糊匹配
*
* @param mix $rgb
* @param int $leval
* @return boolean 匹配成功返回true,失败返回 false
*/
function fuzzyMatch($rgb, $leval = 0) {//模糊匹配
$cm_total = 0;
$leval_add = $leval * 0.8;
if (is_object($rgb) && get_class($rgb) == 'RGB') {

$red = abs($this->red - $rgb->red);
$green = abs($this->green - $rgb->green);
$blue = abs($this->blue - $rgb->blue);

if ($red > $leval)
return false;
else {
$cm_total+= $red;
$cm_total+= $red > $leval_add ? $red - $leval_add : 0;
}
if ($green > $leval) {
return false;
} else {
$cm_total+= $green;
$cm_total+= $green > $leval_add ? $green - $leval_add : 0;
}
if ($blue > $leval) {
return false;
} else {
$cm_total+= $blue;
$cm_total+= $blue > $leval_add ? $blue - $leval_add : 0;
}

if ($cm_total > ($leval * 3)) {
return false;
}
return true;
}
exit('RGB.fuzzyMatch request a rgb class');
}

}

//Image Class
class Image {

private $image = null; //图形资源句柄
private $width = 0; //图形宽度
private $height = 0; //图形的高度
private $imageType = null; //图形的类型
private $imageMime = null; //图片MIME
private $imageFilePath = null; //图片所在的目录
private $imageFileName = null; //图片名称

/**
* construct
*
* @param string $imageFile 载入的图片路径
*/

function __construct($imageFile = null) {
if ($imageFile != null) {
$this->loadImage($imageFile);
}
}

/**
* 载入图片
*
* @param string $imageFile
* @return boolean 成功返回true,失败返回 false
*/
function loadImage($imageFile) {
if (!is_file($imageFile)) {
return false;
}
if ($this->isLoad()) {
$this->close();
}
if (!$image_infor = Image::get_image_infor($imageFile))
return false;

$this->width = $image_infor['width'];
$this->height = $image_infor['height'];
$this->imageMime = $image_infor['mime'];
$pathName = realpath($imageFile);

$this->imageFilePath = str_replace('\\', '/', dirname($pathName) . '/');
$this->imageFileName = basename($pathName);

$this->imageType = $image_infor['type'];
$image_type_array = explode(',', SUPORT_MIME);
if (!in_array($this->imageType, $image_type_array)) {
return false;
}
switch ($this->imageType) {
case 'JPG' :
$this->image = imagecreatefromjpeg($imageFile);
break;
case 'PNG':
$this->image = imagecreatefrompng($imageFile);
break;
case 'GIF':
$this->image = imagecreatefromgif($imageFile);
break;
default:
exit("未处理的图片打开方式'{$this->imageType}'");
}
return true;
}

/**
* 保存图片(图片处理之后的保存操作)
*
* @param string $imgRePath 重定向的保存目录
* @param unknown_type $imgReName 重命名文件
* @return 成功返回 true 失败返回false
*/
function saveImage($imgRePath = null, $imgReName = null) {

$imgName = $this->imageFileName;
$imgPath = $this->imageFilePath;
if ($imgReName != null)
$imgName = $imgReName;
if ($imgRePath != null)
$imgPath = $imgRePath;

if (preg_match("/[\\/]$/", $imgRePath) == 0) { //末尾补 '/'
$imgRePath = $imgRePath . '/';
}
return $this->writeImage($imgPath . $imgName);
}

/**
* 直接输出图片到当前页面
*/
function outPutImage() {
return $this->writeImage(null);
}

/**
* destruct
*
*/
function __destruct() {
$this->close();
}

/**
* getWidth
*
* @return int 返回图片宽
*/
function getWidth() {

if ($this->isLoad()) {
return $this->width;
}
return 0;
}

/**
* getHeight
*
* @return int 返回图片高
*/
function getHeight() {

if ($this->isLoad()) {
return $this->height;
}
return 0;
}

/**
* 获取图片资源句柄
*
* @return resource 资源句柄
*/
function getImage() {
if ($this->isLoad()) {
return $this->image;
}
return null;
}

/**
* 关闭一个打开的图片
*
* @return true
*/
function close() {
if ($this->isLoad()) {
@imagedestroy($this->image);
$this->image = null;
$this->height = 0;
$this->width = 0;
$this->imageMime = null;
$this->imageType = null;
$this->imageFileName = null;
}
return true;
}

/**
* 缩放一张图片
*
* @param int $thumb_width 新的宽度
* @param int $thumb_height 新的高度
* @param RGB $rgb 背景色,此方法将强制限定长宽比,不足的部分填充背景色
* @return boolean 成功返回 true,失败返回false
*/
function thumb($thumb_width, $thumb_height, $rgb = null) {
$x_pos = 0;
$y_pos = 0;
$width_percent = $thumb_width / $this->width; //宽度比例
$height_percent = $thumb_height / $this->height; //高度比例

if (!$this->isLoad()) {//未打开图片
return false;
}
if ($width_percent < $height_percent) {
$percent = $width_percent;
$y_pos = ( $thumb_height - $this->height * $percent) / 2;
} else {
//使用高度比例被压缩
$percent = $height_percent;
$x_pos = ($thumb_width - $this->width * $percent) / 2;
}

$new_width = $this->width * $percent;
$new_height = $this->height * $percent;
if ($thumb_width < 1)
$new_width = 1;
if ($thumb_height < 1)
$new_height = 1;

$bg_rgb = new RGB($rgb);
$new_image = imagecreatetruecolor($thumb_width, $thumb_height);
$back_ground = imagecolorallocate($new_image, $bg_rgb->getRed(), $bg_rgb->getGreen(), $bg_rgb->getBlue());
imagefill($new_image, 0, 0, $back_ground);
imagecopyresampled($new_image, $this->image, $x_pos, $y_pos, 0, 0, $new_width, $new_height, $this->width, $this->height);
imagedestroy($this->image);
$this->image = $new_image;
$this->width = $new_width;
$this->height = $new_height;
return true;
}
/**
* 等比缩略图
* @param type $width
* @param type $height
*/
public function equalRatioThumb($thumb_width,$thumb_height=0){
$width_percent = $thumb_width / $this->width; //宽度比例
$height_percent = $thumb_height / $this->height; //高度比例
if($thumb_width == 0){
$percent = $height_percent;
}else if($thumb_height == 0){
$percent = $width_percent ;
}else{
$percent = $width_percent > $height_percent ? $height_percent : $width_percent ;
}
$new_width = intval($this->width * $percent);
$new_height = intval($this->height * $percent) ;
$new_image = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $new_width, $new_height, $this->width, $this->height);
imagedestroy($this->image);
$this->image = $new_image;
$this->width = $new_width;
$this->height = $new_height;
}

/**
* 裁剪指定区域的部分图片
* 如果指定了背景色,则超出的部分以背景色填充(x<0,y<0时,裁剪后的图片左上部也会填充背景色)
* @param int $xpos 开始的x坐标
* @param int $ypos 开始的y坐标
* @param int $width 选取的宽度
* @param int $height 选取的高度
* @param RGB $bg_rgb 背景色
* @return boolean 成功返回 true 失败返回 false
*/
function cutImage($xpos, $ypos, $width, $height, $bg_rgb = null) {

$dst_xpos = 0;
$dst_ypos = 0;

if (!$this->isLoad()) {//未打开图片
return false;
}
if (!$width || !$height) {//未打开图片
return false;
}
if ($bg_rgb == null) {

if ($xpos < 0) {
$width+= $xpos;
$xpos = 0;
}
if ($ypos < 0) {
$height+= $ypos;
$ypos = 0;
}

$width_max = $this->getWidth() - $xpos; //最大的宽度
$height_max = $this->getHeight() - $ypos; //最大的高度
$width = $width > $width_max ? $width_max : $width;
$height = $height > $height_max ? $height_max : $height;
if ($width < 0)
return false; //x坐标超出了宽度
if ($height < 0)
return false; //y坐标超出了高度
$new_image = imagecreatetruecolor($width, $height);
}else {
$rgb = new RGB($bg_rgb);
$new_image = imagecreatetruecolor($width, $height); //直接使用宽高,超出图片的部分补背景颜色
$back_ground = imagecolorallocate($new_image, $rgb->getRed(), $rgb->getGreen(), $rgb->getBlue());
imagefill($new_image, 0, 0, $back_ground); //使用背景色填充

if ($xpos < 0) {
$width+= $xpos;
$dst_xpos = -$xpos;
$xpos = 0;
}
if ($ypos < 0) {
$height+= $ypos;
$dst_ypos = -$ypos;
$ypos = 0;
}
$width_max = $this->getWidth() - $xpos; //最大的有效宽度
$height_max = $this->getHeight() - $ypos; //最大的有效高度
$width = $width > $width_max ? $width_max : $width;
$height = $height > $height_max ? $height_max : $height;
if ($width < 0) {
imagedestroy($new_image);
return false; //x坐标超出了宽度
}
if ($height < 0) {
imagedestroy($new_image);
return false; //y坐标超出了高度
}
}

imagecopyresampled($new_image, $this->image, $dst_xpos, $dst_ypos, $xpos, $ypos, $width, $height, $width, $height);
imagedestroy($this->image);
$this->image = $new_image;
$this->width = $width;
$this->height = $height;
return true;
}

/**
* 输出image图片,此方法不导出
*
* @param string $imgFileName
*/
private function writeImage($imgFileName) {
$imgFileName=$this->isExistImage($imgFileName);
if($imgFileName=== true)return true ;
if ($imgFileName == null) {
ob_end_clean();
header("Content-Type: {$this->imageMime}");
}
switch ($this->imageType) {
case 'JPG' :
imagejpeg($this->image, $imgFileName, JPEG_SAVE_QUALITY);
break;
case 'PNG':
imagepng($this->image, $imgFileName);
break;
case 'GIF':
imagegif($this->image, $imgFileName);
break;
//case 'WBMP':
// imagewbmp($this->image, $imgFileName);
default:
exit("不支持的图片存储格式 '{$this->imageType}'");
}

return true;
}
/**
* 生成缩略图名称
* @param type $imgFileName
* @return boolean
*/
private function isExistImage($imgFileName){
$pathInfo = pathinfo($imgFileName);
$imgFileName = str_replace($pathInfo['basename'], $pathInfo['filename'].'_'.$this->width.'X'.$this->height.'.'.$pathInfo['extension'], $imgFileName);
if(is_file($imgFileName)){
return true ;
}
return $imgFileName;
}

/**
* 转换图片格式
*
* @param string $newType 新的图片格式(不是所有的都能支持保存)
* @return boolean 成功返回true
*/
function formatConversion($newType) {
if (is_integer($newType)) {
switch ($newType) {
case 1: $newType = 'GIF';
break;
case 2: $newType = 'JPG';
break;
case 3: $newType = 'PNG';
break;
case 4: $newType = 'SWF';
break;
case 5: $newType = 'PSD';
break;
case 6: $newType = 'BMP';
break;
case 7: $newType = 'TIFF';
break;
case 8: $newType = 'TIFF';
break;
case 9: $newType = 'JPC';
break;
case 10: $newType = 'JP2';
break;
case 11: $newType = 'JPX';
break;
case 12: $newType = 'JB2';
break;
case 13: $newType = 'SWC';
break;
case 14: $newType = 'IFF';
break;
case 15: $newType = 'WBMP';
break;
case 16: $newType = 'XBM';
break;
default: exit('未知的图片文件存储格式');
}
}
$newType = strtoupper($newType);
$image_type_array = explode(',', SUPORT_MIME);
if (in_array($newType, $image_type_array)) {
$this->imageType = $newType;

//同时修改将来保存的默认文件名
$reFileNameArr = explode('.', $this->imageFileName);
if (count($reFileNameArr) > 1)
array_pop($reFileNameArr);
$this->imageFileName = implode('.', $reFileNameArr) . '.' . $this->imageType;
return true;
}
exit("不支持的格式转换存储 {$newType}");
}

/**
* 判断图片是否正确加载
*
* @return boolean 成功加载返回 true,出错返回false
*/
function isLoad() {
if ($this->image == null)
return false;
return true;
}

/**
* 获取图片文件的详细信息(该方法公用)
*
* @param string $image_file 图片文件路径
* @return array 成功返回图片详细信息数组,失败返回 null
*/
static function get_image_infor($image_file) {

if (!!$arr_image_infor = @getimagesize($image_file)) {
$image_infor = &$arr_image_infor;
$image_infor['type_index'] = $arr_image_infor[2];
$image_infor['width'] = $arr_image_infor[0];
$image_infor['height'] = $arr_image_infor[1];
$image_infor['mime'] = $arr_image_infor['mime'];
$image_infor['string_size'] = $arr_image_infor[3];

switch ($arr_image_infor[2]) {
case 1: $image_infor['type'] = 'GIF';
break;
case 2: $image_infor['type'] = 'JPG';
break;
case 3: $image_infor['type'] = 'PNG';
break;
case 4: $image_infor['type'] = 'SWF';
break;
case 5: $image_infor['type'] = 'PSD';
break;
case 6: $image_infor['type'] = 'BMP';
break;
case 7: $image_infor['type'] = 'TIFF';
break;
case 8: $image_infor['type'] = 'TIFF';
break;
case 9: $image_infor['type'] = 'JPC';
break;
case 10: $image_infor['type'] = 'JP2';
break;
case 11: $image_infor['type'] = 'JPX';
break;
case 12: $image_infor['type'] = 'JB2';
break;
case 13: $image_infor['type'] = 'SWC';
break;
case 14: $image_infor['type'] = 'IFF';
break;
case 15: $image_infor['type'] = 'WBMP';
break;
case 16: $image_infor['type'] = 'XBM';
break;
default: $image_infor['type'] = '';
}
return $image_infor;
}
return null;
}

/**
* 返回正确载入后的图片格式类型
*
* @return string 成功返回图片格式,失败 返回 null
*/
function imageType() {
if ($this->isLoad()) {
return $this->imageType;
}
return null;
}

/**
* 水印处理方法
*
* @param resource/string $waterImage 打开的水印图片类或文件目录
* @param int $pct 水印深度 0-100
* @return boolean 处理成功返回 true 失败返回false
*/
function waterMark($waterImage, $pct = 50) { //水印应为透底的gif或png图片
$auto_free = false; //对于字符串传递的 waterImage需要使用后关闭
if (is_string($waterImage)) {
$waterImage = new Image($waterImage);
$auto_free = true;
}

if ($waterImage instanceof Image) {

if ($waterImage->isLoad()) {
$image_width = $this->getWidth();
$image_heigth = $this->getHeight();
$waterImage_width = $waterImage->getWidth();
$waterImage_height = $waterImage->getHeight();

for ($start_x = 0; $start_x < $image_width; $start_x+= $waterImage_width) {
for ($start_y = 0; $start_y < $image_heigth; $start_y+= $waterImage_height) {
imagecopymerge($this->image, $waterImage->getImage(), $start_x, $start_y, 0, 0, $waterImage_width, $waterImage_height, $pct);
}
}
if ($auto_free) {
$waterImage->close();
unset($waterImage);
}
return true;
}//waterMark image file not loaded error
}//'error at waterMark';
return false;
}

/**
* 垂直线条的模糊匹配
*
* @param RGB $rgb 匹配颜色
* @param int $x x坐标的一条垂直线
* @param int $cm_leval 颜色匹配级别
* @param float $cmt_persent 匹配次数级别
* @return boolean 成功返回true,失败返回false
*/
private function fuzzyLineMatchH($rgb, $x, $cm_leval = 15, $cmt_persent = 0.9) {
$match_count = 0;
$rgb_bit = new RGB();
$height = $this->getHeight();
for ($y = 0, $count = 0; $y < $height; $y+=SAMPLE_DENSITY, $count++) {
$color_index = imagecolorat($this->image, $x, $y); //取得一点的颜色
$color_tran = imagecolorsforindex($this->image, $color_index);
$rgb_bit->setValue($color_tran);

if ($rgb->fuzzyMatch($rgb_bit, $cm_leval)) {//查找到边缘
$match_count++;
}
}
if (($match_count * 1.0 / $count) > $cmt_persent) {
return true;
} else {
return false;
}
}

/**
* 水平线条的模糊匹配
*
* @param RGB $rgb //匹配的颜色
* @param int $y //以y坐标的水平线
* @param int $cm_leval
* @param float $cmt_persent
* @return 成功返回 true 失败返回 false
*/
private function fuzzyLineMatchV($rgb, $y, $cm_leval = 15, $cmt_persent = 0.9) {
$match_count = 0;
$rgb_bit = new RGB();
for ($x = 0, $count = 0; $x < $this->width; $x+=SAMPLE_DENSITY, $count++) {
$color_index = imagecolorat($this->image, $x, $y); //取得一点的颜色
$color_tran = imagecolorsforindex($this->image, $color_index);
$rgb_bit->setValue($color_tran);
if ($rgb_bit->fuzzyMatch($rgb, $cm_leval)) {//查找到边缘
$match_count++;
}
}
if (($match_count * 1.0 / $count) > $cmt_persent) {
return true;
} else {
return false;
}
}

/**
* 计算垂直线颜色
*
* @param unknown_type $x
* @return RGB 如果y=$x 是一条垂直线,返回线条RGB,否则返回false
*/
private function findLineH($x) {

$red = 0;
$green = 0;
$blue = 0;
$rgb_bits = array();
for ($y = 0, $count = 0; $y < $this->height; $y+=SAMPLE_DENSITY, $count++) {
$color_index = imagecolorat($this->image, $x, $y); //取得一点的颜色
$color_tran = imagecolorsforindex($this->image, $color_index);
$red+= $color_tran['red'];
$green+= $color_tran['green'];
$blue+= $color_tran['blue'];
}
$red /= $count;
$green /= $count;
$blue /= $count;
$rgb = new RGB($red, $green, $blue);
if ($this->fuzzyLineMatchH($rgb, $x, 10, 0.9)) {
return $rgb;
} else {
return false;
}
}

/**
* 自动计算水平线颜色
*
* @param unknown_type $x
* @return RGB 如果y=$x 是一条垂直线,返回线条RGB,否则返回false
*/
private function findLineV($y) { //计算水平线颜色
$red = 0;
$green = 0;
$blue = 0;
$rgb_bits = array();
for ($x = 0, $count = 0; $x < $this->width; $x+=SAMPLE_DENSITY, $count++) {
$color_index = imagecolorat($this->image, $x, $y); //取得一点的颜色
$color_tran = imagecolorsforindex($this->image, $color_index);
$red+= $color_tran['red'];
$green+= $color_tran['green'];
$blue+= $color_tran['blue'];
}

$red /= $count;
$green /= $count;
$blue /= $count;
$rgb = new RGB($red, $green, $blue);
if ($this->fuzzyLineMatchV($rgb, $y, 10, 0.9)) {
return $rgb;
} else {
return false;
}
}

/**
* 查找上边框宽度
*
* @param int $cm_leval 颜色匹配级别 0-255,数字越大,匹配越宽松
* @param RGB $rgb 边框颜色
* @param unknown_type $ctm_persent
* @return int 边框宽度
*/
function shearedEdgeU($cm_leval = 15, $rgb = null, $ctm_persent = 0.9) {

if (!$this->isLoad())
return false;
if ($rgb == null) {
$rgb = $this->findLineV(0);
} else {
$rgb = new RGB($rgb);
}
if ($rgb == null)
return 0;
$y_end = $this->getHeight();
for ($y = 0; $y < $y_end; $y++) {
if (!$this->fuzzyLineMatchV($rgb, $y, $cm_leval, $ctm_persent)) {//查找到边缘
return $y;
}
}
return 0;
}

/**
* 查找左边框宽度
*
* @param int $cm_leval 颜色匹配级别 0-255,数字越大,匹配越宽松
* @param RGB $rgb 边框颜色
* @param unknown_type $ctm_persent
* @return int 边框宽度
*/
function shearedEdgeL($cm_leval = 15, $rgb = null, $ctm_persent = 0.9) {

if (!$this->isLoad())
return false;
if ($rgb == null) {
$rgb = $this->findLineH(0);
} else {
$rgb = new RGB($rgb);
}
if ($rgb == null)
return 0;
$x_end = $this->getWidth();
for ($x = 0; $x < $x_end; $x++) {
if (!$this->fuzzyLineMatchH($rgb, $x, $cm_leval, $ctm_persent)) {//查找到边缘
return $x;
}
}
return 0;
}

/**
* 查找下边框宽度
*
* @param int $cm_leval 颜色匹配级别 0-255,数字越大,匹配越宽松
* @param RGB $rgb 边框颜色
* @param unknown_type $ctm_persent
* @return int 边框宽度
*/
function shearedEdgeD($cm_leval = 15, $rgb = null, $ctm_persent = 0.9) {
if (!$this->isLoad())
return false;
if ($rgb == null) {
$rgb = $this->findLineV($this->getHeight() - 1);
} else {
$rgb = new RGB($rgb);
}
if ($rgb == null)
return 0;
for ($y = $this->getHeight() - 1; $y > 0; $y--) {
if (!$this->fuzzyLineMatchV($rgb, $y, $cm_leval, $ctm_persent)) {//查找到边缘
return $this->getHeight() - 1 - $y;
}
}
return 0;
}

/**
* 查找右边框宽度
*
* @param int $cm_leval 颜色匹配级别 0-255,数字越大,匹配越宽松
* @param RGB $rgb 边框颜色
* @param unknown_type $ctm_persent
* @return int 边框宽度
*/
function shearedEdgeR($cm_leval = 15, $rgb = null, $ctm_persent = 0.9) {
if (!$this->isLoad())
return false;
if ($rgb == null) {
$rgb = $this->findLineH($this->getWidth() - 1);
} else {
$rgb = new RGB($rgb);
}
if ($rgb == null)
return 0;
for ($x = $this->getWidth() - 1; $x >= 0; $x--) {
if (!$this->fuzzyLineMatchH($rgb, $x, $cm_leval, $ctm_persent)) {//查找到边缘
return $this->getWidth() - 1 - $x;
}
}
return 0;
}

/**
* 查找图片边框,并进行裁剪删去边框操作
*
* @param int $leval 颜色匹配级别
* @param RGB $rgb 手动设置边框颜色
* @return 成功返回true,失败false
*/
function shearedEdge($leval = CM_LEVAL, $rgb = null) {

$top = 0; //顶部边框尺寸
$left = 0; //左部边框尺寸
$botom = 0; //底部边框尺寸
$right = 0; //右部边框尺寸

/*
$pcmk= true;
$top_pcmk= true;//顶部边框处理标记
$left_pcmk= true;//左部边框处理标记
$botom_pcmk=true;//底部边框处理标记
$right_pcmk=true;//右部边框处理标记

while($pcmk){
$pcmk= false;

if($top_pcmk && $top= $this->shearedEdgeU($leval,$rgb)){
$top_pcmk= false;
$pcmk= true;
}
if($left_pcmk && $left= $this->shearedEdgeL($leval,$rgb)){
$left_pcmk= false;
$pcmk= true;
}
if($botom_pcmk && $botom= $this->shearedEdgeD($leval,$rgb)){
$botom_pcmk= false;
$pcmk= true;
}
if($right_pcmk && $right= $this->shearedEdgeR($leval,$rgb)){
$right_pcmk= false;
$pcmk= true;
}
}
*/

$top = $this->shearedEdgeU($leval, $rgb); //顶部边框尺寸
$left = $this->shearedEdgeL($leval, $rgb); //左部边框尺寸
$botom = $this->shearedEdgeD($leval, $rgb); //底部边框尺寸
$right = $this->shearedEdgeR($leval, $rgb); //右部边框尺寸

$x = $left;
$y = $top;
$width = $this->getWidth() - $left - $right;
$height = $this->getHeight() - $top - $botom;

return $this->cutImage($x, $y, $width, $height);
}

////////////////////////////////////
/**
* 获取位图表
* @param int $x_pos
* @param int $y_pos
* @param int $width
* @param int $height
* @return boolean|array[][] >
*/
function getBitMap($x_pos, $y_pos, $width, $height) {

$img_width = $this->getWidth(); //缓存像素内存块
$img_height = $this->getHeight();

$x_pos = intval($x_pos);
$y_pos = intval($y_pos);
if ($x_pos < 0 || $x_pos > $img_width || $y_pos < 0 || $y_pos > $img_height)
return false;

if ($width < 0 || $height < 0)
return false;
$width = intval($width + $x_pos);
$height = intval($height + $y_pos);

if ($width > $img_width) {
$width = $img_width;
}
if ($height > $img_height) {
$height = $img_height;
}

$image_bits = array();
for ($x = $x_pos; $x < $width; $x++) {
for ($y = $y_pos; $y < $height; $y++) {
$bit = array();
$pix = imagecolorsforindex($this->image, imagecolorat($this->image, $x, $y));
$bit[0] = $pix['red'];
$bit[1] = $pix['green'];
$bit[2] = $pix['blue'];
$image_bits[$x][$y] = $bit;
}
}
return $image_bits;
}

/**
* 转换灰度模式
*
* @return boolean
*/
function gamma() {

if (!$this->isLoad()) {//未打开图片
return false;
}
$rgb_bit = new RGB();

$width = $this->getWidth();
$height = $this->getHeight();
for ($x = 0; $x < $width; $x++) {
for ($y = 0; $y < $height; $y++) {

$pix_cur = imagecolorsforindex($this->image, imagecolorat($this->image, $x, $y));
$rgb_bit->setValue($pix_cur);
$rgb_bit->Gamma();
$color = imagecolorallocate($this->image, $rgb_bit->getRed(), $rgb_bit->getGreen(), $rgb_bit->getBlue());
imagesetpixel($this->image, $x, $y, $color);
}
}
return true;
}

/**
* 高斯模糊区域处理方法
* @param int $nRadius
* @param int $x_pos
* @param int $y_pos
* @param int $width
* @param int $height
* @return boolean
*/
function gaussPart($nRadius, $x_pos, $y_pos, $width, $height) {

$nRadius = intval($nRadius);
//$diamet = $nRadius *2 + 1; //采样区域直径,或者方阵的边长
$sigma = $nRadius / 3.0; //正态分布的标准偏差σ
$sigma2 = 2.0 * $sigma * $sigma; //2倍的σ平方,参考N维空间正态分布方程
$nuclear = 0.0; //高斯卷积核

if (!$this->isLoad()) {//未打开图片
return false;
}
if ($nRadius < 1) {//采样区域半径
return false;
}

//计算高斯矩阵
$matrix = array(); //高斯矩阵定义
for ($x = -$nRadius; $x <= $nRadius; $x++)
for ($y = -$nRadius; $y <= $nRadius; $y++) {
$result = exp(-($x * $x + $y * $y) / $sigma2);
$nuclear += $result;
$matrix[$x][$y] = $result;
}

//缓存像素内存块
$image_bits = array();
$img_width = $this->getWidth(); //原图片大小
$img_height = $this->getHeight();

//x,y坐标合法性检查
$x_pos = intval($x_pos);
$y_pos = intval($y_pos);
if ($x_pos < 0 || $x_pos >= $img_width || $y_pos < 0 || $y_pos >= $img_height)
return false;

//处理像素矩阵的宽与高
$width = intval($width);
$height = intval($height);
if ($width < 0 || $height < 0)
return false;
$width+= $x_pos;
$height+= $y_pos;
if ($width > $img_width)
$width = $img_width;
if ($height > $img_height)
$height = $img_height;

//采样缓存图片
$pix_x = $x_pos - $nRadius; //为了使边缘自然,采样缓存区域应大于nRadius像素
$pix_y = $y_pos - $nRadius;
$pix_width = $width + $nRadius;
$pix_height = $height + $nRadius;

for ($x = $pix_x; $x < $pix_width; $x++) {
for ($y = $pix_y; $y < $pix_height; $y++) {
$bit = array();
$x_index = $x;
$y_index = $y;

if ($x_index < 0)
$x_index = -$x_index; //插入虚拟坐标点处理,以便使边界更自然
if ($y_index < 0)
$y_index = -$y_index;
$x_index = $x_index % $img_width; //平铺处理边界
$y_index = $y_index % $img_height;

$pix = imagecolorsforindex($this->image, imagecolorat($this->image, $x_index, $y_index));
$bit[0] = $pix['red'];
$bit[1] = $pix['green'];
$bit[2] = $pix['blue'];
$image_bits[$x][$y] = $bit;
}
}
//遍历并处理像素
for ($x = $x_pos; $x < $width; $x++) {
for ($y = $y_pos; $y < $height; $y++) {

$red = 0.0; //分析取样区域
$green = 0.0;
$blue = 0.0;

for ($m = -$nRadius; $m <= $nRadius; $m++) {
$yy = $y + $m;
for ($n = -$nRadius; $n <= $nRadius; $n++) {
$xx = $x + $n;
$weight = $matrix[$m][$n] / $nuclear;
$red += $weight * $image_bits[$xx][$yy][0];
$green += $weight * $image_bits[$xx][$yy][1];
$blue += $weight * $image_bits[$xx][$yy][2];
}
}
//保存一个像素处理结果
$red = $red > 255 ? 255 : intval($red);
$green = $green > 255 ? 255 : intval($green);
$blue = $blue > 255 ? 255 : intval($blue);
$new_color = imagecolorallocate($this->image, $red, $green, $blue);
imagesetpixel($this->image, $x, $y, $new_color);
}
}
return true;
}

/**
* 高斯模糊图片分块处理方法(大图使用分块GAUSS_BLOCK_SIZE处理)
* @param int $nRadius
* @return boolean
*/
function gauss($nRadius) {

$nRadius = intval($nRadius);
//$diamet = $nRadius *2 + 1; //采样区域直径,或者方阵的边长
$sigma = $nRadius / 3.0; //正态分布的标准偏差σ
$sigma2 = 2.0 * $sigma * $sigma; //2倍的σ平方,参考N维空间正态分布方程
$nuclear = 0.0; //高斯卷积核

if (!$this->isLoad()) {//未打开图片
return false;
}
if ($nRadius < 1) {//采样区域半径
return false;
}

//计算高斯矩阵
$matrix = array(); //高斯矩阵定义
for ($x = -$nRadius; $x <= $nRadius; $x++) {
for ($y = -$nRadius; $y <= $nRadius; $y++) {
$result = exp(-($x * $x + $y * $y) / $sigma2);
$nuclear += $result;
$matrix[$x][$y] = $result;
}
}

$width = $this->getWidth(); //原图片大小
$height = $this->getHeight();
$block_count_x = ceil($width / GAUSS_BLOCK_SIZE);
$block_count_y = ceil($height / GAUSS_BLOCK_SIZE);

$block_data_buff = array();
for ($block_x = 0; $block_x < $block_count_x; $block_x++) {
for ($block_y = 0; $block_y < $block_count_y; $block_y++) {

$block_data_left = null;
$block_data_top = null;
if (isset($block_data_buff[$block_x - 1][$block_y])) {
$block_data_left = &$block_data_buff[$block_x - 1][$block_y];
}
if (isset($block_data_buff[$block_x][$block_y - 1])) {
$block_data_top = &$block_data_buff[$block_x][$block_y - 1];
}

$block_data_buff[$block_x][$block_y] = $this->getGaussBlockBitmap($block_x, $block_y, $nRadius, $block_data_left, $block_data_top);
$this->gaussBlockProcess($block_x, $block_y, $nRadius, $matrix, $nuclear, $block_data_buff[$block_x][$block_y]);

if ($block_x > 0 && $block_y > 0) {
unset($block_data_buff[$block_x - 1][$block_y - 1]);
}

if ($block_y == $block_count_y - 1 && $block_x > 0) {
unset($block_data_buff[$block_x - 1][$block_y]);
}
unset($block_data_left);
unset($block_data_top);
}
}
return true;
}

/**
* 高斯模糊:图片位图块选取
* @param int $block_x
* @param int $block_y
* @param int $nRadius
* @param array $block_data_left
* @param array $block_data_top
*/
private function getGaussBlockBitmap($block_x, $block_y, $nRadius, $block_data_left, $block_data_top) {

//缓存像素内存块
$image_bits = array();
$img_width = $this->getWidth(); //原图片大小
$img_height = $this->getHeight();

//x,y坐标位移
$x_pos = $block_x * GAUSS_BLOCK_SIZE;
$y_pos = $block_y * GAUSS_BLOCK_SIZE;

if ($x_pos >= $img_width || $y_pos >= $img_height)
return null;

//处理像素矩阵的宽与高
$width = $x_pos + GAUSS_BLOCK_SIZE;
$height = $y_pos + GAUSS_BLOCK_SIZE;

if ($width > $img_width)
$width = $img_width;
if ($height > $img_height)
$height = $img_height;

//采样缓存图片
$pix_x = $x_pos - $nRadius; //为了使边缘自然,采样缓存区域应大于nRadius像素
$pix_y = $y_pos - $nRadius;
$pix_width = $width + $nRadius;
$pix_height = $height + $nRadius;

//获取像素
if ($block_x != 0 /* && $block_data_left != null */) {
for ($x = $pix_x; $x < $pix_x + $nRadius; $x++) {
for ($y = $pix_y; $y < $pix_height; $y++) {
$image_bits[$x][$y] = $block_data_left[$x][$y];
}
}

$pix_x+= $nRadius;
}

if ($block_y != 0 /* && $block_data_top != null */) {
$a = $pix_y + $nRadius;
for ($x = $pix_x; $x < $pix_width; $x++) {
for ($y = $pix_y; $y < $pix_y + $nRadius; $y++) {
$image_bits[$x][$y] = $block_data_top[$x][$y];
}
}
$pix_y+= $nRadius;
}

for ($x = $pix_x; $x < $pix_width; $x++) {
for ($y = $pix_y; $y < $pix_height; $y++) {

$bit = array();
$x_index = $x;
$y_index = $y;

if ($x_index < 0)
$x_index = -$x_index; //插入虚拟坐标点处理,以便使边界更自然
if ($y_index < 0)
$y_index = -$y_index;
$x_index = $x_index % $img_width; //平铺处理边界
$y_index = $y_index % $img_height;

$pix = imagecolorsforindex($this->image, imagecolorat($this->image, $x_index, $y_index));
$bit[0] = $pix['red'];
$bit[1] = $pix['green'];
$bit[2] = $pix['blue'];
$image_bits[$x][$y] = $bit;
}
}
return $image_bits;
}

/**
* 高斯模糊:图片位图块处理
* @param int $block_x
* @param int $block_y
* @param int $nRadius
* @param array $matrix
* @param double $nuclear
* @param array $image_bits
*/
private function gaussBlockProcess($block_x, $block_y, $nRadius, $matrix, $nuclear, $image_bits) {

$img_width = $this->getWidth(); //原图片大小
$img_height = $this->getHeight();

$x_pos = $block_x * GAUSS_BLOCK_SIZE; //x,y坐标位移
$y_pos = $block_y * GAUSS_BLOCK_SIZE;
$width = $x_pos + GAUSS_BLOCK_SIZE; //处理像素矩阵的宽与高
$height = $y_pos + GAUSS_BLOCK_SIZE;
if ($width > $img_width)
$width = $img_width;
if ($height > $img_height)
$height = $img_height;

for ($x = $x_pos; $x < $width; $x++) {
for ($y = $y_pos; $y < $height; $y++) {

$red = 0.0; //分析取样区域
$green = 0.0;
$blue = 0.0;

for ($m = -$nRadius; $m <= $nRadius; $m++) {
$yy = $y + $m;
for ($n = -$nRadius; $n <= $nRadius; $n++) {
$xx = $x + $n;
$weight = $matrix[$m][$n] / $nuclear;
$red += $weight * $image_bits[$xx][$yy][0];
$green += $weight * $image_bits[$xx][$yy][1];
$blue += $weight * $image_bits[$xx][$yy][2];
}
}

//保存一个像素处理结果
$red = $red > 255 ? 255 : intval($red);
$green = $green > 255 ? 255 : intval($green);
$blue = $blue > 255 ? 255 : intval($blue);

$new_color = imagecolorallocate($this->image, $red, $green, $blue);
imagesetpixel($this->image, $x, $y, $new_color);
}
}
return true;
}

}

?>


本文固定链接: http://blog.wwllcchf.com/?p=356 | 吴文龙的个人博客

作者:wuwenlong 于2013年08月22日发表 &
PHP代码-图片处理类Image.php | 吴文龙的个人博客

报歉!评论已关闭.