1
0
mirror of https://github.com/Intervention/image.git synced 2025-08-19 12:11:26 +02:00

Add DrawRectangleModifier

This commit is contained in:
Oliver Vogel
2022-07-23 10:56:43 +02:00
parent 67307ea863
commit efe7d5bb67
8 changed files with 305 additions and 1 deletions

View File

@@ -21,6 +21,15 @@ abstract class AbstractImage implements ImageInterface
use CanHandleInput;
use CanRunCallback;
public function eachFrame(callable $callback): self
{
foreach ($this as $frame) {
$callback($frame);
}
return $this;
}
public function getSize(): SizeInterface
{
return new Rectangle($this->getWidth(), $this->getHeight());
@@ -210,6 +219,14 @@ abstract class AbstractImage implements ImageInterface
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
{
return $this->modify(

View 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
) {
//
}
}

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

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

View File

@@ -3,11 +3,17 @@
namespace Intervention\Image\Geometry;
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\SizeInterface;
class Rectangle extends Polygon implements SizeInterface
class Rectangle extends Polygon implements SizeInterface, DrawableInterface
{
use HasBorder;
use HasBackgroundColor;
public function __construct(
int $width,
int $height,
@@ -20,11 +26,26 @@ class Rectangle extends Polygon implements SizeInterface
$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
{
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
{
$this[1]->setX($this[0]->getX() + $width);
@@ -205,6 +226,16 @@ class Rectangle extends Polygon implements SizeInterface
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
{
return new RectangleResizer($width, $height);

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

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

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