PHP GD如何圆形裁剪3个正方形图像并合并为1个图像,以保持透明度 [英] PHP GD How to circular crop 3 square images and merge into 1 image maintaining transparency

查看:105
本文介绍了PHP GD如何圆形裁剪3个正方形图像并合并为1个图像,以保持透明度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有2张原始图片,并且想要:

I have 2 source images and I want to:

  1. 对每个图像进行圆形裁剪,使圆形的外部透明
  2. 合并/复制所有图像回到目标透明图像.

我尝试了许多示例,但似乎无法维护最终图像的透明度.

I have tried many examples, but can't seem to maintain transparency on the final image.

我正在尝试实现以下目标:

I'm trying to achieve something like this:

这是我得到的输出的示例:

This is an example of the output I am getting:

这是我的circle_crop函数:

Here's my circle_crop function:

    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函数循环返回裁剪后的图像并将其合并到我的目标图像中.

Here's the code I pass in an array of image URL's and loop through calling the circle_crop function to return a cropped image and merge it onto my destination image.

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 );
}

我已经把头发拉了两天了,所以任何指尖都将不胜感激.

I've pulled my hair out for 2 days, so any pointers would be greatly appreciated.

谢谢杰森.

推荐答案

我编写了以下类来处理所有必需的图像处理:

I've written the following class to handle all the required image processing:

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文件,但如果需要,您应该能够轻松地对其进行修改.

As written, the class will only work with PNG files but you should be able to modify this easily enough, if required.

类用法示例:

// 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();

这将导致下面的图像(当然,将其嵌入此处时看不到透明性,因此请尝试单独打开图像):

This will result in the below image (of course, the transparency is impossible to see when embedded here so try opening the image separately):

我使用了以下两个源图像:

I used these two source images:

这篇关于PHP GD如何圆形裁剪3个正方形图像并合并为1个图像,以保持透明度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