Ответ 1
После нескольких часов тестирования и удара головой о стену, я думаю, что нашел решение. Проблема заключалась в распределении прозрачного цвета с помощью imagecolorallocate()
. Я не понял это с первого взгляда. Это был совершенно неправильный подход. Однако imagecolorallocatealpha()
мне очень помогло.
Кроме того, альфа-смешивание должно быть выключено перед сохранением альфа-канала на рабочем слое. Однако это необходимо сделать сразу после создания пустого изображения с истинным цветом, например
$im = imagecreatetruecolor($w, $h);
$alphacolor = imagecolorallocatealpha($img, $r, $g, $b, 127);
imagealphablending($im, false);
imagesavealpha($im, true);
Этот код является ключом для получения гладких углов в прозрачной области после изменения размера.
В конце концов, я написал эту функцию
function imageCreateCorners($sourceImageFile, $radius) {
# function body
}
Я тестировал его с помощью нескольких изображений, и он возвращал изображение с гладкими углами для каждого цвета bg.
imagepng(imageCreateCorners('jan_vesely_and_james_gist.jpg', 9), 'test.png');
Выход
Исходное изображение
В BROWSER (тот же файл png 'test.png')
Он, наконец, возвращает полностью прозрачный альфа-канал, чтобы вы могли использовать это изображение на каждом желаемом фоне.
Я почти забыл написать код функции:)
function 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.