Мне нужен скрипт, который создает округлые прозрачные углы на поставляемом изображении. Я нашел один, и он работает хорошо, за исключением одного: применяемые углы не выглядят гладкими. imageantialias()
выдает Fatal Error, поскольку PHP работает на Debian, и повторная компиляция не является вариантом.
Трюк, который я нашел, чтобы заставить эти углы выглядеть гладкими, – это изменение размера изображения с помощью imagecopyresampled()
следующим образом:
Но здесь возникает проблема: углы изображения результата (после шага 5) являются гладкими, но не прозрачными . При отправке для вывода изображения после шага 4 (т. Е. До уменьшения его размера) – все так, как должно быть .
Вот часть кода, ответственного за округление углов:
// $ dest = ресурс изображения $ Д = 10; // делает все в 10 раз больше $ New_width = $ ширина * $ Q; $ New_height = $ высота * $ д; $ Радиус = $ радиус * $ д; $ magnified = imagecreatetruecolor ($ new_width, $ new_height); imagecopyresampled ($ magnified, $ dest, 0,0, 0,0, $ new_width, $ new_height, ($ new_width / $ q), ($ new_height / $ q)); // выбор уникального цвета $ 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); // рисование углов imagearc ($ увеличенный, $ radius-1, $ radius-1, $ radius * 2, $ radius * 2, 180, 270, $ colorcode); imagefilltoborder ($ увеличенный, 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 ($ увеличенный, $ 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); // делает уникальный цвет прозрачным imagecolortransparent ($ увеличенный, $ colorcode); // уменьшая увеличенное изображение до его первоначального размера // ожидаем, что углы останутся прозрачными imagecopyresampled ($ dest, $ magnified, 0,0, 0,0, ($ new_width / $ q), ($ new_height / $ q), $ new_width, $ new_height); // но они не // отправка $ увеличенной для вывода для целей тестирования $ Dest = $ возвеличил; // вывод $ dest как image / png
Таким образом, как вы можете видеть, проблема возникает, когда увеличенное изображение imagecopyresampled до его первоначального размера. Прозрачные углы заполняются цветом $colorcode
. Я играю с imagesavealpha()
и imagealphablending()
в соответствии с рекомендациями , но без результата.
Пожалуйста, помогите мне сделать эту работу.
PS Это может быть полезно: при загрузке большого PNG на imgur.com он преобразовал его в JPG, и, как вы можете видеть, все углы заполнены очень восстановленным $ colorcode.
PS Надеюсь, мне не будет запрещено использовать слово «расширение» ðŸ™‚
После нескольких часов тестирования и удариться головой о стену, я думаю, что нашел решение. Проблема заключалась в распределении прозрачного цвета с использованием 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');
Исходное изображение
Он, наконец, возвращает полностью прозрачный альфа-канал, поэтому вы можете использовать это изображение на каждом желаемом фоне.
Я почти забыл написать код функции 🙂
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.
... /* rounded corner */ $radius = 20; // find ghost color do { $r = rand(0, 255); $g = rand(0, 255); $b = rand(0, 255); } while (imagecolorexact($img_resource, $r, $g, $b) < 0); $ghost_color = imagecolorallocate($img_resource, $r, $g, $b); imagearc($img_resource, $radius-1, $radius-1, $radius*2, $radius*2, 180, 270, $ghost_color); imagefilltoborder($img_resource, 0, 0, $ghost_color, $ghost_color); imagearc($img_resource, $img_width-$radius, $radius-1, $radius*2, $radius*2, 270, 0, $ghost_color); imagefilltoborder($img_resource, $img_width-1, 0, $ghost_color, $ghost_color); imagearc($img_resource, $radius-1, $img_height-$radius, $radius*2, $radius*2, 90, 180, $ghost_color); imagefilltoborder($img_resource, 0, $img_height-1, $ghost_color, $ghost_color); imagearc($img_resource, $img_width-$radius, $img_height-$radius, $radius*2, $radius*2, 0, 90, $ghost_color); imagefilltoborder($img_resource, $img_width-1, $img_height-1, $ghost_color, $ghost_color); imagecolortransparent($img_resource, $ghost_color); ...
Попробуй это …