You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助修复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

问题分析与修复

  1. 核心错误原因:原函数的$source参数要求是GD图像资源,但调用时传入的是图片路径字符串,导致所有依赖资源的GD函数报错。
  2. 额外问题:原函数中寻找唯一颜色的循环判断逻辑写反了,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 00:34:55