PHP 图片水印类实现代码:支持文字/图片及透明度控制

陆景行
陆景行
发布时间:2026-10-15| 6人浏览过
原创

本文分享的 PHP 图片水印类代码,利用 GD 库原生函数实现高效图像处理。该类封装了文字水印与图片水印的添加逻辑,支持自定义透明度、字体样式以及九宫格固定或随机定位。开发者只需实例化对象并传入图片路径,即可自动生成并保存带有版权信息的水印图片。

功能特性概述

该 WaterMask 类主要解决了批量图片版权保护的需求,具备以下核心功能:

  • 双模式支持:同时支持纯文字水印和背景透明的图片水印(如 Logo)。
  • 精细控制:可调节水印的透明度(0-100),文字水印支持自定义字体文件、字号及 RGB 颜色。
  • 灵活定位:提供 9 种固定位置(九宫格)及随机位置算法,确保水印布局美观。
  • 自动适配:自动识别源文件格式(PNG/JPEG/GIF)并进行相应的合成与输出。

准备条件

在使用此代码前,请确保服务器环境满足以下要求:

  1. PHP 扩展:必须启用 GD 和 FreeType 扩展。其中 FreeType 用于文字水印渲染。
  2. 权限设置:脚本执行用户对目标图片目录具有读写权限,以便覆盖原文件或生成新文件。
  3. 资源文件:准备一个可用的 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 库应用技巧的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。