Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/encoder options #1260

Merged
merged 13 commits into from Jan 16, 2024
3 changes: 2 additions & 1 deletion src/Analyzers/AbstractAnalyzer.php
Expand Up @@ -4,8 +4,9 @@

use Intervention\Image\Interfaces\AnalyzerInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializableInterface;

abstract class AbstractAnalyzer implements AnalyzerInterface
abstract class AbstractAnalyzer implements AnalyzerInterface, SpecializableInterface
{
/**
* {@inheritdoc}
Expand Down
17 changes: 17 additions & 0 deletions src/Decoders/AbstractDecoder.php
@@ -0,0 +1,17 @@
<?php

namespace Intervention\Image\Decoders;

use Intervention\Image\Exceptions\DecoderException;
use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\DecoderInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializableInterface;

abstract class AbstractDecoder implements DecoderInterface, SpecializableInterface
{
public function decode(mixed $input): ImageInterface|ColorInterface
{
throw new DecoderException('Object must be specialized by the driver first.');
}
}
7 changes: 7 additions & 0 deletions src/Decoders/Base64ImageDecoder.php
@@ -0,0 +1,7 @@
<?php

namespace Intervention\Image\Decoders;

class Base64ImageDecoder extends AbstractDecoder
{
}
7 changes: 7 additions & 0 deletions src/Decoders/BinaryImageDecoder.php
@@ -0,0 +1,7 @@
<?php

namespace Intervention\Image\Decoders;

class BinaryImageDecoder extends AbstractDecoder
{
}
7 changes: 7 additions & 0 deletions src/Decoders/DataUriImageDecoder.php
@@ -0,0 +1,7 @@
<?php

namespace Intervention\Image\Decoders;

class DataUriImageDecoder extends AbstractDecoder
{
}
7 changes: 7 additions & 0 deletions src/Decoders/FilePathImageDecoder.php
@@ -0,0 +1,7 @@
<?php

namespace Intervention\Image\Decoders;

class FilePathImageDecoder extends AbstractDecoder
{
}
7 changes: 7 additions & 0 deletions src/Decoders/FilePointerImageDecoder.php
@@ -0,0 +1,7 @@
<?php

namespace Intervention\Image\Decoders;

class FilePointerImageDecoder extends AbstractDecoder
{
}
7 changes: 7 additions & 0 deletions src/Decoders/ImageObjectDecoder.php
@@ -0,0 +1,7 @@
<?php

namespace Intervention\Image\Decoders;

class ImageObjectDecoder extends AbstractDecoder
{
}
7 changes: 7 additions & 0 deletions src/Decoders/SplFileInfoImageDecoder.php
@@ -0,0 +1,7 @@
<?php

namespace Intervention\Image\Decoders;

class SplFileInfoImageDecoder extends AbstractDecoder
{
}
2 changes: 1 addition & 1 deletion src/Drivers/AbstractDecoder.php
Expand Up @@ -11,7 +11,7 @@
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Traits\CanBuildFilePointer;

abstract class AbstractDecoder implements DecoderInterface
abstract class AbstractDecoder extends DriverSpecialized implements DecoderInterface
{
use CanBuildFilePointer;

Expand Down
3 changes: 2 additions & 1 deletion src/Drivers/AbstractDrawModifier.php
Expand Up @@ -5,12 +5,13 @@
use Intervention\Image\Exceptions\DecoderException;
use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\DrawableInterface;
use Intervention\Image\Interfaces\ModifierInterface;
use Intervention\Image\Interfaces\PointInterface;

/**
* @property DrawableInterface $drawable
*/
abstract class AbstractDrawModifier extends DriverSpecializedModifier
abstract class AbstractDrawModifier extends DriverSpecialized implements ModifierInterface
{
public function position(): PointInterface
{
Expand Down
54 changes: 23 additions & 31 deletions src/Drivers/AbstractDriver.php
Expand Up @@ -2,11 +2,13 @@

namespace Intervention\Image\Drivers;

use Intervention\Image\Analyzers\AbstractAnalyzer;
use Intervention\Image\Encoders\AbstractEncoder;
use Intervention\Image\Exceptions\NotSupportedException;
use Intervention\Image\Interfaces\AnalyzerInterface;
use Intervention\Image\Interfaces\DecoderInterface;
use Intervention\Image\Interfaces\DriverInterface;
use Intervention\Image\Modifiers\AbstractModifier;
use Intervention\Image\Interfaces\EncoderInterface;
use Intervention\Image\Interfaces\ModifierInterface;
use Intervention\Image\Interfaces\SpecializableInterface;
use ReflectionClass;

abstract class AbstractDriver implements DriverInterface
Expand All @@ -17,51 +19,41 @@ public function __construct()
}

/**
* Return a specialized version for the current driver of the given object
* {@inheritdoc}
*
* @param object $input
* @return object
* @throws NotSupportedException
* @see DriverInterface::specialize()
*/
public function resolve(object $input): object
public function specialize(object $object): ModifierInterface|AnalyzerInterface|EncoderInterface|DecoderInterface
{
if ($this->isExternal($input)) {
return $input;
if (!($object instanceof SpecializableInterface)) {
return $object;
}

$driver_namespace = (new ReflectionClass($this))->getNamespaceName();
$class_path = substr(get_class($input), strlen("Intervention\\Image\\"));
$specialized = $driver_namespace . "\\" . $class_path;
$class_path = substr(get_class($object), strlen("Intervention\\Image\\"));
$classname = $driver_namespace . "\\" . $class_path;

if (! class_exists($specialized)) {
if (!class_exists($classname)) {
throw new NotSupportedException(
"Class '" . $class_path . "' is not supported by " . $this->id() . " driver."
);
}

return new $specialized($input, $this);
return forward_static_call([
$classname,
'buildSpecialized'
], $object, $this);
}

/**
* Determine if given object is external custom modifier, analyzer or encoder
* {@inheritdoc}
*
* @param object $input
* @return bool
* @see DriverInterface::specializeMultiple()
*/
private function isExternal(object $input): bool
public function specializeMultiple(array $objects): array
{
if ($input instanceof AbstractModifier) {
return false;
}

if ($input instanceof AbstractAnalyzer) {
return false;
}

if ($input instanceof AbstractEncoder) {
return false;
}

return true;
return array_map(function ($classname) {
return $this->specialize(new $classname());
}, $objects);
}
}
3 changes: 2 additions & 1 deletion src/Drivers/AbstractTextModifier.php
Expand Up @@ -6,13 +6,14 @@
use Intervention\Image\Geometry\Polygon;
use Intervention\Image\Geometry\Rectangle;
use Intervention\Image\Interfaces\FontInterface;
use Intervention\Image\Interfaces\ModifierInterface;
use Intervention\Image\Typography\TextBlock;
use Intervention\Image\Typography\Line;

/**
* @property FontInterface $font
*/
abstract class AbstractTextModifier extends DriverSpecializedModifier
abstract class AbstractTextModifier extends DriverSpecialized implements ModifierInterface
{
abstract protected function boxSize(string $text): Polygon;

Expand Down
58 changes: 58 additions & 0 deletions src/Drivers/DriverSpecialized.php
@@ -0,0 +1,58 @@
<?php

namespace Intervention\Image\Drivers;

use Intervention\Image\Interfaces\DriverInterface;
use Intervention\Image\Interfaces\SpecializedInterface;

abstract class DriverSpecialized implements SpecializedInterface
{
protected DriverInterface $driver;
protected object $generic;

public function __construct()
{
}

public static function buildSpecialized(object $generic, DriverInterface $driver): SpecializedInterface
{
$specialized = new static();
$specialized->generic = $generic;
$specialized->driver = $driver;

return $specialized;
}

public function driver(): DriverInterface
{
return $this->driver;
}

public function generic(): object
{
return $this->generic;
}

/**
* Magic method to read attributes of underlying modifier
*
* @param string $name
* @return mixed
*/
public function __get(string $name): mixed
{
return $this->generic->$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->generic->$name(...$arguments);
}
}
31 changes: 0 additions & 31 deletions src/Drivers/DriverSpecializedAnalyzer.php

This file was deleted.

25 changes: 1 addition & 24 deletions src/Drivers/DriverSpecializedEncoder.php
Expand Up @@ -2,33 +2,10 @@

namespace Intervention\Image\Drivers;

use Intervention\Image\Interfaces\DriverInterface;
use Intervention\Image\Interfaces\EncoderInterface;

abstract class DriverSpecializedEncoder implements EncoderInterface
abstract class DriverSpecializedEncoder extends DriverSpecialized 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 encoder
*
* @param string $name
* @return mixed
*/
public function __get(string $name): mixed
{
return $this->encoder->$name;
}

/**
* Get return value of callback through output buffer
*
Expand Down
43 changes: 0 additions & 43 deletions src/Drivers/DriverSpecializedModifier.php

This file was deleted.

5 changes: 3 additions & 2 deletions src/Drivers/Gd/Analyzers/ColorspaceAnalyzer.php
Expand Up @@ -3,10 +3,11 @@
namespace Intervention\Image\Drivers\Gd\Analyzers;

use Intervention\Image\Colors\Rgb\Colorspace;
use Intervention\Image\Drivers\DriverSpecializedAnalyzer;
use Intervention\Image\Drivers\DriverSpecialized;
use Intervention\Image\Interfaces\AnalyzerInterface;
use Intervention\Image\Interfaces\ImageInterface;

class ColorspaceAnalyzer extends DriverSpecializedAnalyzer
class ColorspaceAnalyzer extends DriverSpecialized implements AnalyzerInterface
{
public function analyze(ImageInterface $image): mixed
{
Expand Down