干预图片圆角上传

问题描述 投票:0回答:2

我正在尝试将我的文件上传为圆圈,但无法使其工作。 我看过一些有关对图像应用蒙版的主题,但是当我应用蒙版时,它需要很长时间并且服务器会关闭请求。

我正在使用 Laravel 的

Intervention Image

我的代码如下:

$identifier = "{$this->loggedUser->id}" . str_random(9) . ".{$file->getClientOriginalExtension()}";
$mask = $this->createCircleMask(200, 200);
$thumbMask = $this->createCircleMask(40, 40);
Image::make($file->getRealPath())->mask($mask)->save(public_path("images/profile/{$identifier}"));
Image::make($file->getRealPath())->mask($thumbMask)->save(public_path("images/profile/thumbs/{$identifier}"));

createCircleMask
方法如下所示:

public function createCircleMask($width, $height)
{
    $circle = Image::canvas($width, $height, '#000000');
    return $circle->circle($width - 1, $width / 2, $height / 2);
}
php image laravel laravel-5 intervention
2个回答
13
投票

这是一个适用于我的情况的函数。但如果我使用 imagick 驱动程序。标准 gd 库非常非常慢,至少在我的测试计算机上是这样。 您可以查看vendor\intervention\image\src\Intervention\Image\Gd\Commands\MaskCommand.php以找出原因。

public function upload() {

    $path = storage_path('app')."/";

    $image = \Image::make(\Input::file('image'));
    $image->encode('png');

    /* if you want to have a perfect and complete circle using the whole width and height the image
     must be shaped as as square. If your images are not guaranteed to be a square maybe you could
     use Intervention's fit() function */
    //  $image->fit(300,300);

    // create empty canvas
    $width = $image->getWidth();
    $height = $image->getHeight();
    $mask = \Image::canvas($width, $height);

    // draw a white circle
    $mask->circle($width, $width/2, $height/2, function ($draw) {
        $draw->background('#fff');
    });

    $image->mask($mask, false);
    $image->save($path."circled.png");

}

0
投票

对于那些在 Laravel 中使用

intervention/image
v3 的人来说,由于
mask
方法已被删除,我们可以使用自定义类来完成这项工作。

<?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;

    }
}

###用法:-

// 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);
© www.soinside.com 2019 - 2024. All rights reserved.