本文目录导读:

在PHP中给图片添加水印,主要使用 GD库 或 Imagick 扩展,下面我给出两种方式的完整代码示例。
使用GD库(最常用)
<?php
/**
* 给图片添加水印
* @param string $source 原图路径
* @param string $watermark 水印图片路径(推荐PNG格式,支持透明)
* @param string $output 输出路径
* @param int $position 位置:1-9,对应九宫格位置
* @param int $padding 边距(像素)
*/
function addWatermark($source, $watermark, $output = '', $position = 9, $padding = 20) {
// 获取原图信息
$sourceInfo = getimagesize($source);
$sourceWidth = $sourceInfo[0];
$sourceHeight = $sourceInfo[1];
$sourceType = $sourceInfo[2];
// 根据图片类型创建原图资源
switch ($sourceType) {
case IMAGETYPE_JPEG:
$sourceImage = imagecreatefromjpeg($source);
break;
case IMAGETYPE_PNG:
$sourceImage = imagecreatefrompng($source);
break;
case IMAGETYPE_GIF:
$sourceImage = imagecreatefromgif($source);
break;
default:
return false;
}
// 获取水印图片信息并创建水印资源
$watermarkInfo = getimagesize($watermark);
$waterWidth = $watermarkInfo[0];
$waterHeight = $watermarkInfo[1];
$waterImage = imagecreatefrompng($watermark);
// 计算水印位置(九宫格定位)
$positionMap = [
1 => ['x' => $padding, 'y' => $padding], // 左上
2 => ['x' => ($sourceWidth - $waterWidth) / 2, 'y' => $padding], // 上中
3 => ['x' => $sourceWidth - $waterWidth - $padding, 'y' => $padding], // 右上
4 => ['x' => $padding, 'y' => ($sourceHeight - $waterHeight) / 2], // 左中
5 => ['x' => ($sourceWidth - $waterWidth) / 2, 'y' => ($sourceHeight - $waterHeight) / 2], // 居中
6 => ['x' => $sourceWidth - $waterWidth - $padding, 'y' => ($sourceHeight - $waterHeight) / 2], // 右中
7 => ['x' => $padding, 'y' => $sourceHeight - $waterHeight - $padding], // 左下
8 => ['x' => ($sourceWidth - $waterWidth) / 2, 'y' => $sourceHeight - $waterHeight - $padding], // 下中
9 => ['x' => $sourceWidth - $waterWidth - $padding, 'y' => $sourceHeight - $waterHeight - $padding], // 右下
];
$pos = $positionMap[$position] ?? $positionMap[9];
// 合并图片(支持透明通道)
imagealphablending($sourceImage, true);
imagesavealpha($sourceImage, true);
imagecopy($sourceImage, $waterImage, $pos['x'], $pos['y'], 0, 0, $waterWidth, $waterHeight);
// 输出/保存
if (empty($output)) {
$output = $source; // 覆盖原图
}
switch ($sourceType) {
case IMAGETYPE_JPEG:
imagejpeg($sourceImage, $output, 100);
break;
case IMAGETYPE_PNG:
imagepng($sourceImage, $output, 0);
break;
case IMAGETYPE_GIF:
imagegif($sourceImage, $output);
break;
}
// 释放内存
imagedestroy($sourceImage);
imagedestroy($waterImage);
return true;
}
// 使用示例
addWatermark('source.jpg', 'watermark.png', 'output.jpg', 9, 20);
?>
使用Imagick(功能更强大)
<?php
/**
* 使用Imagick添加水印
*/
function addWatermarkImagick($source, $watermark, $output = '', $position = 'southeast', $padding = 20) {
try {
$image = new Imagick($source);
$water = new Imagick($watermark);
// 获取尺寸
$imageWidth = $image->getImageWidth();
$imageHeight = $image->getImageHeight();
$waterWidth = $water->getImageWidth();
$waterHeight = $water->getImageHeight();
// 计算位置
switch ($position) {
case 'northwest': // 左上
$x = $padding;
$y = $padding;
break;
case 'north': // 上中
$x = ($imageWidth - $waterWidth) / 2;
$y = $padding;
break;
case 'northeast': // 右上
$x = $imageWidth - $waterWidth - $padding;
$y = $padding;
break;
case 'west': // 左中
$x = $padding;
$y = ($imageHeight - $waterHeight) / 2;
break;
case 'center': // 居中
$x = ($imageWidth - $waterWidth) / 2;
$y = ($imageHeight - $waterHeight) / 2;
break;
case 'east': // 右中
$x = $imageWidth - $waterWidth - $padding;
$y = ($imageHeight - $waterHeight) / 2;
break;
case 'southwest': // 左下
$x = $padding;
$y = $imageHeight - $waterHeight - $padding;
break;
case 'south': // 下中
$x = ($imageWidth - $waterWidth) / 2;
$y = $imageHeight - $waterHeight - $padding;
break;
case 'southeast': // 右下(默认)
default:
$x = $imageWidth - $waterWidth - $padding;
$y = $imageHeight - $waterHeight - $padding;
break;
}
// 合并水印
$image->compositeImage($water, Imagick::COMPOSITE_OVER, $x, $y);
// 输出
if (empty($output)) {
$output = $source;
}
$image->writeImage($output);
// 释放
$image->clear();
$water->clear();
return true;
} catch (Exception $e) {
return false;
}
}
// 使用示例
addWatermarkImagick('source.jpg', 'watermark.png', 'output.jpg', 'southeast', 20);
?>
添加文字水印(GD库)
<?php
/**
* 添加文字水印
*/
function addTextWatermark($source, $text, $output = '', $fontSize = 20, $position = 9) {
// 获取原图信息
$sourceInfo = getimagesize($source);
$sourceWidth = $sourceInfo[0];
$sourceHeight = $sourceInfo[1];
$sourceType = $sourceInfo[2];
// 创建图像资源
switch ($sourceType) {
case IMAGETYPE_JPEG:
$image = imagecreatefromjpeg($source);
break;
case IMAGETYPE_PNG:
$image = imagecreatefrompng($source);
break;
case IMAGETYPE_GIF:
$image = imagecreatefromgif($source);
break;
default:
return false;
}
// 设置文字颜色(白色,半透明)
$textColor = imagecolorallocatealpha($image, 255, 255, 255, 50);
// 中文字体路径(需要下载中文字体文件)
$fontFile = 'path/to/your/font.ttf'; // simsun.ttc 或 msyh.ttf
// 获取文字边界
$bbox = imagettfbbox($fontSize, 0, $fontFile, $text);
$textWidth = $bbox[2] - $bbox[0];
$textHeight = $bbox[1] - $bbox[7];
// 计算位置
$padding = 20;
$positions = [
1 => ['x' => $padding, 'y' => $textHeight + $padding],
2 => ['x' => ($sourceWidth - $textWidth) / 2, 'y' => $textHeight + $padding],
3 => ['x' => $sourceWidth - $textWidth - $padding, 'y' => $textHeight + $padding],
4 => ['x' => $padding, 'y' => ($sourceHeight - $textHeight) / 2],
5 => ['x' => ($sourceWidth - $textWidth) / 2, 'y' => ($sourceHeight - $textHeight) / 2],
6 => ['x' => $sourceWidth - $textWidth - $padding, 'y' => ($sourceHeight - $textHeight) / 2],
7 => ['x' => $padding, 'y' => $sourceHeight - $padding],
8 => ['x' => ($sourceWidth - $textWidth) / 2, 'y' => $sourceHeight - $padding],
9 => ['x' => $sourceWidth - $textWidth - $padding, 'y' => $sourceHeight - $padding],
];
$pos = $positions[$position] ?? $positions[9];
// 写入文字
imagettftext($image, $fontSize, 0, $pos['x'], $pos['y'], $textColor, $fontFile, $text);
// 输出
if (empty($output)) {
$output = $source;
}
switch ($sourceType) {
case IMAGETYPE_JPEG:
imagejpeg($image, $output, 100);
break;
case IMAGETYPE_PNG:
imagepng($image, $output, 0);
break;
case IMAGETYPE_GIF:
imagegif($image, $output);
break;
}
imagedestroy($image);
return true;
}
// 使用示例
addTextWatermark('source.jpg', '© 2024 My Website', 'output.jpg', 24, 9);
?>
注意事项
-
GD库检查:使用前确认已启用GD库:
if (extension_loaded('gd')) { echo "GD库已启用"; } -
水印图片格式:推荐使用PNG格式,支持透明通道
-
字体文件:文字水印需要指定中文字体文件路径
-
性能优化:大量图片处理时建议使用队列或异步处理
-
权限问题:确保图片目录有写入权限
选择哪种方法取决于你的具体需求和服务器环境配置,GD库几乎都有,Imagick功能更强但需要额外安装。