For those who are using intervention/image
v3 in Laravel since the mask
method has been removed, we can use a custom class to do the job.
<?php
namespace App\Helpers\Image;
class CircleImage
{
public $img;
public $width;
public $height;
public $minSize;
public function __construct($img = null)
{
if (!empty($img)) {
$this->img = imagecreatefromstring($img);
$this->width = imagesx($this->img); // Image original width
$this->height = imagesy($this->img); // Image original height
// Get the minimum size
// This will help cut the image in a circular shape
$this->minSize = min($this->width, $this->height);
}
}
public function make(): string
{
$radius = $this->minSize / 2;
// First we crop the image from center
$cropped = imagecrop($this->img, [
// Calculation summary:
// here width/2 gives us the center point, suppose our image width is 200,
// Then the center point is 100, now we want our cropping to start
// at negative $radius from 100 and end at positive $radius from 100,
// So that it crops from the center part into a square with the
// Diameter same as minSize (Same for height)
"x" => $this->width / 2 - $radius,
"y" => $this->height / 2 - $radius,
"width" => $this->minSize, // Diameter
"height" => $this->minSize, // Diameter
]);
if ($cropped !== false) { // in case a new image object was returned
imagedestroy($this->img); // we destroy the original image
$this->img = $cropped; // and assign the cropped image
} else {
throw new \Exception("Failed to crop the image!", 500);
}
// Now create the circular mask
$mask = imagecreatetruecolor($this->minSize, $this->minSize);
$black = imagecolorallocate($mask, 0, 0, 0);
$magenta = imagecolorallocate($mask, 255, 0, 255);
// Fill with magenta color
imagefill($mask, 0, 0, $magenta);
// Create a black circle in the center
imagefilledellipse(
$mask,
$radius,
$radius,
$this->minSize,
$this->minSize,
$black
);
// Now make the black circle part transparent
imagecolortransparent($mask, $black);
// Merge the two images so that only the transparent
// part shows the image and other parts become magenta solid
imagecopymerge(
$this->img,
$mask,
0,
0,
0,
0,
$this->minSize,
$this->minSize,
100
);
// Now make the magenta part transparent
// It now only keeps the center transparent(prev=black) part
// of the original image visible
imagecolortransparent($this->img, $magenta);
// Destroy the mask
imagedestroy($mask);
return $this->render();
}
public function render(): string
{
// Get the string content
// Of the generated image & return
ob_start();
imagepng($this->img);
$imagedata = ob_get_clean();
return $imagedata;
}
}
###Usage:-
// First we scale the image to a smaller size, otherwise the circular crop may time out and get the string value
$image = InterventionImage::read($image)->scale(300, null)->encodeByMediaType(type: "image/png", quality: 90)->toString();
// Now simply Crop the image as a circle with our helper class
$circleImage = new CircleImage($image);
$image = $circleImage->make();
// It returns the png string image content, either convert to base64 or simply put to the storage Like below:-
// Storage: Storage::put("picture/avatar.png", $image);
// base64_encode($image);