Transparent Circle Cropped Image with PHP
Solution 1
There is several things to note :
As @DainisAbols suggested, it should be better to take an unusual color to for your transparency. Here, you are using black :
$red = imagecolorallocate($mask, 0, 0, 0);
imagecopymerge($image, $mask, 0, 0, 0, 0, $this->dst_w, $this->dst_h,100);
imagecolortransparent($image, $red);
Even if your var is called red, your R-G-B value is 0-0-0. Uncommon colors include flashy blue (0-0-255), flashy green (0-255-0), flashy yellow (255-255-0), flashy cyan (0-255-255) and flashy pink (255-0-255). Red is quite common everywhere and is not that flashy so I exclude it from those special colors.
Then, even if your images here are both true color's ones, that's a good practice to allocate a color for each image. In the example above, you create a $red
variable containing black for $mask
, but you're using it as transparency color in $image
.
Finally, you are drawing an ellipse which have the same radius as your image size, so you need to imagefill
each corners of your image and not only the top-left's one. In your example it works, but this is only because you selected black to be the transparent color.
Here is a full implementation.
<?php
class CircleCrop
{
private $src_img;
private $src_w;
private $src_h;
private $dst_img;
private $dst_w;
private $dst_h;
public function __construct($img)
{
$this->src_img = $img;
$this->src_w = imagesx($img);
$this->src_h = imagesy($img);
$this->dst_w = imagesx($img);
$this->dst_h = imagesy($img);
}
public function __destruct()
{
if (is_resource($this->dst_img))
{
imagedestroy($this->dst_img);
}
}
public function display()
{
header("Content-type: image/png");
imagepng($this->dst_img);
return $this;
}
public function reset()
{
if (is_resource(($this->dst_img)))
{
imagedestroy($this->dst_img);
}
$this->dst_img = imagecreatetruecolor($this->dst_w, $this->dst_h);
imagecopy($this->dst_img, $this->src_img, 0, 0, 0, 0, $this->dst_w, $this->dst_h);
return $this;
}
public function size($dstWidth, $dstHeight)
{
$this->dst_w = $dstWidth;
$this->dst_h = $dstHeight;
return $this->reset();
}
public function crop()
{
// Intializes destination image
$this->reset();
// Create a black image with a transparent ellipse, and merge with destination
$mask = imagecreatetruecolor($this->dst_w, $this->dst_h);
$maskTransparent = imagecolorallocate($mask, 255, 0, 255);
imagecolortransparent($mask, $maskTransparent);
imagefilledellipse($mask, $this->dst_w / 2, $this->dst_h / 2, $this->dst_w, $this->dst_h, $maskTransparent);
imagecopymerge($this->dst_img, $mask, 0, 0, 0, 0, $this->dst_w, $this->dst_h, 100);
// Fill each corners of destination image with transparency
$dstTransparent = imagecolorallocate($this->dst_img, 255, 0, 255);
imagefill($this->dst_img, 0, 0, $dstTransparent);
imagefill($this->dst_img, $this->dst_w - 1, 0, $dstTransparent);
imagefill($this->dst_img, 0, $this->dst_h - 1, $dstTransparent);
imagefill($this->dst_img, $this->dst_w - 1, $this->dst_h - 1, $dstTransparent);
imagecolortransparent($this->dst_img, $dstTransparent);
return $this;
}
}
Demo :
$img = imagecreatefromjpeg("test4.jpg");
$crop = new CircleCrop($img);
$crop->crop()->display();
Result :
Solution 2
I couln't get it done with Alain's code either. After some time understanding what each line of code does, here is my fix..
//this creates a pink rectangle of the same size
$mask = imagecreatetruecolor($imgwidth, $imgheight);
$pink = imagecolorallocate($mask, 255, 0, 255);
imagefill($mask, 0, 0, $pink);
//this cuts a hole in the middle of the pink mask
$black = imagecolorallocate($mask, 0, 0, 0);
imagecolortransparent($mask, $black);
imagefilledellipse($mask, $imgwidth/2, $imgheight/2, $imgwidth, $imgheight, $black);
//this merges the mask over the pic and makes the pink corners transparent
imagecopymerge($img, $mask, 0, 0, 0, 0, $imgheight, $imgheight);
imagecolortransparent($img, $pink);
imagepng($img, "my_circle.png");
Solution 3
You are cropping and removing black color ( or setting black as transparent ). Since your image has black color in it, it also gets removed.
Instead of removing the color, try to replace the outer layers color to, ie, pink and then set it to transparent.
Larry
Updated on June 16, 2022Comments
-
Larry almost 2 years
I want to crop a circle image using PHP but it seems that my new image have some transparent pixels. Of course, I want ONLY the outside area of the ellipse to have background transparent
My code is listed below:
$image = imagecreatetruecolor($this->dst_w, $this->dst_h); imagealphablending($image,true); imagecopy ( $image , $image_s , 0, 0, $this->src_x, $this->src_y, $this->dst_w, $this->dst_h ); $mask = imagecreatetruecolor($this->src_x, $this->src_y); $mask = imagecreatetruecolor($this->dst_w, $this->dst_h); $transparent = imagecolorallocate($mask, 255, 0, 0); imagecolortransparent($mask, $transparent); imagefilledellipse($mask, $this->dst_w/2, $this->dst_h/2, $this->dst_w, $this->dst_h, $transparent); $red = imagecolorallocate($mask, 0, 0, 0); imagecopymerge($image, $mask, 0, 0, 0, 0, $this->dst_w, $this->dst_h,100); imagecolortransparent($image, $red); imagefill($image,0,0, $red); if ($ext=="jpg" || $ext=="jpeg") { imagejpeg($image, $this->croppedImage); } else if ($ext=="png") { imagepng($image, $this->croppedImage); } imagedestroy($image); imagedestroy($mask); // <------- END generate cropped Image -------> // <------- START generate transparent Image -------> $this->generateTransparentImage('circle');
......
An example of actual generated image is here:
EDIT: generateTransparentImage function has nothing to do with the code listed above; this function generate this image: http://s7.postimage.org/byybq9163/Koala7_500x375_c_transparent.png
-
hakre over 11 yearsIf you want others to play with your code, you should share the original image as well. Also the code of
generateTransparentImage
is hidden so others can not reproduce either. -
hakre over 11 yearspossible duplicate of PHP - Mask polygon over image - If you don't want to use a library, the source-code of Wideimage is free software so you can port it into your application. Otherwise, there are a lot of existing questions that show various other ways how to do that, fee free to have a look around: stackoverflow.com/search?q=%5Bphp%5D+%5Bgd%5D+mask
-
-
Ravi Jethva about 10 yearsits not transparent its give white colors in background
-
Alain Tiemblo about 10 yearshello, i just checked, and i confirm that transparency works here
-
Alain Tiemblo about 10 yearsproof: home.fuz.org/tests/test-circle-crop.php (use any background color to check if the generated image is transparent)
-
Manoj Prajapat about 4 yearsGood effort but not working as it should do please check generated image in Photoshop.
-
garrettlynchirl over 3 yearsimagecopymerge won't work in this example as the last parameter pct is missing.