PageRenderTime 45ms CodeModel.GetById 16ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 1ms

/libs/system/Image.php

https://github.com/monkeycraps/swoole_framework
PHP | 546 lines | 390 code | 29 blank | 127 comment | 58 complexity | 1b67df208dcaf8558320d00a7ad4394c MD5 | raw file
  1<?php
  2/**
  3 * 图像处理类
  4 * @author Tianfeng.Han
  5 * @package SwooleSystem
  6 * @subpackage Image
  7 * @link http://code.google.com/p/swoole/
  8 */
  9class Image
 10{
 11    /**
 12     * 裁切图片
 13     * @param $pic 源图像
 14     * @param $dst_pic 目标图像
 15     * @param $width 宽度
 16     * @param $height 高度
 17     * @param $qulitity 质量
 18     * @return unknown_type
 19     */
 20    static function cut($pic,$dst_pic,$width,$height=null,$qulitity=100)
 21    {
 22        $im = imagecreatefromjpeg($pic);
 23
 24        if(imagesx($im)>$width)
 25        {
 26            $old_w = imagesx($im);
 27            $old_h = imagesy($im);
 28
 29            if($height==null)
 30            {
 31                $w_h = $old_w/$old_h;
 32                $height = $width*$w_h;
 33            }
 34
 35            $newim = imagecreatetruecolor($width, $height);
 36            imagecopyresampled($newim, $im, 0, 0, 0, 0, $width,$height,$old_w,$old_h);
 37            imagejpeg($newim, $dst_pic,$qulitity);
 38            imagedestroy($im);
 39            return true;
 40        }
 41        elseif($pic!=$dst_pic) copy($pic,$dst_pic);
 42    }
 43    /**
 44     * 压缩图像尺寸
 45     * @param $pic 源图像
 46     * @param $dst_pic 目标图像
 47     * @param $width 宽度
 48     * @param $height 高度
 49     * @param $qulitity 质量
 50     * @return unknown_type
 51     */
 52    static function thumbnail($pic,$dst_pic,$max_width,$max_height=null,$qulitity=100, $copy=true)
 53    {
 54        $im = self::readfile($pic);
 55        $old_w = imagesx($im);
 56        $old_h = imagesy($im);
 57
 58        if($max_height==null) $max_height=$max_width;
 59
 60        if($old_w>$max_width or $old_h>$max_height)
 61        {
 62
 63            $w_h = $old_w / $old_h;
 64            $h_w = $old_h / $old_w;
 65            if($w_h>$h_w)
 66            {
 67                $width = $max_width;
 68                $height = $width*$h_w;
 69            }
 70            else
 71            {
 72                $height = $max_height;
 73                $width = $height*$w_h;
 74            }
 75            $newim = imagecreatetruecolor($width, $height);
 76            imagecopyresampled($newim, $im, 0, 0, 0, 0, $width,$height,$old_w,$old_h);
 77            imagejpeg($newim, $dst_pic, $qulitity);
 78            imagedestroy($im);
 79        }
 80        elseif($pic!=$dst_pic and $copy) copy($pic, $dst_pic);
 81    }
 82    /**
 83     * 读取图像
 84     * @param $pic
 85     * @return unknown_type
 86     */
 87    static function readfile($pic)
 88    {
 89        $image_info = getimagesize($pic);
 90        if($image_info["mime"]=="image/jpeg" || $image_info["mime"]=="image/gif" || $image_info["mime"]=="image/png")
 91        {
 92            switch($image_info["mime"])
 93            {
 94                case "image/jpeg":
 95                    $im = imagecreatefromjpeg($pic);
 96                    break;
 97                case "image/gif":
 98                    $im = imagecreatefromgif($pic);
 99                    break;
100                case "image/png":
101                    $im = imagecreatefrompng($pic);
102                    break;
103            }
104            return $im;
105        }
106        return false;
107    }
108    /**
109     * 加给图片加水印
110     *
111     * @param strimg $groundImage 要加水印地址
112     * @param int $waterPos 水印位置
113     * @param string $waterImage 水印图片地址
114     * @param string $waterText 文本文字
115     * @param int $textFont 文字大小
116     * @param string $textColor 文字颜色
117     * @param int $minWidth 小于此值不加水印
118     * @param int $minHeight 小于此值不加水印
119     * @param float $alpha 透明度
120     * @return FALSE
121     */
122    public static function waterMark($groundImage , $waterPos = 0 , $waterImage = "" , $waterText = "" , $textFont = 15 , $textColor = "#FF0000",$minWidth='100',$minHeight='100',$alpha=0.9)
123    {
124        $isWaterImg = FALSE;
125        $bg_h = $bg_w = $water_h = $water_w = 0;
126        //获取背景图的高,宽
127        if(is_file($groundImage) && !empty($groundImage)){
128            $bg = new Imagick();
129            $bg ->readImage($groundImage);
130            $bg_h = $bg->getImageHeight();
131            $bg_w = $bg->getImageWidth();
132        }
133        //获取水印图的高,宽
134        if(is_file($waterImage) && !empty($waterImage)){
135            $water = new Imagick($waterImage);
136            $water_h = $water->getImageHeight();
137            $water_w = $water->getImageWidth();
138        }
139        //如果背景图的高宽小于水印图的高宽或指定的高和宽则不加水印
140        if($bg_h < $minHeight || $bg_w < $minWidth || $bg_h < $water_h || $bg_w < $water_w ) {
141            return ;
142        }else {
143            $isWaterImg = TRUE;
144        }
145        //加水印
146        if($isWaterImg){
147            $dw = new ImagickDraw();
148            //加图片水印
149            if(is_file($waterImage)){
150                $water->setImageOpacity($alpha);
151                $dw -> setGravity($waterPos);
152                $dw -> composite($water->getImageCompose(),0,0,50,0,$water);
153                $bg -> drawImage($dw);
154                if(!$bg -> writeImage($groundImage)){
155                    return FALSE;
156                }
157            }else{
158                //加文字水印
159                $dw -> setFontSize($textFont);
160                $dw -> setFillColor($textColor);
161                $dw -> setGravity($waterPos);
162                $dw -> setFillAlpha($alpha);
163                $dw -> annotation(0,0,$waterText);
164                $bg -> drawImage($dw);
165                if(!$bg -> writeImage($groundImage)){
166                    return FALSE;
167                }
168            }
169        }
170    }
171    /**
172     * PHP图片水印 (水印支持图片或文字)
173     * 注意:Support GD 2.0,Support FreeType、GIF Read、GIF Create、JPG 、PNG
174     *      $waterImage 和 $waterText 最好不要同时使用,选其中之一即可,优先使用 $waterImage。
175     *      当$waterImage有效时,参数$waterString、$stringFont、$stringColor均不生效。
176     *      加水印后的图片的文件名和 $groundImage 一样。
177     * @param $groundImage  背景图片,即需要加水印的图片,暂只支持GIF,JPG,PNG格式;
178     * @param $waterPos  水印位置,有10种状态,0为随机位置;1为顶端居左,2为顶端居中,3为顶端居右;4为中部居左,5为中部居中,6为中部居右;7为底端居左,8为底端居中,9为底端居右;
179     * @param $waterImage  图片水印,即作为水印的图片,暂只支持GIF,JPG,PNG格式;
180     * @param $waterText   文字水印,即把文字作为为水印,支持ASCII码,不支持中文;
181     * @param $textFont    文字大小
182     * @param $textColor   文字颜色,值为十六进制颜色值,默认为#FF0000(红色);
183     * @param $minwidth
184     * @param $minheight
185     * @return unknown_type
186     */
187    public static function waterMark2($groundImage , $waterPos = 0 , $waterImage = "" , $waterText = "" , $textFont = 5 , $textColor = "#FF0000",$minwidth,$minheight)
188    {
189        $isWaterImage = FALSE ;
190        //$waterImage = SYSROOTPATH . $waterImage;
191
192        $formatMsg = "暂不支持该文件格式,请用图片处理软件将图片转换为GIF、JPG、PNG格式。" ;
193        //读取水印文件
194        if(!empty( $waterImage ) && file_exists ( $waterImage )) {
195            $isWaterImage = TRUE ;
196            $water_info = getimagesize ( $waterImage );
197            $water_w     = $water_info [ 0 ]; //取得水印图片的宽
198            $water_h     = $water_info [ 1 ]; //取得水印图片的高
199
200            switch( $water_info [ 2 ]) //取得水印图片的格式
201            {
202                case 1 : $water_im = imagecreatefromgif ( $waterImage );break;
203                case 2 : $water_im = imagecreatefromjpeg ( $waterImage );break;
204                case 3 : $water_im = imagecreatefrompng ( $waterImage );break;
205                default:die( $formatMsg );
206            }
207        }
208        //读取背景图片
209        if(!empty( $groundImage ) && file_exists ( $groundImage )) {
210            $ground_info = getimagesize ( $groundImage );
211            $ground_w     = $ground_info [ 0 ]; //取得背景图片的宽
212            $ground_h     = $ground_info [ 1 ]; //取得背景图片的高
213
214            switch( $ground_info [ 2 ]) //取得背景图片的格式
215            {
216                case 1 : $ground_im = imagecreatefromgif ( $groundImage );break;
217                case 2 : $ground_im = imagecreatefromjpeg ( $groundImage );break;
218                case 3 : $ground_im = imagecreatefrompng ( $groundImage );break;
219                default:die( $formatMsg );
220            }
221        } else {
222            die( "需要加水印的图片不存在!" );
223        }
224        //水印位置
225        if( $isWaterImage ) //图片水印
226        {
227            $w = $water_w ;
228            $h = $water_h ;
229            $label = "图片的" ;
230        }
231        else //文字水印
232        {
233            $temp = imagettfbbox ( ceil ( $textFont * 2.5 ), 0 , SYSROOTPATH."images/watermark/ant1.ttf" , $waterText ); //取得使用 TrueType 字体的文本的范围
234            $w = $temp [ 2 ] - $temp [ 6 ];
235            $h = $temp [ 3 ] - $temp [ 7 ];
236            unset( $temp );
237            $label = "文字区域" ;
238        }
239        // add
240        if( ( $ground_w < $w ) || ( $ground_h < $h ) || ( $ground_w < $minwidth ) || ( $ground_h < $minheight ) ){
241            echo "需要加水印的图片的长度或宽度比水印" . $label . "还小,无法生成水印!" ;
242            return;
243        }
244        switch( $waterPos ) {
245            case 0 : //随机
246                $posX = rand ( 0 ,( $ground_w - $w ));
247                $posY = rand ( 0 ,( $ground_h - $h ));
248                break;
249            case 1 : //1为顶端居左
250                $posX = 0 ;
251                $posY = 0 ;
252                break;
253            case 2 : //2为顶端居中
254                $posX = ( $ground_w - $w ) / 2 ;
255                $posY = 0 ;
256                break;
257            case 3 : //3为顶端居右
258                $posX = $ground_w - $w ;
259                $posY = 0 ;
260                break;
261            case 4 : //4为中部居左
262                $posX = 0 ;
263                $posY = ( $ground_h - $h ) / 2 ;
264                break;
265            case 5 : //5为中部居中
266                $posX = ( $ground_w - $w ) / 2 ;
267                $posY = ( $ground_h - $h ) / 2 ;
268                break;
269            case 6 : //6为中部居右
270                $posX = $ground_w - $w ;
271                $posY = ( $ground_h - $h ) / 2 ;
272                break;
273            case 7 : //7为底端居左
274                $posX = 0 ;
275                $posY = $ground_h - $h ;
276                break;
277            case 8 : //8为底端居中
278                $posX = ( $ground_w - $w ) / 2 ;
279                $posY = $ground_h - $h ;
280                break;
281            case 9 : //9为底端居右
282                $posX = $ground_w - $w ;
283                $posY = $ground_h - $h ;
284                break;
285            default: //随机
286                $posX = rand ( 0 ,( $ground_w - $w ));
287                $posY = rand ( 0 ,( $ground_h - $h ));
288                break;
289        }
290        //设定图像的混色模式
291        imagealphablending ( $ground_im , true );
292        if( $isWaterImage ) //图片水印
293        {
294            imagecopy ( $ground_im , $water_im , $posX , $posY , 0 , 0 , $water_w , $water_h ); //拷贝水印到目标文件
295        }
296        else //文字水印
297        {
298            if( !empty( $textColor ) && ( strlen ( $textColor )== 7 ) )
299            {
300                $R = hexdec ( substr ( $textColor , 1 , 2 ));
301                $G = hexdec ( substr ( $textColor , 3 , 2 ));
302                $B = hexdec ( substr ( $textColor , 5 ));
303            }
304            else
305            {
306                die( "水印文字颜色格式不正确!" );
307            }
308            imagestring ( $ground_im , $textFont , $posX , $posY , $waterText , imagecolorallocate ( $ground_im , $R , $G , $B ));
309        }
310        //生成水印后的图片
311        @unlink ( $groundImage );
312        switch( $ground_info [ 2 ]) //取得背景图片的格式
313        {
314            case 1 : imagegif ( $ground_im , $groundImage );break;
315            case 2 : imagejpeg ( $ground_im , $groundImage );break;
316            case 3 : imagepng ( $ground_im , $groundImage );break;
317            default:die( $errorMsg );
318        }
319        //释放内存
320        if(isset( $water_info )) unset( $water_info );
321        if(isset( $water_im )) imagedestroy ( $water_im );
322        unset( $ground_info );
323        imagedestroy ( $ground_im );
324    }
325    /**
326     * 生成验证码使用GD
327     * @param $img_width
328     * @param $img_height
329     * @return unknown_type
330     */
331    static function authcode_gd($img_width=80,$img_height=30)
332    {
333        session_start();
334        $authnum = '';
335        srand(microtime() * 100000);
336        for($Tmpa=0;$Tmpa<4;$Tmpa++)
337        {
338            $authnum.=dechex(rand(0,15));
339        }
340        $authnum = strtoupper($authnum);;
341        $_SESSION['authcode'] = $authnum;
342
343        $aimg = imageCreate($img_width,$img_height);       //生成图片
344        ImageColorAllocate($aimg, 255,255,255);            //图片底色,ImageColorAllocate第1次定义颜色PHP就认为是底色了
345
346        //下面该生成雪花背景了,其实就是在图片上生成一些符号
347        for($i=1; $i<=128; $i++)
348        {
349            imageString($aimg,1,mt_rand(1,$img_width),mt_rand(1,$img_height),"*",imageColorAllocate($aimg,mt_rand(200,255),mt_rand(200,255),mt_rand(200,255)));
350            //其实也不是雪花,就是生成*号而已。为了使它们看起来"杂乱无章、5颜6色",就得在1个1个生成它们的时候,让它们的位置、颜色,甚至大小都用随机数,rand()或mt_rand都可以完成。
351        }
352        for($i=0;$i<strlen($_SESSION['authcode']);$i++)
353        {
354            imageString($aimg, mt_rand(8,12),$i*$img_width/4+mt_rand(1,8),mt_rand(1,$img_height/4), $_SESSION['authcode'][$i],imageColorAllocate($aimg,mt_rand(0,100),mt_rand(0,150),mt_rand(0,200)));
355        }
356        header("Content-type: image/png");    //告诉浏览器,下面的数据是图片
357        ImagePng($aimg);                      //生成png格式
358        ImageDestroy($aimg);
359    }
360    static function authcode_im()
361    {
362        if(empty($_SESSION)) session_start();
363        $authnum = '';
364        srand((double)microtime()*1000000);
365        $_SESSION['authcode']="";
366
367        /* imagick对象 *
368         $Imagick = new Imagick();
369
370         /* 背景对象 */
371        $bg = new ImagickPixel();
372
373        /* Set the pixel color to white */
374        $bg->setColor('rgb(235,235,235)');
375
376        /* 画刷 *
377         $ImagickDraw = new ImagickDraw();
378
379         /* Set font and font size. You can also specify /path/to/font.ttf */
380        $ImagickDraw->setFont(LIBPATH.'/../static/fonts/CONSOLA.TTF');
381        $ImagickDraw->setFontSize( 24 );
382        $ImagickDraw->setFillColor('black');
383
384        //生成数字和字母混合的验证码方法
385        $ychar="0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z";
386        $list=explode(",",$ychar);
387        for($i=0;$i<4;$i++)
388        {
389            $randnum=rand(0,35);
390            $authnum.=$list[$randnum];
391        }
392        $authnum = strtoupper($authnum);;
393        $_SESSION['authcode'] = $authnum;
394
395        /* Create new empty image */
396        $Imagick->newImage( 60, 24, $bg );
397
398        /* Write the text on the image */
399        $Imagick->annotateImage( $ImagickDraw, 4, 20, 0, $authnum );
400
401        /* 变形 *
402         //$Imagick->swirlImage( 10 );
403
404         /* 随即线条 */
405        /*$ImagickDraw->line( rand( 0, 70 ), rand( 0, 30 ), rand( 0, 70 ), rand( 0, 30 ) );
406         $ImagickDraw->line( rand( 0, 70 ), rand( 0, 30 ), rand( 0, 70 ), rand( 0, 30 ) );
407         $ImagickDraw->line( rand( 0, 70 ), rand( 0, 30 ), rand( 0, 70 ), rand( 0, 30 ) );
408         $ImagickDraw->line( rand( 0, 70 ), rand( 0, 30 ), rand( 0, 70 ), rand( 0, 30 ) );
409         $ImagickDraw->line( rand( 0, 70 ), rand( 0, 30 ), rand( 0, 70 ), rand( 0, 30 ) );*/
410
411        /* Draw the ImagickDraw object contents to the image. */
412        $Imagick->drawImage( $ImagickDraw );
413
414        /* Give the image a format */
415        $Imagick->setImageFormat( 'png' );
416
417        /* Send headers and output the image */
418        //header( "Content-Type: image/{$Imagick->getImageFormat()}" );
419        echo $Imagick->getImageBlob( );
420    }
421    /**
422     * 生成验证码,使用TTF字体
423     * @param $font
424     * @param $img_width
425     * @param $img_height
426     * @return unknown_type
427     */
428    static function authcode_ttf($font,$width=180,$height=130)
429    {
430        if(empty($_SESSION)) session_start();
431        $length = 4;
432        $code = getRandNumChineseString(4);
433
434        $width = ($length * 45) > $width ? $length * 45 : $width;
435        $_SESSION['authcode'] = md5($code);
436        $im = imagecreatetruecolor($width, $height);
437        $borderColor = imagecolorallocate($im, 100, 100, 100);                    //边框色
438        $bkcolor = imagecolorallocate($im, 250, 250, 250);
439        imagefill($im, 0, 0, $bkcolor);
440        imagerectangle($im, 0, 0, $width - 1, $height - 1, $borderColor);
441        // 干扰
442        for ($i = 0; $i < 15; $i++) {
443            $fontcolor = imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
444            imagearc($im, mt_rand(-10, $width), mt_rand(-10, $height), mt_rand(30, 300), mt_rand(20, 200), 55, 44, $fontcolor);
445        }
446        for ($i = 0; $i < 255; $i++) {
447            $fontcolor = imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
448            imagesetpixel($im, mt_rand(0, $width), mt_rand(0, $height), $fontcolor);
449        }
450
451        for ($i = 0; $i < $length; $i++) {
452            $fontcolor = imagecolorallocate($im, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120)); //这样保证随机出来的颜色较深。
453            $codex = msubstr($code, $i, 1);
454            imagettftext($im, mt_rand(16, 20), mt_rand(-60, 60), 40 * $i + 20, mt_rand(30, 35), $fontcolor, $font, $codex);
455        }
456        Header("Content-type: image/png");    //告诉浏览器,下面的数据是图片
457        ImagePng($im);                      //生成png格式
458        ImageDestroy($im);
459    }
460    static function thumb_name($file_name,$insert='thumb')
461    {
462        $dirname = dirname($file_name);
463        $file_name = basename($file_name);
464        $extend =explode("." , $file_name);
465        return $dirname.'/'.$extend[0].'_'.$insert.'.'.$extend[count($extend)-1];
466    }
467    /**
468     * 裁切图片,制作头像
469     * @param $image  图片相对网站根目录的地址
470     * @param $params 参数,高度height=100,宽度width=116,精度qulitity=80,新图片的地址newfile,原图的真实宽度abs_width
471     * @param $original_size 原始的尺寸
472     * @param $crop_size 裁切的参数,高度,宽度,四点坐标
473     * @return true/false
474     */
475    static function cropImage($image,$params,$original_size,$crop_size)
476    {
477        $qulitity = isset($params['qulitity'])?$params['qulitity']:100;
478        $dst_width = isset($params['width'])?$params['width']:90;
479        $dst_height = isset($params['height'])?$params['height']:105;
480
481        $image = WEBPATH.$image;
482        if(!file_exists($image))
483        return '错误,图片不存在!';
484
485        $image_info = getimagesize($image);
486
487        if($image_info["mime"]=="image/jpeg" || $image_info["mime"]=="image/gif" || $image_info["mime"]=="image/png")
488        {
489            /**
490             * 计算实际裁剪区域,图片是否被缩放,如果不是真实大小,需要计算
491             */
492            if(isset($params['abs_width']))
493            {
494                $tmp_rate = $params['abs_width'] / $original['width'];
495                $crop_size['left'] = $crop_size['left'] * $tmp_rate;
496                $crop_size['top'] = $crop_size['top'] * $tmp_rate;
497                $crop_size['width'] = $crop_size['width'] * $tmp_rate;
498                $crop_size['height'] = $crop_size['height'] * $tmp_rate;
499            }
500
501            //裁剪
502            $image_new = imagecreatetruecolor($dst_width, $dst_height);
503            switch($image_info["mime"]){
504                case "image/jpeg":
505                    $bin_ori = imagecreatefromjpeg($image);
506                    break;
507                case "image/gif":
508                    $bin_ori = imagecreatefromgif($image);
509                    break;
510                case "image/png":
511                    $bin_ori = imagecreatefrompng($image);
512                    break;
513            }
514
515            imagecopyresampled($image_new, $bin_ori, 0, 0, $crop_size['left'], $crop_size['top'], $dst_width, $dst_height, $crop_size['width'], $crop_size['height']);
516            $file_new = WEBPATH.$params['newfile'];
517            if(!file_exists(dirname($file_new))) mkdir(dirname($file_new),0777,true);
518            return imagejpeg($image_new, $file_new , $qulitity);
519        }
520    }
521}
522
523function msubstr($str, $start=0, $length, $charset="utf-8", $suffix=true)
524{
525    if(function_exists("mb_substr")){
526        if ($suffix && strlen($str)>$length)
527        return mb_substr($str, $start, $length, $charset)."...";
528        else
529        return mb_substr($str, $start, $length, $charset);
530    }
531    elseif(function_exists('iconv_substr')) {
532        if ($suffix && strlen($str)>$length)
533        return iconv_substr($str,$start,$length,$charset)."...";
534        else
535        return iconv_substr($str,$start,$length,$charset);
536    }
537    $re['utf-8']   = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
538    $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
539    $re['gbk']    = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
540    $re['big5']   = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
541    preg_match_all($re[$charset], $str, $match);
542    $slice = join("",array_slice($match[0], $start, $length));
543    if($suffix) return $slice."";
544    return $slice;
545}
546?>