123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- <?php
- /**
- * The Feeler framework, licensed under Mit license
- * Author: Rick Guo
- */
- class Image{
- public static $typeMappings = array(
- "jpg" => "jpeg",
- );
-
- public $font;
-
- protected static $instance;
-
- function __construct(){
- $this->font = Yii::app()->basePath."/../css/fonts/yahei_mono.ttf";
- }
-
- protected static function instance(){
- if(!is_object(self::$instance)){
- self::$instance = new self();
- }
-
- return self::$instance;
- }
-
- public static function revertType(&$type){
- if(isset(self::$typeMappings[$type])){
- $type = self::$typeMappings[$type];
- }
-
- return true;
- }
-
- public static function destroy($res){
- return is_resource($res) ? imagedestroy($res) : false;
- }
- public static function create($width, $height, $color = array(255, 255, 255, 100)){
- if(!$width || !$height)
- return false;
-
- $src = imagecreatetruecolor($width, $height);
- if(!($color = self::getColor($src, $color)))
- return false;
-
- imagealphablending($src, true);
- imagefill($src, 0, 0, $color);
- imagesavealpha($src, true);
-
- return is_resource($src) ? $src : false;
- }
-
- public static function createFromFile($srcFile){
- if(!is_file($srcFile))
- return false;
-
- ($type = File::getExt($srcFile)) and self::revertType($type);
-
- switch($type){
- case "jpeg":
- $src = imagecreatefromjpeg($srcFile);
- break;
-
- case "png":
- $src = imagecreatefrompng($srcFile);
- break;
-
- case "gif":
- $src = imagecreatefromgif($srcFile);
- break;
-
- default:
- return false;
- break;
- }
-
- imagealphablending($src, true);
- imagesavealpha($src, true);
-
- return is_resource($src) ? $src : false;
- }
-
- public static function createFromFiles($files){
- $srcs = array();
-
- if(!Arr::isAvailable($files)){
- foreach($files as $file){
- if(is_file($file) && is_resource($src = self::createFromFile($file)))
- $srcs[md5_file($file)] = $src;
- }
- }
-
- return $srcs;
- }
-
- public static function setColor(&$src, $rgb = array()){
- if(!is_resource($src) || !Number::isInt($color = self::getColor($src, $rgb)))
- return false;
-
- imagealphablending($src, true);
- imagefill($src, 0, 0, $color);
- imagesavealpha($src, true);
-
- return true;
- }
-
- public static function saveAs($res, $file){
- if(!is_resource($res) || !$file)
- return false;
-
- if(!File::mkdir(File::getPath($file)))
- return false;
-
- $ext = File::getExt($file);
-
- switch($ext){
- case "jpeg":
- $rs = imagejpeg($res, $file);
- break;
-
- case "png":
- $rs = imagepng($res, $file);
- break;
-
- case "gif":
- $rs = imagegif($res, $file);
- break;
-
- default:
- return false;
- break;
- }
-
- return $rs ? true : false;
- }
-
- public static function getColor($src, $rgb){
- if(!Arr::isAvailable($rgb))
- return null;
-
- $count = count($rgb);
- if($count != 3 && $count != 4)
- return null;
-
- if($count == 4){
- list($r, $g, $b, $a) = $rgb;
- $color = imagecolorallocatealpha($src, $r, $g, $b, $a);
- }
- else if($count == 3){
- list($r, $g, $b) = $rgb;
- $color = imagecolorallocate($src, $r, $g, $b);
- }
-
- return $color;
- }
-
- public static function fillRectangle(&$src, $rectangle = array()){
- if(!is_resource($src) || !Arr::isAvailable($rectangle, array("w", "h", "x", "y", "color")))
- return false;
-
- if(!($rectangle["color"] = self::getColor($src, $rectangle["color"])))
- return false;
-
- return imagefilledrectangle($src, $rectangle["x"], $rectangle["y"], $rectangle["x"] + $rectangle["w"], $rectangle["y"] + $rectangle["h"], $rectangle["color"]);
- }
-
- public static function getImageResSize($res){
- $imageSize = array();
-
- $file = sys_get_temp_dir()."/".Random::uuid().".png";
- if(self::saveAs($res, $file)){
- $imageSize = getimagesize($file);
- $imageSize = array($imageSize[0], $imageSize[1]);
- File::rm($file);
- }
-
- return $imageSize;
- }
-
- private function _getStringRectangleSize($string, $font){
- $size = array();
-
- if($string && isset($font["size"]) && Number::isNumeric($font["size"]) && $font["size"] > 0){
- if(!isset($font["angle"]) || !Number::isNumeric($font["angle"]))
- $font["angle"] = 0;
-
- $size = imageftbbox($font["size"], $font["angle"], $this->font, $string);
- $size = array($size[2] - $size[0], $size[7] - $size[1]);
- $size = array(abs($size[0]), abs($size[1]));
- }
-
- return $size;
- }
-
- public static function getStringRectangleSize($string, $font){
- return self::instance()->_getStringRectangleSize($string, $font);
- }
-
- private function _sign(&$src, $content, $font = array()){
- if(!is_resource($src) || !$content || !Arr::isAvailable($font, array("size", "color", "x", "y")) ||
- !Number::isInt($fontColor = self::getColor($src, $font["color"])) || !($imageSize = self::getImageResSize($src)))
- return false;
-
- if(!($stringRectangleSize = self::getStringRectangleSize($content, $font)))
- return false;
-
- $fontYOffset = $stringRectangleSize[1] - 3;
- list($font["w"], $font["h"]) = $stringRectangleSize;
-
- $position = self::calcPosition($font, array("w" => $imageSize[0], "h" => $imageSize[1]));
- $position[1] += $fontYOffset;
- list($font["x"], $font["y"]) = $position;
-
- if(!isset($font["angle"]) || !Number::isInt($font["angle"])){
- $font["angle"] = 0;
- }
-
- $rs = imagefttext($src, $font["size"], $font["angle"], $font["x"], $font["y"], $fontColor, $this->font, $content);
-
- return $rs ? true : false;
- }
-
- public static function sign(&$src, $content, $font = array()){
- return self::instance()->_sign($src, $content, $font);
- }
-
- public static function zoom(&$src, $size){
- if(!is_resource($src) || (!Arr::isAvailable($size) && !Number::isFloat($size)))
- return false;
-
- $srcSize = self::getImageResSize($src);
-
- if(Number::isNumeric($size))
- $size = array(Number::truncateDecimal($srcSize[0] * $size), Number::truncateDecimal($srcSize[1] * $size));
-
- $res = $src;
- $src = self::create($size[0], $size[1]);
-
- return imagecopyresampled(
- $src, $res,
- 0, 0, 0, 0,
- $size[0], $size[1], $srcSize[0], $srcSize[1]
- );
- }
-
- public static function calcPosition($elementInfo, $containerInfo){
- if(!Arr::isAvailable($elementInfo, array("w", "h", "x", "y")) || !Arr::isAvailable($containerInfo, array("w", "h")))
- return array();
-
- $param = array();
-
- $param["x"] = trim($elementInfo["x"]);
- $param["y"] = trim($elementInfo["y"]);
-
- $param["x"] = str_replace(" ", " ", $param["x"]);
- $param["y"] = str_replace(" ", " ", $param["y"]);
-
- $param["x"] = explode(" ", $param["x"], 2);
- $param["y"] = explode(" ", $param["y"], 2);
-
- $elementInfo["x"] = 0;
- foreach($param["x"] as $key => $val){
- if(empty($val))
- continue;
-
- if(Number::isNumeric($val)){
- $elementInfo["x"] += Number::truncateDecimal($val, 1);
- }
- else{
- if($val == "left"){
- $elementInfo["x"] += 0;
- }
- else if($val == "center"){
- $elementInfo["x"] += Number::truncateDecimal(($containerInfo["w"] - $elementInfo["w"]) / 2, 1);
- }
- else if($val == "right"){
- $elementInfo["x"] += Number::truncateDecimal($containerInfo["w"] - $elementInfo["w"], 1);
- }
- }
- }
-
- $elementInfo["y"] = 0;
- foreach($param["y"] as $key => $val){
- if(empty($val))
- continue;
-
- if(Number::isNumeric($val)){
- $elementInfo["y"] += Number::truncateDecimal($val, 1);
- }
- else{
- if($val == "top"){
- $elementInfo["y"] += 0;
- }
- else if($val == "center"){
- $elementInfo["y"] += Number::truncateDecimal(($containerInfo["h"] - $elementInfo["h"]) / 2, 1);
- }
- else if($val == "bottom"){
- $elementInfo["y"] += Number::truncateDecimal($containerInfo["h"] - $elementInfo["h"], 1);
- }
- }
- }
-
- return array($elementInfo["x"], $elementInfo["y"]);
- }
-
- public static function crop(&$src){
- $params = func_get_args();
- if(!is_resource($src) || !isset($params[1]) || !Arr::isAvailable($params[1], array("x", "y", "w", "h")))
- return false;
-
- if(isset($params[2]) && !Arr::isAvailable($params[2], array("x", "y", "w", "h")))
- return false;
-
- $params = Arr::getVals($params, array(0, 1, 2));
- $imageSize = self::getImageResSize($src);
-
- if(!isset($params[2])){
- $vals = Arr::getVals($params[1], array(
- "destX" => "x",
- "destY" => "y",
- "destW" => "w",
- "destH" => "h",
- "color" => "color",
- ));
- extract($vals);
-
- return imagecopyresampled(
- $src, $src,
- 0, 0, $destX, $destY,
- $destW, $destH, $destW, $destH
- );
- }
- else{
- $elementInfo = Arr::getVals($params[1], array("x", "y", "w", "h"));
- $containerInfo = Arr::getVals($params[2], array("x", "y", "w", "h"));
- if(!($position = self::calcPosition(array("w" => $elementInfo["w"], "h" => $elementInfo["h"], "x" => $containerInfo["x"], "y" => $containerInfo["y"]), $containerInfo)))
- return false;
-
- $containerInfo["x"] = $position[0];
- $containerInfo["y"] = $position[1];
-
- $elementInfo = Arr::getVals($elementInfo, array(
- "srcX" => "x",
- "srcY" => "y",
- "srcW" => "w",
- "srcH" => "h",
- ));
- extract($elementInfo);
-
- $containerInfo = Arr::getVals($containerInfo, array(
- "destX" => "x",
- "destY" => "y",
- "destW" => "w",
- "destH" => "h",
- "color" => "color",
- ));
- extract($containerInfo);
-
- $prevSrc = $src;
- $src = isset($color) ? self::create($destW, $destH, $color) : self::create($destW, $destH);
-
- return $src !== false ? imagecopyresampled(
- $src, $prevSrc,
- $destX, $destY, $srcX, $srcY,
- $srcW, $srcH, $srcW, $srcH
- ) : false;
- }
- }
-
- public static function setBorder(&$src, $borderColor = array(0, 0, 0, 1), $borderSize = 1){
- if(!is_resource($src) || !Number::isInt($borderSize) || $borderSize < 1){
- return false;
- }
-
- if(!($imageSize = self::getImageResSize($src)))
- return false;
-
- $containerSize = array($borderSize * 2 + $imageSize[0], $borderSize * 2 + $imageSize[1]);
-
- return self::crop(
- $src,
- array("x" => 0, "y" => 0, "w" => $imageSize[0], "h" => $imageSize[1]),
- array("x" => $borderSize, "y" => $borderSize, "w" => $containerSize[0], "h" => $containerSize[1], "color" => $borderColor)
- );
- }
-
- public static function puzzle($containerInfo, $images){
- $params = func_get_args();
-
- if(!Arr::isAvailable($containerInfo, array("w", "h")))
- return false;
-
- foreach($images as $key => $image){
- if(!Arr::isAvailable($image, array("res", "layer_num", "x", "y", "w", "h")))
- unset($images[$key]);
- }
-
- if(!$images)
- return false;
-
- Arr::sortByField($images, "layer_num", "DESC");
-
- if(isset($containerInfo["bg_color"]))
- $dest = self::create($containerInfo["w"], $containerInfo["h"], $containerInfo["bg_color"]);
- else
- $dest = self::create($containerInfo["w"], $containerInfo["h"]);
-
- foreach($images as $image){
- $position = self::calcPosition($image, $containerInfo);
- $image["x"] = $position[0];
- $image["y"] = $position[1];
-
- imagecopyresampled(
- $dest, $image["res"],
- $image["x"], $image["y"],
- 0, 0,
- $image["w"], $image["h"],
- $image["w"], $image["h"]
- );
- }
-
- return $dest;
- }
- }
|