gd库实现水印需用imagecopy()+禁用混合+保存alpha以保留png透明度;imagecopymerge()仅适用于无透明灰度图,且第8参数为不透明度百分比;位置计算须基于当前帧尺寸动态得出,不可写死坐标。

PHP 的 GD 库能实现水印位置与透明度的精确控制,但必须手动计算坐标、预设 Alpha 通道并禁用默认混合模式——否则水印会偏移、发虚或完全不透明。
用 imagecopymerge() 还是 imagecopy()?
两者行为差异极大:imagecopymerge() 支持透明度参数(0–100),但会强制做“颜色混合”,导致 PNG 水印边缘失真;imagecopy() 不带透明度,需先调用 imagealphablending(false) 和 imagesavealpha(true) 才能保留源图 Alpha 通道。
- 要保留 PNG 水印原生透明度(如羽化边缘、半透文字)→ 必须用
imagecopy()+ 关闭混合 + 保存 Alpha - 只处理简单灰度水印图(无透明通道),且接受轻微颜色叠加 → 可用
imagecopymerge(),但注意第 8 个参数是“不透明度百分比”,值越小越透明 -
imagecopymerge()的坐标是目标图像上的左上角位置,不是水印自身的锚点;它不识别 PNG 的 alpha,会把透明区域当成黑色
如何算准水印在视频帧中的绝对位置?
视频帧是静态图像,所谓“视频加水印”本质是对每一帧 imagecreatefromjpeg() 或 imagecreatefrompng() 后叠加。位置计算必须基于目标帧尺寸,而非原始视频分辨率(转码可能导致缩放)。
- 先用
getimagesize()读取当前帧图像宽高:$frame_w、$frame_h - 水印图也需
getimagesize()获取其$logo_w、$logo_h - 右下角水印:x =
$frame_w - $logo_w - 10,y =$frame_h - $logo_h - 10(减去 10 是留边距) - 居中水印:x =
($frame_w - $logo_w) / 2,y =($frame_h - $logo_h) / 2,注意结果要(int)强转,GD 不接受浮点坐标 - 别直接写死
100, 100—— 帧尺寸变化时水印会跑出画面或遮挡关键内容
为什么水印看起来“太淡”或“像糊了一层灰”?
根本原因是 GD 默认开启颜色混合(imagealphablending(true)),此时即使 PNG 有完整 Alpha 通道,也会被背景色污染。另外,JPEG 帧本身不支持透明,叠加后透明区域会变成黑色或杂色。
- 对水印资源(PNG):加载后立刻执行
imagealphablending($logo_img, false)和imagesavealpha($logo_img, true) - 对目标帧(JPEG):无需也不该开
imagesavealpha(),但叠加前必须imagealphablending($frame_img, false),否则水印 Alpha 被强制混合 - 叠加完记得恢复目标帧混合状态:
imagealphablending($frame_img, true),否则后续绘图异常 - 如果水印仍是灰色块,检查 PNG 是否真含 Alpha —— 用
var_dump(imagecolortransparent($logo_img)),非 -1 表示有索引透明,需额外处理
真正难的不是写几行代码,而是每次叠加前都得确认三件事:水印图是否已关闭混合、目标图是否临时关闭混合、坐标是否按当前帧动态计算。漏掉任何一环,水印就会出现在意料之外的位置或透明度失控。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











