PHP项目怎么实现图片水印添加?

wen PHP项目 52

本文目录导读:

PHP项目怎么实现图片水印添加?

  1. 使用GD库(最常用,无需额外安装)
  2. 使用Imagick扩展(功能更强大,支持更多格式)
  3. 完整的水印类封装
  4. 配置检查
  5. 常见问题与优化建议

在PHP中实现图片水印添加,主要使用 GD库Imagick 扩展,以下是两种主流方法的详细实现方案:

使用GD库(最常用,无需额外安装)

文字水印

<?php
function addTextWatermark($sourcePath, $savePath, $text = 'Watermark') {
    // 获取原图信息
    list($width, $height, $type) = getimagesize($sourcePath);
    // 根据图片类型创建资源
    switch ($type) {
        case IMAGETYPE_JPEG:
            $image = imagecreatefromjpeg($sourcePath);
            break;
        case IMAGETYPE_PNG:
            $image = imagecreatefrompng($sourcePath);
            break;
        case IMAGETYPE_GIF:
            $image = imagecreatefromgif($sourcePath);
            break;
        default:
            return false;
    }
    // 设置水印颜色(白色半透明)
    $watermarkColor = imagecolorallocatealpha($image, 255, 255, 255, 50);
    // 设置字体文件路径
    $fontFile = './font/arial.ttf'; // 需要实际存在的字体文件
    // 文字大小
    $fontSize = 20;
    // 计算文字位置(右下角)
    $textBox = imagettfbbox($fontSize, 0, $fontFile, $text);
    $textWidth = $textBox[2] - $textBox[0];
    $textHeight = $textBox[1] - $textBox[7];
    $x = $width - $textWidth - 20;
    $y = $height - $textHeight - 20;
    // 添加水印
    imagettftext($image, $fontSize, 0, $x, $y, $watermarkColor, $fontFile, $text);
    // 保存图片
    switch ($type) {
        case IMAGETYPE_JPEG:
            imagejpeg($image, $savePath, 90);
            break;
        case IMAGETYPE_PNG:
            imagepng($image, $savePath);
            break;
        case IMAGETYPE_GIF:
            imagegif($image, $savePath);
            break;
    }
    // 释放内存
    imagedestroy($image);
    return true;
}
// 使用示例
addTextWatermark('original.jpg', 'watermarked.jpg', '© 2024 My Site');
?>

图片水印(添加Logo)

<?php
function addImageWatermark($sourcePath, $watermarkPath, $savePath, $position = 'bottom-right') {
    // 创建原图资源
    list($srcWidth, $srcHeight, $srcType) = getimagesize($sourcePath);
    switch ($srcType) {
        case IMAGETYPE_JPEG:
            $mainImg = imagecreatefromjpeg($sourcePath);
            break;
        case IMAGETYPE_PNG:
            $mainImg = imagecreatefrompng($sourcePath);
            break;
        case IMAGETYPE_GIF:
            $mainImg = imagecreatefromgif($sourcePath);
            break;
        default:
            return false;
    }
    // 创建水印资源
    list($wmWidth, $wmHeight, $wmType) = getimagesize($watermarkPath);
    switch ($wmType) {
        case IMAGETYPE_JPEG:
            $watermark = imagecreatefromjpeg($watermarkPath);
            break;
        case IMAGETYPE_PNG:
            $watermark = imagecreatefrompng($watermarkPath);
            break;
        case IMAGETYPE_GIF:
            $watermark = imagecreatefromgif($watermarkPath);
            break;
        default:
            return false;
    }
    // 计算位置
    $padding = 10;
    switch ($position) {
        case 'top-left':
            $x = $padding;
            $y = $padding;
            break;
        case 'top-right':
            $x = $srcWidth - $wmWidth - $padding;
            $y = $padding;
            break;
        case 'bottom-left':
            $x = $padding;
            $y = $srcHeight - $wmHeight - $padding;
            break;
        case 'bottom-right':
        default:
            $x = $srcWidth - $wmWidth - $padding;
            $y = $srcHeight - $wmHeight - $padding;
            break;
    }
    // 保持PNG透明度
    imagealphablending($mainImg, true);
    imagesavealpha($mainImg, true);
    // 合并图片
    imagecopy($mainImg, $watermark, $x, $y, 0, 0, $wmWidth, $wmHeight);
    // 保存
    switch ($srcType) {
        case IMAGETYPE_JPEG:
            imagejpeg($mainImg, $savePath, 90);
            break;
        case IMAGETYPE_PNG:
            imagepng($mainImg, $savePath);
            break;
        case IMAGETYPE_GIF:
            imagegif($mainImg, $savePath);
            break;
    }
    imagedestroy($mainImg);
    imagedestroy($watermark);
    return true;
}
// 使用示例
addImageWatermark('original.jpg', 'logo.png', 'watermarked.jpg', 'bottom-right');
?>

