使用imagecolorallocatealpha实现透明需先调用imagesavealpha($im, true)并关闭混合,否则alpha通道被丢弃;文字透明需开启imagealphablending(true);PNG合成禁用imagecopymerge,应改用启用alpha的imagecopy;输出前须确保header为image/png且无BOM或空格。

imagecolorallocatealpha 分配透明色必须配 imagesavealpha
直接用 imagecolorallocatealpha 设置颜色却看不到透明效果,八成是漏了 imagesavealpha。GD 默认会丢弃 alpha 通道,哪怕你填了 127 也白搭。
关键操作顺序不能错:
-
imagecreatetruecolor创建画布后,立刻调用imagesavealpha($im, true) - 再用
imagealphablending($im, false)关闭混合(避免后续绘图被背景污染) - 然后才能用
imagecolorallocatealpha($im, 0, 0, 0, 127)定义完全透明色 - 最后
imagefill($im, 0, 0, $transparent)填满整个画布
少一步,输出的 PNG 就是黑底或白底——不是颜色没设对,是 alpha 根本没存进去。
文字透明要开 imagealphablending(true),否则颜色叠不上去
给 PNG 图像加半透明文字时,如果文字显示为实心色块、边缘生硬,大概率是 imagealphablending 状态错了。
立即学习“PHP免费学习笔记(深入)”;
文字绘制和图像合成逻辑不同:
- 填充背景用
imagealphablending($im, false)(防止透明色被混合掉) - 但写文字时必须切回
imagealphablending($im, true),否则imagettftext会把文字当“覆盖层”硬贴,忽略 alpha 值 -
imagecolorallocatealpha返回的颜色在 blending=false 下不会生效
典型错误:全程关 blending,结果文字不透明;全程开 blending,结果背景透明色被文字颜色污染成灰蒙蒙一片。
imagecopymerge 不能用于带原生 Alpha 的 PNG 合成
想把一张 PNG 水印叠加到另一张 PNG 上,别用 imagecopymerge。它只认“不透明度百分比”,会粗暴地把水印所有像素统一压暗,直接毁掉水印自身的柔边、渐变、镂空等原生透明细节。
正确做法是用 imagecopy,但前提很关键:
- 源水印图必须已启用 alpha 保存:
imagesavealpha($watermark, true) - 目标图也要开 alpha 保存:
imagesavealpha($main, true) - 目标图需开启混合:
imagealphablending($main, true) -
imagecopy的宽高参数必须严格等于水印图实际尺寸(用imagesx/imagesy动态取,别写死)
写死尺寸或漏掉 imagesavealpha,轻则水印边缘发黑,重则整块区域变黑底——GD 把缺失的 alpha 区域默认填黑。
输出前 header 必须是 image/png,且不能有空格或 BOM
即使代码全对,浏览器看到的还是黑图或报错,检查输出头和文件编码。
常见断点:
- header 写成
image/jpg或image/jpeg:JPEG 不支持 alpha,强制转码会丢透明通道 - PHP 文件本身含 UTF-8 BOM:BOM 作为不可见字符被提前输出,导致 header 失效,浏览器收到的是“文本+PNG乱码”
- 代码前后有空行或空格:同上,破坏二进制流完整性
最稳做法:把图像生成逻辑单独提成一个无任何 HTML/空行的 .php 文件,仅保留 <?php 开头,结尾不加 ?>,用 imagepng($im) 直接输出。



















