mirror of
https://github.com/Intervention/image.git
synced 2025-08-19 12:11:26 +02:00
Add DrawRectangleModifier
This commit is contained in:
@@ -21,6 +21,15 @@ abstract class AbstractImage implements ImageInterface
|
|||||||
use CanHandleInput;
|
use CanHandleInput;
|
||||||
use CanRunCallback;
|
use CanRunCallback;
|
||||||
|
|
||||||
|
public function eachFrame(callable $callback): self
|
||||||
|
{
|
||||||
|
foreach ($this as $frame) {
|
||||||
|
$callback($frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function getSize(): SizeInterface
|
public function getSize(): SizeInterface
|
||||||
{
|
{
|
||||||
return new Rectangle($this->getWidth(), $this->getHeight());
|
return new Rectangle($this->getWidth(), $this->getHeight());
|
||||||
@@ -210,6 +219,14 @@ abstract class AbstractImage implements ImageInterface
|
|||||||
return $this->modify($modifier);
|
return $this->modify($modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function drawRectangle(int $x, int $y, ?callable $init = null): ImageInterface
|
||||||
|
{
|
||||||
|
$rectangle = $this->runCallback($init, new Rectangle(0, 0));
|
||||||
|
$modifier = $this->resolveDriverClass('Modifiers\DrawRectangleModifier', new Point($x, $y), $rectangle);
|
||||||
|
|
||||||
|
return $this->modify($modifier);
|
||||||
|
}
|
||||||
|
|
||||||
public function resize(?int $width = null, ?int $height = null): ImageInterface
|
public function resize(?int $width = null, ?int $height = null): ImageInterface
|
||||||
{
|
{
|
||||||
return $this->modify(
|
return $this->modify(
|
||||||
|
19
src/Drivers/Abstract/Modifiers/AbstractDrawModifier.php
Normal file
19
src/Drivers/Abstract/Modifiers/AbstractDrawModifier.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Intervention\Image\Drivers\Abstract\Modifiers;
|
||||||
|
|
||||||
|
use Intervention\Image\Interfaces\DrawableInterface;
|
||||||
|
use Intervention\Image\Interfaces\PointInterface;
|
||||||
|
use Intervention\Image\Traits\CanHandleInput;
|
||||||
|
|
||||||
|
class AbstractDrawModifier
|
||||||
|
{
|
||||||
|
use CanHandleInput;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
protected PointInterface $position,
|
||||||
|
protected DrawableInterface $drawable
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
71
src/Drivers/Gd/Modifiers/DrawRectangleModifier.php
Normal file
71
src/Drivers/Gd/Modifiers/DrawRectangleModifier.php
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||||
|
|
||||||
|
use Intervention\Image\Drivers\Abstract\Modifiers\AbstractDrawModifier;
|
||||||
|
use Intervention\Image\Exceptions\DecoderException;
|
||||||
|
use Intervention\Image\Geometry\Rectangle;
|
||||||
|
use Intervention\Image\Interfaces\ImageInterface;
|
||||||
|
use Intervention\Image\Interfaces\ModifierInterface;
|
||||||
|
|
||||||
|
class DrawRectangleModifier extends AbstractDrawModifier implements ModifierInterface
|
||||||
|
{
|
||||||
|
public function apply(ImageInterface $image): ImageInterface
|
||||||
|
{
|
||||||
|
$image->eachFrame(function ($frame) {
|
||||||
|
// draw background
|
||||||
|
if ($this->rectangle()->hasBackgroundColor()) {
|
||||||
|
imagefilledrectangle(
|
||||||
|
$frame->getCore(),
|
||||||
|
$this->position->getX(),
|
||||||
|
$this->position->getY(),
|
||||||
|
$this->position->getX() + $this->rectangle()->bottomRightPoint()->getY(),
|
||||||
|
$this->position->getY() + $this->rectangle()->bottomRightPoint()->getY(),
|
||||||
|
$this->getBackgroundColor()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->rectangle()->hasBorder()) {
|
||||||
|
// draw border
|
||||||
|
imagesetthickness($frame->getCore(), $this->rectangle()->getBorderSize());
|
||||||
|
imagerectangle(
|
||||||
|
$frame->getCore(),
|
||||||
|
$this->position->getX(),
|
||||||
|
$this->position->getY(),
|
||||||
|
$this->position->getX() + $this->rectangle()->bottomRightPoint()->getY(),
|
||||||
|
$this->position->getY() + $this->rectangle()->bottomRightPoint()->getY(),
|
||||||
|
$this->getBorderColor()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return $image;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function rectangle(): Rectangle
|
||||||
|
{
|
||||||
|
return $this->drawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getBackgroundColor(): int
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$color = $this->handleInput($this->rectangle()->getBackgroundColor());
|
||||||
|
} catch (DecoderException $e) {
|
||||||
|
return 2130706432; // transparent
|
||||||
|
}
|
||||||
|
|
||||||
|
return $color->toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getBorderColor(): int
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$color = $this->handleInput($this->rectangle()->getBorderColor());
|
||||||
|
} catch (DecoderException $e) {
|
||||||
|
return 2130706432; // transparent
|
||||||
|
}
|
||||||
|
|
||||||
|
return $color->toInt();
|
||||||
|
}
|
||||||
|
}
|
76
src/Drivers/Imagick/Modifiers/DrawRectangleModifier.php
Normal file
76
src/Drivers/Imagick/Modifiers/DrawRectangleModifier.php
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||||
|
|
||||||
|
use ImagickDraw;
|
||||||
|
use ImagickPixel;
|
||||||
|
use Intervention\Image\Drivers\Abstract\Modifiers\AbstractDrawModifier;
|
||||||
|
use Intervention\Image\Interfaces\ImageInterface;
|
||||||
|
use Intervention\Image\Interfaces\ModifierInterface;
|
||||||
|
use Intervention\Image\Drivers\Imagick\Color;
|
||||||
|
use Intervention\Image\Exceptions\DecoderException;
|
||||||
|
use Intervention\Image\Geometry\Rectangle;
|
||||||
|
|
||||||
|
class DrawRectangleModifier extends AbstractDrawModifier implements ModifierInterface
|
||||||
|
{
|
||||||
|
public function apply(ImageInterface $image): ImageInterface
|
||||||
|
{
|
||||||
|
// setup rectangle
|
||||||
|
$drawing = new ImagickDraw();
|
||||||
|
$drawing->setFillColor($this->getBackgroundColor());
|
||||||
|
if ($this->rectangle()->hasBorder()) {
|
||||||
|
$drawing->setStrokeColor($this->getBorderColor());
|
||||||
|
$drawing->setStrokeWidth($this->rectangle()->getBorderSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
// build rectangle
|
||||||
|
$drawing->rectangle(
|
||||||
|
$this->position->getX(),
|
||||||
|
$this->position->getY(),
|
||||||
|
$this->position->getX() + $this->rectangle()->bottomRightPoint()->getX(),
|
||||||
|
$this->position->getY() + $this->rectangle()->bottomRightPoint()->getY()
|
||||||
|
);
|
||||||
|
|
||||||
|
$image->eachFrame(function ($frame) use ($drawing) {
|
||||||
|
$frame->getCore()->drawImage($drawing);
|
||||||
|
});
|
||||||
|
|
||||||
|
return $image;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function rectangle(): Rectangle
|
||||||
|
{
|
||||||
|
return $this->drawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getBackgroundColor(): ImagickPixel
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$color = $this->handleInput($this->rectangle()->getBackgroundColor());
|
||||||
|
} catch (DecoderException $e) {
|
||||||
|
$color = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->filterImagickPixel($color);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getBorderColor(): ImagickPixel
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$color = $this->handleInput($this->rectangle()->getBorderColor());
|
||||||
|
} catch (DecoderException $e) {
|
||||||
|
$color = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->filterImagickPixel($color);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function filterImagickPixel($color): ImagickPixel
|
||||||
|
{
|
||||||
|
if (!is_a($color, Color::class)) {
|
||||||
|
return new ImagickPixel('transparent');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $color->getPixel();
|
||||||
|
}
|
||||||
|
}
|
@@ -3,11 +3,17 @@
|
|||||||
namespace Intervention\Image\Geometry;
|
namespace Intervention\Image\Geometry;
|
||||||
|
|
||||||
use Intervention\Image\Geometry\Tools\RectangleResizer;
|
use Intervention\Image\Geometry\Tools\RectangleResizer;
|
||||||
|
use Intervention\Image\Geometry\Traits\HasBackgroundColor;
|
||||||
|
use Intervention\Image\Geometry\Traits\HasBorder;
|
||||||
|
use Intervention\Image\Interfaces\DrawableInterface;
|
||||||
use Intervention\Image\Interfaces\PointInterface;
|
use Intervention\Image\Interfaces\PointInterface;
|
||||||
use Intervention\Image\Interfaces\SizeInterface;
|
use Intervention\Image\Interfaces\SizeInterface;
|
||||||
|
|
||||||
class Rectangle extends Polygon implements SizeInterface
|
class Rectangle extends Polygon implements SizeInterface, DrawableInterface
|
||||||
{
|
{
|
||||||
|
use HasBorder;
|
||||||
|
use HasBackgroundColor;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
int $width,
|
int $width,
|
||||||
int $height,
|
int $height,
|
||||||
@@ -20,11 +26,26 @@ class Rectangle extends Polygon implements SizeInterface
|
|||||||
$this->addPoint(new Point($this->pivot->getX(), $this->pivot->getY() - $height));
|
$this->addPoint(new Point($this->pivot->getX(), $this->pivot->getY() - $height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the rectangle dimensions to given width & height
|
||||||
|
*
|
||||||
|
* @param int $width
|
||||||
|
* @param int $height
|
||||||
|
* @return Rectangle
|
||||||
|
*/
|
||||||
public function setSize(int $width, int $height): self
|
public function setSize(int $width, int $height): self
|
||||||
{
|
{
|
||||||
return $this->setWidth($width)->setHeight($height);
|
return $this->setWidth($width)->setHeight($height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of self::setSize()
|
||||||
|
*/
|
||||||
|
public function size(int $width, int $height): self
|
||||||
|
{
|
||||||
|
return $this->setSize($width, $height);
|
||||||
|
}
|
||||||
|
|
||||||
public function setWidth(int $width): self
|
public function setWidth(int $width): self
|
||||||
{
|
{
|
||||||
$this[1]->setX($this[0]->getX() + $width);
|
$this[1]->setX($this[0]->getX() + $width);
|
||||||
@@ -205,6 +226,16 @@ class Rectangle extends Polygon implements SizeInterface
|
|||||||
return $this->getWidth() < $this->getHeight();
|
return $this->getWidth() < $this->getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function topLeftPoint(): PointInterface
|
||||||
|
{
|
||||||
|
return $this->points[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bottomRightPoint(): PointInterface
|
||||||
|
{
|
||||||
|
return $this->points[2];
|
||||||
|
}
|
||||||
|
|
||||||
protected function getResizer(?int $width = null, ?int $height = null): RectangleResizer
|
protected function getResizer(?int $width = null, ?int $height = null): RectangleResizer
|
||||||
{
|
{
|
||||||
return new RectangleResizer($width, $height);
|
return new RectangleResizer($width, $height);
|
||||||
|
30
src/Geometry/Traits/HasBackgroundColor.php
Normal file
30
src/Geometry/Traits/HasBackgroundColor.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Intervention\Image\Geometry\Traits;
|
||||||
|
|
||||||
|
trait HasBackgroundColor
|
||||||
|
{
|
||||||
|
protected $backgroundColor = null;
|
||||||
|
|
||||||
|
public function background($color): self
|
||||||
|
{
|
||||||
|
return $this->setBackgroundColor($color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setBackgroundColor($color): self
|
||||||
|
{
|
||||||
|
$this->backgroundColor = $color;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBackgroundColor()
|
||||||
|
{
|
||||||
|
return $this->backgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasBackgroundColor(): bool
|
||||||
|
{
|
||||||
|
return !is_null($this->backgroundColor);
|
||||||
|
}
|
||||||
|
}
|
43
src/Geometry/Traits/HasBorder.php
Normal file
43
src/Geometry/Traits/HasBorder.php
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Intervention\Image\Geometry\Traits;
|
||||||
|
|
||||||
|
trait HasBorder
|
||||||
|
{
|
||||||
|
protected $borderColor = null;
|
||||||
|
protected $borderSize = 0;
|
||||||
|
|
||||||
|
public function border($color, int $size = 1): self
|
||||||
|
{
|
||||||
|
return $this->setBorderSize($size)->setBorderColor($color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setBorderSize(int $size): self
|
||||||
|
{
|
||||||
|
$this->borderSize = $size;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBorderSize(): int
|
||||||
|
{
|
||||||
|
return $this->borderSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setBorderColor($color): self
|
||||||
|
{
|
||||||
|
$this->borderColor = $color;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBorderColor()
|
||||||
|
{
|
||||||
|
return $this->borderColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasBorder(): bool
|
||||||
|
{
|
||||||
|
return $this->borderSize > 0 && !is_null($this->borderColor);
|
||||||
|
}
|
||||||
|
}
|
17
src/Interfaces/DrawableInterface.php
Normal file
17
src/Interfaces/DrawableInterface.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Intervention\Image\Interfaces;
|
||||||
|
|
||||||
|
interface DrawableInterface
|
||||||
|
{
|
||||||
|
public function setBackgroundColor($color);
|
||||||
|
public function getBackgroundColor();
|
||||||
|
public function hasBackgroundColor();
|
||||||
|
public function background($color);
|
||||||
|
public function border($color, int $size = 1);
|
||||||
|
public function setBorderSize(int $size);
|
||||||
|
public function getBorderSize();
|
||||||
|
public function setBorderColor($color);
|
||||||
|
public function getBorderColor();
|
||||||
|
public function hasBorder();
|
||||||
|
}
|
Reference in New Issue
Block a user