aex*_*exl 11 php png transparency gd rounded-corners
我需要一个脚本,在提供的图像上形成圆角透明角.我找到了一个,它除了一件事之外它的效果很好:应用的角落看起来不平滑.imageantialias()由于PHP在Debian上运行并且重新编译它不是一个选项,因此抛出致命错误.
我发现使这些角落看起来平滑的技巧是调整图像大小imagecopyresampled(),如下所示:
但问题出现了:结果图像的角落(在步骤5之后)是平滑的,但不是透明的.当在步骤4之后发送输出图像时(即在减小它的尺寸之前) - 一切都应该如此.
这是负责使角落四舍五入的代码的一部分:
// $dest = image resource
$q=10;
// making everything 10x bigger
$new_width=$width*$q;
$new_height=$height*$q;
$radius=$radius*$q;
$magnified=imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($magnified, $dest, 0,0, 0,0, $new_width,$new_height, ($new_width/$q),($new_height/$q));
// picking the unique colour
$found = false;
while($found == false) {
$r = rand(0, 255);
$g = rand(0, 255);
$b = rand(0, 255);
if(imagecolorexact($magnified, $r, $g, $b) != (-1)) {
$found = true;
}
}
$colorcode = imagecolorallocate($magnified, $r, $g, $b);
// drawing corners
imagearc($magnified, $radius-1, $radius-1, $radius*2, $radius*2, 180, 270, $colorcode);
imagefilltoborder($magnified, 0, 0, $colorcode, $colorcode);
imagearc($magnified, $new_width-$radius, $radius-1, $radius*2, $radius*2, 270, 0, $colorcode);
imagefilltoborder($magnified, $new_width-1, 0, $colorcode, $colorcode);
imagearc($magnified, $radius-1, $new_height-$radius, $radius*2, $radius*2, 90, 180, $colorcode);
imagefilltoborder($magnified, 0, $new_height-1, $colorcode, $colorcode);
imagearc($magnified, $new_width-$radius, $new_height-$radius, $radius*2, $radius*2, 0, 90, $colorcode);
imagefilltoborder($magnified, $new_width-1, $new_height-1, $colorcode, $colorcode);
// making the unique colour transparent
imagecolortransparent($magnified, $colorcode);
// scaling down the enlarged image to it's original size
// expecting corners to remain transparent
imagecopyresampled($dest, $magnified, 0,0, 0,0, ($new_width/$q),($new_height/$q), $new_width,$new_height);
// but they're not
// sending $magnified to output for testing purposes
$dest=$magnified;
// outputting $dest as image/png
因此,您可以看到,当放大的图像被图像复制到其原始大小时,会出现问题.透明的角落充满了$colorcode颜色.我一直在玩,imagesavealpha()并imagealphablending()按照建议,但没有结果.
请帮我完成这项工作.
PS这可能很有用:当将大型PNG上传到imgur.com时,它已将其转换为JPG,因为您可以看到所有角落都填充了非常恢复的$ colorcode.
PS希望我不会因过度使用"放大"这个词而被禁止:)
Wh1*_*Ck5 21
经过几个小时的测试并将我的头靠在墙上,我想我已经找到了解决方案.问题是关于使用分配透明颜色imagecolorallocate().我没有一见钟情.这是完全错误的方法.但是,imagecolorallocatealpha()帮了我很多.
此外,在工作层上保存Alpha通道之前,必须关闭Alpha混合.但是,必须在创建空白真彩色图像后立即完成
$im = imagecreatetruecolor($w, $h);
$alphacolor = imagecolorallocatealpha($img, $r, $g, $b, 127);
imagealphablending($im, false);
imagesavealpha($im, true);
Run Code Online (Sandbox Code Playgroud)
此代码是在调整大小后获得透明区域中平滑角的关键.
毕竟,我写过这个函数
function imageCreateCorners($sourceImageFile, $radius) {
# function body
}
Run Code Online (Sandbox Code Playgroud)
我用几个图像测试了它,它返回了每个bg颜色有光滑角落的图像.
imagepng(imageCreateCorners('jan_vesely_and_james_gist.jpg', 9), 'test.png');
Run Code Online (Sandbox Code Playgroud)
原始图像


