Давно было интересно как можно в PHP сделать с картинкой что-нибудь такое как указано в заголовке, а тут ещё и задание соответствующее попалось.
Для выполнения задания необходимо было обойтись по возможности штатными средствами PHP, потому что установка чего-то дополнительного — это отдельный процесс. Поэтому я стал искать решения в модуле GD.
Если вам, также как и мне, интересно что значит «GD», то вот ответ:
В GD 1.0, это означало «gif draw». После того как Unisys запатентовало алгоритм LZW сжатия, используемый в GIF и поддержка GIF была убрана, аббревиатура оффицально ничего не обознает, поэтому пусть просто будет «graphics draw» и всё. (поддержка GIF возвращена, благодаря тому что срок действия патента истёк, но GD может гораздо больше чем создание GIF)
Итак, нужно закруглить края картинки причём с прозрачностью. Для этого необходимо воспользоваться дополнительной картинкой такого же размера. Потому что по углам нужно создать области равномерно залитые одним, прозрачным цветом.
На исходной картинке такое сделать нельзя, потому что заливка возможна только либо при создании примитива (заполненный эллипс или заполненный прямоугольник), либо на области равномерно закрашенной каким-либо одним цветом.
- на временной картинке рисую те части, которые должны стать прозрачными в результате;
- накладываю на исходное изображение;
- по нужным координатам заполняю прозрачным цветом (результат вверху).
Чтобы прозрачность работала, у исходной картинки необходимо установить соответствующий флаг при помощи функции:
imagesavealpha($img_res, true);
, а вот наличие альфа канала у временного изображения не важно (я использовал true color, потому что в этом случае на один вызов функции imagecolortransparent() меньше).
Решение:
class ImgUtils { public static function imageToRes($img_file) { $img_res = false; list($tmp, $tmp, $type) = getimagesize($img_file); switch ($type) { case 2: // JPEG $img_res = imagecreatefromjpeg($img_file); break; case 1: // GIF $img_res = imagecreatefromgif($img_file); break; case 3: // PNG $img_res = imagecreatefrompng($img_file); break; } return $img_res; } public static function roundedCorners($img_res, $radius) { $width = imagesx($img_res); $height = imagesy($img_res); imagesavealpha($img_res, true); // corners START $img_tmp = imagecreate($width, $height); $black = imagecolorallocate($img_tmp, 0, 0, 0); $transp = imagecolorallocatealpha($img_tmp, 0, 0, 0, 127); imagefill($img_tmp, $width / 2, $height / 2, $transp); // left upper imagearc($img_tmp, $radius / 2 - 1, $radius / 2 - 1, $radius, $radius, 180, 270, $black); imagefill($img_tmp, 0, 0, $black); // right upper imagearc($img_tmp, $width - $radius / 2, $radius / 2 - 1, $radius, $radius, 270, 0, $black); imagefill($img_tmp, $width - 1, 0, $black); // right lower imagearc($img_tmp, $width - $radius / 2, $height - $radius / 2, $radius, $radius, 0, 90, $black); imagefill($img_tmp, $width - 1, $height - 1, $black); // left lower imagearc($img_tmp, $radius / 2 - 1, $height - $radius / 2, $radius, $radius, 90, 180, $black); imagefill($img_tmp, 0, $height - 1, $black); // corners END imagecopyresampled($img_res, $img_tmp, 0, 0, 0, 0, $width, $height, $width, $height); $transp = imagecolorallocatealpha($img_res, 0, 0, 0, 127); imagefill($img_res, 0, 0, $transp); imagefill($img_res, $width - 1, 0, $transp); imagefill($img_res, $width - 1, $height - 1, $transp); imagefill($img_res, 0, $height - 1, $transp); imagedestroy($img_tmp); return $img_res; } }
Изначально я пытался нарисовать «уголки» на временном изображении при помощи одного прямоугольника и одного эллипса наложенного поверх. Оказалось что в таких условиях трудно контролировать радиусь углов — тогда я стал рисовать на каждый угол по своей окружности.
Фотографию предоставила Анастасия Мельникова (StacyLV).
Фотографию предоставила Анастасия Мельникова (StacyLV).
А можно пример кода использования, для новичков в php?
ОтветитьУдалитьНапример:
ОтветитьУдалить<?php
require_once 'imgutils.php';
header("content-type:image/png");
$img_res = ImgUtils::roundedCorners( ImgUtils::imageToRes('example.png'), 80);
echo imagepng($img_res);
?>