PHP 图片水印类实现代码:支持文字/图片及透明度控制
本文分享的 PHP 图片水印类代码,利用 GD 库原生函数实现高效图像处理。该类封装了文字水印与图片水印的添加逻辑,支持自定义透明度、字体样式以及九宫格固定或随机定位。开发者只需实例化对象并传入图片路径,即可自动生成并保存带有版权信息的水印图片。
功能特性概述
该 WaterMask 类主要解决了批量图片版权保护的需求,具备以下核心功能:
- 双模式支持:同时支持纯文字水印和背景透明的图片水印(如 Logo)。
- 精细控制:可调节水印的透明度(0-100),文字水印支持自定义字体文件、字号及 RGB 颜色。
- 灵活定位:提供 9 种固定位置(九宫格)及随机位置算法,确保水印布局美观。
- 自动适配:自动识别源文件格式(PNG/JPEG/GIF)并进行相应的合成与输出。
准备条件
在使用此代码前,请确保服务器环境满足以下要求:
- PHP 扩展:必须启用
GD和FreeType扩展。其中 FreeType 用于文字水印渲染。 - 权限设置:脚本执行用户对目标图片目录具有读写权限,以便覆盖原文件或生成新文件。
- 资源文件:准备一个可用的 TTF 字体文件(如
AHGBold.ttf)和一个透明背景的 PNG 水印图片。
第 1 步:引入水印类文件
将完整的类代码保存为 WaterMask.php。在需要使用的项目中引入该类:
<?php
require_once 'WaterMask.php';
?
第 2 步:实例化对象
创建 WaterMask 实例,传入需要添加水印的原图路径。类构造函数会自动检查文件是否存在。
$obj = new WaterMask('source_image.jpg');
第 3 步:配置水印参数
根据需求设置公共属性。以下是关键参数的配置说明:
$waterType:设置水印类型。0为文字水印,1为图片水印(默认值 1)。$pos:设置水印位置。0 为随机,1-9 对应九宫格的左上至右下九个位置。$transparent:设置透明度,取值范围 0-100,数值越大越不透明。- 若为图片水印:
-$waterImg:指定水印图片的路径,如'logo.png'。 - 若为文字水印:
-$waterStr:指定要显示的文字内容。
-$fontFile:指定 TTF 字体文件路径。
-$fontSize:设置字体大小。
-$fontColor:设置字体颜色数组 [R, G, B]。
第 4 步:执行加水印并输出
调用 output() 方法,类内部会自动加载图片、计算坐标、合并图层并保存结果。默认操作是直接覆盖源文件。
$obj->output();
完整代码实现
以下是封装好的 WaterMask 类完整源码。代码包含详细的注释,涵盖了图像信息获取、位置算法、透明度混合及最终输出等核心逻辑。
<?php
/**
* 加水印类,支持文字图片水印的透明度设置、水印图片背景透明。
* 使用示例见下方文档说明。
*/
class WaterMask {
public $waterType = 1; // 水印类型:0为文字水印、1为图片水印
public $pos = 0; // 水印位置:0随机,1-9为九宫格
public $transparent = 45; // 水印透明度 (0-100)
// 文字水印相关参数
public $waterStr = 'www.jb51.net'; // 水印文字
public $fontSize = 16; // 文字字体大小
public $fontColor = array(255, 0, 255); // 水印文字颜色(RGB)
public $fontFile = 'AHGBold.ttf'; // 字体文件路径
// 图片水印相关参数
public $waterImg = 'logo.png'; // 水印图片路径
// 私有变量
private $srcImg = ''; // 需要添加水印的图片
private $im = ''; // 图片句柄
private $water_im = ''; // 水印图片句柄
private $srcImg_info = ''; // 图片信息数组
private $waterImg_info = ''; // 水印图片信息数组
private $x = ''; // 水印X坐标
private $y = ''; // 水印Y坐标
function __construct($img) {
if (!file_exists($img)) {
die("源文件 '" . $img . "' 不存在!");
}
$this->srcImg = $img;
}
private function imginfo() {
// 获取源图片信息并载入
$this->srcImg_info = getimagesize($this->srcImg);
switch ($this->srcImg_info[2]) {
case 3: $this->im = imagecreatefrompng($this->srcImg); break;
case 2: $this->im = imagecreatefromjpeg($this->srcImg); break;
case 1: $this->im = imagecreatefromgif($this->srcImg); break;
default: die('不支持的图片格式,仅支持 PNG、JPEG、GIF。');
}
}
private function waterimginfo() {
// 获取水印图片信息并载入
$this->waterImg_info = getimagesize($this->waterImg);
switch ($this->waterImg_info[2]) {
case 3: $this->water_im = imagecreatefrompng($this->waterImg); break;
case 2: $this->water_im = imagecreatefromjpeg($this->waterImg); break;
case 1: $this->water_im = imagecreatefromgif($this->waterImg); break;
default: die('不支持的水印图片格式,仅支持 PNG、JPEG、GIF。');
}
}
private function waterpos() {
// 计算水印位置坐标
$w = $this->srcImg_info[0];
$h = $this->srcImg_info[1];
$sw = isset($this->waterImg_info[0]) ? $this->waterImg_info[0] : 0;
$sh = isset($this->waterImg_info[1]) ? $this->waterImg_info[1] : 0;
switch ($this->pos) {
case 0: // 随机位置
$this->x = rand(0, $w - $sw);
$this->y = rand(0, $h - $sh);
break;
case 1: // 左上
$this->x = 0; $this->y = 0; break;
case 2: // 中上
$this->x = ($w - $sw) / 2; $this->y = 0; break;
case 3: // 右上
$this->x = $w - $sw; $this->y = 0; break;
case 4: // 左中
$this->x = 0; $this->y = ($h - $sh) / 2; break;
case 5: // 正中
$this->x = ($w - $sw) / 2; $this->y = ($h - $sh) / 2; break;
case 6: // 右中
$this->x = $w - $sw; $this->y = ($h - $sh) / 2; break;
case 7: // 左下
$this->x = 0; $this->y = $h - $sh; break;
case 8: // 中下
$this->x = ($w - $sw) / 2; $this->y = $h - $sh; break;
default: // 右下
$this->x = $w - $sw; $this->y = $h - $sh; break;
}
}
private function waterimg() {
// 图片水印合成逻辑
if ($this->srcImg_info[0] <= $this->waterImg_info[0] || $this->srcImg_info[1] <= $this->waterImg_info[1]) {
die('错误:原图尺寸小于水印图片尺寸,无法添加。');
}
$this->waterpos();
// 创建一个临时画布用于合成
$cut = imagecreatetruecolor($this->waterImg_info[0], $this->waterImg_info[1]);
// 复制原图对应区域到临时画布
imagecopy($cut, $this->im, 0, 0, $this->x, $this->y, $this->waterImg_info[0], $this->waterImg_info[1]);
// 复制水印图片到临时画布
imagecopy($cut, $this->water_im, 0, 0, 0, 0, $this->waterImg_info[0], $this->waterImg_info[1]);
$pct = $this->transparent;
// 将合成后的临时画布以指定透明度合并回原图
imagecopymerge($this->im, $cut, $this->x, $this->y, 0, 0, $this->waterImg_info[0], $this->waterImg_info[1], $pct);
imagedestroy($cut);
}
private function waterstr() {
// 文字水印生成逻辑
$rect = imagettfbbox($this->fontSize, 0, $this->fontFile, $this->waterStr);
$w = abs($rect[2] - $rect[6]);
$h = abs($rect[3] - $rect[7]);
// 创建文字水印透明画布
$this->water_im = imagecreatetruecolor($w, $h);
imagealphablending($this->water_im, false);
imagesavealpha($this->water_im, true);
// 填充完全透明背景
$white_alpha = imagecolorallocatealpha($this->water_im, 255, 255, 255, 127);
imagefill($this->water_im, 0, 0, $white_alpha);
// 写入文字
$color = imagecolorallocate($this->water_im, $this->fontColor[0], $this->fontColor[1], $this->fontColor[2]);
imagettftext($this->water_im, $this->fontSize, 0, 0, $this->fontSize, $color, $this->fontFile, $this->waterStr);
// 更新水印信息供后续合成使用
$this->waterImg_info = array(0 => $w, 1 => $h);
// 复用图片水印的合成方法
$this->waterimg();
}
function output() {
$this->imginfo();
if ($this->waterType == 0) {
$this->waterstr();
} else {
$this->waterimginfo();
$this->waterimg();
}
// 根据原图格式保存
switch ($this->srcImg_info[2]) {
case 3: imagepng($this->im, $this->srcImg); break;
case 2: imagejpeg($this->im, $this->srcImg); break;
case 1: imagegif($this->im, $this->srcImg); break;
}
// 释放内存
imagedestroy($this->im);
imagedestroy($this->water_im);
}
}
?>
注意事项与排错
在使用过程中,若遇到以下问题,请参考排查:
- 字体缺失报错:确保
$fontFile指定的 TTF 文件路径正确,且 Web 服务器进程有读取权限。推荐使用系统自带的 Arial 或 simhei.ttf 等常见字体进行测试。 - 水印模糊或失真:检查源图片格式。对于 JPEG 格式的反复编辑会导致压缩损失,建议原始素材尽量使用 PNG 或高质量 JPG。
- 水印尺寸过大:类中包含基础判断,若原图小于水印图会直接中止。如需自适应缩小水印,需在
waterimg()前增加imagescale逻辑。
以上就是 PHP 图片水印类实现代码的详细内容,更多关于 PHP 图像处理与 GD 库应用技巧的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