使用Imagick扩展(功能更强大,支持更多格式)

<?php
function addImagickWatermark($sourcePath, $savePath, $type = 'text', $content = 'Watermark') {
    $image = new Imagick($sourcePath);
    if ($type === 'text') {
        // 文字水印
        $draw = new ImagickDraw();
        $draw->setFillColor(new ImagickPixel('white'));
        $draw->setFontSize(30);
        $draw->setOpacity(0.5);
        $image->annotateImage($draw, 10, $image->getImageHeight() - 30, 0, $content);
    } else {
        // 图片水印
        $watermark = new Imagick($content);
        // 设置水印大小(可选)
        $watermark->scaleImage(100, 0); // 宽度100px,高度自动
        // 设置透明度
        $watermark->evaluateImage(Imagick::EVALUATE_MULTIPLY, 0.5, Imagick::CHANNEL_ALPHA);
        // 计算位置
        $x = $image->getImageWidth() - $watermark->getImageWidth() - 10;
        $y = $image->getImageHeight() - $watermark->getImageHeight() - 10;
        // 合并图片
        $image->compositeImage($watermark, Imagick::COMPOSITE_OVER, $x, $y);
        $watermark->destroy();
    }
    $image->writeImage($savePath);
    $image->destroy();
    return true;
}
// 使用示例
addImagickWatermark('original.jpg', 'watermarked.jpg', 'text', '© 2024');
// 或者
addImagickWatermark('original.jpg', 'watermarked.jpg', 'image', 'logo.png');
?>

完整的水印类封装

<?php
class Watermark {
    private $sourcePath;
    private $savePath;
    private $type; // gd or imagick
    public function __construct($sourcePath, $savePath = null) {
        $this->sourcePath = $sourcePath;
        $this->savePath = $savePath ?: $sourcePath;
        $this->type = extension_loaded('imagick') ? 'imagick' : 'gd';
    }
    public function addText($text, $options = []) {
        $defaults = [
            'fontSize' => 20,
            'color' => 'white',
            'opacity' => 50,
            'position' => 'bottom-right',
            'fontFile' => './font/arial.ttf'
        ];
        $options = array_merge($defaults, $options);
        if ($this->type === 'imagick') {
            return $this->addTextImagick($text, $options);
        } else {
            return $this->addTextGD($text, $options);
        }
    }
    public function addImage($watermarkPath, $options = []) {
        $defaults = [
            'position' => 'bottom-right',
            'opacity' => 80,
            'scale' => 0.3 // 水印缩放比例
        ];
        $options = array_merge($defaults, $options);
        if ($this->type === 'imagick') {
            return $this->addImageImagick($watermarkPath, $options);
        } else {
            return $this->addImageGD($watermarkPath, $options);
        }
    }
    // 私有方法实现细节...
}
?>

配置检查

<?php
// 检查GD库是否可用
if (function_exists('gd_info')) {
    echo "GD库已安装\n";
    print_r(gd_info());
}
// 检查Imagick是否可用
if (class_exists('Imagick')) {
    echo "Imagick已安装\n";
}
?>

常见问题与优化建议

注意事项:

  1. 字体文件:使用imagettftext()时需要提供TrueType字体文件路径
  2. 透明度:PNG水印需要保留透明度信息
  3. 性能优化
    • 使用缓存机制避免重复处理
    • 对于大图片考虑使用缩略图添加水印
    • 使用队列系统处理批量水印

最佳实践:

// 异步处理水印
class WatermarkJob {
    public function handle($imagePath) {
        // 使用队列处理大量图片
        $watermark = new Watermark($imagePath);
        $watermark->addText('© 2024');
    }
}
// 缓存水印处理结果
function getWatermarkedImage($sourcePath) {
    $cachePath = './cache/' . md5($sourcePath) . '.jpg';
    if (file_exists($cachePath)) {
        return $cachePath; // 返回缓存
    }
    // 生成水印
    $watermark = new Watermark($sourcePath, $cachePath);
    $watermark->addText('© 2024');
    return $cachePath;
}

推荐优先使用 GD库,因为它是PHP内置的,无需额外安装,如果项目需要处理大量图片或特殊格式,可以考虑使用 Imagick

抱歉,评论功能暂时关闭!