问题描述
我需要一个脚本,用于在提供的图像上制作圆形的透明角.我发现了一个,除了一件事情外,它工作得很好:所应用的角看起来不光滑. imageantialias()
引发致命错误,因为 PHP在Debian上运行,并且无法重新编译.
I need a script which makes rounded transparent corners on supplied image. I've found one and it works good except the one thing: the applied corners do not look smooth. The imageantialias()
throws Fatal Error since PHP is running on Debian and re-compiling it is not an option.
我发现使这些角看起来更光滑的技巧是使用 imagecopyresampled()
如下:
The trick I've found to make those corners look smooth is resizing the image with imagecopyresampled()
as the following:
- 准备图像;
- imagecopy重新采样到10倍大小;
- 用特殊颜色画角;
- 使该颜色透明;
- 将图片缩小到原始大小
- prepare the image;
- imagecopyresample it to 10x size;
- draw corners with a special colour;
- make that color transparent;
- decrease the image to it's original size
但是问题来了:结果图像(在第5步之后)的角是光滑,但是不透明.在第4步之后(即减小其尺寸之前)发送以输出图像时– 所有内容应该是.
But here comes the problem: the corners of the result image (after step 5) are smooth, but not transparent. When sending to output the image after step 4 (i.e. before decreasing it's size) – everything's as it should be.
这是代码中负责使圆角变圆的部分:
Here's the part of the code responsible for making corners rounded:
// $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()
作为,但没有结果.
So as you can see, the problem occurs when enlarged image is being imagecopyresampled to it's original size. The transparent corners get filled with the $colorcode
colour. I've been playing with imagesavealpha()
and imagealphablending()
as advised, but no result.
请帮助我完成这项工作.
Please help me to make this work.
P.S.这可能很有用:将大PNG 上传到imgur.com它转换为JPG 后,您会看到所有角落都充满了经过修复的$颜色代码.
P.S. This may be useful: when uploaded the large PNG to imgur.com it had it converted to JPG and as you can see all corners got filled with that very restored $colorcode.
P.S.希望我不会因滥用扩大"一词而被禁止使用:)
P.S. Hope I won't get banned for overusing the word "enlargement" :)
推荐答案
经过几个小时的测试并将我的头撞在墙上,我认为我已经找到了解决方案.问题在于使用imagecolorallocate()
分配透明颜色.我没有一见钟情.这是完全错误的方法.但是,imagecolorallocatealpha()
帮助了我很多.
After couple of hours of testing and kicking my head against the wall, I think I've found solution. Problem was about allocating transparent color using imagecolorallocate()
. I did not get it at first sight. It was totally wrong approach. However, imagecolorallocatealpha()
has helped me alot.
此外,在将Alpha通道保存到工作层之前,必须禁用Alpha混合.但是,必须在创建空白的真彩色图像后立即完成,例如
Also, alpha blending must be off before saving alpha channel on working layer. However, it must be done right after creating blank true-color image, like
$im = imagecreatetruecolor($w, $h);
$alphacolor = imagecolorallocatealpha($img, $r, $g, $b, 127);
imagealphablending($im, false);
imagesavealpha($im, true);
此代码是在调整大小后在透明区域获得平滑角的关键.
This code is a key for getting smooth corners in transparent area after resize-down.
毕竟,我已经编写了此函数
After all, I've wrote this function
function imageCreateCorners($sourceImageFile, $radius) {
# function body
}
我已经用几张图像对其进行了测试,对于每种bg颜色,它返回的图像均具有平滑的角.
I've tested it with couple of images and it returned image with smooth corners for every bg color.
imagepng(imageCreateCorners('jan_vesely_and_james_gist.jpg', 9), 'test.png');
输出
原始图片
它最终返回完全透明的Alpha通道,因此您可以在所需的每个背景上使用该图像.
It finally returns fully transparent alpha channel so you can use that image on every background you want.
我差点忘了发布功能代码:)
I almost forgot to post function code :)
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配合使用也很不错.
Function works with solid JPEG, GIF and PNG images. Also, it works great with transparent PNGs and GIFs.
这篇关于使用imagecopyresampled()倒圆角的透明_smooth_角PHP GD的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!