🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# GD 图像操作 图片缩略、文字水印和图片水印实现,以及验证码实现。 ``` <?php /** * 图片缩略 * * @param string $file_name 文件名 * @param string $dst_path 缩略图保存路径 * @param string $prefix 缩略图保存的前缀 * @param null $dst_w 目标的最大宽度 * @param null $dst_h 目标的最大高度 * @param float $scale 缩放比例 * @param bool $delete_source 是否删除源文件的标志 */ function thumb_image($file_name, $dst_path = 'thumb', $prefix = 'thumb_', $dst_w = null, $dst_h = null, $scale = 0.5, $delete_source = false) { $file_info = getImageInfo($file_name); $src_w = $file_info['width']; $src_h = $file_info['height']; // 如果指定最大宽度和高度按照等比例缩放进行处理 if (is_numeric($dst_w) && is_numeric($dst_h)) { $ratio_orig = $src_w / $src_h; if ($dst_w / $dst_h > $ratio_orig) { $dst_w = $dst_h * $ratio_orig; } else { $dst_h = $dst_w / $ratio_orig; } } else { $dst_w = ceil($src_w * $scale); $dst_h = ceil($src_h * $scale); } $dst_image = imagecreatetruecolor($dst_w, $dst_h); $src_image = $file_info['create_fun']($file_name); imagecopyresampled($dst_image, $src_image, 0, 0, 0, 0, $dst_w, $dst_h, $src_w, $src_h); // 检测目标目录是否存在 if ($dst_path && !file_exists($dst_path)) { mkdir($dst_path, 0777, true); } $dst_name = "{$prefix}{$file_info['file_name']}" . $file_info['extension']; $destination = $dst_path ? $dst_path . '/' . $dst_name : $dst_name; // 保存的文件名 $file_info['out_fun']($dst_image, $destination); if ($delete_source) { @unlink($file_name); } imagedestroy($src_image); imagedestroy($dst_image); } /** * 文字水印函数 * * @param string $file_name 文件名 * @param string $font_file 字体文件 * @param string $text 水印文字 * @param string $dest_path 水印保存地址 * @param string $prefix 保存文件前缀 * @param int $r 水印颜色 Red * @param int $g 水印颜色 Green * @param int $b 水印颜色 Blue * @param int $alpha 水印颜色 Alpha * @param int $angle 水印角度 * @param int $x 水印所在图片 x 位置 * @param int $y 水印所在图片 y 位置 * @param int $size 水印文字大小 * @param bool $delete_source 是否删除源文件 * @return string */ function water_text($file_name, $font_file, $text = 'webfad', $dest_path = 'watertext', $prefix = 'watertext_', $r = 255, $g = 0, $b = 0, $alpha = 80, $angle = 0, $x = 0, $y = 30, $size = 30, $delete_source = false) { $file_info = getImageInfo($file_name); $image = $file_info['create_fun']($file_name); $color = imagecolorallocatealpha($image, $r, $g, $b, $alpha); imagettftext($image, $size, $angle, $x, $y, $color, $font_file, $text); if ($dest_path && !(file_exists($dest_path))) { mkdir($dest_path, 0777, true); } $dest_name = "{$prefix}{$file_info['file_name']}" . $file_info['extension']; $destination = $dest_path ? $dest_path . "/" . $dest_name : $dest_name; $file_info['out_fun']($image, $destination); if ($delete_source) { @unlink($file_name); } imagedestroy($image); return $destination; } /** * 图片水印函数 * * @param string $dst_name 目标地址文件名 * @param string $src_name 水印图片地址文件名 * @param integer $position 水印位置 0:左上 1:中上 2:右上 3:左中 4:中中 5:右中 6:左下 7:中下 8:右下 * @param string $dest_path 目标文件位置 * @param string $prefix 文件保存前缀 * @param int $pct 水印图片融合度 * @param bool $delete_source 是否删除源文件 * @return string */ function water_image($dst_name, $src_name, $position, $dest_path = 'water_image', $prefix = 'water_image_', $pct = 60, $delete_source = false) { $dst_info = getImageInfo($dst_name); $src_info = getImageInfo($src_name); $dst_image = $dst_info['create_fun']($dst_name); $src_image = $src_info['create_fun']($src_name); $dst_width = $dst_info['width']; $dst_height = $dst_info['height']; $src_width = $src_info['width']; $src_height = $src_info['height']; switch ($position) { case 0 : $x = 0; $y = 0; break; case 1: $x = ($dst_width - $src_width) / 2; $y = 0; break; case 2: $x = $dst_width - $src_width; $y = 0; break; case 3: $x = 0; $y = ($dst_height - $src_height) / 2; break; case 4: $x = ($dst_width - $src_width) / 2; $y = ($dst_height - $src_height) / 2; break; case 5: $x = $dst_width - $src_width; $y = ($dst_height - $src_height) / 2; break; case 6: $x = 0; $y = $dst_height - $src_height; break; case 7: $x = ($dst_width - $src_width) / 2; $y = $dst_height - $src_height; break; case 8: $x = $dst_width - $src_width; $y = $dst_height - $src_height; break; default: $x = 0; $y = 0; break; } imagecopymerge($dst_image, $src_image, $x, $y, 0, 0, $src_width, $src_height, $pct); if ($dest_path && !(file_exists($dest_path))) { mkdir($dest_path, 0777, true); } $dest_name = "{$prefix}{$src_info['file_name']}" . $dst_info['extension']; $destination = $dest_path ? $dest_path . "/" . $dest_name : $dest_name; $dst_info['out_fun']($dst_image, $destination); if ($delete_source) { @unlink($dst_name); } return $destination; } /** * @param $filename string 文件名 * @return array */ function getImageInfo($filename) { if (!$info = getimagesize($filename)) { exit('文件不是真实图片!'); } $file_info['file_name'] = pathinfo($filename)['filename']; $file_info['width'] = $info[0]; $file_info['height'] = $info[1]; $mime = image_type_to_mime_type($info[2]); $file_info['extension'] = image_type_to_extension($info[2], true); $file_info['create_fun'] = str_replace('/', 'createfrom', $mime); $file_info['out_fun'] = str_replace('/', '', $mime); return $file_info; } ?> ``` ## 验证码 ``` <?php // 验证码 class Verify { protected $_font_file; // 字体文件 protected $_width = 120; // 画布宽度 protected $_height = 60; // 画布高度 protected $_size = 20; // 字体大小 protected $_length = 4; // 验证码长度 protected $_snow = 0; // 干扰元素雪花个数 protected $_pixel = 0; // 干扰元素像素个数 protected $_line = 0; // 干扰元素线段个数 private $_image = null; // 画布资源 /** * Verify constructor. * @param array $config */ public function __construct($config = []) { if (is_array($config) && !empty($config)) { // 检测字体文件是否存在并且可读 if ($config['font_file'] && is_file($config['font_file']) && is_readable($config['font_file'])) { $this->_font_file = $config['font_file']; } } else { return false; } // 检测画布宽 if (isset($config['width']) && (int)$config['width'] > 0) { $this->_width = (int)$config['width']; } // 检测画布高 if (isset($config['height']) && (int)$config['height'] > 0) { $this->_height = (int)$config['height']; } // 检测字体大小 if (isset($config['size']) && (int)$config['size'] > 0) { $this->_size = (int)$config['size']; } // 验证码长度 if (isset($config['length']) && (int)$config['length'] > 0) { $this->_length = (int)$config['length']; } // 干扰元素像素 if (isset($config['pixel']) && (int)$config['pixel'] > 0) { $this->_pixel = (int)$config['pixel']; } // 干扰元素线段 if (isset($config['line']) && (int)$config['line'] > 0) { $this->_line = (int)$config['line']; } // 干扰元素雪花 if (isset($config['snow']) && (int)$config['snow'] > 0) { $this->_snow = (int)$config['snow']; } // 图片资源 $this->_image = imagecreatetruecolor($this->_width, $this->_height); return $this->_image; } public function getVerify() { $white = imagecolorallocate($this->_image, 255, 255, 255); imagefilledrectangle($this->_image, 0, 0, $this->_width, $this->_height, $white); // 填充矩形 $string = $this->_generateStr($this->_length); if ($string == false) { return false; } // 绘制验证码 for ($i = 0; $i < $this->_length; $i++) { $x = ceil($this->_width / $this->_length) * $i + mt_rand(5, 10); $y = ceil($this->_height / 1.5); imagettftext($this->_image, $this->_size, mt_rand(-30, 30), $x, $y, $this->_getRandColor(), $this->_font_file, mb_substr($string, $i, 1, 'utf-8')); } // 干扰元素 if ($this->_snow) { $this->_getSnow(); } else { if ($this->_pixel) { $this->_getPixel(); } if ($this->_line) { $this->_getLine(); } } // 输出图像 header('content-type: image/jpeg'); imagejpeg($this->_image); return $string; // 返回验证码字符串 } /** * 生成随机字符串 * * @param $len string 字符长度 * @return bool|string */ private function _generateStr($len) { if ($len < 1 || $len >= 30) { return false; } $chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'X', 'Y', 'Z', 1, 2, 3, 4, 5, 6, 7, 8, 9]; return implode('', array_rand(array_flip($chars), $len)); } /** * 生成随机颜色 * * @return int */ private function _getRandColor() { return imagecolorallocate($this->_image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255)); } /** * 绘制雪花作为干扰元素 */ private function _getSnow() { for ($i = 1; $i <= $this->_snow; $i++) { imagestring($this->_image, mt_rand(1, 5), mt_rand(0, $this->_width), mt_rand(0, $this->_height), '*', $this->_getRandColor()); } } /** * 绘制相像素作为干扰元素 */ private function _getPixel() { for ($i = 1; $i < $this->_pixel; $i++) { imagesetpixel($this->_image, mt_rand(0, $this->_width), mt_rand(0, $this->_height), $this->_getRandColor()); } } /** * 绘制线段作为干扰元素 */ private function _getLine() { for ($i = 1; $i < $this->_pixel; $i++) { imageline($this->_image, mt_rand(0, $this->_width), mt_rand(0, $this->_height), mt_rand(0, $this->_width), mt_rand(0, $this->_height), $this->_getRandColor()); } } /** * 析构函数 销毁画布 */ public function __destruct() { imagedestroy($this->_image); } } $config = [ 'font_file' => './fonts/PingFang.ttc', 'pixel' => 50, ]; $verify = new Verify($config); $verify_code = $verify->getVerify(); ?> ```