引言

环境准备

首先,确保你的PHP环境已经安装了GD库。GD库是一个开源的图像处理库,支持多种图像格式,包括JPEG、PNG和GIF。你可以通过以下命令检查GD库是否已安装:

php -m | grep gd

如果未安装,可以通过以下命令进行安装(以Ubuntu为例):

sudo apt-get install php-gd
sudo service apache2 restart

基础知识

在开始编写代码之前,了解一些基础的图像处理函数是很有帮助的:

  • imagecreatefromjpeg(): 从JPEG文件创建图像资源。
  • imagecreatefrompng(): 从PNG文件创建图像资源。
  • imagecreatefromgif(): 从GIF文件创建图像资源。
  • imagecolorallocate(): 分配颜色。
  • imagettftext(): 用TrueType字体向图像写入文本。
  • imagecopy(): 复制图像的一部分。

实现文字水印

步骤一:封装文字水印类

首先,我们定义一个类FontWatermark来封装文字水印的相关操作。

class FontWatermark {
    private $image;
    private $fontFile;
    private $fontSize;
    private $fontColor;
    private $position;

    public function __construct($imagePath, $fontFile, $fontSize, $fontColor, $position) {
        $this->image = $this->createImage($imagePath);
        $this->fontFile = $fontFile;
        $this->fontSize = $fontSize;
        $this->fontColor = $this->allocateColor($fontColor);
        $this->position = $position;
    }

    private function createImage($imagePath) {
        $type = exif_imagetype($imagePath);
        switch ($type) {
            case IMAGETYPE_JPEG:
                return imagecreatefromjpeg($imagePath);
            case IMAGETYPE_PNG:
                return imagecreatefrompng($imagePath);
            case IMAGETYPE_GIF:
                return imagecreatefromgif($imagePath);
            default:
                throw new Exception("Unsupported image type");
        }
    }

    private function allocateColor($color) {
        return imagecolorallocate($this->image, $color[0], $color[1], $color[2]);
    }

    public function addTextWatermark($text) {
        $textBox = imagettfbbox($this->fontSize, 0, $this->fontFile, $text);
        $textWidth = $textBox[2] - $textBox[0];
        $textHeight = $textBox[7] - $textBox[1];

        $x = $this->position['x'] - ($textWidth / 2);
        $y = $this->position['y'] - ($textHeight / 2);

        imagettftext($this->image, $this->fontSize, 0, $x, $y, $this->fontColor, $this->fontFile, $text);
    }

    public function saveImage($outputPath) {
        $type = exif_imagetype($outputPath);
        switch ($type) {
            case IMAGETYPE_JPEG:
                imagejpeg($this->image, $outputPath);
                break;
            case IMAGETYPE_PNG:
                imagepng($this->image, $outputPath);
                break;
            case IMAGETYPE_GIF:
                imagegif($this->image, $outputPath);
                break;
        }
        imagedestroy($this->image);
    }
}

步骤二:使用文字水印类

$imagePath = 'path/to/your/image.jpg';
$fontFile = 'path/to/your/font.ttf';
$fontSize = 20;
$fontColor = [255, 255, 255]; // 白色
$position = ['x' => 100, 'y' => 100]; // 水印位置

$watermark = new FontWatermark($imagePath, $fontFile, $fontSize, $fontColor, $position);
$watermark->addTextWatermark('Your Text Here');
$watermark->saveImage('path/to/output/image.jpg');

实现图片水印

步骤一:封装图片水印类

class WatermarkImage {
    private $sourceImage;
    private $watermarkImage;
    private $position;

    public function __construct($sourcePath, $watermarkPath, $position) {
        $this->sourceImage = $this->createImage($sourcePath);
        $this->watermarkImage = $this->createImage($watermarkPath);
        $this->position = $position;
    }

    private function createImage($imagePath) {
        $type = exif_imagetype($imagePath);
        switch ($type) {
            case IMAGETYPE_JPEG:
                return imagecreatefromjpeg($imagePath);
            case IMAGETYPE_PNG:
                return imagecreatefrompng($imagePath);
            case IMAGETYPE_GIF:
                return imagecreatefromgif($imagePath);
            default:
                throw new Exception("Unsupported image type");
        }
    }

    public function addImageWatermark() {
        $sourceWidth = imagesx($this->sourceImage);
        $sourceHeight = imagesy($this->sourceImage);
        $watermarkWidth = imagesx($this->watermarkImage);
        $watermarkHeight = imagesy($this->watermarkImage);

        $x = $this->position['x'];
        $y = $this->position['y'];

        imagecopy($this->sourceImage, $this->watermarkImage, $x, $y, 0, 0, $watermarkWidth, $watermarkHeight);
    }

    public function saveImage($outputPath) {
        $type = exif_imagetype($outputPath);
        switch ($type) {
            case IMAGETYPE_JPEG:
                imagejpeg($this->sourceImage, $outputPath);
                break;
            case IMAGETYPE_PNG:
                imagepng($this->sourceImage, $outputPath);
                break;
            case IMAGETYPE_GIF:
                imagegif($this->sourceImage, $outputPath);
                break;
        }
        imagedestroy($this->sourceImage);
        imagedestroy($this->watermarkImage);
    }
}

步骤二:使用图片水印类

$sourceImagePath = 'path/to/your/image.jpg';
$watermarkImagePath = 'path/to/your/watermark.png';
$position = ['x' => 50, 'y' => 50]; // 水印位置

$watermark = new WatermarkImage($sourceImagePath, $watermarkImagePath, $position);
$watermark->addImageWatermark();
$watermark->saveImage('path/to/output/image.jpg');

高级技巧

透明度处理

imagecolortransparent($this->watermarkImage, imagecolorallocatealpha($this->watermarkImage, 0, 0, 0, 127));
imagealphablending($this->watermarkImage, false);
imagesavealpha($this->watermarkImage, true);

动态位置

$sourceWidth = imagesx($this->sourceImage);
$sourceHeight = imagesy($this->sourceImage);
$watermarkWidth = imagesx($this->watermarkImage);
$watermarkHeight = imagesy($this->watermarkImage);

// 居中
$x = ($sourceWidth - $watermarkWidth) / 2;
$y = ($sourceHeight - $watermarkHeight) / 2;

性能优化

缓存机制

$cachePath = 'path/to/cache/image.jpg';
if (file_exists($cachePath)) {
    // 使用缓存图片
} else {
    // 处理图片并保存到缓存
}

异步处理

安全性考虑

  • 验证上传文件的类型和大小。
  • 使用getimagesize函数检查文件是否为有效的图像。
  • 对文件名进行过滤和消毒。

总结