Sin Descripción

SaeImage.class.php 18KB

    <?php class SaeImage extends SaeObject { private $_img_data = ''; //图片数据 private $_options = array(); //图片选项 private $_width = 0; private $_height = 0; private $_image = null; //存储image资源 const image_limitsize = 2097152; public function __construct($img_data='') { parent::__construct(); return $this->setData($img_data); } //添加文字注释 public function annotate($txt, $opacity=0.5, $gravity=SAE_Static, $font=array()) { $opacity = floatval($opacity); if ($this->imageNull()) return false; //设置默认字体样式 $font_default = array('name' => SAE_SimSun, 'size' => 15, 'weight' => 300, 'color' => 'black'); $font = array_merge($font_default, $font); array_push($this->_options, array('act' => 'annotate', "txt" => $txt, "opacity" => $opacity, "gravity" => $gravity, "font" => array("name" => $font['name'], "size" => $font["size"], "weight" => $font["weight"], "color" => $font["color"]))); return true; } //数据重新初始化 public function clean() { $this->_img_data = ''; $this->_options = array(); $this->_width = 0; $this->_height = 0; $this->_image = null; } //图片合成, data为数组,在其他操作执行前进行操作 public function composite($width, $height, $color="black") { $width = intval($width); $height = intval($height); if ($this->imageNull()) return false; array_push($this->_options, array('act' => 'composite', "width" => $width, "height" => $height, "color" => $color)); return true; } //裁剪图片 public function crop($lx=0.25, $rx=0.75, $by=0.25, $ty=0.75) { $lx = floatval($lx); $rx = floatval($rx); $by = floatval($by); $ty = floatval($ty); if ($this->imageNull()) return false; array_push($this->_options, array('act' => 'crop', "lx" => $lx, "rx" => $rx, "by" => $by, "ty" => $ty)); return true; } //进行图片处理操作 public function exec($format='jpg', $display=false) { if ($this->imageNull()) return false; if (!in_array($format, array('jpg', 'gif', 'png'))) { $this->errno = SAE_ErrParameter; $this->errmsg = "format must be one of 'jpg', 'gif' and 'png'"; return false; } if ($format == "jpg") $format = "jpeg"; if ($this->_options[0]["act"] == "composite" && !is_array($this->_img_data)) { $this->errno = SAE_ErrParameter; $this->errmsg = "composite imagedata must be an array, pls see doc:"; return false; } if ($this->_options[0]["act"] != "composite" && is_array($this->_img_data)) { $this->errno = SAE_ErrParameter; $this->errmsg = "imagedata is array only when composite image and composite must be the first operation"; return false; } if (!$this->_image_create()) return false; //循环处理 foreach ($this->_options as $options) { call_user_func(array($this, "_" . $options['act']), $options); } $imgFun = 'image' . $format; if ($display) { header("Content-Type: image/" . $format); $imgFun($this->_image); } else { ob_start(); $imgFun($this->_image); return ob_get_clean(); } imagedestroy($this->_image); } //创建画布 private function _image_create() { if ($this->_options[0]["act"] == "composite") { //合并多张图片 $w = $this->_options[0]["width"]; $h = $this->_options[0]["height"]; $this->_width=$w; $this->_height=$h; $_image = imagecreatetruecolor($w, $h); //设置背景颜色 $color = $this->toRGB($this->_options[0]['color']); $bg = imagecolorallocate($_image, $color['r'], $color['g'], $color['b']); imagefill($_image, 0, 0, $bg); foreach ($this->_img_data as $data) { $img_data = $data[0]; $x = isset($data[1]) ? $data[1] : 0; $y = isset($data[2]) ? $data[2] : 0; $o = isset($data[3]) ? $data[3] * 100 : 100; $p = isset($data[4]) ? $data[4] : SAE_TOP_LEFT; $tmp_file = tempnam(SAE_TMP_PATH, "SAE_IMAGE"); if (!file_put_contents($tmp_file, $img_data)) { $this->errmsg = "file_put_contents to SAETMP_PATH failed when getImageAttr"; return false; } $info = getimagesize($tmp_file); $sw = $info[0]; $sh = $info[1]; $image_type = strtolower(substr(image_type_to_extension($info[2]), 1)); $createFun = "imagecreatefrom" . $image_type; $sImage = $createFun($tmp_file); //设置位置 switch ($p) { case SAE_TOP_LEFT: $dst_x = $x; $dst_y = -$y; break; case SAE_TOP_CENTER: $dst_x = ($w - $sw) / 2 + $x; $dst_y = -$y; break; case SAE_TOP_RIGHT: $dst_x = $w - $sw + $x; $dst_y = -$y; break; case SAE_CENTER_LEFT: $dst_x = $x; $dst_y = ($h - $sh) / 2 - $y; break; case SAE_CENTER_CENTER: $dst_x = ($w - $sw) / 2 + $x; $dst_y = ($h - $sh) / 2 - $y; break; case SAE_CENTER_RIGHT: $dst_x = $w - $sw + $x; $dst_y = ($h - $sh) / 2 - $y; break; case SAE_BOTTOM_LEFT: $dst_x = $x; $dst_y = $h - $sh - $y; break; case SAE_BOTTOM_CENTER: $dst_x = ($w - $sw) / 2 + $x; $dst_y = $h - $sh - $y; break; case SAE_BOTTOM_RIGHT: $dst_x = $w - $sw + $x; $dst_y = $h - $sh - $y; break; } $this->imagecopymerge_alpha($_image, $sImage, $dst_x, $dst_y, 0, 0, $sw, $sh, $o); unlink($tmp_file); } $this->_image = $_image; unset($this->_options[0]); } else { if (is_null($this->_image)) $this->getImageAttr(); } return true; } //修复合并时png透明问题 private function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct){ $w = imagesx($src_im); $h = imagesy($src_im); $cut = imagecreatetruecolor($src_w, $src_h); imagecopy($cut, $dst_im, 0, 0, $dst_x, $dst_y, $src_w, $src_h); imagecopy($cut, $src_im, 0, 0, $src_x, $src_y, $src_w, $src_h); imagecopymerge($dst_im, $cut, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h,$pct); } //水平翻转 public function flipH() { if ($this->imageNull()) return false; array_push($this->_options, array('act' => 'flipH')); return true; } //垂直翻转 public function flipV() { if ($this->imageNull()) return false; array_push($this->_options, array('act' => 'flipV')); return true; } //获取图像属性 public function getImageAttr() { if ($this->imageNull()) return false; $fn = tempnam(SAE_TMP_PATH, "SAE_IMAGE"); if ($fn == false) { $this->errmsg = "tempnam call failed when getImageAttr"; return false; } if (!file_put_contents($fn, $this->_img_data)) { $this->errmsg = "file_put_contents to SAETMP_PATH failed when getImageAttr"; return false; } if (!($size = getimagesize($fn, $info))) { $this->errmsg = "getimagesize failed when getImageAttr"; return false; } foreach ($info as $k => $v) { $size[$k] = $v; } $this->_width = $size[0]; $this->_height = $size[1]; //建立图片资源 $image_type = strtolower(substr(image_type_to_extension($size[2]), 1)); $createFun = "imagecreatefrom" . $image_type; $this->_image = $createFun($fn); unlink($fn); //删除临时文件 return $size; } //去噪点,改善图片质量,通常用于exec之前 public function improve() { if ($this->imageNull()) return false; array_push($this->_options, array('act' => 'improve')); return true; } //等比例缩放 public function resize($width=0, $height=0) { $width = intval($width); $height = intval($height); if ($this->imageNull()) return false; array_push($this->_options, array('act' => 'resize', "width" => $width, "height" => $height)); return true; } //按比例缩放 public function resizeRatio($ratio=0.5) { $ratio = floatval($ratio); if ($this->imageNull()) return false; if ($this->_width == 0) { $attr = $this->getImageAttr(); if (!$attr) return false; } array_push($this->_options, array('act' => 'resize', "width" => $this->_width * $ratio, "height" => $this->_height * $ratio)); return true; } //顺时针旋转图片 public function rotate($degree=90) { $degree = intval($degree); if ($this->imageNull()) return false; array_push($this->_options, array('act' => 'rotate', "degree" => $degree)); return true; } //设置数据 public function setData($img_data) { if (is_array($img_data)) { $_size = 0; foreach ($img_data as $k => $i) { if (count($i) < 1 || count($i) > 5) { $this->errno = SAE_ErrParameter; $this->errmsg = "image data array you supplied invalid"; return false; } if (is_null($i[1]) || $i[1] === false) $img_data[$k][1] = 0; if (is_null($i[2]) || $i[1] === false) $img_data[$k][2] = 0; if (is_null($i[3]) || $i[1] === false) $img_data[$k][3] = 1; if (is_null($i[4]) || $i[1] === false) $img_data[$k][4] = SAE_TOP_LEFT; $_size += strlen($i[0]); } if ($_size > self::image_limitsize) { $this->errno = SAE_ErrParameter; $this->errmsg = "image datas length more than 2M"; return false; } } else if (strlen($img_data) > self::image_limitsize) { $this->errno = SAE_ErrParameter; $this->errmsg = "image data length more than 2M"; return false; } $this->_img_data = $img_data; return true; } //判断图片数据是否可用 private function imageNull() { if (empty($this->_img_data)) { $this->errno = SAE_ErrParameter; $this->errmsg = "image data cannot be empty"; return true; } else { return false; } } //将颜色转换为RGB格式 private function toRGB($color) { $color = trim($color); if (preg_match('/^rgb\((\d+),(\d+),(\d+)\)$/i', $color, $arr)) { //支持rgb(r,g,b)格式 return array( 'r' => $arr[1], 'g' => $arr[2], 'b' => $arr[3] ); } $e_color = array( //支持英文颜色名 'black' => '#000', 'red' => '#f00', 'blue'=>'#00f' //TODU 增加其他 ); $hexColor = str_replace(array_keys($e_color), array_values($e_color), $color); $color = str_replace('#', '', $hexColor); if (strlen($color) > 3) { $rgb = array( 'r' => hexdec(substr($color, 0, 2)), 'g' => hexdec(substr($color, 2, 2)), 'b' => hexdec(substr($color, 4, 2)) ); } else { $color = str_replace('#', '', $hexColor); $r = substr($color, 0, 1) . substr($color, 0, 1); $g = substr($color, 1, 1) . substr($color, 1, 1); $b = substr($color, 2, 1) . substr($color, 2, 1); $rgb = array( 'r' => hexdec($r), 'g' => hexdec($g), 'b' => hexdec($b) ); } return $rgb; } /** * 添加文字 * 参数格式 * array("txt" => $txt, "opacity" => $opacity, "gravity" => $gravity, "font" => array("name" => $font['name'], "size" => $font["size"], "weight" => $font["weight"], "color" => $font["color"])) * @param array $args */ private function _annotate($args) { $font = $args['font']; $rgb = $this->toRGB($font['color']); $color = imagecolorclosestalpha($this->_image, $rgb['r'], $rgb['g'], $rgb['b'], (1 - $args['opacity']) * 100); //设置位置 $fontSize = imagettfbbox($font['size'], 0, $font['name'], $args['txt']); $textWidth = $fontSize [4]; //取出宽 $textHeight = abs($fontSize[7]); //取出高 switch ($args['gravity']) { case SAE_NorthWest: $x=0; $y=$textHeight; break; case SAE_North: $x=($this->_width-$textWidth)/2;; $y=$textHeight; break; case SAE_NorthEast: $x=$this->_width-$textWidth;; $y=$textHeight; break; case SAE_West: $x=0; $y=($this->_height-$textHeight)/2; break; case SAE_East: $x=$this->_width-$textWidth; $y=($this->_height-$textHeight)/2; break; case SAE_SouthWest: $x=0; $y=$this->_height-$textHeight; break; case SAE_South: $x=($this->_width-$textWidth)/2; $y=$this->_height-$textHeight; break; case SAE_SouthEast: $x=$this->_width-$textWidth; $y=$this->_height-$textHeight; break; case SAE_Static: default : $x=($this->_width-$textWidth)/2; $y=($this->_height-$textHeight)/2; break; } imagettftext($this->_image, $font['size'], 0, $x, $y, $color, $font['name'], $args['txt']); } /** *截取图片 * 参数 array("lx" => $lx, "rx" => $rx, "by" => $by, "ty" => $ty) * @param array $args */ private function _crop($args){ $width=($args['rx']-$args['lx'])*$this->_width; $height=($args['ty']-$args['by'])*$this->_height; $x=$args['lx']*$this->_width; $y=$args['by']*$this->_height; $_image=imagecreatetruecolor($width, $height); imagecopyresampled($_image,$this->_image,0,0,$x,$y, $width,$height,$width,$height); $this->_image=$_image; } /** *图片放缩 * 参数:array( "width" => $width, "height" => $height) * @param array $args */ private function _resize($args){ if($args['width']==0 && $args['heigth']==0) return ; if($args['width']==0){ //高度固定等比例放缩 $h=$args['heigth']; $w=$h/$this->_height*$this->_width; }elseif($args['heigth']==0){ //宽度固定等比例放缩 $w=$args['width']; $h=$w/$this->_width*$this->_height; }else{ $w=$args['width']; $h=$args['height']; } $_image=imagecreatetruecolor($w, $h); imagecopyresampled($_image, $this->_image, 0, 0, 0, 0, $w, $h, $this->_width, $this->_height); $this->_image=$_image; } /** *旋转角度 * @param array $args */ private function _rotate($args){ $this->_image=imagerotate($this->_image, 360-$args['degree'],0); } //水平翻转 private function _flipH($args) { $_image=imagecreatetruecolor($this->_width, $this->_height); for ($i = 0; $i < $this->_width; $i++) { imagecopyresampled($_image, $this->_image, ($this->_width - $i), 0, $i, 0, 1, $this->_height, 1, $this->_height); } $this->_image=$_image; } //垂直翻转 private function _flipV($args) { $this->_flipH(array()); $this->_rotate(array('degree'=>180)); } //去除噪点 private function _improve($args){ //本地不做任何处理 } }