У меня есть 2 исходных изображения, и я хочу:
Я пробовал много примеров , но не могу сохранить прозрачность на конечном изображении.
Я пытаюсь добиться чего-то вроде этого:
Это пример вывода, который я получаю:
Вот моя функция circle_crop:
function create_circle( $img_path ) { // Attribution: by NerdsOfTech // Step 1 - Start with image as layer 1 (canvas). if (! $img1 = $this->imageCreateFromAny( $img_path )) { return FALSE; } $x=imagesx($img1); $y=imagesy($img1); // Step 2 - Create a blank image. $img2 = imagecreatetruecolor($x, $y); $bg = imagecolorallocate($img2, 255,0,255, 127); // wierdo pink background // $bg = imagecolorallocate($img2, 0, 0, 0, 127 ); // white background imagefill($img2, 0, 0, $bg); imagecolortransparent($img2, $bg); // Step 3 - Create the ellipse OR circle mask. $e = imagecolorallocate($img2, 255, 255, 255); // black mask color // Draw a ellipse mask imagefilledellipse ($img2, ($x/2), ($y/2), $x, $y, $e); // OR // Draw a circle mask // $r = $x <= $y ? $x : $y; // use smallest side as radius & center shape // imagefilledellipse ($img2, ($x/2), ($y/2), $r, $r, $e); // Step 4 - Make shape color transparent imagecolortransparent($img2, $e); // Step 5 - Merge the mask into canvas with 100 percent opacity imagecopymerge($img1, $img2, 0, 0, 0, 0, $x, $y, 100); // Step 6 - Make outside border color around circle transparent imagecolortransparent($img1, $bg); /* Clean up memory */ imagedestroy($img2); return $img1; }
Вот код, который я передаю в массив URL-адресов изображений и цикл через вызов функции circle_crop, чтобы вернуть обрезанное изображение и объединить его на моем целевом изображении.
function generate_collage( $img_name_path_array, $effect = 'POLAROID' ) { $base_img_width = 800; $base_img_height = 650; if (empty($img_name_path_array)) { error_log('Image name_path_array is blank?'.PHP_EOL); return FALSE; } $effect = strtoupper($effect); /* Create canvas */ $collage_img = imagecreatetruecolor($base_img_width, $base_img_height); imagealphablending($collage_img, false); imagesavealpha($collage_img,true); /* Create alpha channel for transparent layer */ $trans_col=imagecolorallocatealpha($collage_img,255,255,255, 127); /* Create overlapping transparent layer */ imagefilledrectangle($collage_img,0,0,$base_img_width,$base_img_height,$trans_col); /* Continue to keep layers transparent */ imagealphablending($collage_img,true); $size_reduction = .80; $start_size = 100; foreach ($img_name_path_array as $image_array ) { $img_text = $image_array[0]; $img_path = $image_array[1]; if (! empty($img_path)) { switch ($effect) { /* Add other collage image effects here */ case 'POLAROID' : { $temp_img = $this->create_polaroid($img_path, $img_text, TRUE); break; } case 'CIRCLES' : { // $temp_img = $this->circle_crop($img_path); $temp_img = $this->create_circle($img_path); break; } default : { /* Default to polaroid for now */ $temp_img = $this->create_polaroid($img_path, $img_text, TRUE); break; } } if ($temp_img) { /* Get original height and width paramaters */ $source_w = imagesx($temp_img); $source_h = imagesy($temp_img); /* Randomise X and Y coordinates */ $random_x_pos = rand(0, (int) ($base_img_width * .66)); $random_y_pos = rand(0, (int) ($base_img_height * .3)); /* Randomise image size */ $start_size = ($start_size * $size_reduction); $random_img_size_ratio = $start_size / 100; /* Add generated image to base collage image */ imagecopyresampled($collage_img, $temp_img, $random_x_pos, $random_y_pos, 0, 0, ($base_img_width * $random_img_size_ratio), ($base_img_height * $random_img_size_ratio), $source_w, $source_h); imagecolortransparent($collage_img, $trans_col); /* Keep transparent when saving */ imagesavealpha($collage_img,true); /* Memory clean up */ imagedestroy($temp_img); // break; } } } /* Now display PNG to browser */ $this->show_png_from_image_object($collage_img); }
Вот моя функция отображения:
function show_png_from_image_object( $img_obj ) { header ( 'Content-Type: image/png' ); /* Display PNG with max compression */ imagepng ( $img_obj, NULL, 9, PNG_ALL_FILTERS); imagedestroy ( $img_obj ); }
Я вытащил свои волосы в течение 2 дней, поэтому любые указатели будут очень благодарны.
Спасибо, Джейсон.
Я написал следующий класс для обработки всей необходимой обработки изображений:
class Img { public $img; public $transparent; public $width; public $height; public function __construct($img = null) { if (!empty($img)) { $this->img = imagecreatefrompng($img); $this->width = imagesx($this->img); $this->height = imagesy($this->img); $this->setTransparentColour(); } } public function create($width, $height, $transparent) { $this->img = imagecreatetruecolor($width, $height); $this->width = $width; $this->height =$height; $this->setTransparentColour(); if (true === $transparent) { imagefill($this->img, 0, 0, $this->transparent); } } public function setTransparentColour($red = 255, $green = 0, $blue = 255) { $this->transparent = imagecolorallocate($this->img, $red, $green, $blue); imagecolortransparent($this->img, $this->transparent); } public function circleCrop() { $mask = imagecreatetruecolor($this->width, $this->height); $black = imagecolorallocate($mask, 0, 0, 0); $magenta = imagecolorallocate($mask, 255, 0, 255); imagefill($mask, 0, 0, $magenta); imagefilledellipse( $mask, ($this->width / 2), ($this->height / 2), $this->width, $this->height, $black ); imagecolortransparent($mask, $black); imagecopymerge($this->img, $mask, 0, 0, 0, 0, $this->width, $this->height, 100); imagedestroy($mask); } public function merge(Img $in, $dst_x = 0, $dst_y = 0) { imagecopymerge( $this->img, $in->img, $dst_x, $dst_y, 0, 0, $in->width, $in->height, 100 ); } public function render() { header('Content-type: image/png'); imagepng($this->img); } }
-class Img { public $img; public $transparent; public $width; public $height; public function __construct($img = null) { if (!empty($img)) { $this->img = imagecreatefrompng($img); $this->width = imagesx($this->img); $this->height = imagesy($this->img); $this->setTransparentColour(); } } public function create($width, $height, $transparent) { $this->img = imagecreatetruecolor($width, $height); $this->width = $width; $this->height =$height; $this->setTransparentColour(); if (true === $transparent) { imagefill($this->img, 0, 0, $this->transparent); } } public function setTransparentColour($red = 255, $green = 0, $blue = 255) { $this->transparent = imagecolorallocate($this->img, $red, $green, $blue); imagecolortransparent($this->img, $this->transparent); } public function circleCrop() { $mask = imagecreatetruecolor($this->width, $this->height); $black = imagecolorallocate($mask, 0, 0, 0); $magenta = imagecolorallocate($mask, 255, 0, 255); imagefill($mask, 0, 0, $magenta); imagefilledellipse( $mask, ($this->width / 2), ($this->height / 2), $this->width, $this->height, $black ); imagecolortransparent($mask, $black); imagecopymerge($this->img, $mask, 0, 0, 0, 0, $this->width, $this->height, 100); imagedestroy($mask); } public function merge(Img $in, $dst_x = 0, $dst_y = 0) { imagecopymerge( $this->img, $in->img, $dst_x, $dst_y, 0, 0, $in->width, $in->height, 100 ); } public function render() { header('Content-type: image/png'); imagepng($this->img); } }
Как написано, класс будет работать только с файлами PNG, но вы должны иметь возможность модифицировать его достаточно легко, если это необходимо.
Пример использования класса:
// create a transparent base image that we will merge the cropped images into. $img = new Img(); $img->create(400, 400, true); // first image; crop and merge with base. $img2 = new Img('./crop_1.png'); $img2->circleCrop(); $img->merge($img2, 50, 50); // second image; crop and merge with base. $img3 = new Img('./crop_2.png'); $img3->circleCrop(); $img->merge($img3, 25, 200); $img->render();
Это приведет к изображению ниже (разумеется, прозрачность невозможно увидеть, когда она встроена, поэтому попробуйте открыть изображение отдельно):
Я использовал эти два исходных изображения:
вы можете использовать ImageArtist, который создала оболочка GD для безупречного управления изображением с помощью php
$overlay = new Overlay(720, 480, new Color(34,34,36)); $w = $overlay->getWidth(); $h = $overlay->getHeight(); $mi = new CircularShape("./mi.jpg"); $mi->scale(21); $mi->setAxises(60,60); $mi->build(); $mali = new CircularShape("./mali.jpg"); $mali->scale(60); $mali->setAxises(140,140); $mali->build(); $bach = new CircularShape("./har.jpeg"); $bach->scale(40); $bach->setAxises(80,80); $bach->build(); $borderd = new CircularShape(new Overlay($bach->getWidth()+10,$bach->getHeight()+10,new Color(255,255,255))); $borderd->build(); $bach = $borderd->merge($bach,5,5); $img = $overlay->merge($mi,$w/2 + 60,120); $img->merge($mali,170,60); $img->merge($bach,$w/2,200); $img->dump(); //this just for demo, but you can use other methods to save this to disk
на данный момент ImageArtist не поддерживает границы, но если вы немного креативны, вы можете использовать наложение вместо этого. здесь приведен результат вышеприведенного кода.