我需要一个脚本,它可以在提供的图像上制作圆角透明角。我找到了一个,除了一件事外效果很好:应用的角看起来不光滑。 imageantialias()
自 PHP is running on Debian 后抛出 fatal error 并重新编译它不是一种选择。
我发现使这些角看起来平滑的技巧是使用 imagecopyresampled()
调整图像大小。如下所示:
- 准备图片;
- imagecopyresample 到 10 倍大小;
- 用特殊颜色画角;
- 使该颜色透明;
- 将图片缩小到原来的大小
但问题来了:结果图像的角(在第 5 步之后)是 smooth, but not transparent .在第 4 步之后发送以输出图像时(即在减小其大小之前)– everything's as it should be .
下面是负责使角变圆的代码部分:
// $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()
作为advised , 但没有结果。
请帮助我完成这项工作。
附言这可能有用:上传时 large PNG到 imgur.com 它有它 converted to JPG正如您所看到的,所有角落都充满了经过修复的 $colorcode。
附言希望我不会因为过度使用“扩大”这个词而被禁止:)
最佳答案
经过几个小时的测试并将我的头撞到墙上,我想我找到了解决方案。问题是关于使用 imagecolorallocate()
分配透明颜色。我第一眼没看懂。这是完全错误的做法。然而,imagecolorallocatealpha()
帮了我很多。
此外,在工作层上保存 alpha channel 之前,必须关闭 alpha 混合。但是,它必须在创建空白真彩色图像后立即完成,例如
$im = imagecreatetruecolor($w, $h);
$alphacolor = imagecolorallocatealpha($img, $r, $g, $b, 127);
imagealphablending($im, false);
imagesavealpha($im, true);
这段代码是在缩小尺寸后在透明区域获得光滑角的关键。
毕竟这个函数是我写的
function imageCreateCorners($sourceImageFile, $radius) {
# function body
}
我用几张图片对其进行了测试,它返回的图片每个背景颜色都带有平滑的角。
imagepng(imageCreateCorners('jan_vesely_and_james_gist.jpg', 9), 'test.png');
输出
原图
在浏览器中(相同的 png 文件 'test.png')
它最终会返回完全透明的 alpha channel ,因此您可以在任何您想要的背景上使用该图像。
我差点忘了发布功能代码:)
函数 imageCreateCorners($sourceImageFile, $radius)
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;
}
函数返回GD对象或false。
函数适用于纯 JPEG、GIF 和 PNG 图像。此外,它还适用于透明的 PNG 和 GIF。
关于php - 使用 imagecopyresampled() PHP GD 圆角透明_平滑_角,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5766865/