求助修复PHP GD实现图片圆角的@Enyby低内存函数
修复PHP GD低内存占用图片圆角函数
我尝试使用一个低内存占用的PHP GD图片圆角函数,但调用时出现错误。另一个可用的圆角函数内存占用过高,因此需要修复这个低内存版本的函数。
原函数代码如下:
function roundCorners($source, $radius) { $ws = imagesx($source); $hs = imagesy($source); $corner = $radius + 2; $s = $corner*2; $src = imagecreatetruecolor($s, $s); imagecopy($src, $source, 0, 0, 0, 0, $corner, $corner); imagecopy($src, $source, $corner, 0, $ws - $corner, 0, $corner, $corner); imagecopy($src, $source, $corner, $corner, $ws - $corner, $hs - $corner, $corner, $corner); imagecopy($src, $source, 0, $corner, 0, $hs - $corner, $corner, $corner); $q = 8; # change this if you want $radius *= $q; # find unique color do { $r = rand(0, 255); $g = rand(0, 255); $b = rand(0, 255); } while (imagecolorexact($src, $r, $g, $b) < 0); $ns = $s * $q; $img = imagecreatetruecolor($ns, $ns); $alphacolor = imagecolorallocatealpha($img, $r, $g, $b, 127); imagealphablending($img, false); imagefilledrectangle($img, 0, 0, $ns, $ns, $alphacolor); imagefill($img, 0, 0, $alphacolor); imagecopyresampled($img, $src, 0, 0, 0, 0, $ns, $ns, $s, $s); imagedestroy($src); imagearc($img, $radius - 1, $radius - 1, $radius * 2, $radius * 2, 180, 270, $alphacolor); imagefilltoborder($img, 0, 0, $alphacolor, $alphacolor); imagearc($img, $ns - $radius, $radius - 1, $radius * 2, $radius * 2, 270, 0, $alphacolor); imagefilltoborder($img, $ns - 1, 0, $alphacolor, $alphacolor); imagearc($img, $radius - 1, $ns - $radius, $radius * 2, $radius * 2, 90, 180, $alphacolor); imagefilltoborder($img, 0, $ns - 1, $alphacolor, $alphacolor); imagearc($img, $ns - $radius, $ns - $radius, $radius * 2, $radius * 2, 0, 90, $alphacolor); imagefilltoborder($img, $ns - 1, $ns - 1, $alphacolor, $alphacolor); imagealphablending($img, true); imagecolortransparent($img, $alphacolor); # resize image down $dest = imagecreatetruecolor($s, $s); imagealphablending($dest, false); imagefilledrectangle($dest, 0, 0, $s, $s, $alphacolor); imagecopyresampled($dest, $img, 0, 0, 0, 0, $s, $s, $ns, $ns); imagedestroy($img); # output image imagealphablending($source, false); imagecopy($source, $dest, 0, 0, 0, 0, $corner, $corner); imagecopy($source, $dest, $ws - $corner, 0, $corner, 0, $corner, $corner); imagecopy($source, $dest, $ws - $corner, $hs - $corner, $corner, $corner, $corner, $corner); imagecopy($source, $dest, 0, $hs - $corner, 0, $corner, $corner, $corner); imagealphablending($source, true); imagedestroy($dest); return $source; }
我原本的调用方式:
imagepng(roundCorners("images/test.jpg", 10));
出现的错误信息:
Warning: imagesx() expects parameter 1 to be resource, string given in C:\xampp\htdocs\php\rounded-img.php on line 3 Warning: imagesy() expects parameter 1 to be resource, string given in C:\xampp\htdocs\php\rounded-img.php on line 4 Warning: imagecopy() expects parameter 2 to be resource, string given in C:\xampp\htdocs\php\rounded-img.php on line 10 Warning: imagecopy() expects parameter 2 to be resource, string given in C:\xampp\htdocs\php\rounded-img.php on line 11 Warning: imagecopy() expects parameter 2 to be resource, string given in C:\xampp\htdocs\php\rounded-img.php on line 12 Warning: imagecopy() expects parameter 2 to be resource, string given in C:\xampp\htdocs\php\rounded-img.php on line 13 Warning: imagealphablending() expects parameter 1 to be resource, string given in C:\xampp\htdocs\php\rounded-img.php on line 55 Warning: imagecopy() expects parameter 1 to be resource, string given in C:\xampp\htdocs\php\rounded-img.php on line 56 Warning: imagecopy() expects parameter 1 to be resource, string given in C:\xampp\htdocs\php\rounded-img.php on line 57 Warning: imagecopy() expects parameter 1 to be resource, string given in C:\xampp\htdocs\php\rounded-img.php on line 58 Warning: imagecopy() expects parameter 1 to be resource, string given in C:\xampp\htdocs\php\rounded-img.php on line 59 Warning: imagealphablending() expects parameter 1 to be resource, string given in C:\xampp\htdocs\php\rounded-img.php on line 60
问题分析与修复
- 核心错误原因:原函数的
$source参数要求是GD图像资源,但调用时传入的是图片路径字符串,导致所有依赖资源的GD函数报错。 - 额外问题:原函数中寻找唯一颜色的循环判断逻辑写反了,
imagecolorexact找到颜色时返回索引值(>=0),没找到返回-1,原代码的判断会导致找到已存在的颜色才停止,与“找唯一颜色”的目的相反,需要修正。
修复后的完整函数及调用示例
修复后的函数
function roundCorners($source, $radius) { // 处理传入的是图片路径的情况,转换为GD资源 if (is_string($source)) { $ext = strtolower(pathinfo($source, PATHINFO_EXTENSION)); switch ($ext) { case 'jpg': case 'jpeg': $source = imagecreatefromjpeg($source); break; case 'png': $source = imagecreatefrompng($source); break; case 'gif': $source = imagecreatefromgif($source); break; default: throw new Exception("不支持的图片格式"); } if (!$source) { throw new Exception("图片加载失败"); } // 确保图片支持alpha通道 imagealphablending($source, true); imagesavealpha($source, true); } $ws = imagesx($source); $hs = imagesy($source); $corner = $radius + 2; $s = $corner*2; $src = imagecreatetruecolor($s, $s); // 为临时图片开启alpha支持 imagealphablending($src, false); imagesavealpha($src, true); imagefill($src, 0, 0, imagecolorallocatealpha($src, 0, 0, 0, 127)); imagecopy($src, $source, 0, 0, 0, 0, $corner, $corner); imagecopy($src, $source, $corner, 0, $ws - $corner, 0, $corner, $corner); imagecopy($src, $source, $corner, $corner, $ws - $corner, $hs - $corner, $corner, $corner); imagecopy($src, $source, 0, $corner, 0, $hs - $corner, $corner, $corner); $q = 8; # 调整此值可改变圆角精度 $radius *= $q; // 寻找图片中不存在的唯一颜色 do { $r = rand(0, 255); $g = rand(0, 255); $b = rand(0, 255); } while (imagecolorexact($src, $r, $g, $b) >= 0); $ns = $s * $q; $img = imagecreatetruecolor($ns, $ns); $alphacolor = imagecolorallocatealpha($img, $r, $g, $b, 127); imagealphablending($img, false); imagefilledrectangle($img, 0, 0, $ns, $ns, $alphacolor); imagefill($img, 0, 0, $alphacolor); imagecopyresampled($img, $src, 0, 0, 0, 0, $ns, $ns, $s, $s); imagedestroy($src); imagearc($img, $radius - 1, $radius - 1, $radius * 2, $radius * 2, 180, 270, $alphacolor); imagefilltoborder($img, 0, 0, $alphacolor, $alphacolor); imagearc($img, $ns - $radius, $radius - 1, $radius * 2, $radius * 2, 270, 0, $alphacolor); imagefilltoborder($img, $ns - 1, 0, $alphacolor, $alphacolor); imagearc($img, $radius - 1, $ns - $radius, $radius * 2, $radius * 2, 90, 180, $alphacolor); imagefilltoborder($img, 0, $ns - 1, $alphacolor, $alphacolor); imagearc($img, $ns - $radius, $ns - $radius, $radius * 2, $radius * 2, 0, 90, $alphacolor); imagefilltoborder($img, $ns - 1, $ns - 1, $alphacolor, $alphacolor); imagealphablending($img, true); imagecolortransparent($img, $alphacolor); // 缩小图片到目标尺寸 $dest = imagecreatetruecolor($s, $s); imagealphablending($dest, false); imagesavealpha($dest, true); imagefilledrectangle($dest, 0, 0, $s, $s, $alphacolor); imagecopyresampled($dest, $img, 0, 0, 0, 0, $s, $s, $ns, $ns); imagedestroy($img); // 将圆角角落复制回原图 imagealphablending($source, false); imagecopy($source, $dest, 0, 0, 0, 0, $corner, $corner); imagecopy($source, $dest, $ws - $corner, 0, $corner, 0, $corner, $corner); imagecopy($source, $dest, $ws - $corner, $hs - $corner, $corner, $corner, $corner, $corner); imagecopy($source, $dest, 0, $hs - $corner, 0, $corner, $corner, $corner); imagealphablending($source, true); imagedestroy($dest); return $source; }
正确调用示例
// 调用函数并输出图片 header('Content-Type: image/png'); $img = roundCorners("images/test.jpg", 10); imagepng($img); imagedestroy($img);
额外说明
- 修复后的函数同时支持传入图片路径字符串或已加载的GD资源,使用更灵活。
- 增加了图片格式判断和加载失败的异常抛出,便于排查问题。
- 为临时图片开启了alpha通道支持,避免圆角边缘出现黑色锯齿。
- 修正了原函数中寻找唯一颜色的逻辑错误,确保生成的透明色不会与图片原有颜色冲突。
内容的提问来源于stack exchange,提问作者wowtom16
相关产品推荐
相关产品推荐

