PHP实现添加图片水印的详细指南与示例代码
在网站开发中,为了保护原创图片的版权或增加品牌曝光度,给图片添加水印是一项非常常见的功能。PHP作为一门强大的服务端脚本语言,内置了GD库,能够非常方便地处理图像。本文将详细介绍如何使用PHP和GD库实现图片水印功能,并提供完整的示例代码。
一、前置条件
在开始编写代码之前,请确保你的PHP环境已经安装并启用了GD库。你可以通过创建一个包含 phpinfo(); 的PHP文件来查看是否支持GD库。如果未启用,需要在 php.ini 文件中取消 extension=gd 的注释并重启服务器。
二、核心GD函数介绍
在实现图片水印的过程中,我们会用到以下几个关键的GD函数:
imagecreatefromjpeg()/imagecreatefrompng():从文件或URL创建新图像。imagecopymerge():拷贝并合并图像的一部分,支持设置透明度,通常用于图片水印。imagettftext():用 TrueType 字体向图像写入文本,通常用于文字水印。imagejpeg()/imagepng():输出图像到浏览器或文件。imagedestroy():销毁图像资源,释放内存。
三、PHP实现图片水印示例代码
下面是一个封装好的图片水印类,支持设置水印位置、透明度,并将处理后的图片保存到指定路径。
<?php
class ImageWatermark {
// 原图路径
private $sourceImage;
// 水印图片路径
private $watermarkImage;
// 保存路径
private $outputPath;
// 水印位置 (0-9代表不同位置,如9代表右下角)
private $position;
// 透明度 (0-100)
private $opacity;
public function __construct($source, $watermark, $output, $position = 9, $opacity = 50) {
$this->sourceImage = $source;
$this->watermarkImage = $watermark;
$this->outputPath = $output;
$this->position = $position;
$this->opacity = $opacity;
}
public function addWatermark() {
// 获取原图信息
$sourceInfo = getimagesize($this->sourceImage);
$sourceWidth = $sourceInfo[0];
$sourceHeight = $sourceInfo[1];
$sourceMime = $sourceInfo['mime'];
// 创建原图资源
switch ($sourceMime) {
case 'image/jpeg':
$sourceRes = imagecreatefromjpeg($this->sourceImage);
break;
case 'image/png':
$sourceRes = imagecreatefrompng($this->sourceImage);
break;
default:
throw new Exception("Unsupported source image type.");
}
// 获取水印图信息
$watermarkInfo = getimagesize($this->watermarkImage);
$watermarkWidth = $watermarkInfo[0];
$watermarkHeight = $watermarkInfo[1];
$watermarkMime = $watermarkInfo['mime'];
// 创建水印图资源
switch ($watermarkMime) {
case 'image/jpeg':
$watermarkRes = imagecreatefromjpeg($this->watermarkImage);
break;
case 'image/png':
$watermarkRes = imagecreatefrompng($this->watermarkImage);
break;
default:
throw new Exception("Unsupported watermark image type.");
}
// 计算水印位置
$positionCoords = $this->calculatePosition($sourceWidth, $sourceHeight, $watermarkWidth, $watermarkHeight);
// 合并水印与原图
imagecopymerge($sourceRes, $watermarkRes, $positionCoords['x'], $positionCoords['y'], 0, 0, $watermarkWidth, $watermarkHeight, $this->opacity);
// 输出图片
switch ($sourceMime) {
case 'image/jpeg':
imagejpeg($sourceRes, $this->outputPath, 90);
break;
case 'image/png':
imagepng($sourceRes, $this->outputPath);
break;
}
// 销毁资源
imagedestroy($sourceRes);
imagedestroy($watermarkRes);
return true;
}
private function calculatePosition($sw, $sh, $ww, $wh) {
$padding = 10; // 边距
$x = 0;
$y = 0;
switch ($this->position) {
case 1: // 左上
$x = $padding;
$y = $padding;
break;
case 2: // 中上
$x = ($sw - $ww) / 2;
$y = $padding;
break;
case 3: // 右上
$x = $sw - $ww - $padding;
$y = $padding;
break;
case 4: // 左中
$x = $padding;
$y = ($sh - $wh) / 2;
break;
case 5: // 居中
$x = ($sw - $ww) / 2;
$y = ($sh - $wh) / 2;
break;
case 6: // 右中
$x = $sw - $ww - $padding;
$y = ($sh - $wh) / 2;
break;
case 7: // 左下
$x = $padding;
$y = $sh - $wh - $padding;
break;
case 8: // 中下
$x = ($sw - $ww) / 2;
$y = $sh - $wh - $padding;
break;
case 9: // 右下
default:
$x = $sw - $ww - $padding;
$y = $sh - $wh - $padding;
break;
}
return ['x' => $x, 'y' => $y];
}
}
// 使用示例
try {
$watermark = new ImageWatermark(
'source.jpg',
'logo.png',
'output.jpg',
9,
60
);
if ($watermark->addWatermark()) {
echo "Watermark added successfully!";
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
?>四、代码逻辑解析
上述代码封装了一个 ImageWatermark 类,实现了以下核心逻辑:
资源创建:根据图片的MIME类型(如
image/jpeg或image/png),动态调用对应的函数创建图像资源。位置计算:通过
calculatePosition方法,将九宫格位置(1-9)转换为具体的坐标点,支持边距设置。水印合成:使用
imagecopymerge()函数将水印图按照指定的透明度和坐标合并到原图上。保存与销毁:将合成后的图片保存至输出路径,并调用
imagedestroy()释放内存。
五、补充:文字水印的实现
除了图片水印,文字水印也很常见。文字水印主要依赖 imagettftext() 函数。下面是文字水印的核心代码片段:
<?php
// 创建原图资源
$image = imagecreatefromjpeg('source.jpg');
// 设置文字颜色 (RGB)
$textColor = imagecolorallocate($image, 255, 255, 255);
// 字体文件路径
$fontFile = 'arial.ttf';
// 水印文字内容
$text = 'Copyright 2023';
// 将文字写入图片
// 参数:图像资源,字体大小,角度,x坐标,y坐标,颜色,字体文件,文字内容
imagettftext($image, 20, 0, 50, 50, $textColor, $fontFile, $text);
// 保存并销毁
imagejpeg($image, 'text_output.jpg');
imagedestroy($image);
?>注意,使用文字水印时,必须提供有效的TrueType字体文件(如 .ttf 文件)。
六、注意事项
透明度问题:如果是PNG透明水印,
imagecopymerge()会破坏原水印的透明通道。如果需要保留PNG的透明度,建议使用imagecopy()代替,但这样会失去整体透明度调节功能。内存限制:处理大图时需要消耗大量内存,如果遇到空白或报错,请调整
php.ini中的memory_limit设置。路径问题:确保传入的图片路径和字体路径准确无误,建议使用绝对路径。