功能说明
本函数支持以图片和文字两种方式为图片添加水印,是网站开发中常用的图片处理功能,特别适用于外贸网站、图片分享网站等需要保护图片版权的场景。
支持格式
- 目标图片:GIF、PNG、JPG
- 水印图片:PNG、GIF(支持透明度)
- 水印文字:支持TrueType字体
完整代码
<?php
function setWater($imgSrc, $markImg, $markText, $TextColor, $markPos, $fontType, $markType)
{
$srcInfo = @getimagesize($imgSrc);
if (!$srcInfo) return false;
$srcImg_w = $srcInfo[0];
$srcImg_h = $srcInfo[1];
// 根据图片类型创建图像资源
switch ($srcInfo[2]) {
case 1: $srcim = @imagecreatefromgif($imgSrc); break;
case 2: $srcim = @imagecreatefromjpeg($imgSrc); break;
case 3: $srcim = @imagecreatefrompng($imgSrc); break;
default: return false;
}
if (!$srcim) return false;
$logow = 0; $logoh = 0;
// 图片水印处理
if ($markType == "img" && !empty($markImg)) {
if (!file_exists($markImg)) return false;
$markImgInfo = @getimagesize($markImg);
if (!$markImgInfo) return false;
$markImg_w = $markImgInfo[0];
$markImg_h = $markImgInfo[1];
if ($srcImg_w < $markImg_w || $srcImg_h < $markImg_h) return false;
switch ($markImgInfo[2]) {
case 1: $markim = @imagecreatefromgif($markImg); break;
case 3:
$markim = @imagecreatefrompng($markImg);
imagealphablending($markim, true);
imagesavealpha($markim, true);
break;
default: return false;
}
$logow = $markImg_w;
$logoh = $markImg_h;
}
// 文字水印处理
if ($markType == "text" && !empty($markText)) {
$fontSize = 16;
if (!file_exists($fontType)) return false;
$box = @imagettfbbox($fontSize, 0, $fontType, $markText);
$logow = max($box[2], $box[4]) - min($box[0], $box[6]);
$logoh = max($box[1], $box[3]) - min($box[5], $box[7]);
}
if ($markPos == 0) $markPos = rand(1, 9);
// 九宫格坐标计算
switch ($markPos) {
case 1: $x = 5; $y = $logoh + 5; break;
case 2: $x = ($srcImg_w - $logow) / 2; $y = $logoh + 5; break;
case 3: $x = $srcImg_w - $logow - 5; $y = $logoh + 5; break;
case 4: $x = 5; $y = ($srcImg_h + $logoh) / 2; break;
case 5: $x = ($srcImg_w - $logow) / 2; $y = ($srcImg_h + $logoh) / 2; break;
case 6: $x = $srcImg_w - $logow - 5; $y = ($srcImg_h + $logoh) / 2; break;
case 7: $x = 5; $y = $srcImg_h - 5; break;
case 8: $x = ($srcImg_w - $logow) / 2; $y = $srcImg_h - 5; break;
case 9: $x = $srcImg_w - $logow - 5; $y = $srcImg_h - 5; break;
default: return false;
}
// 创建目标图像
$dst_img = @imagecreatetruecolor($srcImg_w, $srcImg_h);
// PNG透明度处理
if ($srcInfo[2] == 3) {
imagealphablending($dst_img, false);
imagesavealpha($dst_img, true);
$transparent = imagecolorallocatealpha($dst_img, 0, 0, 0, 127);
imagefill($dst_img, 0, 0, $transparent);
}
imagecopy($dst_img, $srcim, 0, 0, 0, 0, $srcImg_w, $srcImg_h);
// 添加图片水印
if ($markType == "img" && isset($markim)) {
imagecopy($dst_img, $markim, $x, $y - $logoh, 0, 0, $logow, $logoh);
}
// 添加文字水印
if ($markType == "text" && !empty($markText)) {
$rgb = explode(',', $TextColor);
$color = imagecolorallocate($dst_img, $rgb[0], $rgb[1], $rgb[2]);
@imagettftext($dst_img, $fontSize, 0, $x, $y, $color, $fontType, $markText);
}
// 保存图片
switch ($srcInfo[2]) {
case 1: imagegif($dst_img, $imgSrc); break;
case 2: imagejpeg($dst_img, $imgSrc, 85); break;
case 3: imagepng($dst_img, $imgSrc); break;
}
imagedestroy($dst_img);
if (isset($markim)) imagedestroy($markim);
imagedestroy($srcim);
return true;
}
参数说明
| 参数 | 说明 | 示例 |
|---|---|---|
$imgSrc | 目标图片路径 | "uploads/photo.jpg" |
$markImg | 水印图片(PNG/GIF) | "images/logo.png" |
$markText | 水印文字 | "Copyright 2026" |
$TextColor | 文字颜色(RGB) | "255,255,255" |
$markPos | 位置(0=随机,1-9九宫格) | 5(居中) |
$fontType | TrueType字体路径 | "fonts/simhei.ttf" |
$markType | 水印类型 | "img" 或 "text" |
水印位置示意图
+-------------------------+ | 1:左上 2:中上 3:右上 | | | | 4:左中 5:居中 6:右中 | | | | 7:左下 8:中下 9:右下 | +-------------------------+ 0: 随机位置
使用示例
示例1:添加图片水印
$result = setWater(
'uploads/product.jpg', // 目标图片
'images/watermark.png', // 水印Logo
'', // 无文字
'255,255,255', // 文字颜色
5, // 居中
'', // 字体文件
'img' // 图片模式
);
示例2:添加文字水印
$result = setWater(
'uploads/photo.jpg', // 目标图片
'', // 无图片水印
'© 2026 YBB.Press', // 水印文字
'255,255,255', // 白色文字
9, // 右下角
'fonts/msyh.ttc', // 微软雅黑
'text' // 文字模式
);
示例3:批量处理图片
$dir = 'uploads/images/';
$files = glob($dir . '*.{jpg,jpeg,png,gif}', GLOB_BRACE);
foreach ($files as $file) {
setWater($file, 'images/logo.png', 'YBB.Press', '200,200,200', 0, 'fonts/simhei.ttf', 'img');
}
九宫格位置详解
| 位置值 | 位置说明 | 坐标计算方式 |
|---|---|---|
| 0 | 随机位置 | rand(1, 9) |
| 1 | 左上角 | x=5, y=字体高+5 |
| 2 | 顶部居中 | x=(宽-水印宽)/2, y=字体高+5 |
| 3 | 右上角 | x=宽-水印宽-5, y=字体高+5 |
| 4 | 左边居中 | x=5, y=(高+水印高)/2 |
| 5 | 正中心 | x=(宽-水印宽)/2, y=(高+水印高)/2 |
| 6 | 右边居中 | x=宽-水印宽-5, y=(高+水印高)/2 |
| 7 | 左下角 | x=5, y=高-5 |
| 8 | 底部居中 | x=(宽-水印宽)/2, y=高-5 |
| 9 | 右下角 | x=宽-水印宽-5, y=高-5 |
优化说明
- 错误处理增强:添加文件存在性、图像资源验证
- 透明度支持:正确处理PNG透明背景,避免黑底问题
- 坐标修正:修正文字水印Y坐标计算,确保完整显示
- JPG质量参数:imagejpeg添加85%质量,平衡质量与大小
- 内存管理:及时释放图像资源,避免内存泄漏
- 代码规范:详细注释,提高可读性和可维护性
环境要求
- PHP版本:PHP 5.4+(推荐PHP 7.4+或PHP 8.x)
- GD库:必须启用(编译时添加 --with-gd)
- FreeType:文字水印需要(--with-freetype-dir)
- 图像格式:GIF、JPEG、PNG
注意事项
- 水印图片建议使用PNG格式(支持透明)
- 字体文件需TrueType(.ttf/.ttc),中文字体文件较大
- 处理大图注意PHP内存限制,可调整memory_limit
- 本函数会覆盖原图,如需保留原图请先备份
- 批量生产建议添加延时处理,避免服务器负载过高
常见问题
Q: 文字水印显示乱码怎么办?
A: 确保字体文件支持中文字符,使用UTF-8编码。
Q: 透明PNG水印出现黑底?
A: 需要使用imagesavealpha()函数保留透明度信息。
Q: 图片处理时内存不足?
A: 在脚本开头增加内存限制:ini_set('memory_limit', '256M');
本文来源于NDF俱乐部实践总结,优化整理分享。

发表评论 取消回复