【PHP】自有图片服务器,图片动态裁剪缩放
本文链接:https://www.cnblogs.com/tujia/p/14677098.html
背景:
1)几年前的PHP老项目,没用使用OSS来保存图片,而是用了一台独立的服务器来放图片。
2)但因为后台没有限制图片上传的大小,经营人员也没有手动裁剪图片,导致图片的尺寸很大,前端加载很慢,影响用户体验,也浪费带宽。
3)所以,我想着能不能改造一下图片服务器,像阿里云OSS那样,显示的时候,在url增加一个参数,就能动态裁剪(缩放)输出。
一、闲话少说,直接上代码吧(图片服务器根目录增加一个 crop.php 文件)
/** * @Author Tiac * @DateTime 2021-04-16 * @Description 图片裁剪 * @see https://www.cnblogs.com/tujia/p/14677098.html */ error_reporting(E_ALL); ini_set('display_errors', 'On'); define('ROOT', str_replace('\\', '/', __DIR__)); $img = isset($_GET['img'])? trim($_GET['img']):''; $debug = isset($_GET['debug'])? intval($_GET['debug']):0; // 2022.01.05 兼容 阿里云 oss 参数 list($w, $h, $wm) = array(0, 0, ''); $ossString = isset($_GET['x-oss-process'])? $_GET['x-oss-process']:''; if ($ossString == '') { $w = isset($_GET['w'])? intval($_GET['w']):0; $h = isset($_GET['h'])? intval($_GET['h']):0; $wm = isset($_GET['wm'])? $_GET['wm']:''; } elseif (strpos($ossString, 'image/resize') !== false) { $process = explode(',', $ossString); $process = array_reduce($process, function($carry, $item){ if (strrpos($item, '_') > 0) { list($k, $v) = explode('_', $item); $carry[$k] = $v; } return $carry; }); $w = isset($process['w'])? intval($process['w']):0; $h = isset($process['h'])? intval($process['h']):0; } if (empty($img) || !file_exists(ROOT . $img)) { header('HTTP/1.1 404 Not Found'); header("status: 404 Not Found"); exit; } $src = ROOT . $img; // CDN缓存 header('Cache-Control: max-age=604800'); if (function_exists('mime_content_type')) { $mime = mime_content_type($src); } elseif (function_exists('finfo_open')) { $finfo = finfo_open(FILEINFO_MIME); $info = finfo_file($finfo, $src); finfo_close($finfo); list($mime, $charset) = explode('; ', $info); } else { $parts = pathinfo($src); $extension = strtolower($parts['extension']); $mime = 'image/' . ($extension=='jpg'?'jpeg':$extension); } if ($debug == 0) { header('Content-Type: ' . $mime); } // 没设置宽高的,直接输出 if ($w == 0 && $h == 0 && $wm == '') { echo file_get_contents($src); exit; } switch($mime) { case 'image/jpeg': $img_r = @imagecreatefromjpeg($src); break; case 'image/png': $img_r = @imagecreatefrompng($src); break; case 'image/gif': $img_r = @imagecreatefromgif($src); break; case 'image/webp': $img_r = @imagecreatefromwbmp($src); break; } if ($img_r === false) { $mime = 'image/jpeg'; $img_r = @imagecreatefromjpeg($src); } if ($debug == 1) { var_dump($img_r);exit; } // 水印 if (strpos($wm, '_') !== false) { list($wm_x, $wm_y) = explode('_', $wm); list($wm_w, $wm_h, $wm_type, $wm_attr) = getimagesize('wm.png'); $wm = imagecreatefrompng('wm.png'); imagecopy($img_r, $wm, $wm_x, $wm_y, 0, 0, $wm_w, $wm_h); } list($width, $height, $type, $attr) = getimagesize($src); if ($w > 0 && $h > 0) { $minw = intval($width / $height * $h); $minh = intval($height / $width * $w); $w > $minw && $w = $minw; $h > $minh && $h = $minh; } elseif ($w < 0 || $h < 0) { $width += $w; $height += $h; $w = $width; $h = $height; } else { $w == 0 && $w = intval($width / $height * $h); $h == 0 && $h = intval($height / $width * $w); } if ($w > 0 && $h > 0) { $dst_r = ImageCreateTrueColor($w, $h); if (in_array($mime, ['image/png', 'image/gif'])) { $color = imagecolorallocate($dst_r, 255, 255, 255); // imagecolortransparent($dst_r, $color); imagefill($dst_r, 0, 0, $color); } $result = imagecopyresampled( $dst_r, $img_r, 0, 0, 0, 0, $w, $h, $width, $height ); if ($result !== true) { die('wrong.'); } } else { $dst_r = $img_r; } switch($mime) { case 'image/jpeg': imagejpeg($dst_r, null, 100); break; case 'image/png': imagepng($dst_r); break; case 'image/gif': imagegif($dst_r); break; case 'image/webp': imagewebp($dst_r); break; }
注:
1)创建好crop.php之后,就可以直接用 https://img.xxx.com/crop.php?img=/article/202103/31/161717171088039.jpg&w=500 这种url形式来动态缩放图片了;
2)但为了美观及小改动原代码,还需要增加一个rewrite规则;
3)服务器记得要打开 php_fileinfo 扩展;
4)2022.01.05 兼容 阿里云 oss 参数。
二、增加一个 nginx rewrite 规则
if ($query_string ~ [wh]=\d+) { rewrite ^([^\?]+)(.*) /crop.php?img=$1 last; }
注:这里是判断query_string里有 w= 或 h= 关键字时才重写url,如果你的图片服务器url有冲突,那这个if条件你得改改。
三、最终url示例
https://img.xxx.com/article/202103/31/161717171088039.jpg?w=200&h=200
https://img.xxx.com/article/202103/31/161717171088039.jpg?w=500
https://img.xxx.com/article/202103/31/161717171088039.jpg?h=200
https://img.xxx.com/article/202103/31/161717171088039.jpg?x-oss-process=image/resize,w_200
https://img.xxx.com/article/202103/31/161717171088039.jpg?x-oss-process=image/resize,h_200
注:我只弄了等比例缩放,所以同时填了w和h参数时,会自动约束计算最小的宽和高,等比例缩放;如果想要强制拉抻图片效果的,改一下代码就可以了
本文链接:https://www.cnblogs.com/tujia/p/14677098.html
完。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步