mirror of
https://github.com/Intervention/image.git
synced 2025-08-01 11:30:16 +02:00
Refactor architecture
This commit is contained in:
@@ -13,7 +13,6 @@ class Collection implements CollectionInterface, IteratorAggregate, Countable
|
||||
{
|
||||
public function __construct(protected array $items = [])
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,6 +26,11 @@ class Collection implements CollectionInterface, IteratorAggregate, Countable
|
||||
return new self($items);
|
||||
}
|
||||
|
||||
public function has(int|string $key): bool
|
||||
{
|
||||
return array_key_exists($key, $this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Iterator
|
||||
*
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace Intervention\Image\Colors\Cmyk\Decoders;
|
||||
|
||||
use Intervention\Image\Colors\Cmyk\Color;
|
||||
use Intervention\Image\Drivers\Abstract\Decoders\AbstractDecoder;
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
|
@@ -7,5 +7,4 @@ use Intervention\Image\Interfaces\ProfileInterface;
|
||||
|
||||
class Profile extends GenericData implements ProfileInterface
|
||||
{
|
||||
//
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace Intervention\Image\Colors\Rgb\Decoders;
|
||||
|
||||
use Intervention\Image\Colors\Rgb\Color;
|
||||
use Intervention\Image\Drivers\Abstract\Decoders\AbstractDecoder;
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace Intervention\Image\Colors\Rgb\Decoders;
|
||||
|
||||
use Intervention\Image\Colors\Rgb\Color;
|
||||
use Intervention\Image\Drivers\Abstract\Decoders\AbstractDecoder;
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
|
@@ -19,7 +19,7 @@ use Intervention\Image\Traits\CanHandleInput;
|
||||
use Intervention\Image\Traits\CanResolveDriverClass;
|
||||
use Intervention\Image\Traits\CanRunCallback;
|
||||
|
||||
abstract class AbstractImage implements ImageInterface
|
||||
abstract class DELETE___AbstractImage implements ImageInterface
|
||||
{
|
||||
use CanResolveDriverClass;
|
||||
use CanHandleInput;
|
||||
|
@@ -8,7 +8,7 @@ use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\InputHandlerInterface;
|
||||
|
||||
abstract class AbstractInputHandler implements InputHandlerInterface
|
||||
abstract class DELETE____AbstractInputHandler implements InputHandlerInterface
|
||||
{
|
||||
/**
|
||||
* Array of decoders which will be stacked into to the input handler chain
|
||||
|
@@ -9,7 +9,7 @@ use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Traits\CanBuildFilePointer;
|
||||
|
||||
abstract class AbstractDecoder implements DecoderInterface
|
||||
abstract class DELETE___AbstractDecoder implements DecoderInterface
|
||||
{
|
||||
use CanBuildFilePointer;
|
||||
|
||||
|
@@ -14,18 +14,11 @@ use Intervention\Image\Interfaces\PointInterface;
|
||||
use Intervention\Image\Traits\CanCheckType;
|
||||
use Intervention\Image\Traits\CanHandleInput;
|
||||
|
||||
class AbstractDrawModifier
|
||||
class DELETE__AbstractDrawModifier
|
||||
{
|
||||
use CanHandleInput;
|
||||
use CanCheckType;
|
||||
|
||||
public function __construct(
|
||||
protected PointInterface $position,
|
||||
protected DrawableInterface $drawable
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
public function drawable(): DrawableInterface
|
||||
{
|
||||
return $this->drawable;
|
||||
|
@@ -6,14 +6,13 @@ use Intervention\Image\Geometry\Rectangle;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\SizeInterface;
|
||||
|
||||
abstract class AbstractFitModifier
|
||||
abstract class DELETE___AbstractFitModifier
|
||||
{
|
||||
public function __construct(
|
||||
protected int $width,
|
||||
protected int $height,
|
||||
protected string $position = 'center'
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
protected function getCropSize(ImageInterface $image): SizeInterface
|
||||
|
@@ -7,7 +7,7 @@ use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\SizeInterface;
|
||||
use Intervention\Image\Traits\CanCheckType;
|
||||
|
||||
abstract class AbstractPadModifier
|
||||
abstract class DELETE___AbstractPadModifier
|
||||
{
|
||||
use CanCheckType;
|
||||
|
||||
@@ -20,14 +20,14 @@ abstract class AbstractPadModifier
|
||||
//
|
||||
}
|
||||
|
||||
protected function getCropSize(ImageInterface $image): SizeInterface
|
||||
public function getCropSize(ImageInterface $image): SizeInterface
|
||||
{
|
||||
return $image->size()
|
||||
->contain($this->width, $this->height)
|
||||
->alignPivotTo($this->getResizeSize($image), $this->position);
|
||||
}
|
||||
|
||||
protected function getResizeSize(ImageInterface $image): SizeInterface
|
||||
public function getResizeSize(ImageInterface $image): SizeInterface
|
||||
{
|
||||
return new Rectangle($this->width, $this->height);
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ use Intervention\Image\Exceptions\InputException;
|
||||
use Intervention\Image\Interfaces\FrameInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
abstract class AbstractRemoveAnimationModifier implements ModifierInterface
|
||||
abstract class DELETE___AbstractRemoveAnimationModifier implements ModifierInterface
|
||||
{
|
||||
protected function chosenFrame($image, int|string $position): FrameInterface
|
||||
{
|
||||
|
@@ -8,7 +8,7 @@ use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Traits\CanCheckType;
|
||||
use Intervention\Image\Traits\CanHandleInput;
|
||||
|
||||
abstract class AbstractRotateModifier
|
||||
abstract class DELETE____AbstractRotateModifier
|
||||
{
|
||||
use CanHandleInput;
|
||||
use CanCheckType;
|
||||
|
155
src/Drivers/AbstractDecoder.php
Normal file
155
src/Drivers/AbstractDecoder.php
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers;
|
||||
|
||||
use Exception;
|
||||
use Intervention\Image\Collection;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\CollectionInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Traits\CanBuildFilePointer;
|
||||
|
||||
abstract class AbstractDecoder implements DecoderInterface
|
||||
{
|
||||
use CanBuildFilePointer;
|
||||
|
||||
public function __construct(protected ?AbstractDecoder $successor = null)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
final public function handle($input): ImageInterface|ColorInterface
|
||||
{
|
||||
try {
|
||||
$decoded = $this->decode($input);
|
||||
} catch (DecoderException $e) {
|
||||
if (!$this->hasSuccessor()) {
|
||||
throw new DecoderException($e->getMessage());
|
||||
}
|
||||
|
||||
return $this->successor->handle($input);
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
protected function hasSuccessor(): bool
|
||||
{
|
||||
return $this->successor !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return media type (MIME) of given input
|
||||
*
|
||||
* @param string $input
|
||||
* @return string
|
||||
*/
|
||||
protected function mediaType(string $input): string
|
||||
{
|
||||
$pointer = $this->buildFilePointer($input);
|
||||
$type = mime_content_type($pointer);
|
||||
fclose($pointer);
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
protected function decodeExifData(string $image_data): CollectionInterface
|
||||
{
|
||||
if (!function_exists('exif_read_data')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
$pointer = $this->buildFilePointer($image_data);
|
||||
$data = @exif_read_data($pointer, null, true);
|
||||
fclose($pointer);
|
||||
} catch (Exception $e) {
|
||||
$data = [];
|
||||
}
|
||||
|
||||
return new Collection(is_array($data) ? $data : []);
|
||||
}
|
||||
|
||||
protected function isValidBase64($input): bool
|
||||
{
|
||||
if (!is_string($input)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return base64_encode(base64_decode($input)) === str_replace(["\n", "\r"], '', $input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse data uri
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return object
|
||||
*/
|
||||
protected function parseDataUri($value): object
|
||||
{
|
||||
$pattern = "/^data:(?P<mediatype>\w+\/[-+.\w]+)?" .
|
||||
"(?P<parameters>(;[-\w]+=[-\w]+)*)(?P<base64>;base64)?,(?P<data>.*)/";
|
||||
|
||||
$result = preg_match($pattern, $value, $matches);
|
||||
|
||||
return new class ($matches, $result)
|
||||
{
|
||||
private $matches;
|
||||
private $result;
|
||||
|
||||
public function __construct($matches, $result)
|
||||
{
|
||||
$this->matches = $matches;
|
||||
$this->result = $result;
|
||||
}
|
||||
|
||||
public function isValid(): bool
|
||||
{
|
||||
return (bool) $this->result;
|
||||
}
|
||||
|
||||
public function mediaType(): ?string
|
||||
{
|
||||
if (isset($this->matches['mediatype']) && !empty($this->matches['mediatype'])) {
|
||||
return $this->matches['mediatype'];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function hasMediaType(): bool
|
||||
{
|
||||
return !empty($this->mediaType());
|
||||
}
|
||||
|
||||
public function parameters(): array
|
||||
{
|
||||
if (isset($this->matches['parameters']) && !empty($this->matches['parameters'])) {
|
||||
return explode(';', trim($this->matches['parameters'], ';'));
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function isBase64Encoded(): bool
|
||||
{
|
||||
if (isset($this->matches['base64']) && $this->matches['base64'] === ';base64') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function data(): ?string
|
||||
{
|
||||
if (isset($this->matches['data']) && !empty($this->matches['data'])) {
|
||||
return $this->matches['data'];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
33
src/Drivers/AbstractDriver.php
Normal file
33
src/Drivers/AbstractDriver.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers;
|
||||
|
||||
use Intervention\Image\Interfaces\DriverInterface;
|
||||
use ReflectionClass;
|
||||
|
||||
abstract class AbstractDriver implements DriverInterface
|
||||
{
|
||||
public function resolve(object $input): object
|
||||
{
|
||||
$ns = (new ReflectionClass($this))->getNamespaceName();
|
||||
$classname = (new ReflectionClass($input))->getShortName();
|
||||
|
||||
preg_match("/(?P<dept>[A-Z][a-z]+)$/", $classname, $matches);
|
||||
$department = array_key_exists('dept', $matches) ? $matches['dept'] : null;
|
||||
$department = match ($department) {
|
||||
'Modifier', 'Writer' => 'Modifiers',
|
||||
'Encoder' => 'Encoders',
|
||||
default => null,
|
||||
};
|
||||
|
||||
$specialized = implode("\\", array_filter([
|
||||
$ns,
|
||||
$department,
|
||||
$classname
|
||||
], function ($dept) {
|
||||
return !empty($dept);
|
||||
}));
|
||||
|
||||
return new $specialized($input, $this);
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Abstract;
|
||||
namespace Intervention\Image\Drivers;
|
||||
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\FontInterface;
|
52
src/Drivers/AbstractInputHandler.php
Normal file
52
src/Drivers/AbstractInputHandler.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers;
|
||||
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\InputHandlerInterface;
|
||||
|
||||
abstract class AbstractInputHandler implements InputHandlerInterface
|
||||
{
|
||||
protected array $decoders = [];
|
||||
|
||||
public function __construct(array $decoders = [])
|
||||
{
|
||||
$this->decoders = count($decoders) ? $decoders : $this->decoders;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see InputHandlerInterface::handle()
|
||||
*/
|
||||
public function handle($input): ImageInterface|ColorInterface
|
||||
{
|
||||
return $this->chain()->handle($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stack the decoder array into a nested decoder object
|
||||
*
|
||||
* @return AbstractDecoder
|
||||
*/
|
||||
protected function chain(): AbstractDecoder
|
||||
{
|
||||
if (count($this->decoders) == 0) {
|
||||
throw new DecoderException('No decoders found in ' . get_class($this));
|
||||
}
|
||||
|
||||
// get instance of last decoder in stack
|
||||
list($classname) = array_slice(array_reverse($this->decoders), 0, 1);
|
||||
$chain = new $classname();
|
||||
|
||||
// build decoder chain
|
||||
foreach (array_slice(array_reverse($this->decoders), 1) as $classname) {
|
||||
$chain = new $classname($chain);
|
||||
}
|
||||
|
||||
return $chain;
|
||||
}
|
||||
}
|
37
src/Drivers/DrawModifier.php
Normal file
37
src/Drivers/DrawModifier.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers;
|
||||
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Geometry\Point;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
|
||||
abstract class DrawModifier extends DriverModifier
|
||||
{
|
||||
public function position(): Point
|
||||
{
|
||||
return $this->drawable->pivot();
|
||||
}
|
||||
|
||||
public function backgroundColor(): ColorInterface
|
||||
{
|
||||
try {
|
||||
$color = $this->driver()->handleInput($this->drawable->backgroundColor());
|
||||
} catch (DecoderException $e) {
|
||||
return $this->driver()->handleInput('transparent');
|
||||
}
|
||||
|
||||
return $color;
|
||||
}
|
||||
|
||||
public function borderColor(): ColorInterface
|
||||
{
|
||||
try {
|
||||
$color = $this->driver()->handleInput($this->drawable->borderColor());
|
||||
} catch (DecoderException $e) {
|
||||
return $this->driver()->handleInput('transparent');
|
||||
}
|
||||
|
||||
return $color;
|
||||
}
|
||||
}
|
47
src/Drivers/DriverEncoder.php
Normal file
47
src/Drivers/DriverEncoder.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers;
|
||||
|
||||
use Intervention\Image\Interfaces\DriverInterface;
|
||||
use Intervention\Image\Interfaces\EncoderInterface;
|
||||
|
||||
abstract class DriverEncoder implements EncoderInterface
|
||||
{
|
||||
public function __construct(
|
||||
protected EncoderInterface $encoder,
|
||||
protected DriverInterface $driver
|
||||
) {
|
||||
}
|
||||
|
||||
public function driver(): DriverInterface
|
||||
{
|
||||
return $this->driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method to read attributes of underlying endcoder
|
||||
*
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get(string $name): mixed
|
||||
{
|
||||
return $this->encoder->$name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get return value of callback through output buffer
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return string
|
||||
*/
|
||||
protected function getBuffered(callable $callback): string
|
||||
{
|
||||
ob_start();
|
||||
$callback();
|
||||
$buffer = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
}
|
43
src/Drivers/DriverModifier.php
Normal file
43
src/Drivers/DriverModifier.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers;
|
||||
|
||||
use Intervention\Image\Interfaces\DriverInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
abstract class DriverModifier implements ModifierInterface
|
||||
{
|
||||
public function __construct(
|
||||
protected ModifierInterface $modifier,
|
||||
protected DriverInterface $driver
|
||||
) {
|
||||
}
|
||||
|
||||
public function driver(): DriverInterface
|
||||
{
|
||||
return $this->driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method to read attributes of underlying modifier
|
||||
*
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get(string $name): mixed
|
||||
{
|
||||
return $this->modifier->$name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method to call methods of underlying modifier
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $arguments
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call(string $name, array $arguments): mixed
|
||||
{
|
||||
return $this->modifier->$name(...$arguments);
|
||||
}
|
||||
}
|
54
src/Drivers/Gd/ColorProcessor.php
Normal file
54
src/Drivers/Gd/ColorProcessor.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd;
|
||||
|
||||
use Intervention\Image\Colors\Rgb\Channels\Alpha;
|
||||
use Intervention\Image\Colors\Rgb\Channels\Blue;
|
||||
use Intervention\Image\Colors\Rgb\Channels\Green;
|
||||
use Intervention\Image\Colors\Rgb\Channels\Red;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorProcessorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
|
||||
class ColorProcessor implements ColorProcessorInterface
|
||||
{
|
||||
public function __construct(protected ColorspaceInterface $colorspace = new Colorspace())
|
||||
{
|
||||
}
|
||||
|
||||
public function colorToNative(ColorInterface $color): int
|
||||
{
|
||||
$r = $color->channel(Red::class)->value();
|
||||
$g = $color->channel(Green::class)->value();
|
||||
$b = $color->channel(Blue::class)->value();
|
||||
$a = $color->channel(Alpha::class)->value();
|
||||
|
||||
// convert alpha value to gd alpha
|
||||
// ([opaque]255-0[transparent]) to ([opaque]0-127[transparent])
|
||||
$a = (int) $this->convertRange($a, 0, 255, 127, 0);
|
||||
|
||||
return ($a << 24) + ($r << 16) + ($g << 8) + $b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert input in range (min) to (max) to the corresponding value
|
||||
* in target range (targetMin) to (targetMax).
|
||||
*
|
||||
* @param float|int $input
|
||||
* @param float|int $min
|
||||
* @param float|int $max
|
||||
* @param float|int $targetMin
|
||||
* @param float|int $targetMax
|
||||
* @return float|int
|
||||
*/
|
||||
protected function convertRange(
|
||||
float|int $input,
|
||||
float|int $min,
|
||||
float|int $max,
|
||||
float|int $targetMin,
|
||||
float|int $targetMax
|
||||
): float|int {
|
||||
return ceil(((($input - $min) * ($targetMax - $targetMin)) / ($max - $min)) + $targetMin);
|
||||
}
|
||||
}
|
51
src/Drivers/Gd/Core.php
Normal file
51
src/Drivers/Gd/Core.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd;
|
||||
|
||||
use Intervention\Image\Collection;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
use Intervention\Image\Interfaces\CoreInterface;
|
||||
use Intervention\Image\Interfaces\FrameInterface;
|
||||
|
||||
class Core extends Collection implements CoreInterface
|
||||
{
|
||||
protected int $loops = 0;
|
||||
|
||||
public function native()
|
||||
{
|
||||
return $this->first()->data();
|
||||
}
|
||||
|
||||
public function width(): int
|
||||
{
|
||||
return imagesx($this->native());
|
||||
}
|
||||
|
||||
public function height(): int
|
||||
{
|
||||
return imagesy($this->native());
|
||||
}
|
||||
|
||||
public function frame(int $position): FrameInterface
|
||||
{
|
||||
return $this->getAtPosition($position);
|
||||
}
|
||||
|
||||
public function loops(): int
|
||||
{
|
||||
return $this->loops;
|
||||
}
|
||||
|
||||
public function setLoops(int $loops): self
|
||||
{
|
||||
$this->loops = $loops;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function colorspace(): ColorspaceInterface
|
||||
{
|
||||
return new RgbColorspace();
|
||||
}
|
||||
}
|
@@ -2,17 +2,17 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Decoders;
|
||||
|
||||
use GdImage;
|
||||
use Intervention\Image\Collection;
|
||||
use Intervention\Image\Drivers\Abstract\Decoders\AbstractDecoder;
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Frame;
|
||||
use Intervention\Image\Drivers\Gd\Image;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Gif\Decoder as GifDecoder;
|
||||
use Intervention\Gif\Splitter as GifSplitter;
|
||||
use Intervention\Image\Drivers\Gd\Core;
|
||||
use Intervention\Image\Drivers\Gd\Driver;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Image;
|
||||
|
||||
class BinaryImageDecoder extends AbstractDecoder implements DecoderInterface
|
||||
{
|
||||
@@ -26,40 +26,45 @@ class BinaryImageDecoder extends AbstractDecoder implements DecoderInterface
|
||||
return $this->decodeGif($input); // decode (animated) gif
|
||||
}
|
||||
|
||||
$gd = $this->coreFromString($input);
|
||||
|
||||
// build image instance
|
||||
$image = new Image(new Collection([new Frame($gd)]));
|
||||
$image->setExif($this->decodeExifData($input));
|
||||
$image = new Image(
|
||||
new Driver(),
|
||||
$this->coreFromString($input),
|
||||
$this->decodeExifData($input)
|
||||
);
|
||||
|
||||
return $image;
|
||||
|
||||
// fix image orientation
|
||||
return match ($image->exif('IFD0.Orientation')) {
|
||||
2 => $image->flip(),
|
||||
3 => $image->rotate(180),
|
||||
4 => $image->rotate(180)->flip(),
|
||||
5 => $image->rotate(270)->flip(),
|
||||
6 => $image->rotate(270),
|
||||
7 => $image->rotate(90)->flip(),
|
||||
8 => $image->rotate(90),
|
||||
default => $image
|
||||
};
|
||||
// return match ($image->exif('IFD0.Orientation')) {
|
||||
// 2 => $image->flip(),
|
||||
// 3 => $image->rotate(180),
|
||||
// 4 => $image->rotate(180)->flip(),
|
||||
// 5 => $image->rotate(270)->flip(),
|
||||
// 6 => $image->rotate(270),
|
||||
// 7 => $image->rotate(90)->flip(),
|
||||
// 8 => $image->rotate(90),
|
||||
// default => $image
|
||||
// };
|
||||
}
|
||||
|
||||
private function coreFromString(string $input): GdImage
|
||||
private function coreFromString(string $input): Core
|
||||
{
|
||||
$gd = @imagecreatefromstring($input);
|
||||
$data = @imagecreatefromstring($input);
|
||||
|
||||
if ($gd === false) {
|
||||
if ($data === false) {
|
||||
throw new DecoderException('Unable to decode input');
|
||||
}
|
||||
|
||||
if (!imageistruecolor($gd)) {
|
||||
imagepalettetotruecolor($gd);
|
||||
if (!imageistruecolor($data)) {
|
||||
imagepalettetotruecolor($data);
|
||||
}
|
||||
|
||||
imagesavealpha($gd, true);
|
||||
imagesavealpha($data, true);
|
||||
|
||||
return $gd;
|
||||
return new Core([
|
||||
new Frame($data)
|
||||
]);
|
||||
}
|
||||
|
||||
private function decodeGif(string $input): ImageInterface
|
||||
@@ -68,22 +73,26 @@ class BinaryImageDecoder extends AbstractDecoder implements DecoderInterface
|
||||
|
||||
if (!$gif->isAnimated()) {
|
||||
return new Image(
|
||||
new Collection([new Frame(
|
||||
$this->coreFromString($input)
|
||||
)]),
|
||||
new Driver(),
|
||||
$this->coreFromString($input)
|
||||
);
|
||||
}
|
||||
|
||||
$image = new Image(new Collection());
|
||||
$image->setLoops($gif->getMainApplicationExtension()?->getLoops());
|
||||
|
||||
$splitter = GifSplitter::create($gif)->split();
|
||||
|
||||
$delays = $splitter->getDelays();
|
||||
foreach ($splitter->coalesceToResources() as $key => $gd) {
|
||||
$image->addFrame((new Frame($gd))->setDelay($delays[$key] / 100));
|
||||
|
||||
// build core
|
||||
$core = new Core();
|
||||
$core->setLoops($gif->getMainApplicationExtension()?->getLoops());
|
||||
foreach ($splitter->coalesceToResources() as $key => $data) {
|
||||
$core->push(
|
||||
(new Frame($data))->setDelay($delays[$key] / 100)
|
||||
);
|
||||
}
|
||||
|
||||
return $image;
|
||||
return new Image(
|
||||
new Driver(),
|
||||
$core
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Decoders\AbstractDecoder;
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Decoders\AbstractDecoder;
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
|
40
src/Drivers/Gd/Driver.php
Normal file
40
src/Drivers/Gd/Driver.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd;
|
||||
|
||||
use Intervention\Image\Drivers\AbstractDriver;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class Driver extends AbstractDriver
|
||||
{
|
||||
public function createImage(int $width, int $height): ImageInterface
|
||||
{
|
||||
// build new transparent GDImage
|
||||
$data = imagecreatetruecolor($width, $height);
|
||||
imagesavealpha($data, true);
|
||||
$background = imagecolorallocatealpha($data, 255, 0, 255, 127);
|
||||
imagealphablending($data, false);
|
||||
imagefill($data, 0, 0, $background);
|
||||
imagecolortransparent($data, $background);
|
||||
|
||||
return new Image(
|
||||
$this,
|
||||
new Core([
|
||||
new Frame($data)
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
public function handleInput(mixed $input): ImageInterface|ColorInterface
|
||||
{
|
||||
return (new InputHandler())->handle($input);
|
||||
}
|
||||
|
||||
public function colorToNative(ColorInterface $color, ColorspaceInterface $colorspace): mixed
|
||||
{
|
||||
return (new ColorProcessor($colorspace))->colorToNative($color);
|
||||
}
|
||||
}
|
9
src/Drivers/Gd/Element.php
Normal file
9
src/Drivers/Gd/Element.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd;
|
||||
|
||||
use Intervention\Image\Collection;
|
||||
|
||||
class Element extends Collection
|
||||
{
|
||||
}
|
@@ -2,22 +2,17 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Encoders;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder;
|
||||
use Intervention\Image\Drivers\DriverEncoder;
|
||||
use Intervention\Image\EncodedImage;
|
||||
use Intervention\Image\Interfaces\EncoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class AvifEncoder extends AbstractEncoder implements EncoderInterface
|
||||
class AvifEncoder extends DriverEncoder
|
||||
{
|
||||
public function __construct(int $quality)
|
||||
{
|
||||
$this->quality = $quality;
|
||||
}
|
||||
|
||||
public function encode(ImageInterface $image): EncodedImage
|
||||
{
|
||||
$data = $this->getBuffered(function () use ($image) {
|
||||
imageavif($image->frame()->core(), null, $this->quality);
|
||||
$gd = $image->core()->native();
|
||||
$data = $this->getBuffered(function () use ($gd) {
|
||||
imageavif($gd, null, $this->quality);
|
||||
});
|
||||
|
||||
return new EncodedImage($data, 'image/avif');
|
||||
|
@@ -2,24 +2,19 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Encoders;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder;
|
||||
use Intervention\Image\Drivers\Gd\Modifiers\LimitColorsModifier;
|
||||
use Intervention\Image\Drivers\DriverEncoder;
|
||||
use Intervention\Image\Modifiers\LimitColorsModifier;
|
||||
use Intervention\Image\EncodedImage;
|
||||
use Intervention\Image\Interfaces\EncoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class BmpEncoder extends AbstractEncoder implements EncoderInterface
|
||||
class BmpEncoder extends DriverEncoder
|
||||
{
|
||||
public function __construct(protected int $color_limit = 0)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function encode(ImageInterface $image): EncodedImage
|
||||
{
|
||||
$image = $image->modify(new LimitColorsModifier($this->color_limit));
|
||||
$data = $this->getBuffered(function () use ($image) {
|
||||
imagebmp($image->frame()->core(), null, false);
|
||||
$gd = $image->core()->native();
|
||||
$data = $this->getBuffered(function () use ($gd) {
|
||||
imagebmp($gd, null, false);
|
||||
});
|
||||
|
||||
return new EncodedImage($data, 'image/bmp');
|
||||
|
@@ -3,19 +3,13 @@
|
||||
namespace Intervention\Image\Drivers\Gd\Encoders;
|
||||
|
||||
use Intervention\Gif\Builder as GifBuilder;
|
||||
use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder;
|
||||
use Intervention\Image\Drivers\Gd\Modifiers\LimitColorsModifier;
|
||||
use Intervention\Image\Drivers\DriverEncoder;
|
||||
use Intervention\Image\Modifiers\LimitColorsModifier;
|
||||
use Intervention\Image\EncodedImage;
|
||||
use Intervention\Image\Interfaces\EncoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class GifEncoder extends AbstractEncoder implements EncoderInterface
|
||||
class GifEncoder extends DriverEncoder
|
||||
{
|
||||
public function __construct(protected int $color_limit = 0)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function encode(ImageInterface $image): EncodedImage
|
||||
{
|
||||
if ($image->isAnimated()) {
|
||||
@@ -23,8 +17,9 @@ class GifEncoder extends AbstractEncoder implements EncoderInterface
|
||||
}
|
||||
|
||||
$image = $image->modify(new LimitColorsModifier($this->color_limit));
|
||||
$data = $this->getBuffered(function () use ($image) {
|
||||
imagegif($image->frame()->core());
|
||||
$gd = $image->core()->native();
|
||||
$data = $this->getBuffered(function () use ($gd) {
|
||||
imagegif($gd);
|
||||
});
|
||||
|
||||
return new EncodedImage($data, 'image/gif');
|
||||
@@ -40,7 +35,7 @@ class GifEncoder extends AbstractEncoder implements EncoderInterface
|
||||
|
||||
foreach ($image as $frame) {
|
||||
$builder->addFrame(
|
||||
$this->encode($frame->toImage()),
|
||||
$this->encode($frame->toImage($image->driver())),
|
||||
$frame->delay()
|
||||
);
|
||||
}
|
||||
|
@@ -2,22 +2,17 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Encoders;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder;
|
||||
use Intervention\Image\Drivers\DriverEncoder;
|
||||
use Intervention\Image\EncodedImage;
|
||||
use Intervention\Image\Interfaces\EncoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class JpegEncoder extends AbstractEncoder implements EncoderInterface
|
||||
class JpegEncoder extends DriverEncoder
|
||||
{
|
||||
public function __construct(int $quality)
|
||||
{
|
||||
$this->quality = $quality;
|
||||
}
|
||||
|
||||
public function encode(ImageInterface $image): EncodedImage
|
||||
{
|
||||
$data = $this->getBuffered(function () use ($image) {
|
||||
imagejpeg($image->frame()->core(), null, $this->quality);
|
||||
$gd = $image->core()->native();
|
||||
$data = $this->getBuffered(function () use ($gd) {
|
||||
imagejpeg($gd, null, $this->quality);
|
||||
});
|
||||
|
||||
return new EncodedImage($data, 'image/jpeg');
|
||||
|
@@ -2,24 +2,19 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Encoders;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder;
|
||||
use Intervention\Image\Drivers\Gd\Modifiers\LimitColorsModifier;
|
||||
use Intervention\Image\Drivers\DriverEncoder;
|
||||
use Intervention\Image\EncodedImage;
|
||||
use Intervention\Image\Interfaces\EncoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Modifiers\LimitColorsModifier;
|
||||
|
||||
class PngEncoder extends AbstractEncoder implements EncoderInterface
|
||||
class PngEncoder extends DriverEncoder
|
||||
{
|
||||
public function __construct(protected int $color_limit = 0)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function encode(ImageInterface $image): EncodedImage
|
||||
{
|
||||
$image = $image->modify(new LimitColorsModifier($this->color_limit));
|
||||
$data = $this->getBuffered(function () use ($image) {
|
||||
imagepng($image->frame()->core(), null, -1);
|
||||
$gd = $image->core()->native();
|
||||
$data = $this->getBuffered(function () use ($gd) {
|
||||
imagepng($gd, null, -1);
|
||||
});
|
||||
|
||||
return new EncodedImage($data, 'image/png');
|
||||
|
@@ -2,22 +2,17 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Encoders;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder;
|
||||
use Intervention\Image\Drivers\DriverEncoder;
|
||||
use Intervention\Image\EncodedImage;
|
||||
use Intervention\Image\Interfaces\EncoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class WebpEncoder extends AbstractEncoder implements EncoderInterface
|
||||
class WebpEncoder extends DriverEncoder
|
||||
{
|
||||
public function __construct(int $quality)
|
||||
{
|
||||
$this->quality = $quality;
|
||||
}
|
||||
|
||||
public function encode(ImageInterface $image): EncodedImage
|
||||
{
|
||||
$data = $this->getBuffered(function () use ($image) {
|
||||
imagewebp($image->frame()->core(), null, $this->quality);
|
||||
$gd = $image->core()->native();
|
||||
$data = $this->getBuffered(function () use ($gd) {
|
||||
imagewebp($gd, null, $this->quality);
|
||||
});
|
||||
|
||||
return new EncodedImage($data, 'image/webp');
|
||||
|
@@ -12,7 +12,7 @@ use Intervention\Image\Interfaces\FactoryInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Traits\CanHandleInput;
|
||||
|
||||
class Factory implements FactoryInterface
|
||||
class DELETE___Factory implements FactoryInterface
|
||||
{
|
||||
use CanHandleInput;
|
||||
use CanHandleColors;
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\AbstractFont;
|
||||
use Intervention\Image\Drivers\AbstractFont;
|
||||
use Intervention\Image\Geometry\Point;
|
||||
use Intervention\Image\Geometry\Polygon;
|
||||
use Intervention\Image\Geometry\Rectangle;
|
||||
|
@@ -3,8 +3,9 @@
|
||||
namespace Intervention\Image\Drivers\Gd;
|
||||
|
||||
use GdImage;
|
||||
use Intervention\Image\Collection;
|
||||
use Intervention\Image\Geometry\Rectangle;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Interfaces\DriverInterface;
|
||||
use Intervention\Image\Interfaces\FrameInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\SizeInterface;
|
||||
@@ -12,7 +13,7 @@ use Intervention\Image\Interfaces\SizeInterface;
|
||||
class Frame implements FrameInterface
|
||||
{
|
||||
public function __construct(
|
||||
protected GdImage $core,
|
||||
protected GdImage $data,
|
||||
protected float $delay = 0,
|
||||
protected int $dispose = 1,
|
||||
protected int $offset_left = 0,
|
||||
@@ -21,26 +22,31 @@ class Frame implements FrameInterface
|
||||
//
|
||||
}
|
||||
|
||||
public function setCore($core): FrameInterface
|
||||
public function toImage(DriverInterface $driver): ImageInterface
|
||||
{
|
||||
$this->core = $core;
|
||||
return new Image($driver, new Core([$this]));
|
||||
}
|
||||
|
||||
public function setData($data): FrameInterface
|
||||
{
|
||||
$this->data = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function core(): GdImage
|
||||
public function data(): GdImage
|
||||
{
|
||||
return $this->core;
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function unsetCore(): void
|
||||
public function unsetData(): void
|
||||
{
|
||||
unset($this->core);
|
||||
unset($this->data);
|
||||
}
|
||||
|
||||
public function size(): SizeInterface
|
||||
{
|
||||
return new Rectangle(imagesx($this->core), imagesy($this->core));
|
||||
return new Rectangle(imagesx($this->data), imagesy($this->data));
|
||||
}
|
||||
|
||||
public function delay(): float
|
||||
@@ -98,9 +104,4 @@ class Frame implements FrameInterface
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toImage(): ImageInterface
|
||||
{
|
||||
return new Image(new Collection([$this]));
|
||||
}
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ use Intervention\Image\Resolution;
|
||||
use IteratorAggregate;
|
||||
use Traversable;
|
||||
|
||||
class Image extends AbstractImage implements ImageInterface, IteratorAggregate
|
||||
class DELETE__Image extends AbstractImage implements ImageInterface, IteratorAggregate
|
||||
{
|
||||
use CanHandleColors;
|
||||
|
||||
|
@@ -7,7 +7,7 @@ use Intervention\Image\Colors\Rgb\Decoders\StringColorDecoder as RgbStringColorD
|
||||
use Intervention\Image\Colors\Rgb\Decoders\HtmlColornameDecoder;
|
||||
use Intervention\Image\Colors\Rgb\Decoders\TransparentColorDecoder;
|
||||
use Intervention\Image\Colors\Cmyk\Decoders\StringColorDecoder as CmykStringColorDecoder;
|
||||
use Intervention\Image\Drivers\Abstract\AbstractInputHandler;
|
||||
use Intervention\Image\Drivers\AbstractInputHandler;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\ImageObjectDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\ColorObjectDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\FilePointerImageDecoder;
|
||||
|
@@ -2,30 +2,19 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Interfaces\FrameInterface;
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class BlurModifier implements ModifierInterface
|
||||
class BlurModifier extends DriverModifier
|
||||
{
|
||||
public function __construct(protected int $amount)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
foreach ($image as $frame) {
|
||||
$this->blurFrame($frame);
|
||||
for ($i = 0; $i < $this->amount; $i++) {
|
||||
imagefilter($frame->data(), IMG_FILTER_GAUSSIAN_BLUR);
|
||||
}
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
protected function blurFrame(FrameInterface $frame): void
|
||||
{
|
||||
for ($i = 0; $i < $this->amount; $i++) {
|
||||
imagefilter($frame->core(), IMG_FILTER_GAUSSIAN_BLUR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,20 +2,15 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class BrightnessModifier implements ModifierInterface
|
||||
class BrightnessModifier extends DriverModifier
|
||||
{
|
||||
public function __construct(protected int $level)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
foreach ($image as $frame) {
|
||||
imagefilter($frame->core(), IMG_FILTER_BRIGHTNESS, intval($this->level * 2.55));
|
||||
imagefilter($frame->data(), IMG_FILTER_BRIGHTNESS, intval($this->level * 2.55));
|
||||
}
|
||||
|
||||
return $image;
|
||||
|
@@ -2,19 +2,11 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class ColorizeModifier implements ModifierInterface
|
||||
class ColorizeModifier extends DriverModifier
|
||||
{
|
||||
public function __construct(
|
||||
protected int $red = 0,
|
||||
protected int $green = 0,
|
||||
protected int $blue = 0
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
// normalize colorize levels
|
||||
@@ -23,7 +15,7 @@ class ColorizeModifier implements ModifierInterface
|
||||
$blue = round($this->blue * 2.55);
|
||||
|
||||
foreach ($image as $frame) {
|
||||
imagefilter($frame->core(), IMG_FILTER_COLORIZE, $red, $green, $blue);
|
||||
imagefilter($frame->data(), IMG_FILTER_COLORIZE, $red, $green, $blue);
|
||||
}
|
||||
|
||||
return $image;
|
||||
|
22
src/Drivers/Gd/Modifiers/ColorspaceModifier.php
Normal file
22
src/Drivers/Gd/Modifiers/ColorspaceModifier.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Exceptions\NotSupportedException;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class ColorspaceModifier extends DriverModifier
|
||||
{
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
if (!is_a($this->targetColorspace(), RgbColorspace::class)) {
|
||||
throw new NotSupportedException(
|
||||
'Only RGB colorspace is supported with GD driver.'
|
||||
);
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
@@ -2,20 +2,15 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class ContrastModifier implements ModifierInterface
|
||||
class ContrastModifier extends DriverModifier
|
||||
{
|
||||
public function __construct(protected int $level)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
foreach ($image as $frame) {
|
||||
imagefilter($frame->core(), IMG_FILTER_CONTRAST, ($this->level * -1));
|
||||
imagefilter($frame->data(), IMG_FILTER_CONTRAST, ($this->level * -1));
|
||||
}
|
||||
|
||||
return $image;
|
||||
|
@@ -2,32 +2,16 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Geometry\Rectangle;
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\FrameInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
use Intervention\Image\Interfaces\SizeInterface;
|
||||
use Intervention\Image\Traits\CanBuildNewImage;
|
||||
|
||||
class CropModifier implements ModifierInterface
|
||||
class CropModifier extends DriverModifier
|
||||
{
|
||||
use CanBuildNewImage;
|
||||
|
||||
public function __construct(
|
||||
protected int $width,
|
||||
protected int $height,
|
||||
protected int $offset_x = 0,
|
||||
protected int $offset_y = 0,
|
||||
protected string $position = 'top-left'
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$crop = new Rectangle($this->width, $this->height);
|
||||
$crop->align($this->position);
|
||||
$crop->alignPivotTo($image->size(), $this->position);
|
||||
$crop = $this->crop($image);
|
||||
|
||||
foreach ($image as $frame) {
|
||||
$this->cropFrame($frame, $crop);
|
||||
@@ -39,13 +23,13 @@ class CropModifier implements ModifierInterface
|
||||
protected function cropFrame(FrameInterface $frame, SizeInterface $resizeTo): void
|
||||
{
|
||||
// create new image
|
||||
$modified = $this->imageFactory()->newCore(
|
||||
$resizeTo->width(),
|
||||
$resizeTo->height()
|
||||
);
|
||||
$modified = $this->driver()
|
||||
->createImage($resizeTo->width(), $resizeTo->height())
|
||||
->core()
|
||||
->native();
|
||||
|
||||
// get original image
|
||||
$original = $frame->core();
|
||||
$original = $frame->data();
|
||||
|
||||
// preserve transparency
|
||||
$transIndex = imagecolortransparent($original);
|
||||
@@ -72,6 +56,6 @@ class CropModifier implements ModifierInterface
|
||||
);
|
||||
|
||||
// set new content as recource
|
||||
$frame->setCore($modified);
|
||||
$frame->setData($modified);
|
||||
}
|
||||
}
|
||||
|
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class DestroyModifier implements ModifierInterface
|
||||
{
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
foreach ($image as $frame) {
|
||||
$frame->unsetCore();
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
@@ -2,55 +2,65 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Modifiers\AbstractDrawModifier;
|
||||
use Intervention\Image\Drivers\Gd\Traits\CanHandleColors;
|
||||
use Intervention\Image\Drivers\DrawModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class DrawEllipseModifier extends AbstractDrawModifier implements ModifierInterface
|
||||
class DrawEllipseModifier extends DrawModifier
|
||||
{
|
||||
use CanHandleColors;
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
return $image->mapFrames(function ($frame) {
|
||||
if ($this->ellipse()->hasBorder()) {
|
||||
foreach ($image as $frame) {
|
||||
if ($this->drawable->hasBorder()) {
|
||||
// slightly smaller ellipse to keep 1px bordered edges clean
|
||||
if ($this->ellipse()->hasBackgroundColor()) {
|
||||
if ($this->drawable->hasBackgroundColor()) {
|
||||
imagefilledellipse(
|
||||
$frame->core(),
|
||||
$this->position->x(),
|
||||
$this->position->y(),
|
||||
$this->ellipse()->getWidth() - 1,
|
||||
$this->ellipse()->getHeight() - 1,
|
||||
$this->colorToInteger($this->getBackgroundColor())
|
||||
$frame->data(),
|
||||
$this->position()->x(),
|
||||
$this->position()->y(),
|
||||
$this->drawable->width() - 1,
|
||||
$this->drawable->height() - 1,
|
||||
$this->driver()->colorToNative(
|
||||
$this->backgroundColor(),
|
||||
$image->colorspace()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
imagesetthickness($frame->core(), $this->ellipse()->getBorderSize());
|
||||
// gd's imageellipse ignores imagesetthickness
|
||||
// so i use imagearc with 360 degrees instead.
|
||||
imagesetthickness(
|
||||
$frame->data(),
|
||||
$this->drawable->borderSize(),
|
||||
);
|
||||
|
||||
// gd's imageellipse ignores imagesetthickness so i use
|
||||
// imagearc with 360 degrees instead.
|
||||
imagearc(
|
||||
$frame->core(),
|
||||
$this->position->x(),
|
||||
$this->position->y(),
|
||||
$this->ellipse()->getWidth(),
|
||||
$this->ellipse()->getHeight(),
|
||||
$frame->data(),
|
||||
$this->position()->x(),
|
||||
$this->position()->y(),
|
||||
$this->drawable->width(),
|
||||
$this->drawable->height(),
|
||||
0,
|
||||
360,
|
||||
$this->colorToInteger($this->getBorderColor())
|
||||
$this->driver()->colorToNative(
|
||||
$this->borderColor(),
|
||||
$image->colorspace()
|
||||
)
|
||||
);
|
||||
} else {
|
||||
imagefilledellipse(
|
||||
$frame->core(),
|
||||
$this->position->x(),
|
||||
$this->position->y(),
|
||||
$this->ellipse()->getWidth(),
|
||||
$this->ellipse()->getHeight(),
|
||||
$this->colorToInteger($this->getBackgroundColor())
|
||||
$frame->data(),
|
||||
$this->position()->x(),
|
||||
$this->position()->y(),
|
||||
$this->drawable->width(),
|
||||
$this->drawable->height(),
|
||||
$this->driver()->colorToNative(
|
||||
$this->backgroundColor(),
|
||||
$image->colorspace()
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
||||
|
@@ -2,26 +2,27 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Modifiers\AbstractDrawModifier;
|
||||
use Intervention\Image\Drivers\Gd\Traits\CanHandleColors;
|
||||
use Intervention\Image\Drivers\DrawModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class DrawLineModifier extends AbstractDrawModifier implements ModifierInterface
|
||||
class DrawLineModifier extends DrawModifier
|
||||
{
|
||||
use CanHandleColors;
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
return $image->mapFrames(function ($frame) {
|
||||
foreach ($image as $frame) {
|
||||
imageline(
|
||||
$frame->core(),
|
||||
$this->line()->getStart()->x(),
|
||||
$this->line()->getStart()->y(),
|
||||
$this->line()->getEnd()->x(),
|
||||
$this->line()->getEnd()->y(),
|
||||
$this->colorToInteger($this->getBackgroundColor())
|
||||
$frame->data(),
|
||||
$this->drawable->getStart()->x(),
|
||||
$this->drawable->getStart()->y(),
|
||||
$this->drawable->getEnd()->x(),
|
||||
$this->drawable->getEnd()->y(),
|
||||
$this->driver()->colorToNative(
|
||||
$this->backgroundColor(),
|
||||
$image->colorspace()
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
||||
|
@@ -2,34 +2,27 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\Gd\Traits\CanHandleColors;
|
||||
use Intervention\Image\Geometry\Point;
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
use Intervention\Image\Traits\CanHandleInput;
|
||||
|
||||
class DrawPixelModifier implements ModifierInterface
|
||||
class DrawPixelModifier extends DriverModifier
|
||||
{
|
||||
use CanHandleInput;
|
||||
use CanHandleColors;
|
||||
|
||||
public function __construct(
|
||||
protected Point $position,
|
||||
protected $color
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$color = $this->handleInput($this->color);
|
||||
return $image->mapFrames(function ($frame) use ($color) {
|
||||
$color = $this->driver()->colorToNative(
|
||||
$this->driver()->handleInput($this->color),
|
||||
$image->colorspace()
|
||||
);
|
||||
|
||||
foreach ($image as $frame) {
|
||||
imagesetpixel(
|
||||
$frame->core(),
|
||||
$frame->data(),
|
||||
$this->position->x(),
|
||||
$this->position->y(),
|
||||
$this->colorToInteger($color)
|
||||
$color
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
||||
|
@@ -2,42 +2,38 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Modifiers\AbstractDrawModifier;
|
||||
use Intervention\Image\Drivers\Gd\Traits\CanHandleColors;
|
||||
use Intervention\Image\Interfaces\DrawableInterface;
|
||||
use Intervention\Image\Drivers\DrawModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class DrawPolygonModifier extends AbstractDrawModifier implements ModifierInterface
|
||||
class DrawPolygonModifier extends DrawModifier
|
||||
{
|
||||
use CanHandleColors;
|
||||
|
||||
public function __construct(
|
||||
protected DrawableInterface $drawable
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
return $image->mapFrames(function ($frame) {
|
||||
if ($this->polygon()->hasBackgroundColor()) {
|
||||
foreach ($image as $frame) {
|
||||
if ($this->drawable->hasBackgroundColor()) {
|
||||
imagefilledpolygon(
|
||||
$frame->core(),
|
||||
$this->polygon()->toArray(),
|
||||
$this->colorToInteger($this->getBackgroundColor())
|
||||
$frame->data(),
|
||||
$this->drawable->toArray(),
|
||||
$this->driver()->colorToNative(
|
||||
$this->backgroundColor(),
|
||||
$image->colorspace()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->polygon()->hasBorder()) {
|
||||
imagesetthickness($frame->core(), $this->polygon()->getBorderSize());
|
||||
if ($this->drawable->hasBorder()) {
|
||||
imagesetthickness($frame->data(), $this->drawable->borderSize());
|
||||
imagepolygon(
|
||||
$frame->core(),
|
||||
$this->polygon()->toArray(),
|
||||
$this->polygon()->count(),
|
||||
$this->colorToInteger($this->getBorderColor())
|
||||
$frame->data(),
|
||||
$this->drawable->toArray(),
|
||||
$this->driver()->colorToNative(
|
||||
$this->borderColor(),
|
||||
$image->colorspace()
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
||||
|
@@ -2,43 +2,45 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Modifiers\AbstractDrawModifier;
|
||||
use Intervention\Image\Drivers\Gd\Traits\CanHandleColors;
|
||||
use Intervention\Image\Drivers\DrawModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class DrawRectangleModifier extends AbstractDrawModifier implements ModifierInterface
|
||||
class DrawRectangleModifier extends DrawModifier
|
||||
{
|
||||
use CanHandleColors;
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$image->mapFrames(function ($frame) {
|
||||
foreach ($image as $frame) {
|
||||
// draw background
|
||||
if ($this->rectangle()->hasBackgroundColor()) {
|
||||
if ($this->drawable->hasBackgroundColor()) {
|
||||
imagefilledrectangle(
|
||||
$frame->core(),
|
||||
$frame->data(),
|
||||
$this->position->x(),
|
||||
$this->position->y(),
|
||||
$this->position->x() + $this->rectangle()->bottomRightPoint()->x(),
|
||||
$this->position->y() + $this->rectangle()->bottomRightPoint()->y(),
|
||||
$this->colorToInteger($this->getBackgroundColor())
|
||||
$this->position->x() + $this->drawable->width(),
|
||||
$this->position->y() + $this->drawable->height(),
|
||||
$this->driver()->colorToNative(
|
||||
$this->backgroundColor(),
|
||||
$image->colorspace()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->rectangle()->hasBorder()) {
|
||||
// draw border
|
||||
imagesetthickness($frame->core(), $this->rectangle()->getBorderSize());
|
||||
// draw border
|
||||
if ($this->drawable->hasBorder()) {
|
||||
imagesetthickness($frame->data(), $this->drawable->borderSize());
|
||||
imagerectangle(
|
||||
$frame->core(),
|
||||
$frame->data(),
|
||||
$this->position->x(),
|
||||
$this->position->y(),
|
||||
$this->position->x() + $this->rectangle()->bottomRightPoint()->x(),
|
||||
$this->position->y() + $this->rectangle()->bottomRightPoint()->y(),
|
||||
$this->colorToInteger($this->getBorderColor())
|
||||
$this->position->x() + $this->drawable->width(),
|
||||
$this->position->y() + $this->drawable->height(),
|
||||
$this->driver()->colorToNative(
|
||||
$this->borderColor(),
|
||||
$image->colorspace()
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
@@ -2,25 +2,16 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Colors\Rgb\Colorspace;
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Drivers\Gd\Frame;
|
||||
use Intervention\Image\Drivers\Gd\Traits\CanHandleColors;
|
||||
use Intervention\Image\Geometry\Point;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class FillModifier implements ModifierInterface
|
||||
class FillModifier extends DriverModifier
|
||||
{
|
||||
use CanHandleColors;
|
||||
|
||||
public function __construct(protected ColorInterface $color, protected ?Point $position = null)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$color = $this->colorToInteger($this->color);
|
||||
$color = $this->color();
|
||||
|
||||
foreach ($image as $frame) {
|
||||
if ($this->hasPosition()) {
|
||||
@@ -33,21 +24,29 @@ class FillModifier implements ModifierInterface
|
||||
return $image;
|
||||
}
|
||||
|
||||
protected function floodFillWithColor(Frame $frame, int $color): void
|
||||
private function color(): int
|
||||
{
|
||||
return $this->driver()->colorToNative(
|
||||
$this->driver()->handleInput($this->color),
|
||||
new Colorspace()
|
||||
);
|
||||
}
|
||||
|
||||
private function floodFillWithColor(Frame $frame, int $color): void
|
||||
{
|
||||
imagefill(
|
||||
$frame->core(),
|
||||
$frame->data(),
|
||||
$this->position->x(),
|
||||
$this->position->y(),
|
||||
$color
|
||||
);
|
||||
}
|
||||
|
||||
protected function fillAllWithColor(Frame $frame, int $color): void
|
||||
private function fillAllWithColor(Frame $frame, int $color): void
|
||||
{
|
||||
imagealphablending($frame->core(), true);
|
||||
imagealphablending($frame->data(), true);
|
||||
imagefilledrectangle(
|
||||
$frame->core(),
|
||||
$frame->data(),
|
||||
0,
|
||||
0,
|
||||
$frame->size()->width() - 1,
|
||||
@@ -55,9 +54,4 @@ class FillModifier implements ModifierInterface
|
||||
$color
|
||||
);
|
||||
}
|
||||
|
||||
protected function hasPosition(): bool
|
||||
{
|
||||
return !empty($this->position);
|
||||
}
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ use Intervention\Image\Interfaces\SizeInterface;
|
||||
|
||||
class FitDownModifier extends FitModifier
|
||||
{
|
||||
protected function getResizeSize(SizeInterface $size): SizeInterface
|
||||
public function getResizeSize(SizeInterface $size): SizeInterface
|
||||
{
|
||||
return $size->scaleDown($this->width, $this->height);
|
||||
}
|
||||
|
@@ -2,17 +2,13 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Modifiers\AbstractFitModifier;
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\FrameInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
use Intervention\Image\Interfaces\SizeInterface;
|
||||
use Intervention\Image\Traits\CanBuildNewImage;
|
||||
|
||||
class FitModifier extends AbstractFitModifier implements ModifierInterface
|
||||
class FitModifier extends DriverModifier
|
||||
{
|
||||
use CanBuildNewImage;
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$crop = $this->getCropSize($image);
|
||||
@@ -28,13 +24,13 @@ class FitModifier extends AbstractFitModifier implements ModifierInterface
|
||||
protected function modifyFrame(FrameInterface $frame, SizeInterface $crop, SizeInterface $resize): void
|
||||
{
|
||||
// create new image
|
||||
$modified = $this->imageFactory()->newCore(
|
||||
$modified = $this->driver()->createImage(
|
||||
$resize->width(),
|
||||
$resize->height()
|
||||
);
|
||||
)->core()->native();
|
||||
|
||||
// get original image
|
||||
$original = $frame->core();
|
||||
$original = $frame->data();
|
||||
|
||||
// preserve transparency
|
||||
$transIndex = imagecolortransparent($original);
|
||||
@@ -61,6 +57,6 @@ class FitModifier extends AbstractFitModifier implements ModifierInterface
|
||||
);
|
||||
|
||||
// set new content as resource
|
||||
$frame->setCore($modified);
|
||||
$frame->setData($modified);
|
||||
}
|
||||
}
|
||||
|
@@ -2,15 +2,15 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class FlipModifier implements ModifierInterface
|
||||
class FlipModifier extends DriverModifier
|
||||
{
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
foreach ($image as $frame) {
|
||||
imageflip($frame->core(), IMG_FLIP_VERTICAL);
|
||||
imageflip($frame->data(), IMG_FLIP_VERTICAL);
|
||||
}
|
||||
|
||||
return $image;
|
||||
|
@@ -2,15 +2,15 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class FlopModifier implements ModifierInterface
|
||||
class FlopModifier extends DriverModifier
|
||||
{
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
foreach ($image as $frame) {
|
||||
imageflip($frame->core(), IMG_FLIP_HORIZONTAL);
|
||||
imageflip($frame->data(), IMG_FLIP_HORIZONTAL);
|
||||
}
|
||||
|
||||
return $image;
|
||||
|
@@ -2,20 +2,15 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class GammaModifier implements ModifierInterface
|
||||
class GammaModifier extends DriverModifier
|
||||
{
|
||||
public function __construct(protected float $gamma)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
foreach ($image as $frame) {
|
||||
imagegammacorrect($frame->core(), 1, $this->gamma);
|
||||
imagegammacorrect($frame->data(), 1, $this->gamma);
|
||||
}
|
||||
|
||||
return $image;
|
||||
|
@@ -2,15 +2,15 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class GreyscaleModifier implements ModifierInterface
|
||||
class GreyscaleModifier extends DriverModifier
|
||||
{
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
foreach ($image as $frame) {
|
||||
imagefilter($frame->core(), IMG_FILTER_GRAYSCALE);
|
||||
imagefilter($frame->data(), IMG_FILTER_GRAYSCALE);
|
||||
}
|
||||
|
||||
return $image;
|
||||
|
@@ -2,15 +2,15 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class InvertModifier implements ModifierInterface
|
||||
class InvertModifier extends DriverModifier
|
||||
{
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
foreach ($image as $frame) {
|
||||
imagefilter($frame->core(), IMG_FILTER_NEGATE);
|
||||
imagefilter($frame->data(), IMG_FILTER_NEGATE);
|
||||
}
|
||||
|
||||
return $image;
|
||||
|
@@ -2,16 +2,11 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class LimitColorsModifier implements ModifierInterface
|
||||
class LimitColorsModifier extends DriverModifier
|
||||
{
|
||||
public function __construct(protected int $limit = 0, protected int $threshold = 256)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
// no color limit: no reduction
|
||||
@@ -43,15 +38,15 @@ class LimitColorsModifier implements ModifierInterface
|
||||
imagecolortransparent($reduced, $matte);
|
||||
|
||||
// copy original image
|
||||
imagecopy($reduced, $frame->core(), 0, 0, 0, 0, $width, $height);
|
||||
imagecopy($reduced, $frame->data(), 0, 0, 0, 0, $width, $height);
|
||||
|
||||
// reduce limit by one to include possible transparency in palette
|
||||
$limit = imagecolortransparent($frame->core()) === -1 ? $this->limit : $this->limit - 1;
|
||||
$limit = imagecolortransparent($frame->data()) === -1 ? $this->limit : $this->limit - 1;
|
||||
|
||||
// decrease colors
|
||||
imagetruecolortopalette($reduced, true, $limit);
|
||||
|
||||
$frame->setCore($reduced);
|
||||
$frame->setData($reduced);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -2,24 +2,6 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Geometry\Rectangle;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\SizeInterface;
|
||||
|
||||
class PadDownModifier extends PadModifier
|
||||
{
|
||||
protected function getCropSize(ImageInterface $image): SizeInterface
|
||||
{
|
||||
$resize = $this->getResizeSize($image);
|
||||
|
||||
return $image->size()
|
||||
->contain($resize->width(), $resize->height())
|
||||
->alignPivotTo($resize, $this->position);
|
||||
}
|
||||
|
||||
protected function getResizeSize(ImageInterface $image): SizeInterface
|
||||
{
|
||||
return (new Rectangle($this->width, $this->height))
|
||||
->resizeDown($image->width(), $image->height());
|
||||
}
|
||||
}
|
||||
|
@@ -2,27 +2,20 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Modifiers\AbstractPadModifier;
|
||||
use Intervention\Image\Drivers\Gd\Traits\CanHandleColors;
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\FrameInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
use Intervention\Image\Interfaces\SizeInterface;
|
||||
use Intervention\Image\Traits\CanBuildNewImage;
|
||||
use Intervention\Image\Traits\CanHandleInput;
|
||||
use Intervention\Image\Modifiers\FillModifier;
|
||||
|
||||
class PadModifier extends AbstractPadModifier implements ModifierInterface
|
||||
class PadModifier extends DriverModifier
|
||||
{
|
||||
use CanHandleInput;
|
||||
use CanHandleColors;
|
||||
use CanBuildNewImage;
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$crop = $this->getCropSize($image);
|
||||
$resize = $this->getResizeSize($image);
|
||||
$background = $this->handleInput($this->background);
|
||||
$background = $this->driver()->handleInput($this->background);
|
||||
|
||||
foreach ($image as $frame) {
|
||||
$this->modify($frame, $crop, $resize, $background);
|
||||
@@ -38,11 +31,12 @@ class PadModifier extends AbstractPadModifier implements ModifierInterface
|
||||
ColorInterface $background
|
||||
): void {
|
||||
// create new gd image
|
||||
$modified = $this->imageFactory()->newCore(
|
||||
$modified = $this->driver()->createImage(
|
||||
$resize->width(),
|
||||
$resize->height(),
|
||||
$background
|
||||
);
|
||||
$resize->height()
|
||||
)->modify(
|
||||
new FillModifier($background)
|
||||
)->core()->native();
|
||||
|
||||
// make image area transparent to keep transparency
|
||||
// even if background-color is set
|
||||
@@ -62,7 +56,7 @@ class PadModifier extends AbstractPadModifier implements ModifierInterface
|
||||
imagealphablending($modified, true);
|
||||
imagecopyresampled(
|
||||
$modified,
|
||||
$frame->core(),
|
||||
$frame->data(),
|
||||
$crop->pivot()->x(),
|
||||
$crop->pivot()->y(),
|
||||
0,
|
||||
@@ -74,6 +68,6 @@ class PadModifier extends AbstractPadModifier implements ModifierInterface
|
||||
);
|
||||
|
||||
// set new content as recource
|
||||
$frame->setCore($modified);
|
||||
$frame->setData($modified);
|
||||
}
|
||||
}
|
||||
|
@@ -2,21 +2,15 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Interfaces\FrameInterface;
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class PixelateModifier implements ModifierInterface
|
||||
class PixelateModifier extends DriverModifier
|
||||
{
|
||||
public function __construct(protected int $size)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
foreach ($image as $frame) {
|
||||
imagefilter($frame->core(), IMG_FILTER_PIXELATE, $this->size, true);
|
||||
imagefilter($frame->data(), IMG_FILTER_PIXELATE, $this->size, true);
|
||||
}
|
||||
|
||||
return $image;
|
||||
|
@@ -2,38 +2,21 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
use Intervention\Image\Interfaces\PointInterface;
|
||||
use Intervention\Image\Traits\CanHandleInput;
|
||||
|
||||
class PlaceModifier implements ModifierInterface
|
||||
class PlaceModifier extends DriverModifier
|
||||
{
|
||||
use CanHandleInput;
|
||||
|
||||
/**
|
||||
* Create new modifier
|
||||
*
|
||||
*/
|
||||
public function __construct(
|
||||
protected $element,
|
||||
protected string $position,
|
||||
protected int $offset_x,
|
||||
protected int $offset_y
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$watermark = $this->handleInput($this->element);
|
||||
$watermark = $this->driver()->handleInput($this->element);
|
||||
$position = $this->getPosition($image, $watermark);
|
||||
|
||||
foreach ($image as $frame) {
|
||||
imagealphablending($frame->core(), true);
|
||||
imagealphablending($frame->data(), true);
|
||||
imagecopy(
|
||||
$frame->core(),
|
||||
$watermark->frame()->core(),
|
||||
$frame->data(),
|
||||
$watermark->core()->native(),
|
||||
$position->x(),
|
||||
$position->y(),
|
||||
0,
|
||||
@@ -45,12 +28,4 @@ class PlaceModifier implements ModifierInterface
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
protected function getPosition(ImageInterface $image, ImageInterface $watermark): PointInterface
|
||||
{
|
||||
$image_size = $image->size()->movePivot($this->position, $this->offset_x, $this->offset_y);
|
||||
$watermark_size = $watermark->size()->movePivot($this->position);
|
||||
|
||||
return $image_size->relativePositionTo($watermark_size);
|
||||
}
|
||||
}
|
||||
|
17
src/Drivers/Gd/Modifiers/ProfileModifier.php
Normal file
17
src/Drivers/Gd/Modifiers/ProfileModifier.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Exceptions\NotSupportedException;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class ProfileModifier extends DriverModifier
|
||||
{
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
throw new NotSupportedException(
|
||||
'Color profiles are not supported by GD driver.'
|
||||
);
|
||||
}
|
||||
}
|
17
src/Drivers/Gd/Modifiers/ProfileRemovalModifier.php
Normal file
17
src/Drivers/Gd/Modifiers/ProfileRemovalModifier.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Exceptions\NotSupportedException;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class ProfileRemovalModifier extends DriverModifier
|
||||
{
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
throw new NotSupportedException(
|
||||
'Color profiles are not supported by GD driver.'
|
||||
);
|
||||
}
|
||||
}
|
@@ -2,26 +2,21 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Collection;
|
||||
use Intervention\Image\Drivers\Abstract\Modifiers\AbstractRemoveAnimationModifier;
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Drivers\Gd\Core;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Traits\CanCheckType;
|
||||
use Intervention\Image\Drivers\Gd\Image;
|
||||
|
||||
class RemoveAnimationModifier extends AbstractRemoveAnimationModifier
|
||||
class RemoveAnimationModifier extends DriverModifier
|
||||
{
|
||||
use CanCheckType;
|
||||
|
||||
public function __construct(protected int|string $position = 0)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$image = $this->failIfNotClass($image, Image::class);
|
||||
return $image->setFrames(new Collection([
|
||||
$this->chosenFrame($image, $this->position)
|
||||
]));
|
||||
return new Image(
|
||||
$image->driver(),
|
||||
new Core([
|
||||
$this->chosenFrame($image, $this->position)
|
||||
]),
|
||||
$image->exif()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -2,22 +2,16 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\FrameInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
use Intervention\Image\Interfaces\SizeInterface;
|
||||
|
||||
class ResizeModifier implements ModifierInterface
|
||||
class ResizeModifier extends DriverModifier
|
||||
{
|
||||
public function __construct(protected ?int $width = null, protected ?int $height = null)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$resizeTo = $this->getAdjustedSize($image);
|
||||
|
||||
foreach ($image as $frame) {
|
||||
$this->resizeFrame($frame, $resizeTo);
|
||||
}
|
||||
@@ -25,12 +19,7 @@ class ResizeModifier implements ModifierInterface
|
||||
return $image;
|
||||
}
|
||||
|
||||
protected function getAdjustedSize(ImageInterface $image): SizeInterface
|
||||
{
|
||||
return $image->size()->resize($this->width, $this->height);
|
||||
}
|
||||
|
||||
protected function resizeFrame(FrameInterface $frame, SizeInterface $resizeTo): void
|
||||
private function resizeFrame(FrameInterface $frame, SizeInterface $resizeTo): void
|
||||
{
|
||||
// create new image
|
||||
$modified = imagecreatetruecolor(
|
||||
@@ -38,8 +27,8 @@ class ResizeModifier implements ModifierInterface
|
||||
$resizeTo->height()
|
||||
);
|
||||
|
||||
// get current image
|
||||
$current = $frame->core();
|
||||
// get current GDImage
|
||||
$current = $frame->data();
|
||||
|
||||
// preserve transparency
|
||||
$transIndex = imagecolortransparent($current);
|
||||
@@ -69,6 +58,11 @@ class ResizeModifier implements ModifierInterface
|
||||
);
|
||||
|
||||
// set new content as recource
|
||||
$frame->setCore($modified);
|
||||
$frame->setData($modified);
|
||||
}
|
||||
|
||||
protected function getAdjustedSize(ImageInterface $image): SizeInterface
|
||||
{
|
||||
return $image->size()->resize($this->width, $this->height);
|
||||
}
|
||||
}
|
||||
|
@@ -2,23 +2,18 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class ResolutionModifier implements ModifierInterface
|
||||
class ResolutionModifier extends DriverModifier
|
||||
{
|
||||
public function __construct(protected float $x, protected float $y)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$x = intval(round($this->x));
|
||||
$y = intval(round($this->y));
|
||||
|
||||
foreach ($image as $frame) {
|
||||
imageresolution($frame->core(), $x, $y);
|
||||
imageresolution($frame->data(), $x, $y);
|
||||
}
|
||||
|
||||
return $image;
|
||||
|
@@ -5,29 +5,24 @@ namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
use Intervention\Image\Colors\Rgb\Channels\Blue;
|
||||
use Intervention\Image\Colors\Rgb\Channels\Green;
|
||||
use Intervention\Image\Colors\Rgb\Channels\Red;
|
||||
use Intervention\Image\Drivers\Abstract\Modifiers\AbstractRotateModifier;
|
||||
use Intervention\Image\Drivers\Gd\Traits\CanHandleColors;
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Exceptions\RuntimeException;
|
||||
use Intervention\Image\Exceptions\MissingDriverComponentException;
|
||||
use Intervention\Image\Geometry\Rectangle;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\FrameInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
use Intervention\Image\Traits\CanBuildNewImage;
|
||||
use Intervention\Image\Modifiers\FillModifier;
|
||||
use ReflectionException;
|
||||
|
||||
class RotateModifier extends AbstractRotateModifier implements ModifierInterface
|
||||
class RotateModifier extends DriverModifier
|
||||
{
|
||||
use CanHandleColors;
|
||||
use CanBuildNewImage;
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$background = $this->handleInput($this->background);
|
||||
$background = $this->driver()->handleInput($this->background);
|
||||
|
||||
foreach ($image as $frame) {
|
||||
$this->modify($frame, $background);
|
||||
$this->modifyFrame($frame, $background);
|
||||
}
|
||||
|
||||
return $image;
|
||||
@@ -44,12 +39,12 @@ class RotateModifier extends AbstractRotateModifier implements ModifierInterface
|
||||
* @throws MissingDriverComponentException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
protected function modify(FrameInterface $frame, ColorInterface $background): void
|
||||
protected function modifyFrame(FrameInterface $frame, ColorInterface $background): void
|
||||
{
|
||||
// get transparent color from frame core
|
||||
$transparent = match ($transparent = imagecolortransparent($frame->core())) {
|
||||
$transparent = match ($transparent = imagecolortransparent($frame->data())) {
|
||||
-1 => imagecolorallocatealpha(
|
||||
$frame->core(),
|
||||
$frame->data(),
|
||||
$background->channel(Red::class)->value(),
|
||||
$background->channel(Green::class)->value(),
|
||||
$background->channel(Blue::class)->value(),
|
||||
@@ -60,7 +55,7 @@ class RotateModifier extends AbstractRotateModifier implements ModifierInterface
|
||||
|
||||
// rotate original image against transparent background
|
||||
$rotated = imagerotate(
|
||||
$frame->core(),
|
||||
$frame->data(),
|
||||
$this->rotationAngle(),
|
||||
$transparent
|
||||
);
|
||||
@@ -73,19 +68,20 @@ class RotateModifier extends AbstractRotateModifier implements ModifierInterface
|
||||
|
||||
// create size from original and rotate points
|
||||
$cutout = (new Rectangle(
|
||||
imagesx($frame->core()),
|
||||
imagesy($frame->core()),
|
||||
imagesx($frame->data()),
|
||||
imagesy($frame->data()),
|
||||
$container->pivot()
|
||||
))->align('center')
|
||||
->valign('center')
|
||||
->rotate($this->rotationAngle() * -1);
|
||||
|
||||
// create new gd core
|
||||
$modified = $this->imageFactory()->newCore(
|
||||
// create new gd image
|
||||
$modified = $this->driver()->createImage(
|
||||
imagesx($rotated),
|
||||
imagesy($rotated),
|
||||
$background
|
||||
);
|
||||
imagesy($rotated)
|
||||
)->modify(new FillModifier($background))
|
||||
->core()
|
||||
->native();
|
||||
|
||||
// draw the cutout on new gd image to have a transparent
|
||||
// background where the rotated image will be placed
|
||||
@@ -109,6 +105,6 @@ class RotateModifier extends AbstractRotateModifier implements ModifierInterface
|
||||
imagesy($rotated)
|
||||
);
|
||||
|
||||
$frame->setCore($modified);
|
||||
$frame->setData($modified);
|
||||
}
|
||||
}
|
||||
|
@@ -2,27 +2,22 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class SharpenModifier implements ModifierInterface
|
||||
class SharpenModifier extends DriverModifier
|
||||
{
|
||||
public function __construct(protected int $amount)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$matrix = $this->matrix();
|
||||
foreach ($image as $frame) {
|
||||
imageconvolution($frame->core(), $matrix, 1, 0);
|
||||
imageconvolution($frame->data(), $matrix, 1, 0);
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
protected function matrix(): array
|
||||
private function matrix(): array
|
||||
{
|
||||
$min = $this->amount >= 10 ? $this->amount * -0.01 : 0;
|
||||
$max = $this->amount * -0.025;
|
||||
|
@@ -2,26 +2,25 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\AbstractTextWriter;
|
||||
use Intervention\Image\Drivers\Gd\Font;
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Drivers\Gd\Traits\CanHandleColors;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class TextWriter extends AbstractTextWriter
|
||||
class TextWriter extends DriverModifier
|
||||
{
|
||||
use CanHandleColors;
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$lines = $this->getAlignedTextBlock();
|
||||
$font = $this->failIfNotClass($this->getFont(), Font::class);
|
||||
$font = $this->font;
|
||||
$color = $this->colorToInteger($font->getColor());
|
||||
|
||||
foreach ($image as $frame) {
|
||||
if ($this->font->hasFilename()) {
|
||||
foreach ($lines as $line) {
|
||||
imagettftext(
|
||||
$frame->core(),
|
||||
$frame->data(),
|
||||
$font->getSize(),
|
||||
$font->getAngle() * (-1),
|
||||
$line->getPosition()->x(),
|
||||
@@ -34,7 +33,7 @@ class TextWriter extends AbstractTextWriter
|
||||
} else {
|
||||
foreach ($lines as $line) {
|
||||
imagestring(
|
||||
$frame->core(),
|
||||
$frame->data(),
|
||||
$font->getGdFont(),
|
||||
$line->getPosition()->x(),
|
||||
$line->getPosition()->y(),
|
||||
|
@@ -10,7 +10,7 @@ use Intervention\Image\Colors\Rgb\Channels\Blue;
|
||||
use Intervention\Image\Colors\Rgb\Channels\Green;
|
||||
use Intervention\Image\Colors\Rgb\Channels\Red;
|
||||
|
||||
trait CanHandleColors
|
||||
trait DELETE___CanHandleColors
|
||||
{
|
||||
/**
|
||||
* Allocate given color in given gd image and return color value/index
|
||||
|
22
src/Drivers/Imagick/ColorProcessor.php
Normal file
22
src/Drivers/Imagick/ColorProcessor.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick;
|
||||
|
||||
use ImagickPixel;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorProcessorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
|
||||
class ColorProcessor implements ColorProcessorInterface
|
||||
{
|
||||
public function __construct(protected ColorspaceInterface $colorspace)
|
||||
{
|
||||
}
|
||||
|
||||
public function colorToNative(ColorInterface $color): ImagickPixel
|
||||
{
|
||||
return new ImagickPixel(
|
||||
(string) $color->convertTo($this->colorspace)
|
||||
);
|
||||
}
|
||||
}
|
107
src/Drivers/Imagick/Core.php
Normal file
107
src/Drivers/Imagick/Core.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick;
|
||||
|
||||
use Imagick;
|
||||
use ImagickException;
|
||||
use Iterator;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
use Intervention\Image\Interfaces\CoreInterface;
|
||||
use Intervention\Image\Colors\Cmyk\Colorspace as CmykColorspace;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\Exceptions\AnimationException;
|
||||
use Intervention\Image\Interfaces\FrameInterface;
|
||||
|
||||
class Core implements CoreInterface, Iterator
|
||||
{
|
||||
protected int $iteratorIndex = 0;
|
||||
|
||||
public function __construct(protected Imagick $imagick)
|
||||
{
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return $this->imagick->getNumberImages();
|
||||
}
|
||||
|
||||
public function current(): mixed
|
||||
{
|
||||
$this->imagick->setIteratorIndex($this->iteratorIndex);
|
||||
|
||||
return new Frame($this->imagick->current());
|
||||
}
|
||||
|
||||
public function next(): void
|
||||
{
|
||||
$this->iteratorIndex = $this->iteratorIndex + 1;
|
||||
}
|
||||
|
||||
public function key(): mixed
|
||||
{
|
||||
return $this->iteratorIndex;
|
||||
}
|
||||
|
||||
public function valid(): bool
|
||||
{
|
||||
try {
|
||||
$result = $this->imagick->setIteratorIndex($this->iteratorIndex);
|
||||
} catch (ImagickException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function rewind(): void
|
||||
{
|
||||
$this->iteratorIndex = 0;
|
||||
}
|
||||
|
||||
public function native()
|
||||
{
|
||||
return $this->imagick;
|
||||
}
|
||||
|
||||
public function width(): int
|
||||
{
|
||||
return $this->imagick->getImageWidth();
|
||||
}
|
||||
|
||||
public function height(): int
|
||||
{
|
||||
return $this->imagick->getImageHeight();
|
||||
}
|
||||
|
||||
public function frame(int $position): FrameInterface
|
||||
{
|
||||
foreach ($this->imagick as $core) {
|
||||
if ($core->getIteratorIndex() == $position) {
|
||||
return new Frame($core);
|
||||
}
|
||||
}
|
||||
|
||||
throw new AnimationException('Frame #' . $position . ' is not be found in the image.');
|
||||
}
|
||||
|
||||
public function loops(): int
|
||||
{
|
||||
return $this->imagick->getImageIterations();
|
||||
}
|
||||
|
||||
public function setLoops(int $loops): CoreInterface
|
||||
{
|
||||
$this->imagick = $this->imagick->coalesceImages();
|
||||
$this->imagick->setImageIterations($loops);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function colorspace(): ColorspaceInterface
|
||||
{
|
||||
return match ($this->imagick->getImageColorspace()) {
|
||||
Imagick::COLORSPACE_CMYK => new CmykColorspace(),
|
||||
default => new RgbColorspace(),
|
||||
};
|
||||
}
|
||||
}
|
@@ -4,9 +4,11 @@ namespace Intervention\Image\Drivers\Imagick\Decoders;
|
||||
|
||||
use Imagick;
|
||||
use ImagickException;
|
||||
use Intervention\Image\Drivers\Abstract\Decoders\AbstractDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Image;
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Core;
|
||||
use Intervention\Image\Drivers\Imagick\Driver;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
@@ -46,9 +48,11 @@ class BinaryImageDecoder extends AbstractDecoder implements DecoderInterface
|
||||
// set new orientation in image
|
||||
$imagick->setImageOrientation(Imagick::ORIENTATION_TOPLEFT);
|
||||
|
||||
$image = new Image($imagick);
|
||||
$image->setLoops($imagick->getImageIterations());
|
||||
$image->setExif($this->decodeExifData($input));
|
||||
$image = new Image(
|
||||
new Driver(),
|
||||
new Core($imagick),
|
||||
$this->decodeExifData($input)
|
||||
);
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Decoders\AbstractDecoder;
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Decoders\AbstractDecoder;
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
|
38
src/Drivers/Imagick/Driver.php
Normal file
38
src/Drivers/Imagick/Driver.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick;
|
||||
|
||||
use Imagick;
|
||||
use ImagickPixel;
|
||||
use Intervention\Image\Drivers\AbstractDriver;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class Driver extends AbstractDriver
|
||||
{
|
||||
public function createImage(int $width, int $height): ImageInterface
|
||||
{
|
||||
$background = new ImagickPixel('rgba(0, 0, 0, 0)');
|
||||
|
||||
$imagick = new Imagick();
|
||||
$imagick->newImage($width, $height, $background, 'png');
|
||||
$imagick->setType(Imagick::IMGTYPE_UNDEFINED);
|
||||
$imagick->setImageType(Imagick::IMGTYPE_UNDEFINED);
|
||||
$imagick->setColorspace(Imagick::COLORSPACE_SRGB);
|
||||
$imagick->setImageResolution(96, 96);
|
||||
|
||||
return new Image($this, new Core($imagick));
|
||||
}
|
||||
|
||||
public function handleInput(mixed $input): ImageInterface|ColorInterface
|
||||
{
|
||||
return (new InputHandler())->handle($input);
|
||||
}
|
||||
|
||||
public function colorToNative(ColorInterface $color, ColorspaceInterface $colorspace): mixed
|
||||
{
|
||||
return (new ColorProcessor($colorspace))->colorToNative($color);
|
||||
}
|
||||
}
|
@@ -3,24 +3,18 @@
|
||||
namespace Intervention\Image\Drivers\Imagick\Encoders;
|
||||
|
||||
use Imagick;
|
||||
use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder;
|
||||
use Intervention\Image\Drivers\DriverEncoder;
|
||||
use Intervention\Image\EncodedImage;
|
||||
use Intervention\Image\Interfaces\EncoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class AvifEncoder extends AbstractEncoder implements EncoderInterface
|
||||
class AvifEncoder extends DriverEncoder
|
||||
{
|
||||
public function __construct(int $quality)
|
||||
{
|
||||
$this->quality = $quality;
|
||||
}
|
||||
|
||||
public function encode(ImageInterface $image): EncodedImage
|
||||
{
|
||||
$format = 'AVIF';
|
||||
$compression = Imagick::COMPRESSION_ZIP;
|
||||
|
||||
$imagick = $image->frame()->core();
|
||||
$imagick = $image->core()->native();
|
||||
$imagick->setFormat($format);
|
||||
$imagick->setImageFormat($format);
|
||||
$imagick->setCompression($compression);
|
||||
|
@@ -3,26 +3,20 @@
|
||||
namespace Intervention\Image\Drivers\Imagick\Encoders;
|
||||
|
||||
use Imagick;
|
||||
use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder;
|
||||
use Intervention\Image\Drivers\Imagick\Modifiers\LimitColorsModifier;
|
||||
use Intervention\Image\Drivers\DriverEncoder;
|
||||
use Intervention\Image\Modifiers\LimitColorsModifier;
|
||||
use Intervention\Image\EncodedImage;
|
||||
use Intervention\Image\Interfaces\EncoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class BmpEncoder extends AbstractEncoder implements EncoderInterface
|
||||
class BmpEncoder extends DriverEncoder
|
||||
{
|
||||
public function __construct(protected int $color_limit = 0)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function encode(ImageInterface $image): EncodedImage
|
||||
{
|
||||
$format = 'bmp';
|
||||
$compression = Imagick::COMPRESSION_NO;
|
||||
|
||||
$image = $image->modify(new LimitColorsModifier($this->color_limit));
|
||||
$imagick = $image->frame()->core();
|
||||
$imagick = $image->core()->native();
|
||||
$imagick->setFormat($format);
|
||||
$imagick->setImageFormat($format);
|
||||
$imagick->setCompression($compression);
|
||||
|
@@ -3,37 +3,23 @@
|
||||
namespace Intervention\Image\Drivers\Imagick\Encoders;
|
||||
|
||||
use Imagick;
|
||||
use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder;
|
||||
use Intervention\Image\Drivers\Imagick\Image;
|
||||
use Intervention\Image\Drivers\Imagick\Modifiers\LimitColorsModifier;
|
||||
use Intervention\Image\Drivers\DriverEncoder;
|
||||
use Intervention\Image\Modifiers\LimitColorsModifier;
|
||||
use Intervention\Image\EncodedImage;
|
||||
use Intervention\Image\Exceptions\EncoderException;
|
||||
use Intervention\Image\Interfaces\EncoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Traits\CanCheckType;
|
||||
|
||||
class GifEncoder extends AbstractEncoder implements EncoderInterface
|
||||
class GifEncoder extends DriverEncoder
|
||||
{
|
||||
use CanCheckType;
|
||||
|
||||
public function __construct(protected int $color_limit = 0)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function encode(ImageInterface $image): EncodedImage
|
||||
{
|
||||
$image = $image->modify(new LimitColorsModifier($this->color_limit));
|
||||
|
||||
|
||||
$format = 'gif';
|
||||
$compression = Imagick::COMPRESSION_LZW;
|
||||
|
||||
if (!is_a($image, Image::class)) {
|
||||
throw new EncoderException('Image does not match the current driver.');
|
||||
}
|
||||
$imagick = $image->core()->native();
|
||||
|
||||
$image = $this->failIfNotClass($image, Image::class);
|
||||
|
||||
$image = $image->modify(new LimitColorsModifier($this->color_limit));
|
||||
$imagick = $image->getImagick();
|
||||
$imagick->setFormat($format);
|
||||
$imagick->setImageFormat($format);
|
||||
$imagick->setCompression($compression);
|
||||
|
@@ -3,24 +3,18 @@
|
||||
namespace Intervention\Image\Drivers\Imagick\Encoders;
|
||||
|
||||
use Imagick;
|
||||
use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder;
|
||||
use Intervention\Image\Drivers\DriverEncoder;
|
||||
use Intervention\Image\EncodedImage;
|
||||
use Intervention\Image\Interfaces\EncoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class JpegEncoder extends AbstractEncoder implements EncoderInterface
|
||||
class JpegEncoder extends DriverEncoder
|
||||
{
|
||||
public function __construct(int $quality)
|
||||
{
|
||||
$this->quality = $quality;
|
||||
}
|
||||
|
||||
public function encode(ImageInterface $image): EncodedImage
|
||||
{
|
||||
$format = 'jpeg';
|
||||
$compression = Imagick::COMPRESSION_JPEG;
|
||||
|
||||
$imagick = $image->frame()->core();
|
||||
$imagick = $image->core()->native();
|
||||
$imagick->setImageBackgroundColor('white');
|
||||
$imagick->setBackgroundColor('white');
|
||||
$imagick->setFormat($format);
|
||||
|
@@ -3,26 +3,20 @@
|
||||
namespace Intervention\Image\Drivers\Imagick\Encoders;
|
||||
|
||||
use Imagick;
|
||||
use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder;
|
||||
use Intervention\Image\Drivers\Imagick\Modifiers\LimitColorsModifier;
|
||||
use Intervention\Image\Drivers\DriverEncoder;
|
||||
use Intervention\Image\Modifiers\LimitColorsModifier;
|
||||
use Intervention\Image\EncodedImage;
|
||||
use Intervention\Image\Interfaces\EncoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class PngEncoder extends AbstractEncoder implements EncoderInterface
|
||||
class PngEncoder extends DriverEncoder
|
||||
{
|
||||
public function __construct(protected int $color_limit = 0)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function encode(ImageInterface $image): EncodedImage
|
||||
{
|
||||
$format = 'png';
|
||||
$compression = Imagick::COMPRESSION_ZIP;
|
||||
|
||||
$image = $image->modify(new LimitColorsModifier($this->color_limit));
|
||||
$imagick = $image->frame()->core();
|
||||
$imagick = $image->core()->frame()->data();
|
||||
$imagick->setFormat($format);
|
||||
$imagick->setImageFormat($format);
|
||||
$imagick->setCompression($compression);
|
||||
|
@@ -4,24 +4,18 @@ namespace Intervention\Image\Drivers\Imagick\Encoders;
|
||||
|
||||
use Imagick;
|
||||
use ImagickPixel;
|
||||
use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder;
|
||||
use Intervention\Image\Drivers\DriverEncoder;
|
||||
use Intervention\Image\EncodedImage;
|
||||
use Intervention\Image\Interfaces\EncoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class WebpEncoder extends AbstractEncoder implements EncoderInterface
|
||||
class WebpEncoder extends DriverEncoder
|
||||
{
|
||||
public function __construct(int $quality)
|
||||
{
|
||||
$this->quality = $quality;
|
||||
}
|
||||
|
||||
public function encode(ImageInterface $image): EncodedImage
|
||||
{
|
||||
$format = 'webp';
|
||||
$compression = Imagick::COMPRESSION_ZIP;
|
||||
|
||||
$imagick = $image->frame()->core();
|
||||
$imagick = $image->core()->native();
|
||||
$imagick->setImageBackgroundColor(new ImagickPixel('transparent'));
|
||||
|
||||
$imagick = $imagick->mergeImageLayers(Imagick::LAYERMETHOD_MERGE);
|
||||
|
@@ -13,7 +13,7 @@ use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Traits\CanCheckType;
|
||||
use Intervention\Image\Traits\CanHandleInput;
|
||||
|
||||
class Factory implements FactoryInterface
|
||||
class DELETE___FactoryFactory implements FactoryInterface
|
||||
{
|
||||
use CanHandleInput;
|
||||
use CanCheckType;
|
||||
|
@@ -4,7 +4,7 @@ namespace Intervention\Image\Drivers\Imagick;
|
||||
|
||||
use Imagick;
|
||||
use ImagickDraw;
|
||||
use Intervention\Image\Drivers\Abstract\AbstractFont;
|
||||
use Intervention\Image\Drivers\AbstractFont;
|
||||
use Intervention\Image\Drivers\Imagick\Traits\CanHandleColors;
|
||||
use Intervention\Image\Exceptions\FontException;
|
||||
use Intervention\Image\Geometry\Polygon;
|
||||
|
@@ -4,66 +4,72 @@ namespace Intervention\Image\Drivers\Imagick;
|
||||
|
||||
use Imagick;
|
||||
use Intervention\Image\Geometry\Rectangle;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Interfaces\DriverInterface;
|
||||
use Intervention\Image\Interfaces\FrameInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\SizeInterface;
|
||||
|
||||
class Frame implements FrameInterface
|
||||
{
|
||||
public function __construct(protected Imagick $core)
|
||||
public function __construct(protected Imagick $data)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function setCore($core): FrameInterface
|
||||
public function toImage(DriverInterface $driver): ImageInterface
|
||||
{
|
||||
$this->core = $core;
|
||||
return new Image($driver, new Core($this->data()));
|
||||
}
|
||||
|
||||
public function setData($data): FrameInterface
|
||||
{
|
||||
$this->data = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function core(): Imagick
|
||||
public function data(): Imagick
|
||||
{
|
||||
return $this->core;
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function size(): SizeInterface
|
||||
{
|
||||
return new Rectangle(
|
||||
$this->core->getImageWidth(),
|
||||
$this->core->getImageHeight()
|
||||
$this->data->getImageWidth(),
|
||||
$this->data->getImageHeight()
|
||||
);
|
||||
}
|
||||
|
||||
public function delay(): float
|
||||
{
|
||||
return $this->core->getImageDelay() / 100;
|
||||
return $this->data->getImageDelay() / 100;
|
||||
}
|
||||
|
||||
public function setDelay(float $delay): FrameInterface
|
||||
{
|
||||
$this->core->setImageDelay(intval(round($delay * 100)));
|
||||
$this->data->setImageDelay(intval(round($delay * 100)));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function dispose(): int
|
||||
{
|
||||
return $this->core->getImageDispose();
|
||||
return $this->data->getImageDispose();
|
||||
}
|
||||
|
||||
public function setDispose(int $dispose): FrameInterface
|
||||
{
|
||||
$this->core->setImageDispose($dispose);
|
||||
$this->data->setImageDispose($dispose);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setOffset(int $left, int $top): FrameInterface
|
||||
{
|
||||
$this->core->setImagePage(
|
||||
$this->core->getImageWidth(),
|
||||
$this->core->getImageHeight(),
|
||||
$this->data->setImagePage(
|
||||
$this->data->getImageWidth(),
|
||||
$this->data->getImageHeight(),
|
||||
$left,
|
||||
$top
|
||||
);
|
||||
@@ -73,7 +79,7 @@ class Frame implements FrameInterface
|
||||
|
||||
public function offsetLeft(): int
|
||||
{
|
||||
return $this->core->getImagePage()['x'];
|
||||
return $this->data->getImagePage()['x'];
|
||||
}
|
||||
|
||||
public function setOffsetLeft(int $offset): FrameInterface
|
||||
@@ -83,16 +89,11 @@ class Frame implements FrameInterface
|
||||
|
||||
public function offsetTop(): int
|
||||
{
|
||||
return $this->core->getImagePage()['y'];
|
||||
return $this->data->getImagePage()['y'];
|
||||
}
|
||||
|
||||
public function setOffsetTop(int $offset): FrameInterface
|
||||
{
|
||||
return $this->setOffset($this->offsetLeft(), $offset);
|
||||
}
|
||||
|
||||
public function toImage(): ImageInterface
|
||||
{
|
||||
return new Image($this->core());
|
||||
}
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@ use Intervention\Image\Interfaces\ResolutionInterface;
|
||||
use Intervention\Image\Resolution;
|
||||
use Iterator;
|
||||
|
||||
class Image extends AbstractImage implements ImageInterface, Iterator
|
||||
class DELETE__Image extends AbstractImage implements ImageInterface, Iterator
|
||||
{
|
||||
use CanHandleColors;
|
||||
|
||||
|
@@ -7,7 +7,7 @@ use Intervention\Image\Colors\Rgb\Decoders\StringColorDecoder as RgbStringColorD
|
||||
use Intervention\Image\Colors\Rgb\Decoders\HtmlColornameDecoder;
|
||||
use Intervention\Image\Colors\Rgb\Decoders\TransparentColorDecoder;
|
||||
use Intervention\Image\Colors\Cmyk\Decoders\StringColorDecoder as CmykStringColorDecoder;
|
||||
use Intervention\Image\Drivers\Abstract\AbstractInputHandler;
|
||||
use Intervention\Image\Drivers\AbstractInputHandler;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\ImageObjectDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\ColorObjectDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\FilePointerImageDecoder;
|
||||
|
@@ -2,20 +2,15 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class BlurModifier implements ModifierInterface
|
||||
class BlurModifier extends DriverModifier
|
||||
{
|
||||
public function __construct(protected int $amount)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
foreach ($image as $frame) {
|
||||
$frame->core()->blurImage(1 * $this->amount, 0.5 * $this->amount);
|
||||
$frame->data()->blurImage(1 * $this->amount, 0.5 * $this->amount);
|
||||
}
|
||||
|
||||
return $image;
|
||||
|
@@ -2,20 +2,15 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class BrightnessModifier implements ModifierInterface
|
||||
class BrightnessModifier extends DriverModifier
|
||||
{
|
||||
public function __construct(protected int $level)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
foreach ($image as $frame) {
|
||||
$frame->core()->modulateImage(100 + $this->level, 100, 100);
|
||||
$frame->data()->modulateImage(100 + $this->level, 100, 100);
|
||||
}
|
||||
|
||||
return $image;
|
||||
|
@@ -3,31 +3,22 @@
|
||||
namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||
|
||||
use Imagick;
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class ColorizeModifier implements ModifierInterface
|
||||
class ColorizeModifier extends DriverModifier
|
||||
{
|
||||
public function __construct(
|
||||
protected int $red = 0,
|
||||
protected int $green = 0,
|
||||
protected int $blue = 0
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
// normalize colorize levels
|
||||
$red = $this->normalizeLevel($this->red);
|
||||
$green = $this->normalizeLevel($this->green);
|
||||
$blue = $this->normalizeLevel($this->blue);
|
||||
|
||||
foreach ($image as $frame) {
|
||||
$qrange = $frame->core()->getQuantumRange();
|
||||
$frame->core()->levelImage(0, $red, $qrange['quantumRangeLong'], Imagick::CHANNEL_RED);
|
||||
$frame->core()->levelImage(0, $green, $qrange['quantumRangeLong'], Imagick::CHANNEL_GREEN);
|
||||
$frame->core()->levelImage(0, $blue, $qrange['quantumRangeLong'], Imagick::CHANNEL_BLUE);
|
||||
$qrange = $frame->data()->getQuantumRange();
|
||||
$frame->data()->levelImage(0, $red, $qrange['quantumRangeLong'], Imagick::CHANNEL_RED);
|
||||
$frame->data()->levelImage(0, $green, $qrange['quantumRangeLong'], Imagick::CHANNEL_GREEN);
|
||||
$frame->data()->levelImage(0, $blue, $qrange['quantumRangeLong'], Imagick::CHANNEL_BLUE);
|
||||
}
|
||||
|
||||
return $image;
|
||||
|
@@ -3,34 +3,23 @@
|
||||
namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||
|
||||
use Imagick;
|
||||
use Intervention\Image\Colors\Cmyk\Colorspace as CmykColorspace;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\Drivers\Imagick\Image;
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Exceptions\NotSupportedException;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
use Intervention\Image\Traits\CanCheckType;
|
||||
|
||||
class ColorspaceModifier implements ModifierInterface
|
||||
class ColorspaceModifier extends DriverModifier
|
||||
{
|
||||
use CanCheckType;
|
||||
|
||||
protected static $mapping = [
|
||||
RgbColorspace::class => Imagick::COLORSPACE_SRGB,
|
||||
CmykColorspace::class => Imagick::COLORSPACE_CMYK,
|
||||
];
|
||||
|
||||
public function __construct(protected string|ColorspaceInterface $target)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$colorspace = $this->targetColorspace();
|
||||
|
||||
$imagick = $this->failIfNotClass($image, Image::class)->getImagick();
|
||||
$imagick = $image->core()->native();
|
||||
$imagick->transformImageColorspace(
|
||||
$this->getImagickColorspace($colorspace)
|
||||
);
|
||||
@@ -46,21 +35,4 @@ class ColorspaceModifier implements ModifierInterface
|
||||
|
||||
return self::$mapping[get_class($colorspace)];
|
||||
}
|
||||
|
||||
private function targetColorspace(): ColorspaceInterface
|
||||
{
|
||||
if (is_object($this->target)) {
|
||||
return $this->target;
|
||||
}
|
||||
|
||||
if (in_array($this->target, ['rgb', 'RGB', RgbColorspace::class])) {
|
||||
return new RgbColorspace();
|
||||
}
|
||||
|
||||
if (in_array($this->target, ['cmyk', 'CMYK', CmykColorspace::class])) {
|
||||
return new CmykColorspace();
|
||||
}
|
||||
|
||||
throw new NotSupportedException('Given colorspace is not supported.');
|
||||
}
|
||||
}
|
||||
|
@@ -2,20 +2,15 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class ContrastModifier implements ModifierInterface
|
||||
class ContrastModifier extends DriverModifier
|
||||
{
|
||||
public function __construct(protected int $level)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
foreach ($image as $frame) {
|
||||
$frame->core()->sigmoidalContrastImage($this->level > 0, abs($this->level / 4), 0);
|
||||
$frame->data()->sigmoidalContrastImage($this->level > 0, abs($this->level / 4), 0);
|
||||
}
|
||||
|
||||
return $image;
|
||||
|
@@ -2,30 +2,17 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||
|
||||
use Intervention\Image\Geometry\Rectangle;
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class CropModifier implements ModifierInterface
|
||||
class CropModifier extends DriverModifier
|
||||
{
|
||||
public function __construct(
|
||||
protected int $width,
|
||||
protected int $height,
|
||||
protected int $offset_x = 0,
|
||||
protected int $offset_y = 0,
|
||||
protected string $position = 'top-left'
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$crop = new Rectangle($this->width, $this->height);
|
||||
$crop->align($this->position);
|
||||
$crop->alignPivotTo($image->size(), $this->position);
|
||||
$crop = $this->crop($image);
|
||||
|
||||
foreach ($image as $frame) {
|
||||
$frame->core()->extentImage(
|
||||
$frame->data()->extentImage(
|
||||
$crop->width(),
|
||||
$crop->height(),
|
||||
$crop->pivot()->x() + $this->offset_x,
|
||||
|
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class DestroyModifier implements ModifierInterface
|
||||
{
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
foreach ($image as $frame) {
|
||||
$frame->core()->clear();
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
@@ -3,40 +3,44 @@
|
||||
namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||
|
||||
use ImagickDraw;
|
||||
use Intervention\Image\Drivers\Abstract\Modifiers\AbstractDrawModifier;
|
||||
use Intervention\Image\Drivers\Imagick\Traits\CanHandleColors;
|
||||
use Intervention\Image\Drivers\DrawModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class DrawEllipseModifier extends AbstractDrawModifier implements ModifierInterface
|
||||
class DrawEllipseModifier extends DrawModifier
|
||||
{
|
||||
use CanHandleColors;
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$colorspace = $image->colorspace();
|
||||
$background_color = $this->colorToPixel($this->getBackgroundColor(), $colorspace);
|
||||
$border_color = $this->colorToPixel($this->getBorderColor(), $colorspace);
|
||||
$background_color = $this->driver()->colorToNative(
|
||||
$this->backgroundColor(),
|
||||
$image->colorspace()
|
||||
);
|
||||
|
||||
return $image->mapFrames(function ($frame) use ($background_color, $border_color) {
|
||||
$border_color = $this->driver()->colorToNative(
|
||||
$this->borderColor(),
|
||||
$image->colorspace()
|
||||
);
|
||||
|
||||
foreach ($image as $frame) {
|
||||
$drawing = new ImagickDraw();
|
||||
$drawing->setFillColor($background_color);
|
||||
|
||||
if ($this->ellipse()->hasBorder()) {
|
||||
$drawing->setStrokeWidth($this->ellipse()->getBorderSize());
|
||||
if ($this->drawable->hasBorder()) {
|
||||
$drawing->setStrokeWidth($this->drawable->borderSize());
|
||||
$drawing->setStrokeColor($border_color);
|
||||
}
|
||||
|
||||
$drawing->ellipse(
|
||||
$this->position->x(),
|
||||
$this->position->y(),
|
||||
$this->ellipse()->getWidth() / 2,
|
||||
$this->ellipse()->getHeight() / 2,
|
||||
$this->position()->x(),
|
||||
$this->position()->y(),
|
||||
$this->drawable->width() / 2,
|
||||
$this->drawable->height() / 2,
|
||||
0,
|
||||
360
|
||||
);
|
||||
|
||||
$frame->core()->drawImage($drawing);
|
||||
});
|
||||
$frame->data()->drawImage($drawing);
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
||||
|
@@ -3,32 +3,33 @@
|
||||
namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||
|
||||
use ImagickDraw;
|
||||
use Intervention\Image\Drivers\Abstract\Modifiers\AbstractDrawModifier;
|
||||
use Intervention\Image\Drivers\Imagick\Traits\CanHandleColors;
|
||||
use Intervention\Image\Drivers\DrawModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class DrawLineModifier extends AbstractDrawModifier implements ModifierInterface
|
||||
class DrawLineModifier extends DrawModifier
|
||||
{
|
||||
use CanHandleColors;
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$drawing = new ImagickDraw();
|
||||
$drawing->setStrokeWidth($this->line()->getWidth());
|
||||
$drawing->setStrokeWidth($this->drawable->getWidth());
|
||||
$drawing->setStrokeColor(
|
||||
$this->colorToPixel($this->getBackgroundColor(), $image->colorspace())
|
||||
$this->driver()->colorToNative(
|
||||
$this->backgroundColor(),
|
||||
$image->colorspace()
|
||||
)
|
||||
);
|
||||
|
||||
$drawing->line(
|
||||
$this->line()->getStart()->x(),
|
||||
$this->line()->getStart()->y(),
|
||||
$this->line()->getEnd()->x(),
|
||||
$this->line()->getEnd()->y(),
|
||||
$this->drawable->getStart()->x(),
|
||||
$this->drawable->getStart()->y(),
|
||||
$this->drawable->getEnd()->x(),
|
||||
$this->drawable->getEnd()->y(),
|
||||
);
|
||||
|
||||
return $image->mapFrames(function ($frame) use ($drawing) {
|
||||
$frame->core()->drawImage($drawing);
|
||||
});
|
||||
foreach ($image as $frame) {
|
||||
$frame->data()->drawImage($drawing);
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
||||
|
@@ -3,38 +3,26 @@
|
||||
namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||
|
||||
use ImagickDraw;
|
||||
use Intervention\Image\Drivers\Imagick\Traits\CanHandleColors;
|
||||
use Intervention\Image\Geometry\Point;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Drivers\DriverModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
use Intervention\Image\Traits\CanCheckType;
|
||||
use Intervention\Image\Traits\CanHandleInput;
|
||||
|
||||
class DrawPixelModifier implements ModifierInterface
|
||||
class DrawPixelModifier extends DriverModifier
|
||||
{
|
||||
use CanHandleInput;
|
||||
use CanHandleColors;
|
||||
use CanCheckType;
|
||||
|
||||
public function __construct(protected Point $position, protected mixed $color)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$color = $this->failIfNotInstance(
|
||||
$this->handleInput($this->color),
|
||||
ColorInterface::class
|
||||
$color = $this->driver()->colorToNative(
|
||||
$this->driver()->handleInput($this->color),
|
||||
$image->colorspace()
|
||||
);
|
||||
|
||||
$pixel = new ImagickDraw();
|
||||
$pixel->setFillColor($this->colorToPixel($color, $image->colorspace()));
|
||||
$pixel->setFillColor($color);
|
||||
$pixel->point($this->position->x(), $this->position->y());
|
||||
|
||||
return $image->mapFrames(function ($frame) use ($pixel) {
|
||||
$frame->core()->drawImage($pixel);
|
||||
});
|
||||
foreach ($image as $frame) {
|
||||
$frame->data()->drawImage($pixel);
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
||||
|
@@ -3,49 +3,47 @@
|
||||
namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||
|
||||
use ImagickDraw;
|
||||
use Intervention\Image\Drivers\Abstract\Modifiers\AbstractDrawModifier;
|
||||
use Intervention\Image\Drivers\Imagick\Traits\CanHandleColors;
|
||||
use Intervention\Image\Interfaces\DrawableInterface;
|
||||
use Intervention\Image\Drivers\DrawModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class DrawPolygonModifier extends AbstractDrawModifier implements ModifierInterface
|
||||
class DrawPolygonModifier extends DrawModifier
|
||||
{
|
||||
use CanHandleColors;
|
||||
|
||||
public function __construct(
|
||||
protected DrawableInterface $drawable
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$drawing = new ImagickDraw();
|
||||
$colorspace = $image->colorspace();
|
||||
$background_color = $this->colorToPixel($this->getBackgroundColor(), $colorspace);
|
||||
$border_color = $this->colorToPixel($this->getBorderColor(), $colorspace);
|
||||
|
||||
if ($this->polygon()->hasBackgroundColor()) {
|
||||
if ($this->drawable->hasBackgroundColor()) {
|
||||
$background_color = $this->driver()->colorToNative(
|
||||
$this->backgroundColor(),
|
||||
$image->colorspace()
|
||||
);
|
||||
|
||||
$drawing->setFillColor($background_color);
|
||||
}
|
||||
|
||||
if ($this->polygon()->hasBorder()) {
|
||||
if ($this->drawable->hasBorder()) {
|
||||
$border_color = $this->driver()->colorToNative(
|
||||
$this->borderColor(),
|
||||
$image->colorspace()
|
||||
);
|
||||
|
||||
$drawing->setStrokeColor($border_color);
|
||||
$drawing->setStrokeWidth($this->polygon()->getBorderSize());
|
||||
$drawing->setStrokeWidth($this->drawable->borderSize());
|
||||
}
|
||||
|
||||
$drawing->polygon($this->points());
|
||||
|
||||
return $image->mapFrames(function ($frame) use ($drawing) {
|
||||
$frame->core()->drawImage($drawing);
|
||||
});
|
||||
foreach ($image as $frame) {
|
||||
$frame->data()->drawImage($drawing);
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
private function points(): array
|
||||
{
|
||||
$points = [];
|
||||
foreach ($this->polygon() as $point) {
|
||||
foreach ($this->drawable as $point) {
|
||||
$points[] = ['x' => $point->x(), 'y' => $point->y()];
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user