mirror of
https://github.com/Intervention/image.git
synced 2025-08-03 20:37:27 +02:00
Feature/code modernization (#1412)
* Update phpstan dependency version * Remove unused code * Optimize code * Add type hints * Change property visibility on final classes * Modernize code
This commit is contained in:
@@ -26,7 +26,7 @@
|
|||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^10.0 || ^11.0",
|
"phpunit/phpunit": "^10.0 || ^11.0",
|
||||||
"mockery/mockery": "^1.6",
|
"mockery/mockery": "^1.6",
|
||||||
"phpstan/phpstan": "^2",
|
"phpstan/phpstan": "^2.1",
|
||||||
"squizlabs/php_codesniffer": "^3.8",
|
"squizlabs/php_codesniffer": "^3.8",
|
||||||
"slevomat/coding-standard": "~8.0"
|
"slevomat/coding-standard": "~8.0"
|
||||||
},
|
},
|
||||||
|
@@ -153,7 +153,7 @@ class Collection implements CollectionInterface, IteratorAggregate, Countable
|
|||||||
return $this->items[$query];
|
return $this->items[$query];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_string($query) && strpos($query, '.') === false) {
|
if (is_string($query) && !str_contains($query, '.')) {
|
||||||
return array_key_exists($query, $this->items) ? $this->items[$query] : $default;
|
return array_key_exists($query, $this->items) ? $this->items[$query] : $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,8 +9,9 @@ use Intervention\Image\Interfaces\ColorChannelInterface;
|
|||||||
use Intervention\Image\Interfaces\ColorInterface;
|
use Intervention\Image\Interfaces\ColorInterface;
|
||||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
|
use Stringable;
|
||||||
|
|
||||||
abstract class AbstractColor implements ColorInterface
|
abstract class AbstractColor implements ColorInterface, Stringable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Color channels
|
* Color channels
|
||||||
@@ -38,7 +39,7 @@ abstract class AbstractColor implements ColorInterface
|
|||||||
{
|
{
|
||||||
$channels = array_filter(
|
$channels = array_filter(
|
||||||
$this->channels(),
|
$this->channels(),
|
||||||
fn(ColorChannelInterface $channel) => $channel::class == $classname,
|
fn(ColorChannelInterface $channel): bool => $channel::class === $classname,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (count($channels) == 0) {
|
if (count($channels) == 0) {
|
||||||
@@ -56,7 +57,7 @@ abstract class AbstractColor implements ColorInterface
|
|||||||
public function normalize(): array
|
public function normalize(): array
|
||||||
{
|
{
|
||||||
return array_map(
|
return array_map(
|
||||||
fn(ColorChannelInterface $channel) => $channel->normalize(),
|
fn(ColorChannelInterface $channel): float => $channel->normalize(),
|
||||||
$this->channels(),
|
$this->channels(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -69,7 +70,7 @@ abstract class AbstractColor implements ColorInterface
|
|||||||
public function toArray(): array
|
public function toArray(): array
|
||||||
{
|
{
|
||||||
return array_map(
|
return array_map(
|
||||||
fn(ColorChannelInterface $channel) => $channel->value(),
|
fn(ColorChannelInterface $channel): int => $channel->value(),
|
||||||
$this->channels()
|
$this->channels()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -6,8 +6,9 @@ namespace Intervention\Image\Colors;
|
|||||||
|
|
||||||
use Intervention\Image\Exceptions\ColorException;
|
use Intervention\Image\Exceptions\ColorException;
|
||||||
use Intervention\Image\Interfaces\ColorChannelInterface;
|
use Intervention\Image\Interfaces\ColorChannelInterface;
|
||||||
|
use Stringable;
|
||||||
|
|
||||||
abstract class AbstractColorChannel implements ColorChannelInterface
|
abstract class AbstractColorChannel implements ColorChannelInterface, Stringable
|
||||||
{
|
{
|
||||||
protected int $value;
|
protected int $value;
|
||||||
|
|
||||||
|
@@ -30,7 +30,7 @@ class StringColorDecoder extends AbstractDecoder implements DecoderInterface
|
|||||||
throw new DecoderException('Unable to decode input');
|
throw new DecoderException('Unable to decode input');
|
||||||
}
|
}
|
||||||
|
|
||||||
$values = array_map(function ($value) {
|
$values = array_map(function (string $value): int {
|
||||||
return intval(round(floatval(trim(str_replace('%', '', $value)))));
|
return intval(round(floatval(trim(str_replace('%', '', $value)))));
|
||||||
}, [$matches['c'], $matches['m'], $matches['y'], $matches['k']]);
|
}, [$matches['c'], $matches['m'], $matches['y'], $matches['k']]);
|
||||||
|
|
||||||
|
@@ -68,7 +68,7 @@ class Colorspace implements ColorspaceInterface
|
|||||||
|
|
||||||
// normalized values of rgb channels
|
// normalized values of rgb channels
|
||||||
$values = array_map(
|
$values = array_map(
|
||||||
fn(ColorChannelInterface $channel) => $channel->normalize(),
|
fn(ColorChannelInterface $channel): float => $channel->normalize(),
|
||||||
$color->channels(),
|
$color->channels(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ class Colorspace implements ColorspaceInterface
|
|||||||
};
|
};
|
||||||
|
|
||||||
// calculate hue
|
// calculate hue
|
||||||
list($r, $g, $b) = $values;
|
[$r, $g, $b] = $values;
|
||||||
$hue = match (true) {
|
$hue = match (true) {
|
||||||
($delta == 0) => 0,
|
($delta == 0) => 0,
|
||||||
($max == $r) => 60 * fmod((($g - $b) / $delta), 6),
|
($max == $r) => 60 * fmod((($g - $b) / $delta), 6),
|
||||||
@@ -118,8 +118,8 @@ class Colorspace implements ColorspaceInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// normalized values of hsv channels
|
// normalized values of hsv channels
|
||||||
list($h, $s, $v) = array_map(
|
[$h, $s, $v] = array_map(
|
||||||
fn(ColorChannelInterface $channel) => $channel->normalize(),
|
fn(ColorChannelInterface $channel): float => $channel->normalize(),
|
||||||
$color->channels(),
|
$color->channels(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -30,7 +30,7 @@ class StringColorDecoder extends AbstractDecoder implements DecoderInterface
|
|||||||
throw new DecoderException('Unable to decode input');
|
throw new DecoderException('Unable to decode input');
|
||||||
}
|
}
|
||||||
|
|
||||||
$values = array_map(function ($value) {
|
$values = array_map(function (string $value): int {
|
||||||
return match (strpos($value, '%')) {
|
return match (strpos($value, '%')) {
|
||||||
false => intval(trim($value)),
|
false => intval(trim($value)),
|
||||||
default => intval(trim(str_replace('%', '', $value))),
|
default => intval(trim(str_replace('%', '', $value))),
|
||||||
|
@@ -67,7 +67,7 @@ class Colorspace implements ColorspaceInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// normalized values of rgb channels
|
// normalized values of rgb channels
|
||||||
$values = array_map(fn(ColorChannelInterface $channel) => $channel->normalize(), $color->channels());
|
$values = array_map(fn(ColorChannelInterface $channel): float => $channel->normalize(), $color->channels());
|
||||||
|
|
||||||
// take only RGB
|
// take only RGB
|
||||||
$values = array_slice($values, 0, 3);
|
$values = array_slice($values, 0, 3);
|
||||||
@@ -89,7 +89,7 @@ class Colorspace implements ColorspaceInterface
|
|||||||
$s = 100 * ($chroma / $max);
|
$s = 100 * ($chroma / $max);
|
||||||
|
|
||||||
// calculate hue
|
// calculate hue
|
||||||
list($r, $g, $b) = $values;
|
[$r, $g, $b] = $values;
|
||||||
$h = match (true) {
|
$h = match (true) {
|
||||||
($r == $min) => 3 - (($g - $b) / $chroma),
|
($r == $min) => 3 - (($g - $b) / $chroma),
|
||||||
($b == $min) => 1 - (($r - $g) / $chroma),
|
($b == $min) => 1 - (($r - $g) / $chroma),
|
||||||
@@ -115,7 +115,10 @@ class Colorspace implements ColorspaceInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// normalized values of hsl channels
|
// normalized values of hsl channels
|
||||||
list($h, $s, $l) = array_map(fn(ColorChannelInterface $channel) => $channel->normalize(), $color->channels());
|
[$h, $s, $l] = array_map(
|
||||||
|
fn(ColorChannelInterface $channel): float => $channel->normalize(),
|
||||||
|
$color->channels()
|
||||||
|
);
|
||||||
|
|
||||||
$v = $l + $s * min($l, 1 - $l);
|
$v = $l + $s * min($l, 1 - $l);
|
||||||
$s = ($v == 0) ? 0 : 2 * (1 - $l / $v);
|
$s = ($v == 0) ? 0 : 2 * (1 - $l / $v);
|
||||||
|
@@ -30,7 +30,7 @@ class StringColorDecoder extends AbstractDecoder implements DecoderInterface
|
|||||||
throw new DecoderException('Unable to decode input');
|
throw new DecoderException('Unable to decode input');
|
||||||
}
|
}
|
||||||
|
|
||||||
$values = array_map(function ($value) {
|
$values = array_map(function (string $value): int {
|
||||||
return match (strpos($value, '%')) {
|
return match (strpos($value, '%')) {
|
||||||
false => intval(trim($value)),
|
false => intval(trim($value)),
|
||||||
default => intval(trim(str_replace('%', '', $value))),
|
default => intval(trim(str_replace('%', '', $value))),
|
||||||
|
@@ -99,9 +99,8 @@ class Colorspace implements ColorspaceInterface
|
|||||||
};
|
};
|
||||||
|
|
||||||
// add to each value
|
// add to each value
|
||||||
$values = array_map(fn($value) => $value + $color->value()->normalize() - $chroma, $values);
|
$values = array_map(fn(float|int $value): float => $value + $color->value()->normalize() - $chroma, $values);
|
||||||
|
$values[] = 1; // append alpha channel value
|
||||||
array_push($values, 1); // append alpha channel value
|
|
||||||
|
|
||||||
return $this->colorFromNormalized($values);
|
return $this->colorFromNormalized($values);
|
||||||
}
|
}
|
||||||
@@ -118,8 +117,8 @@ class Colorspace implements ColorspaceInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// normalized values of hsl channels
|
// normalized values of hsl channels
|
||||||
list($h, $s, $l) = array_map(
|
[$h, $s, $l] = array_map(
|
||||||
fn(ColorChannelInterface $channel) => $channel->normalize(),
|
fn(ColorChannelInterface $channel): float => $channel->normalize(),
|
||||||
$color->channels()
|
$color->channels()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -136,9 +135,8 @@ class Colorspace implements ColorspaceInterface
|
|||||||
default => [$c, 0, $x],
|
default => [$c, 0, $x],
|
||||||
};
|
};
|
||||||
|
|
||||||
$values = array_map(fn($value) => $value + $m, $values);
|
$values = array_map(fn(float|int $value): float => $value + $m, $values);
|
||||||
|
$values[] = 1; // append alpha channel value
|
||||||
array_push($values, 1); // append alpha channel value
|
|
||||||
|
|
||||||
return $this->colorFromNormalized($values);
|
return $this->colorFromNormalized($values);
|
||||||
}
|
}
|
||||||
|
@@ -30,14 +30,13 @@ class HexColorDecoder extends AbstractDecoder implements DecoderInterface
|
|||||||
throw new DecoderException('Unable to decode input');
|
throw new DecoderException('Unable to decode input');
|
||||||
}
|
}
|
||||||
|
|
||||||
$values = str_split($matches['hex']);
|
|
||||||
$values = match (strlen($matches['hex'])) {
|
$values = match (strlen($matches['hex'])) {
|
||||||
3, 4 => str_split($matches['hex']),
|
3, 4 => str_split($matches['hex']),
|
||||||
6, 8 => str_split($matches['hex'], 2),
|
6, 8 => str_split($matches['hex'], 2),
|
||||||
default => throw new DecoderException('Unable to decode input'),
|
default => throw new DecoderException('Unable to decode input'),
|
||||||
};
|
};
|
||||||
|
|
||||||
$values = array_map(function ($value) {
|
$values = array_map(function (string $value): float|int {
|
||||||
return match (strlen($value)) {
|
return match (strlen($value)) {
|
||||||
1 => hexdec($value . $value),
|
1 => hexdec($value . $value),
|
||||||
2 => hexdec($value),
|
2 => hexdec($value),
|
||||||
|
@@ -32,7 +32,7 @@ class StringColorDecoder extends AbstractDecoder implements DecoderInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rgb values
|
// rgb values
|
||||||
$values = array_map(function ($value) {
|
$values = array_map(function (string $value): int {
|
||||||
return match (strpos($value, '%')) {
|
return match (strpos($value, '%')) {
|
||||||
false => intval(trim($value)),
|
false => intval(trim($value)),
|
||||||
default => intval(round(floatval(trim(str_replace('%', '', $value))) / 100 * 255)),
|
default => intval(round(floatval(trim(str_replace('%', '', $value))) / 100 * 255)),
|
||||||
|
@@ -21,7 +21,7 @@ class TransparentColorDecoder extends HexColorDecoder
|
|||||||
throw new DecoderException('Unable to decode input');
|
throw new DecoderException('Unable to decode input');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strtolower($input) != 'transparent') {
|
if (strtolower($input) !== 'transparent') {
|
||||||
throw new DecoderException('Unable to decode input');
|
throw new DecoderException('Unable to decode input');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -52,7 +52,7 @@ class Config
|
|||||||
*/
|
*/
|
||||||
private function prepareOptions(array $options): array
|
private function prepareOptions(array $options): array
|
||||||
{
|
{
|
||||||
if (count($options) === 0) {
|
if ($options === []) {
|
||||||
return $options;
|
return $options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -112,25 +112,18 @@ abstract class AbstractDecoder implements DecoderInterface
|
|||||||
$pattern = "/^data:(?P<mediatype>\w+\/[-+.\w]+)?" .
|
$pattern = "/^data:(?P<mediatype>\w+\/[-+.\w]+)?" .
|
||||||
"(?P<parameters>(;[-\w]+=[-\w]+)*)(?P<base64>;base64)?,(?P<data>.*)/";
|
"(?P<parameters>(;[-\w]+=[-\w]+)*)(?P<base64>;base64)?,(?P<data>.*)/";
|
||||||
|
|
||||||
$result = preg_match($pattern, $input, $matches);
|
$result = preg_match($pattern, (string) $input, $matches);
|
||||||
|
|
||||||
return new class ($matches, $result)
|
return new class ($matches, $result)
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @var array<mixed>
|
|
||||||
*/
|
|
||||||
private array $matches;
|
|
||||||
private int|false $result;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<mixed> $matches
|
* @param array<mixed> $matches
|
||||||
* @param int|false $result
|
* @param int|false $result
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct(array $matches, int|false $result)
|
public function __construct(private array $matches, private int|false $result)
|
||||||
{
|
{
|
||||||
$this->matches = $matches;
|
//
|
||||||
$this->result = $result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isValid(): bool
|
public function isValid(): bool
|
||||||
@@ -154,11 +147,7 @@ abstract class AbstractDecoder implements DecoderInterface
|
|||||||
|
|
||||||
public function isBase64Encoded(): bool
|
public function isBase64Encoded(): bool
|
||||||
{
|
{
|
||||||
if (isset($this->matches['base64']) && $this->matches['base64'] === ';base64') {
|
return isset($this->matches['base64']) && $this->matches['base64'] === ';base64';
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function data(): ?string
|
public function data(): ?string
|
||||||
|
@@ -103,13 +103,16 @@ abstract class AbstractDriver implements DriverInterface
|
|||||||
*/
|
*/
|
||||||
public function specializeMultiple(array $objects): array
|
public function specializeMultiple(array $objects): array
|
||||||
{
|
{
|
||||||
return array_map(function ($object) {
|
return array_map(
|
||||||
|
function (string|object $object): ModifierInterface|AnalyzerInterface|EncoderInterface|DecoderInterface {
|
||||||
return $this->specialize(
|
return $this->specialize(
|
||||||
match (true) {
|
match (true) {
|
||||||
is_string($object) => new $object(),
|
is_string($object) => new $object(),
|
||||||
is_object($object) => $object,
|
is_object($object) => $object,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}, $objects);
|
},
|
||||||
|
$objects
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -36,9 +36,9 @@ abstract class AbstractFontProcessor implements FontProcessorInterface
|
|||||||
foreach ($lines as $line) {
|
foreach ($lines as $line) {
|
||||||
$lineBoxSize = $this->boxSize((string) $line, $font);
|
$lineBoxSize = $this->boxSize((string) $line, $font);
|
||||||
$lineWidth = $lineBoxSize->width() + $lineBoxSize->pivot()->x();
|
$lineWidth = $lineBoxSize->width() + $lineBoxSize->pivot()->x();
|
||||||
$xAdjustment = $font->alignment() == 'left' ? 0 : $blockWidth - $lineWidth;
|
$xAdjustment = $font->alignment() === 'left' ? 0 : $blockWidth - $lineWidth;
|
||||||
$xAdjustment = $font->alignment() == 'right' ? intval(round($xAdjustment)) : $xAdjustment;
|
$xAdjustment = $font->alignment() === 'right' ? intval(round($xAdjustment)) : $xAdjustment;
|
||||||
$xAdjustment = $font->alignment() == 'center' ? intval(round($xAdjustment / 2)) : $xAdjustment;
|
$xAdjustment = $font->alignment() === 'center' ? intval(round($xAdjustment / 2)) : $xAdjustment;
|
||||||
$position = new Point($x + $xAdjustment, $y);
|
$position = new Point($x + $xAdjustment, $y);
|
||||||
$position->rotate($font->angle(), $pivot);
|
$position->rotate($font->angle(), $pivot);
|
||||||
$line->setPosition($position);
|
$line->setPosition($position);
|
||||||
@@ -132,14 +132,14 @@ abstract class AbstractFontProcessor implements FontProcessorInterface
|
|||||||
// calculate width of newly formatted line
|
// calculate width of newly formatted line
|
||||||
$lineWidth = $this->boxSize(match ($formattedLine->count()) {
|
$lineWidth = $this->boxSize(match ($formattedLine->count()) {
|
||||||
0 => $word,
|
0 => $word,
|
||||||
default => (string) $formattedLine . ' ' . $word,
|
default => $formattedLine . ' ' . $word,
|
||||||
}, $font)->width();
|
}, $font)->width();
|
||||||
|
|
||||||
// decide if word fits on current line or a new line must be created
|
// decide if word fits on current line or a new line must be created
|
||||||
if ($line->count() === 1 || $lineWidth <= $font->wrapWidth()) {
|
if ($line->count() === 1 || $lineWidth <= $font->wrapWidth()) {
|
||||||
$formattedLine->add($word);
|
$formattedLine->add($word);
|
||||||
} else {
|
} else {
|
||||||
if ($formattedLine->count()) {
|
if ($formattedLine->count() !== 0) {
|
||||||
$wrapped[] = $formattedLine;
|
$wrapped[] = $formattedLine;
|
||||||
}
|
}
|
||||||
$formattedLine = new Line($word);
|
$formattedLine = new Line($word);
|
||||||
|
@@ -22,6 +22,6 @@ class Base64ImageDecoder extends BinaryImageDecoder implements DecoderInterface
|
|||||||
throw new DecoderException('Unable to decode input');
|
throw new DecoderException('Unable to decode input');
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::decode(base64_decode($input));
|
return parent::decode(base64_decode((string) $input));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,7 @@ class AvifEncoder extends GenericAvifEncoder implements SpecializedInterface
|
|||||||
*/
|
*/
|
||||||
public function encode(ImageInterface $image): EncodedImage
|
public function encode(ImageInterface $image): EncodedImage
|
||||||
{
|
{
|
||||||
return $this->createEncodedImage(function ($pointer) use ($image) {
|
return $this->createEncodedImage(function ($pointer) use ($image): void {
|
||||||
imageavif($image->core()->native(), $pointer, $this->quality);
|
imageavif($image->core()->native(), $pointer, $this->quality);
|
||||||
}, 'image/avif');
|
}, 'image/avif');
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,7 @@ class BmpEncoder extends GenericBmpEncoder implements SpecializedInterface
|
|||||||
*/
|
*/
|
||||||
public function encode(ImageInterface $image): EncodedImage
|
public function encode(ImageInterface $image): EncodedImage
|
||||||
{
|
{
|
||||||
return $this->createEncodedImage(function ($pointer) use ($image) {
|
return $this->createEncodedImage(function ($pointer) use ($image): void {
|
||||||
imagebmp($image->core()->native(), $pointer, false);
|
imagebmp($image->core()->native(), $pointer, false);
|
||||||
}, 'image/bmp');
|
}, 'image/bmp');
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ class GifEncoder extends GenericGifEncoder implements SpecializedInterface
|
|||||||
|
|
||||||
$gd = Cloner::clone($image->core()->native());
|
$gd = Cloner::clone($image->core()->native());
|
||||||
|
|
||||||
return $this->createEncodedImage(function ($pointer) use ($gd) {
|
return $this->createEncodedImage(function ($pointer) use ($gd): void {
|
||||||
imageinterlace($gd, $this->interlaced);
|
imageinterlace($gd, $this->interlaced);
|
||||||
imagegif($gd, $pointer);
|
imagegif($gd, $pointer);
|
||||||
}, 'image/gif');
|
}, 'image/gif');
|
||||||
|
@@ -28,7 +28,7 @@ class JpegEncoder extends GenericJpegEncoder implements SpecializedInterface
|
|||||||
background: $blendingColor
|
background: $blendingColor
|
||||||
);
|
);
|
||||||
|
|
||||||
return $this->createEncodedImage(function ($pointer) use ($output) {
|
return $this->createEncodedImage(function ($pointer) use ($output): void {
|
||||||
imageinterlace($output, $this->progressive);
|
imageinterlace($output, $this->progressive);
|
||||||
imagejpeg($output, $pointer, $this->quality);
|
imagejpeg($output, $pointer, $this->quality);
|
||||||
}, 'image/jpeg');
|
}, 'image/jpeg');
|
||||||
|
@@ -25,7 +25,7 @@ class PngEncoder extends GenericPngEncoder implements SpecializedInterface
|
|||||||
{
|
{
|
||||||
$output = $this->prepareOutput($image);
|
$output = $this->prepareOutput($image);
|
||||||
|
|
||||||
return $this->createEncodedImage(function ($pointer) use ($output) {
|
return $this->createEncodedImage(function ($pointer) use ($output): void {
|
||||||
imageinterlace($output, $this->interlaced);
|
imageinterlace($output, $this->interlaced);
|
||||||
imagepng($output, $pointer, -1);
|
imagepng($output, $pointer, -1);
|
||||||
}, 'image/png');
|
}, 'image/png');
|
||||||
|
@@ -20,7 +20,7 @@ class WebpEncoder extends GenericWebpEncoder implements SpecializedInterface
|
|||||||
{
|
{
|
||||||
$quality = $this->quality === 100 ? IMG_WEBP_LOSSLESS : $this->quality;
|
$quality = $this->quality === 100 ? IMG_WEBP_LOSSLESS : $this->quality;
|
||||||
|
|
||||||
return $this->createEncodedImage(function ($pointer) use ($image, $quality) {
|
return $this->createEncodedImage(function ($pointer) use ($image, $quality): void {
|
||||||
imagewebp($image->core()->native(), $pointer, $quality);
|
imagewebp($image->core()->native(), $pointer, $quality);
|
||||||
}, 'image/webp');
|
}, 'image/webp');
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,7 @@ class ColorspaceModifier extends GenericColorspaceModifier implements Specialize
|
|||||||
*/
|
*/
|
||||||
public function apply(ImageInterface $image): ImageInterface
|
public function apply(ImageInterface $image): ImageInterface
|
||||||
{
|
{
|
||||||
if (!is_a($this->targetColorspace(), RgbColorspace::class)) {
|
if (!($this->targetColorspace() instanceof RgbColorspace)) {
|
||||||
throw new NotSupportedException(
|
throw new NotSupportedException(
|
||||||
'Only RGB colorspace is supported by GD driver.'
|
'Only RGB colorspace is supported by GD driver.'
|
||||||
);
|
);
|
||||||
|
@@ -26,7 +26,7 @@ class DrawBezierModifier extends ModifiersDrawBezierModifier implements Speciali
|
|||||||
throw new GeometryException('You must specify either 3 or 4 points to create a bezier curve');
|
throw new GeometryException('You must specify either 3 or 4 points to create a bezier curve');
|
||||||
}
|
}
|
||||||
|
|
||||||
list($polygon, $polygon_border_segments) = $this->calculateBezierPoints();
|
[$polygon, $polygon_border_segments] = $this->calculateBezierPoints();
|
||||||
|
|
||||||
if ($this->drawable->hasBackgroundColor() || $this->drawable->hasBorder()) {
|
if ($this->drawable->hasBackgroundColor() || $this->drawable->hasBorder()) {
|
||||||
imagealphablending($frame->native(), true);
|
imagealphablending($frame->native(), true);
|
||||||
@@ -54,7 +54,8 @@ class DrawBezierModifier extends ModifiersDrawBezierModifier implements Speciali
|
|||||||
if ($this->drawable->borderSize() === 1) {
|
if ($this->drawable->borderSize() === 1) {
|
||||||
imagesetthickness($frame->native(), $this->drawable->borderSize());
|
imagesetthickness($frame->native(), $this->drawable->borderSize());
|
||||||
|
|
||||||
for ($i = 0; $i < count($polygon); $i += 2) {
|
$count = count($polygon);
|
||||||
|
for ($i = 0; $i < $count; $i += 2) {
|
||||||
if (array_key_exists($i + 2, $polygon) && array_key_exists($i + 3, $polygon)) {
|
if (array_key_exists($i + 2, $polygon) && array_key_exists($i + 3, $polygon)) {
|
||||||
imageline(
|
imageline(
|
||||||
$frame->native(),
|
$frame->native(),
|
||||||
@@ -160,11 +161,11 @@ class DrawBezierModifier extends ModifiersDrawBezierModifier implements Speciali
|
|||||||
$polygon_border_segments = [];
|
$polygon_border_segments = [];
|
||||||
|
|
||||||
// define ratio t; equivalent to 5 percent distance along edge
|
// define ratio t; equivalent to 5 percent distance along edge
|
||||||
$t = (float) 0.05;
|
$t = 0.05;
|
||||||
|
|
||||||
$polygon[] = $this->drawable->first()->x();
|
$polygon[] = $this->drawable->first()->x();
|
||||||
$polygon[] = $this->drawable->first()->y();
|
$polygon[] = $this->drawable->first()->y();
|
||||||
for ($i = 0 + $t; $i < 1; $i += $t) {
|
for ($i = $t; $i < 1; $i += $t) {
|
||||||
if ($this->drawable->count() === 3) {
|
if ($this->drawable->count() === 3) {
|
||||||
$ip = $this->calculateQuadraticBezierInterpolationPoint($i);
|
$ip = $this->calculateQuadraticBezierInterpolationPoint($i);
|
||||||
} elseif ($this->drawable->count() === 4) {
|
} elseif ($this->drawable->count() === 4) {
|
||||||
|
@@ -178,7 +178,7 @@ class Core implements CoreInterface, Iterator
|
|||||||
*/
|
*/
|
||||||
public function next(): void
|
public function next(): void
|
||||||
{
|
{
|
||||||
$this->iteratorIndex = $this->iteratorIndex + 1;
|
$this->iteratorIndex += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -247,7 +247,7 @@ class Core implements CoreInterface, Iterator
|
|||||||
public function frame(int $position): FrameInterface
|
public function frame(int $position): FrameInterface
|
||||||
{
|
{
|
||||||
foreach ($this->imagick as $core) {
|
foreach ($this->imagick as $core) {
|
||||||
if ($core->getIteratorIndex() == $position) {
|
if ($core->getIteratorIndex() === $position) {
|
||||||
return new Frame($core);
|
return new Frame($core);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,6 @@ class Base64ImageDecoder extends BinaryImageDecoder
|
|||||||
throw new DecoderException('Unable to decode input');
|
throw new DecoderException('Unable to decode input');
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::decode(base64_decode($input));
|
return parent::decode(base64_decode((string) $input));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -35,7 +35,7 @@ class NativeObjectDecoder extends SpecializableDecoder implements SpecializedInt
|
|||||||
// For some JPEG formats, the "coalesceImages()" call leads to an image
|
// For some JPEG formats, the "coalesceImages()" call leads to an image
|
||||||
// completely filled with background color. The logic behind this is
|
// completely filled with background color. The logic behind this is
|
||||||
// incomprehensible for me; could be an imagick bug.
|
// incomprehensible for me; could be an imagick bug.
|
||||||
if ($input->getImageFormat() != 'JPEG') {
|
if ($input->getImageFormat() !== 'JPEG') {
|
||||||
$input = $input->coalesceImages();
|
$input = $input->coalesceImages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -63,7 +63,7 @@ class FontProcessor extends AbstractFontProcessor
|
|||||||
$draw->setFontSize($this->nativeFontSize($font));
|
$draw->setFontSize($this->nativeFontSize($font));
|
||||||
$draw->setTextAlignment(Imagick::ALIGN_LEFT);
|
$draw->setTextAlignment(Imagick::ALIGN_LEFT);
|
||||||
|
|
||||||
if ($color) {
|
if ($color instanceof ImagickPixel) {
|
||||||
$draw->setFillColor($color);
|
$draw->setFillColor($color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,7 +13,7 @@ class BlurModifier extends GenericBlurModifier implements SpecializedInterface
|
|||||||
public function apply(ImageInterface $image): ImageInterface
|
public function apply(ImageInterface $image): ImageInterface
|
||||||
{
|
{
|
||||||
foreach ($image as $frame) {
|
foreach ($image as $frame) {
|
||||||
$frame->native()->blurImage(1 * $this->amount, 0.5 * $this->amount);
|
$frame->native()->blurImage($this->amount, 0.5 * $this->amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $image;
|
return $image;
|
||||||
|
@@ -122,7 +122,7 @@ class TextModifier extends GenericTextModifier implements SpecializedInterface
|
|||||||
?ImagickDraw $draw = null,
|
?ImagickDraw $draw = null,
|
||||||
PointInterface $offset = new Point(),
|
PointInterface $offset = new Point(),
|
||||||
): void {
|
): void {
|
||||||
if ($draw !== null) {
|
if ($draw instanceof ImagickDraw) {
|
||||||
$frame->native()->annotateImage(
|
$frame->native()->annotateImage(
|
||||||
$draw,
|
$draw,
|
||||||
$textline->position()->x() + $offset->x(),
|
$textline->position()->x() + $offset->x(),
|
||||||
|
@@ -8,8 +8,9 @@ use Intervention\Image\Exceptions\NotWritableException;
|
|||||||
use Intervention\Image\Exceptions\RuntimeException;
|
use Intervention\Image\Exceptions\RuntimeException;
|
||||||
use Intervention\Image\Interfaces\FileInterface;
|
use Intervention\Image\Interfaces\FileInterface;
|
||||||
use Intervention\Image\Traits\CanBuildFilePointer;
|
use Intervention\Image\Traits\CanBuildFilePointer;
|
||||||
|
use Stringable;
|
||||||
|
|
||||||
class File implements FileInterface
|
class File implements FileInterface, Stringable
|
||||||
{
|
{
|
||||||
use CanBuildFilePointer;
|
use CanBuildFilePointer;
|
||||||
|
|
||||||
@@ -64,7 +65,7 @@ class File implements FileInterface
|
|||||||
|
|
||||||
if (is_file($filepath) && !is_writable($filepath)) {
|
if (is_file($filepath) && !is_writable($filepath)) {
|
||||||
throw new NotWritableException(
|
throw new NotWritableException(
|
||||||
"Can't write image. Path ({$filepath}) is not writable."
|
sprintf("Can't write image. Path (%s) is not writable.", $filepath)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ class File implements FileInterface
|
|||||||
$saved = @file_put_contents($filepath, $this->pointer);
|
$saved = @file_put_contents($filepath, $this->pointer);
|
||||||
if ($saved === false) {
|
if ($saved === false) {
|
||||||
throw new NotWritableException(
|
throw new NotWritableException(
|
||||||
"Can't write image data to path ({$filepath})."
|
sprintf("Can't write image data to path (%s).", $filepath)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -88,7 +88,7 @@ enum Format
|
|||||||
{
|
{
|
||||||
return array_filter(
|
return array_filter(
|
||||||
MediaType::cases(),
|
MediaType::cases(),
|
||||||
fn(MediaType $mediaType) => $mediaType->format() === $this
|
fn(MediaType $mediaType): bool => $mediaType->format() === $this
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ enum Format
|
|||||||
{
|
{
|
||||||
return array_filter(
|
return array_filter(
|
||||||
FileExtension::cases(),
|
FileExtension::cases(),
|
||||||
fn(FileExtension $fileExtension) => $fileExtension->format() === $this
|
fn(FileExtension $fileExtension): bool => $fileExtension->format() === $this
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ enum Format
|
|||||||
$reflectionClass = new ReflectionClass($classname);
|
$reflectionClass = new ReflectionClass($classname);
|
||||||
if ($constructor = $reflectionClass->getConstructor()) {
|
if ($constructor = $reflectionClass->getConstructor()) {
|
||||||
$parameters = array_map(
|
$parameters = array_map(
|
||||||
fn($parameter) => $parameter->getName(),
|
fn($parameter): string => $parameter->getName(),
|
||||||
$constructor->getParameters(),
|
$constructor->getParameters(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -163,7 +163,7 @@ enum Format
|
|||||||
// filter out unavailable options of target encoder
|
// filter out unavailable options of target encoder
|
||||||
$options = array_filter(
|
$options = array_filter(
|
||||||
$options,
|
$options,
|
||||||
fn($key) => in_array($key, $parameters),
|
fn($key): bool => in_array($key, $parameters),
|
||||||
ARRAY_FILTER_USE_KEY,
|
ARRAY_FILTER_USE_KEY,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -214,12 +214,9 @@ class Polygon implements IteratorAggregate, Countable, ArrayAccess, DrawableInte
|
|||||||
*/
|
*/
|
||||||
public function mostLeftPoint(): PointInterface
|
public function mostLeftPoint(): PointInterface
|
||||||
{
|
{
|
||||||
$points = [];
|
$points = $this->points;
|
||||||
foreach ($this->points as $point) {
|
|
||||||
$points[] = $point;
|
|
||||||
}
|
|
||||||
|
|
||||||
usort($points, function ($a, $b) {
|
usort($points, function (PointInterface $a, PointInterface $b): int {
|
||||||
if ($a->x() === $b->x()) {
|
if ($a->x() === $b->x()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -236,12 +233,9 @@ class Polygon implements IteratorAggregate, Countable, ArrayAccess, DrawableInte
|
|||||||
*/
|
*/
|
||||||
public function mostRightPoint(): PointInterface
|
public function mostRightPoint(): PointInterface
|
||||||
{
|
{
|
||||||
$points = [];
|
$points = $this->points;
|
||||||
foreach ($this->points as $point) {
|
|
||||||
$points[] = $point;
|
|
||||||
}
|
|
||||||
|
|
||||||
usort($points, function ($a, $b) {
|
usort($points, function (PointInterface $a, PointInterface $b): int {
|
||||||
if ($a->x() === $b->x()) {
|
if ($a->x() === $b->x()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -258,12 +252,9 @@ class Polygon implements IteratorAggregate, Countable, ArrayAccess, DrawableInte
|
|||||||
*/
|
*/
|
||||||
public function mostTopPoint(): PointInterface
|
public function mostTopPoint(): PointInterface
|
||||||
{
|
{
|
||||||
$points = [];
|
$points = $this->points;
|
||||||
foreach ($this->points as $point) {
|
|
||||||
$points[] = $point;
|
|
||||||
}
|
|
||||||
|
|
||||||
usort($points, function ($a, $b) {
|
usort($points, function (PointInterface $a, PointInterface $b): int {
|
||||||
if ($a->y() === $b->y()) {
|
if ($a->y() === $b->y()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -280,12 +271,9 @@ class Polygon implements IteratorAggregate, Countable, ArrayAccess, DrawableInte
|
|||||||
*/
|
*/
|
||||||
public function mostBottomPoint(): PointInterface
|
public function mostBottomPoint(): PointInterface
|
||||||
{
|
{
|
||||||
$points = [];
|
$points = $this->points;
|
||||||
foreach ($this->points as $point) {
|
|
||||||
$points[] = $point;
|
|
||||||
}
|
|
||||||
|
|
||||||
usort($points, function ($a, $b) {
|
usort($points, function (PointInterface $a, PointInterface $b): int {
|
||||||
if ($a->y() === $b->y()) {
|
if ($a->y() === $b->y()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -111,13 +111,13 @@ class Rectangle extends Polygon implements SizeInterface
|
|||||||
case 'center-top':
|
case 'center-top':
|
||||||
case 'middle-top':
|
case 'middle-top':
|
||||||
$x = intval(round($this->width() / 2)) + $offset_x;
|
$x = intval(round($this->width() / 2)) + $offset_x;
|
||||||
$y = 0 + $offset_y;
|
$y = $offset_y;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'top-right':
|
case 'top-right':
|
||||||
case 'right-top':
|
case 'right-top':
|
||||||
$x = $this->width() - $offset_x;
|
$x = $this->width() - $offset_x;
|
||||||
$y = 0 + $offset_y;
|
$y = $offset_y;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'left':
|
case 'left':
|
||||||
@@ -125,7 +125,7 @@ class Rectangle extends Polygon implements SizeInterface
|
|||||||
case 'left-middle':
|
case 'left-middle':
|
||||||
case 'center-left':
|
case 'center-left':
|
||||||
case 'middle-left':
|
case 'middle-left':
|
||||||
$x = 0 + $offset_x;
|
$x = $offset_x;
|
||||||
$y = intval(round($this->height() / 2)) + $offset_y;
|
$y = intval(round($this->height() / 2)) + $offset_y;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -140,7 +140,7 @@ class Rectangle extends Polygon implements SizeInterface
|
|||||||
|
|
||||||
case 'bottom-left':
|
case 'bottom-left':
|
||||||
case 'left-bottom':
|
case 'left-bottom':
|
||||||
$x = 0 + $offset_x;
|
$x = $offset_x;
|
||||||
$y = $this->height() - $offset_y;
|
$y = $this->height() - $offset_y;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -170,8 +170,8 @@ class Rectangle extends Polygon implements SizeInterface
|
|||||||
default:
|
default:
|
||||||
case 'top-left':
|
case 'top-left':
|
||||||
case 'left-top':
|
case 'left-top':
|
||||||
$x = 0 + $offset_x;
|
$x = $offset_x;
|
||||||
$y = 0 + $offset_y;
|
$y = $offset_y;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -52,7 +52,7 @@ class RectangleResizer
|
|||||||
*/
|
*/
|
||||||
protected function hasTargetWidth(): bool
|
protected function hasTargetWidth(): bool
|
||||||
{
|
{
|
||||||
return is_integer($this->width);
|
return is_int($this->width);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,7 +72,7 @@ class RectangleResizer
|
|||||||
*/
|
*/
|
||||||
protected function hasTargetHeight(): bool
|
protected function hasTargetHeight(): bool
|
||||||
{
|
{
|
||||||
return is_integer($this->height);
|
return is_int($this->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -107,7 +107,7 @@ final class Image implements ImageInterface
|
|||||||
*
|
*
|
||||||
* @var Origin
|
* @var Origin
|
||||||
*/
|
*/
|
||||||
protected Origin $origin;
|
private Origin $origin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new instance
|
* Create new instance
|
||||||
@@ -119,9 +119,9 @@ final class Image implements ImageInterface
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected DriverInterface $driver,
|
private DriverInterface $driver,
|
||||||
protected CoreInterface $core,
|
private CoreInterface $core,
|
||||||
protected CollectionInterface $exif = new Collection()
|
private CollectionInterface $exif = new Collection()
|
||||||
) {
|
) {
|
||||||
$this->origin = new Origin();
|
$this->origin = new Origin();
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,7 @@ use Intervention\Image\Interfaces\ImageManagerInterface;
|
|||||||
|
|
||||||
final class ImageManager implements ImageManagerInterface
|
final class ImageManager implements ImageManagerInterface
|
||||||
{
|
{
|
||||||
protected DriverInterface $driver;
|
private DriverInterface $driver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @link https://image.intervention.io/v3/basics/image-manager#create-a-new-image-manager-instance
|
* @link https://image.intervention.io/v3/basics/image-manager#create-a-new-image-manager-instance
|
||||||
|
@@ -17,6 +17,6 @@ class FillModifier extends SpecializableModifier
|
|||||||
|
|
||||||
public function hasPosition(): bool
|
public function hasPosition(): bool
|
||||||
{
|
{
|
||||||
return !empty($this->position);
|
return $this->position instanceof PointInterface;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -50,8 +50,7 @@ class RemoveAnimationModifier extends SpecializableModifier
|
|||||||
|
|
||||||
$total = count($image);
|
$total = count($image);
|
||||||
$position = intval(round($total / 100 * intval($matches['percent'])));
|
$position = intval(round($total / 100 * intval($matches['percent'])));
|
||||||
$position = $position == $total ? $position - 1 : $position;
|
|
||||||
|
|
||||||
return $position;
|
return $position == $total ? $position - 1 : $position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,8 +5,9 @@ declare(strict_types=1);
|
|||||||
namespace Intervention\Image;
|
namespace Intervention\Image;
|
||||||
|
|
||||||
use Intervention\Image\Interfaces\ResolutionInterface;
|
use Intervention\Image\Interfaces\ResolutionInterface;
|
||||||
|
use Stringable;
|
||||||
|
|
||||||
class Resolution implements ResolutionInterface
|
class Resolution implements ResolutionInterface, Stringable
|
||||||
{
|
{
|
||||||
public const PER_INCH = 1;
|
public const PER_INCH = 1;
|
||||||
public const PER_CM = 2;
|
public const PER_CM = 2;
|
||||||
|
@@ -9,12 +9,13 @@ use Countable;
|
|||||||
use Intervention\Image\Geometry\Point;
|
use Intervention\Image\Geometry\Point;
|
||||||
use Intervention\Image\Interfaces\PointInterface;
|
use Intervention\Image\Interfaces\PointInterface;
|
||||||
use IteratorAggregate;
|
use IteratorAggregate;
|
||||||
|
use Stringable;
|
||||||
use Traversable;
|
use Traversable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements IteratorAggregate<string>
|
* @implements IteratorAggregate<string>
|
||||||
*/
|
*/
|
||||||
class Line implements IteratorAggregate, Countable
|
class Line implements IteratorAggregate, Countable, Stringable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Segments (usually individual words including punctuation marks) of the line
|
* Segments (usually individual words including punctuation marks) of the line
|
||||||
|
@@ -67,7 +67,7 @@ class TextBlock extends Collection
|
|||||||
public function longestLine(): Line
|
public function longestLine(): Line
|
||||||
{
|
{
|
||||||
$lines = $this->lines();
|
$lines = $this->lines();
|
||||||
usort($lines, function (Line $a, Line $b) {
|
usort($lines, function (Line $a, Line $b): int {
|
||||||
if ($a->length() === $b->length()) {
|
if ($a->length() === $b->length()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user