imagecopymerge() 透明区域变黑是因为它不支持 alpha 通道,仅处理 rgb 并丢弃透明度;正确做法是用 imagecreatetruecolor 创建画布,配合 imagealphablending(false) 和 imagesavealpha(true),再使用 imagecopy() 拼接。

PHP 用 imagecopymerge() 拼图为什么透明区域变黑?
因为 imagecopymerge() 不支持 alpha 通道,PNG 中的透明度会被强制转成黑色(或背景色)。它本质是按指定透明度做「颜色混合」,不是「图层叠加」,底层用的是 GD 的 gdImageCopyMerge(),只处理 RGB,丢弃 Alpha。
实操建议:
- 如果源图是 PNG 且含透明区域,必须先用
imagealphablending($dst, false)+imagesavealpha($dst, true)关闭混合并保留 alpha - 改用
imagecopy()或imagecopyresampled()替代 —— 它们能正确传递透明像素(前提是目标图已启用 alpha 支持) -
imagecopymerge()的$pct参数实际是「覆盖强度」,设为 100 时等价于普通复制;设为 0 则无效果;中间值会产生半透叠印,但对透明图无效
拼接两张 PNG 图片:imagecopy() 的必备初始化步骤
直接调用 imagecopy() 拼 PNG,大概率出现黑底、锯齿或透明变灰。关键不在函数本身,而在图像资源创建时的配置。
正确流程:
- 用
imagecreatetruecolor($w, $h)创建真彩色画布(别用imagecreate()) - 立即执行
imagealphablending($img, false)—— 关闭 alpha 混合,否则后续imagecopy()会把透明像素和默认黑底混合 - 再调用
imagesavealpha($img, true)—— 确保保存时保留 alpha 通道 - 最后才用
imagecopy($dst, $src, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h)拼接
漏掉前两步中的任意一个,imagecopy() 就会“吃掉”透明信息。
imagecopymerge() 还有没有适用场景?
有,但非常有限:仅适用于两张 JPG(或无透明通道的 GIF)做带强度控制的叠印,比如水印淡入、老照片褪色效果。
典型用例:
- 给 JPG 封面加半透明文字水印:
imagecopymerge($bg, $watermark, 10, 10, 0, 0, $w, $h, 30)(30% 强度) - 两张 JPG 合成景深模糊效果(前景 JPG 覆盖在背景 JPG 上,用低
$pct模拟虚化) - 注意:目标图和源图都必须是不带 alpha 的格式,且不能用
imagesavealpha(),否则行为不可控
生成带透明背景的拼接图:完整代码骨架
以下是最简可靠写法,适配 PHP 7.4+ 和 GD 扩展开启 alpha 支持的环境:
// 创建透明画布
$canvas = imagecreatetruecolor(800, 600);
imagealphablending($canvas, false);
imagesavealpha($canvas, true);
// 填充透明背景(可选,避免意外黑底)
$transparent = imagecolorallocatealpha($canvas, 0, 0, 0, 127);
imagefilledrectangle($canvas, 0, 0, 799, 599, $transparent);
// 加载 PNG 源图(确保它们本身含 alpha)
$top = imagecreatefrompng('top.png');
$bottom = imagecreatefrompng('bottom.png');
// 拼接:top 放在 bottom 上方
imagecopy($canvas, $bottom, 0, 0, 0, 0, imagesx($bottom), imagesy($bottom));
imagecopy($canvas, $top, 100, 50, 0, 0, imagesx($top), imagesy($top));
// 输出 PNG(不要用 imagejpeg!)
header('Content-Type: image/png');
imagepng($canvas);
imagedestroy($canvas);
imagedestroy($top);
imagedestroy($bottom);
最容易被忽略的是最后一行的 imagedestroy() —— GD 资源不手动释放,在循环拼图或高并发时会快速耗尽内存,错误提示常是 Allowed memory size exhausted,而非图像异常。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











