PHP GD How to circular crop 3 square images and merge into 1 image maintaining transparency

巧了我就是萌 提交于 2019-12-01 11:06:01

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

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

Example class usage:

// 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:

you can use ImageArtist which a GD wrapper created for making image manipulation insanely easy with 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

at the moment ImageArtist does not support borders but if you be little creative you can use an overlay instead. here is the output of the above code.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!