2020-08-06 18:28:00
围观(3691)
压缩图片
图片压缩其实很多场景都会用得上, 著名的有 tinypng 压缩服务.
博主之前也经常用 tinypng 但是感觉有点限制.
所以试着用 GD 库简单实现一下压缩图片, 当然这样的压缩是有损的.
直接上博主已经写好的代码:
/** * @param $params * ['photo'] // 图片地址 * ['quality'] // 图片压缩后的质量 值范围: 1 - 75 默认值 50 * ['like_width'] // 偏好宽度, 如果图片宽度大于该宽度值 会自动压缩为该宽度的数字大小 默认为 900PX * ['cover'] // 是否覆盖原图 0为不覆盖 1为覆盖 * @return false|string */ function compressPicture($params) { $gd_info = gd_info(); if (empty($gd_info['GD Version'])) exit('请安装GD库'); if (empty($params['photo'])) exit('请输入图片地址'); if (!file_exists($params['photo'])) exit('图片文件不存在'); $quality = $params['quality'] ?? 50; if ($quality < 1 || $quality > 75) exit('压缩质量错误'); $like_width = $params['like_width'] ?? 900; // 获取图片信息(高度和宽度) $photo_file = file_get_contents($params['photo']); $photo_size = getimagesizefromstring($photo_file); $photo_width = $photo_size[0]; $photo_height = $photo_size[1]; $new_width = $photo_width; $new_height = $photo_height; // 使用原图创建新画布 switch ($photo_size['mime']){ case 'image/jpeg': $image = imagecreatefromjpeg($params['photo']); break; case 'image/gif': $image = imagecreatefromgif($params['photo']); break; case 'image/png': $image = imagecreatefrompng($params['photo']); break; } if (!isset($image)) exit('请上传图片或图片格式错误'); if ($photo_width > $like_width) { // 裁剪图片尺寸 $new_width = $like_width; $proportion = $like_width / $photo_width; $new_height = $proportion * $photo_height; } $new_image = imagecreatetruecolor($new_width, $new_height); if ($photo_size['mime'] == 'image/png') { // 解决 PNG 格式图片透明背景 $color = imagecolorallocate($new_image,255,255,255); // 为一幅图像分配颜色 imagecolortransparent($new_image, $color); // 设置透明 imagealphablending($new_image, false); // 设定图像的混色模式 imagesavealpha($new_image, true); // 设置标记以在保存 PNG 图像时保存完整的 alpha 通道信息 } imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $photo_width, $photo_height); $ext = pathinfo($params['photo'],PATHINFO_EXTENSION); $new_photo_name = md5(time() . mt_rand(1000, 9999)) . '.' . $ext; if (!empty($params['cover'])) { // 覆盖原图 $new_photo_name = $params['photo']; } switch ($photo_size['mime']){ case 'image/jpeg': imagejpeg($new_image, $new_photo_name, $quality); break; case 'image/gif': imagegif($new_image, $new_photo_name); break; case 'image/png': imagepng($new_image, $new_photo_name); break; } // 销毁资源 imagedestroy($image); imagedestroy($new_image); return json_encode([ 'code' => 0, 'url' => $new_photo_name, ]); }
可以在方法外面增加一个判断:
if ($_GET['action'] == 'compress_picture') { // 图片压缩 exit(compressPicture($_GET)); }
接着可以用 Postman 或者浏览器直接请求测试. 博主用了一张 3M 左右的 JPG 格式图片进行测试:
进行请求压缩:
此时再查看该图片的大小:
增加水印
博主写的方法:
/** * @param $params * * 水印所需参数: * ['photo'] // 图片地址 * ['content'] // 水印内容(如果是文字水印 则直接传文字内容 如果是图片水印 传图片路径) * ['x'] // 水印所在位置的 X 轴坐标 * ['y'] // 水印所在位置的 Y 轴坐标 * ['type'] // 1图片水印 2文字水印 * ['cover'] // 是否覆盖原图 0为不覆盖 1为覆盖 * * @return false|string */ function addWatermark($params) { $gd_info = gd_info(); if (empty($gd_info['GD Version'])) exit('请安装GD库'); if (empty($params['photo'])) exit('请输入图片地址'); if (!file_exists($params['photo'])) exit('图片文件不存在'); if(empty($params['content'])) exit('缺少水印内容'); $x = 10; $y = 30; if (!empty($params['x']) && is_numeric($params['x'])) $x = $params['x']; if (!empty($params['y']) && is_numeric($params['y'])) $y = $params['y']; // 获取图片信息(高度和宽度) $photo_file = file_get_contents($params['photo']); $photo_size = getimagesizefromstring($photo_file); $photo_width = $photo_size[0]; $photo_height = $photo_size[1]; // 使用原图创建新画布 switch ($photo_size['mime']){ case 'image/jpeg': $image = imagecreatefromjpeg($params['photo']); break; case 'image/gif': $image = imagecreatefromgif($params['photo']); break; case 'image/png': $image = imagecreatefrompng($params['photo']); break; } if (!isset($image)) exit('请上传图片或图片格式错误'); $new_image = imagecreatetruecolor($photo_width, $photo_height); if ($photo_size['mime'] == 'image/png') { // 解决 PNG 格式图片透明背景 $color = imagecolorallocate($new_image,255,255,255); // 为一幅图像分配颜色 imagecolortransparent($new_image, $color); // 设置透明 imagealphablending($new_image, false); // 设定图像的混色模式 imagesavealpha($new_image, true); // 设置标记以在保存 PNG 图像时保存完整的 alpha 通道信息 } imagecopyresampled( $new_image, $image, 0, 0, 0, 0, $photo_width, $photo_height, $photo_width, $photo_height ); // 增加图片水印 if ($params['type'] == 1) { $watermark_info = getimagesize($params['content']); // 获取水印图片的类型 $watermark_type = image_type_to_extension($watermark_info[2], false); // 在内存创建图像 $watermark_create_image_function = "imagecreatefrom{$watermark_type}"; // 把水印图片复制到内存中 $watermark = $watermark_create_image_function($params['content']); // 特别处理设置透明 // $color = imagecolorallocate($watermark, 255, 255, 255); // imagefill($watermark, 0, 0, $color); // imagecolortransparent($watermark, $color); // 合并图片 imagecopymerge($new_image, $watermark, $x, $y, 0, 0, $watermark_info[0], $watermark_info[1], 100); } // 增加文字水印 if ($params['type'] == 2) { // 字体颜色默认值 $red = $params['red'] ?? 255; $green = $params['green'] ?? 255; $blue = $params['blue'] ?? 255; $alpha = $params['alpha'] ?? 0; if (!is_numeric($red) || !is_numeric($green) || !is_numeric($blue) || !is_numeric($alpha)) exit('字体颜色错误'); $color = imagecolorallocatealpha($new_image, $red, $green, $blue, $alpha); // 设置字体颜色和透明度 // 字体大小 $font_size = $params['font_size'] ?? 30; $font_path = __DIR__ . '/wen.ttf'; // 写入文字 imagettftext($new_image, $font_size, 0, $x, $y, $color, $font_path, $params['content']); } $ext = pathinfo($params['photo'],PATHINFO_EXTENSION); $new_photo_name = md5(time() . mt_rand(1000, 9999)) . '.' . $ext; if (!empty($params['cover'])) { // 覆盖原图 $new_photo_name = $params['photo']; } switch ($photo_size['mime']){ case 'image/jpeg': imagejpeg($new_image, $new_photo_name); break; case 'image/gif': imagegif($new_image, $new_photo_name); break; case 'image/png': imagepng($new_image, $new_photo_name); break; } // 销毁资源 imagedestroy($image); imagedestroy($new_image); return json_encode([ 'code' => 0, 'url' => $new_photo_name, ]); }
在方法外面继续增加一个判断:
if ($_GET['action'] == 'add_watermark') { // 图片加水印 exit(addWatermark($_GET)); }
文字水印测试:
加上水印后的效果:
图片水印测试:
加上水印后的效果:
注意
如果认真查看本文的代码, 可以看到两个方法里面重复的代码是可以优化的, 特别是两个方法的开头, 具体优化博主就不写了.
还有就是方法里面用了很多判断并 exit 结束运行, 如果是想要弄得更完善, 可以修改为返回 JSON.
关于文字水印的字体, 博主用的是站酷的免费字体, 看介绍是可以免费商用的.
站酷的字体: www.zcool.com.cn/special/zcoolfonts
本文地址 : bubaijun.com/page.php?id=204
版权声明 : 未经允许禁止转载!
上一篇文章: PHP获取指定日期的开始及结束时间
下一篇文章: Laravel实现RBAC权限管理