下面给你一份可直接运行、基于 PHP GD 库的「图片水印」完整示例,包含
✔ 图片水印
✔ 透明度控制
✔ 多格式支持
✔ 常见坑说明
非常适合博客、CMS、上传系统使用。
一、效果说明
在原图右下角添加一张 PNG 水印图(支持透明)
二、环境要求
- PHP ≥ 7.0
- 开启 GD 扩展
php -m | grep gd
三、完整示例代码(图片水印)
<?php
/**
* 给图片添加图片水印
* @param string $src 原图路径
* @param string $water 水印图路径(PNG推荐)
* @param string $savePath 保存路径(为空则覆盖原图)
* @param int $alpha 水印透明度 0-100
*/
function addImageWatermark($src, $water, $savePath = '', $alpha = 60)
{
if (!file_exists($src) || !file_exists($water)) {
return false;
}
// 获取原图信息
$srcInfo = getimagesize($src);
$waterInfo = getimagesize($water);
list($srcW, $srcH, $srcType) = $srcInfo;
list($waterW, $waterH) = $waterInfo;
// 创建原图资源
switch ($srcType) {
case IMAGETYPE_JPEG:
$srcImg = imagecreatefromjpeg($src);
break;
case IMAGETYPE_PNG:
$srcImg = imagecreatefrompng($src);
break;
case IMAGETYPE_GIF:
$srcImg = imagecreatefromgif($src);
break;
default:
return false;
}
// 创建水印资源
$waterImg = imagecreatefrompng($water);
// 水印位置(右下角,留 10px 边距)
$dstX = $srcW - $waterW - 10;
$dstY = $srcH - $waterH - 10;
// 合并水印(支持透明)
imagecopymerge(
$srcImg,
$waterImg,
$dstX,
$dstY,
0,
0,
$waterW,
$waterH,
$alpha
);
// 保存图片
$savePath = $savePath ?: $src;
switch ($srcType) {
case IMAGETYPE_JPEG:
imagejpeg($srcImg, $savePath, 90);
break;
case IMAGETYPE_PNG:
imagepng($srcImg, $savePath);
break;
case IMAGETYPE_GIF:
imagegif($srcImg, $savePath);
break;
}
// 释放资源
imagedestroy($srcImg);
imagedestroy($waterImg);
return true;
}
四、使用示例
$srcImage = './upload/photo.jpg';
$waterImage = './watermark/logo.png';
addImageWatermark($srcImage, $waterImage, './upload/photo_water.jpg', 70);
五、支持的水印位置扩展
// 左上
$dstX = 10;
$dstY = 10;
// 左下
$dstX = 10;
$dstY = $srcH - $waterH - 10;
// 右上
$dstX = $srcW - $waterW - 10;
$dstY = 10;
// 居中
$dstX = ($srcW - $waterW) / 2;
$dstY = ($srcH - $waterH) / 2;
六、PNG 水印透明度问题(重点)
❗ imagecopymerge 的坑
- 对 PNG 原生透明支持不好
- 会导致水印变灰
✅ 解决方案(推荐)
使用 imagecopy + 保留 Alpha:
imagealphablending($srcImg, true);
imagesavealpha($srcImg, true);
imagecopy(
$srcImg,
$waterImg,
$dstX,
$dstY,
0,
0,
$waterW,
$waterH
);
(此方式使用 PNG 自带透明度)
七、常见问题汇总
❓ 为什么水印模糊?
- 水印图片本身分辨率低
- JPEG 压缩质量过低
❓ GIF 动图能加水印吗?
- ❌ GD 不支持动图逐帧
- ✅ 需 Imagick
❓ 图片太小怎么办?
if ($srcW < $waterW || $srcH < $waterH) {
return false;
}
八、Imagick(更高级,可选)
$img = new Imagick('photo.jpg');
$water = new Imagick('logo.png');
$img->compositeImage($water, Imagick::COMPOSITE_OVER, 20, 20);
$img->writeImage('out.jpg');
✔ 支持 GIF
✔ 更好透明处理
❌ 扩展安装复杂
九、一句话总结
GD 够用,Imagick 更强;PNG 水印最佳;注意透明度处理
发表回复