分享一個圖片處理類

發表於2019-05-11

<?php
/**
 * 影像處理類
 *
 * @author Carmen <e.carmen.hyc@gmail.com>
 * 
 *
 * 生成驗證碼:Image::verify(長度, 寬, 高)
 *
 * 加蓋圖片水印:Image::water(圖片路徑, 水印圖路徑, 儲存路徑)
 *
 * 加蓋文字水印:Image::text(圖片路徑, 文字內容, 儲存路徑)
 *
 * 生成縮圖:Image::thumb(圖片路徑, 寬, 高, 儲存路徑)
 *
 * ps:儲存路徑引數均為留空則替換原圖
 * 
 * 為了減少引數,部份配置項採用常量定義
 * 嵌入框架時,找到每個方法的初始處把常量替換成配置檔案項
 * 如 ThinkPHP 可採用 C() 函式代替常量定義
 */
 
/**********縮圖配置項**********/
//縮圖寬度
define('THUMB_WIDTH', 200);
//縮圖高度
define('THUMB_HEIGHT', 120);
 
Class Image {
 
    /**
     * 生成驗證碼
     * @param  [Integer] $length [驗證碼長度]
     * @param  [Integer] $width  [驗證碼寬度]
     * @param  [Integer] $height [驗證碼高度]
     * @return [boolean]
     */
    Static Public function verify ($length = NULL, $width = NULL, $height = NULL) {
 
        //環境檢測
        if (!self::checkCondition()) return false;
 
        //初始化引數(放進框架時把常量換成 讀取配置檔案項 )
        $length = empty($length) ? C('VERIFY_LENGTH') : $length;
        $width = empty($width) ? C('VERIFY_WIDTH') : $width;
        $height= empty($height) ? C('VERIFY_HEIGHT') : $height;
        $bgColor = C('VERIFY_BGCOLOR');
        $seed = C('VERIFY_SEED');
        $fontFile = C('VERIFY_FONTFILE');
        $size = C('VERIFY_SIZE');
        $fontColor = C('VERIFY_COLOR');
        $name = C('VERIFY_NAME');
        $fn = C('VERIFY_FUNC');
 
        //建立畫布影像
        $verify = imagecreatetruecolor($width, $height);
 
        //畫布背景色
        $rgb = self::colorTrans($bgColor);
        $color = imagecolorallocate($verify, $rgb['red'], $rgb['green'], $rgb['blue']);
        imagefill($verify, 0, 0, $color);
 
        //寫入背景干擾字型
        $len = strlen($seed) - 1;
        for ($i = 0; $i < 20; $i++) {
            $color = imagecolorallocate($verify, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
            imagestring($verify, 5, mt_rand(0, $width), mt_rand(0, $height), $seed[mt_rand(0, $len)], $color);
        }
 
        $rgb = self::colorTrans($fontColor);
        $fontColor = imagecolorallocate($verify, $rgb['red'], $rgb['green'], $rgb['blue']);
 
 
        //寫入驗證碼
        $code = '';
        $left = ($width - $size * $length) / 2;
        $y = $height - ($height - $size) / 2;
        for ($i = 0; $i < $length; $i++) {
            $font = $seed[mt_rand(0, $len)];
            $x = $size * $i + $left;
            imagettftext($verify, $size, mt_rand(-30, 30), $x, $y, $fontColor, $fontFile, $font);
            $code .= $font;
        }
        $_SESSION[$name] = $fn($code);
 
        //干擾線
        for ($i = 0, $h = $height / 2 - 2; $i < 5; $i++, $h++) {
            $color = imagecolorallocate($verify, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
            $cx = mt_rand(-10, $width + 10);
            $cy = mt_rand(-10, $height + 10);
            $cw = mt_rand(-10, $width + 10);
            $ch = mt_rand(-10, $height + 10);
            imageellipse($verify, $cx, $cy, $cw, $ch, $color);
            imageellipse($verify, $cx + 1, $cy + 1, $cw + 1, $ch + 1, $color);
 
            imageline($verify, 0, $h, $width, $h, $fontColor);
        }
 
        //輸入影像
        header('Content-type:image/png');
        imagepng($verify);
        imagedestroy($verify);
        return true;
    }
 
    /**
     * 加蓋圖片水印
     * @param  [String] $img   [圖片路徑]
     * @param  [String] $water [水印圖路徑]
     * @param  [String] $save  [儲存路徑|留空則替換原圖]
     * @return [Boolean]
     */
    Static Public function water ($img, $water = '', $save = NULL) {
        if (!self::checkCondition($img)) return false;
         
        //初始化引數(放進框架時把常量換成 讀取配置檔案項 )
        $water = empty($water) ? C('WATER_IMAGE') : $water;
        $pos = C('WATER_POS');
        $alpha = C('WATER_ALPHA');
        $compression = C('WATER_COMPRESSION');
 
        if (!file_exists($water)) return false;
 
        //原圖寬、高與型別
        $imgInfo = getimagesize($img);
        $imgW = $imgInfo[0];
        $imgH = $imgInfo[1];
        $imgT = self::getImageType($imgInfo[2]);
 
        //水印圖寬、高與型別
        $waterInfo = getimagesize($water);
        $waterW = $waterInfo[0];
        $waterH = $waterInfo[1];
        $waterT = self::getImageType($waterInfo[2]);
 
        //水印圖大於原圖時不作處理
        if ($imgW < $waterW || $imgH < $waterH) return false;
 
        //計算水印位置
        $pos = self::getPosition($imgW, $imgH, $waterW, $waterH, $pos);
        $x = $pos['x'];
        $y = $pos['y'];
 
        //開啟原圖資源
        $fn = 'imagecreatefrom' . $imgT;
        $image = $fn($img);
 
        //開啟水印圖資源
        $fn = 'imagecreatefrom' . $waterT;
        $water = $fn($water);
 
        //蓋上水印圖
        if ($waterT == 'png') {
            imagecopy($image, $water, $x, $y, 0, 0, $waterW, $waterH);
        } else {
            imagecopymerge($image, $water, $x, $y, 0, 0, $waterW, $waterH, $alpha);
        }
 
        //儲存路徑
        $save = self::savePath($save, $img);
        $fn = 'image' . $imgT;
        if ($imgT == 'jpeg') {
            $fn($image, $save, $compression);
        } else {
            $fn($image, $save);
        }
 
        //釋放資源
        imagedestroy($image);
        imagedestroy($water);
        return true;
    }
 
    /**
     * 加蓋文字水印
     * @param  [String] $img  [圖片路徑]
     * @param  [String] $text [文字內容]
     * @param  [String] $save [儲存路徑|留空則替換原圖]
     * @return [Boolean]
     */
    Static Public function text ($img, $text = '', $save = NULL) {
        if (!self::checkCondition($img)) return false;
 
        //初始化引數(放進框架時把常量換成 讀取配置檔案項 )
        $text = empty($text) ? WATER_TEXT : $text;
        $pos = WATER_POS;
        $angle = WATER_ANGLE;
        $fontSize = WATER_FONTSIZE;
        $fontColor = WATER_FONTCOLOR;
        $fontFile = WATER_FONTFILE;
        $charset = WATER_CHARSET;
        $compression = WATER_COMPRESSION;
 
        //文字水印寬、高
        $waterInfo = imagettfbbox($fontSize, $angle, $fontFile, $text);
        $waterW = $waterInfo[2] - $waterInfo[0];
        $waterH = $waterInfo[1] - $waterInfo[7];
 
        //原圖寬、高、型別
        $imgInfo = getimagesize($img);
        $imgW = $imgInfo[0];
        $imgH = $imgInfo[1];
        $type = self::getImageType($imgInfo[2]);
 
        //計算水印位置
        $pos = self::getPosition($imgW, $imgH, $waterW, $waterH, $pos);
        $x = $pos['x'];
        $y = $pos['y'] + $fontSize / 2;
 
        //開啟原圖資源
        $fn = 'imagecreatefrom' . $type;
        $image = $fn($img);
 
        //寫入水印文字
        $rgb = self::colorTrans($fontColor);
        $color = imagecolorallocate($image, $rgb['red'], $rgb['green'], $rgb['blue']);
        $text = iconv($charset, 'UTF-8', $text);
        imagettftext($image, $fontSize, $angle, $x, $y, $color, $fontFile, $text);
 
        //儲存路徑
        $save = self::savePath($save, $img);
        $fn = 'image' . $type;
        if ($type == 'jpeg') {
            $fn($image, $save, $compression);
        } else {
            $fn($image, $save);
        }
 
        //釋放資源
        imagedestroy($image);
        return true;
 
    }
 
    /**
     * 生成縮圖(等比例縮放)
     * @param  [String] $img    [圖片路徑]
     * @param  [String] $width  [縮略寬度]
     * @param  [String] $height [縮略高度]
     * @param  [String] $save   [儲存路徑|留空則替換原圖]
     * @return [Boolean]
     */
    Static Public function thumb ($img, $width = '', $height = '', $save = NULL) {
        if (!self::checkCondition($img)) return false;
 
        //初始化引數(放進框架時把常量換成 讀取配置檔案項 )
        $width = empty($width) ? THUMB_WIDTH : $width;
        $height = empty($height) ? THUMB_HEIGHT : $height;
 
        //原圖寬、高、型別
        $imgInfo = getimagesize($img);
        $imgW = $imgInfo[0];
        $imgH = $imgInfo[1];
        $type = self::getImageType($imgInfo[2]);
 
        //縮放比
        $ratio = max($width / $imgW, $height / $imgH);
        //縮圖大於原圖不作處理
        if ($ratio >= 1) return false;
 
        //等比例縮放後寬、高
        $width = floor($imgW * $ratio);
        $height = floor($imgH * $ratio);
 
        //建立縮圖畫布
        if ($type == 'gif') {
            $thumb = imagecreate($width, $height);
            $color = imagecolorallocate($thumb, 0, 255, 0);
        } else {
            $thumb = imagecreatetruecolor($width, $height);
            //PNG圖片透明處理
            if ($type == 'png') {
                //關閉混色模式
                imagealphablending($thumb, false);
                //儲存透明通道
                imagesavealpha($thumb, true);
            }
        }
 
        //開啟原圖資源
        $fn = 'imagecreatefrom' . $type;
        $image = $fn($img);
 
        //原圖移至縮圖畫布並調整大小
        if (function_exists('imagecopyresampled')) {
            imagecopyresampled($thumb, $image, 0, 0, 0, 0, $width, $height, $imgW, $imgH);
        } else {
            imagecopyresized($thumb, $image, 0, 0, 0, 0, $width, $height, $imgW, $imgH);
        }
 
        //GIF圖透明處理
        if ($type == 'gif') imagecolortransparent($thumb, $color);
 
        //儲存路徑
        $save = self::savePath($save, $img);
        $fn = 'image' . $type;
        $fn($thumb, $save);
 
        //釋放資源
        imagedestroy($image);
        imagedestroy($thumb);
        return true;
 
    }
 
    /**
     * 圖片儲存路徑
     * @param  [String] $save [儲存路徑]
     * @param  [String] $img  [原圖路徑]
     * @return [String]
     */
    Static Private function savePath ($save, $img) {
        if (!$save) return $img;
 
        $pathInfo = pathinfo($img);
        $path = rtrim($save, '/') . '/';
        is_dir($path) || mkdir($path, 0777, true);
        return $path . time() . mt_rand(1000, 9999) . '.' . $pathInfo['extension'];
    }
 
    /**
     * 計算水印圖位置
     * @param  [Integer] $IW  [原圖寬]
     * @param  [Integer] $IH  [原圖高]
     * @param  [Integer] $WW  [水印寬]
     * @param  [Integer] $WH  [水印高]
     * @param  [Integer] $pos [九宮格位置]
     * @return [Array]      [x, y]
     */
    Static Private function getPosition ($IW, $IH, $WW, $WH, $pos) {
        $x = 20;
        $y = 20;
        switch ($pos) {
            case 1 : 
                break;
 
            case 2 :
                $x = ($IW - $WW) / 2;
                break;
 
            case 3 :
                $x = $IW - $WW - 20;
                break;
 
            case 4 :
                $y = ($IH - $WH) / 2;
                break;
 
            case 5 :
                $x = ($IW - $WW) / 2;
                $y = ($IH - $WH) / 2;
                break;
 
            case 6 :
                $x = $IW - $WW - 20;
                $y = ($IH - $WH) / 2;
                break;
 
            case 7 :
                $y = $IH - $WH - 20;
                break;
 
            case 8 :
                $x = ($IW - $WW) / 2;
                $y = $IH - $WH - 20;
                break;
 
            case 9 :
                $x = $IW - $WW - 20;
                $y = $IH - $WH - 20;
                break;
 
            default :
                $x = mt_rand(0, $IW - $WW);
                $y = mt_rand(0, $IH - $WH);
        }
 
        return array('x' => $x, 'y' => $y);
    }
 
    /**
     * 圖片型別
     * @param  [Integer] $typeNum [型別識別號]
     * @return [String]
     */
    Static Private function getImageType ($typeNum) {
        switch($typeNum) {
            case 1 : 
                return 'gif';
            case 2 :
                return 'jpeg';
            case 3 :
                return 'png';
        }
    }
 
    /**
     * 16進位制色值轉換為RGB
     * @param  [Sting] $color [16進位制色值]
     * @return [Array]        [red, green, blue]
     */
    Static Private function colorTrans($color) {
        $color = ltrim($color, '#');
        return array(
            'red' => hexdec($color[0] . $color[1]),
            'green' => hexdec($color[2] . $color[3]),
            'blue' => hexdec($color[4] . $color[5])
            );
    }
 
    /**
     * 影像處理環境檢測
     * @return boolean
     */
    Static Private function checkCondition ($file = NULL) {
        return is_null($file) ? extension_loaded('GD') && function_exists('imagecreatetruecolor') && function_exists('imagepng') : extension_loaded('GD') && file_exists($file);
    }
}
?>
評論(2)

相關文章