美文网首页
原生PHP使用GD库压缩图片及增加水印

原生PHP使用GD库压缩图片及增加水印

作者: 码农工号9527 | 来源:发表于2021-09-15 15:40 被阅读0次

压缩图片

本文参考源自博主: 前端萌新&初级后端攻城狮 的文章,灰常感谢,亲测可用

图片压缩其实很多场景都会用得上, 著名的有 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));
}

增加水印:

/**
 * @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));
}

相关文章

网友评论

      本文标题:原生PHP使用GD库压缩图片及增加水印

      本文链接:https://www.haomeiwen.com/subject/gyakgltx.html