它最终返回完全透明的alpha通道,因此您可以在所需的每个背景上使用该图像.
我差点忘了发布功能代码:)
function imageCreateCorners($sourceImageFile, $radius) {
# test source image
if (file_exists($sourceImageFile)) {
$res = is_array($info = getimagesize($sourceImageFile));
}
else $res = false;
# open image
if ($res) {
$w = $info[0];
$h = $info[1];
switch ($info['mime']) {
case 'image/jpeg': $src = imagecreatefromjpeg($sourceImageFile);
break;
case 'image/gif': $src = imagecreatefromgif($sourceImageFile);
break;
case 'image/png': $src = imagecreatefrompng($sourceImageFile);
break;
default:
$res = false;
}
}
# create corners
if ($res) {
$q = 10; # 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);
$nw = $w*$q;
$nh = $h*$q;
$img = imagecreatetruecolor($nw, $nh);
$alphacolor = imagecolorallocatealpha($img, $r, $g, $b, 127);
imagealphablending($img, false);
imagesavealpha($img, true);
imagefilledrectangle($img, 0, 0, $nw, $nh, $alphacolor);
imagefill($img, 0, 0, $alphacolor);
imagecopyresampled($img, $src, 0, 0, 0, 0, $nw, $nh, $w, $h);
imagearc($img, $radius-1, $radius-1, $radius*2, $radius*2, 180, 270, $alphacolor);
imagefilltoborder($img, 0, 0, $alphacolor, $alphacolor);
imagearc($img, $nw-$radius, $radius-1, $radius*2, $radius*2, 270, 0, $alphacolor);
imagefilltoborder($img, $nw-1, 0, $alphacolor, $alphacolor);
imagearc($img, $radius-1, $nh-$radius, $radius*2, $radius*2, 90, 180, $alphacolor);
imagefilltoborder($img, 0, $nh-1, $alphacolor, $alphacolor);
imagearc($img, $nw-$radius, $nh-$radius, $radius*2, $radius*2, 0, 90, $alphacolor);
imagefilltoborder($img, $nw-1, $nh-1, $alphacolor, $alphacolor);
imagealphablending($img, true);
imagecolortransparent($img, $alphacolor);
# resize image down
$dest = imagecreatetruecolor($w, $h);
imagealphablending($dest, false);
imagesavealpha($dest, true);
imagefilledrectangle($dest, 0, 0, $w, $h, $alphacolor);
imagecopyresampled($dest, $img, 0, 0, 0, 0, $w, $h, $nw, $nh);
# output image
$res = $dest;
imagedestroy($src);
imagedestroy($img);
}
return $res;
}
Run Code Online (Sandbox Code Playgroud)
函数返回GD对象或false.
功能适用于纯JPEG,GIF和PNG图像.此外,它适用于透明的PNG和GIF.
改进了@Wh1T3h4Ck5 的代码。此功能拍摄图像并为其制作圆角,不会浪费内存。它还必须在大图像上运行得更快。例如,原始代码中 1024*1024 图像需要 400MB 临时图像。现在只有 230 KB。(如果您使用半径 10 像素)。
函数获取 GD 图像对象,以 px 为单位的半径并返回 GD 图像对象。目前它与原始 GD 图像对象相同。
函数假设图像的尺寸从半径来看更大。确切地说,它需要从($radius + 2)*2任何一侧都更大(或等于)。
还为此图像imagealphablending设置了功能。true如果您需要保存为 png,请不要忘记设置imagesavealpha为true.
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;
}
Run Code Online (Sandbox Code Playgroud)