Dockerfile 0000644 00000001605 15073164707 0006552 0 ustar 00 FROM php:8-cli
RUN apt update \
&& apt install -y \
libpng-dev \
libicu-dev \
libpq-dev \
libzip-dev \
zip \
zlib1g-dev \
locales \
locales-all \
libmagickwand-dev \
libwebp-dev \
&& pecl install imagick \
&& docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
&& docker-php-ext-enable imagick \
&& docker-php-ext-install \
intl \
opcache \
pdo \
pdo_pgsql \
pdo_mysql \
pgsql \
fileinfo \
mysqli \
gd \
bcmath \
exif \
zip \
&& apt-get clean
# install composer
#
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
LICENSE 0000644 00000002066 15073164707 0005567 0 ustar 00 The MIT License (MIT)
Copyright (c) 2021 Oliver Vogel
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. composer.json 0000644 00000001616 15073164707 0007304 0 ustar 00 {
"name": "intervention/image",
"description": "PHP image manipulation",
"homepage": "https://image.intervention.io/",
"keywords": ["image", "gd", "imagick", "laravel", "watermark", "thumbnail"],
"license": "MIT",
"authors": [
{
"name": "Oliver Vogel",
"email": "oliver@intervention.io",
"homepage": "https://intervention.io/"
}
],
"require": {
"php": "^8.1",
"intervention/gif": "^3.0",
"intervention/mimesniffer": "^0.4.2"
},
"require-dev": {
"phpunit/phpunit": "^9",
"mockery/mockery": "^1.4",
"phpstan/phpstan": "^1"
},
"autoload": {
"psr-4": {
"Intervention\\Image\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Intervention\\Image\\Tests\\": "tests"
}
},
"minimum-stability": "alpha"
}
docker-compose.yml 0000644 00000000535 15073164707 0010216 0 ustar 00 version: '3'
services:
tests:
build: ./
working_dir: /project
command: bash -c "composer install && ./vendor/bin/phpunit -vvv"
volumes:
- ./:/project
analysis:
build: ./
working_dir: /project
command: bash -c "composer install && ./vendor/bin/phpstan analyze --level=4 ./src"
volumes:
- ./:/project
phpunit.xml.dist 0000644 00000001264 15073164707 0007734 0 ustar 00
./tests/
src
readme.md 0000644 00000004126 15073164707 0006340 0 ustar 00 # Intervention Image
## PHP Image Manipulation
[](https://packagist.org/packages/intervention/image)
[](https://github.com/Intervention/image/actions)
[](https://packagist.org/packages/intervention/image/stats)
Intervention Image is a **image handling and manipulation library written in PHP** providing an easier and expressive way to create, edit, and compose images. GD library or Imagick can be selected as the base layer for all operations.
- Simple interface for common tasks
- Interchangable driver architecture
- Support for animated images
- Framework-agnostic
- PSR-12 compliant
## Code Examples
```php
// create image manager with desired driver
$manager = new ImageManager('gd')
// open an image file
$image = $manager->read('images/example.gif');
// resize image instance
$image->resize(height: 300);
// insert a watermark
$image->place('images/watermark.png');
// encode edited image
$encoded = $image->toJpg();
// save encoded image
$encoded->save('images/example.jpg');
```
## Requirements
- PHP >= 8.1
## Supported Image Libraries
- GD Library
- Imagick PHP extension
## Installation
```bash
composer require intervention/image
```
## Getting started
Learn the [basics](https://image.intervention.io/v3/basics/instantiation/) on how to use Intervention Image and more with the [official documentation](https://image.intervention.io/v3/).
## Development & Testing
With this package comes a Docker image to build a test suite and analysis container. To build this container you have to have Docker installed on your system. You can run all tests with this command.
```bash
docker-compose run --rm --build tests
```
Run the static analyzer on the code base.
```bash
docker-compose run --rm --build analysis
```
## License
Intervention Image is licensed under the [MIT License](http://opensource.org/licenses/MIT).
Copyright 2022 Oliver Vogel
src/Collection.php 0000644 00000007445 15073164707 0010163 0 ustar 00 items);
}
public function toArray(): array
{
return $this->items;
}
/**
* Count items in collection
*
* @return integer
*/
public function count(): int
{
return count($this->items);
}
/**
* Append new item to collection
*
* @param mixed $item
* @return CollectionInterface
*/
public function push($item): CollectionInterface
{
$this->items[] = $item;
return $this;
}
/**
* Return first item in collection
*
* @return mixed
*/
public function first()
{
if ($item = reset($this->items)) {
return $item;
}
return null;
}
/**
* Returns last item in collection
*
* @return mixed
*/
public function last()
{
if ($item = end($this->items)) {
return $item;
}
return null;
}
/**
* Return item with given key
*
* @param integer $key
* @return mixed
*/
public function get(int $key = 0, $default = null)
{
if (! array_key_exists($key, $this->items)) {
return $default;
}
return $this->items[$key];
}
public function has(int $key): bool
{
return array_key_exists($key, $this->items);
}
public function query(string $query, $default = null)
{
$items = $this->getItemsFlat();
if (!array_key_exists($query, $items)) {
return $default;
}
return $items[$query];
}
public function map(callable $callback): self
{
$items = array_map(function ($item) use ($callback) {
return $callback($item);
}, $this->items);
return new self($items);
}
/**
* Run callback on each item of the collection an remove it if it does not return true
*
* @param callable $callback
* @return Collection
*/
public function filter(callable $callback): self
{
$items = array_filter($this->items, function ($item) use ($callback) {
return $callback($item);
});
return new self($items);
}
public function pushEach(array $data, ?callable $callback = null): CollectionInterface
{
if (! is_iterable($data)) {
throw new RuntimeException('Unable to iterate given data.');
}
foreach ($data as $item) {
$this->push(is_callable($callback) ? $callback($item) : $item);
}
return $this;
}
private function getItemsFlat(): array
{
$iterator = new RecursiveIteratorIterator(
new RecursiveArrayIterator($this->items)
);
$items = [];
foreach ($iterator as $value) {
$keys = [];
foreach (range(0, $iterator->getDepth()) as $depth) {
$keys[] = $iterator->getSubIterator($depth)->key();
}
$items[join('.', $keys)] = $value;
}
return $items;
}
}
src/Drivers/Abstract/AbstractColor.php 0000644 00000001351 15073164707 0014001 0 ustar 00 red(),
$this->green(),
$this->blue()
);
}
/**
* Determine if color is greyscale
*
* @return boolean
*/
public function isGreyscale(): bool
{
return ($this->red() === $this->green()) && ($this->green() === $this->blue());
}
}
src/Drivers/Abstract/AbstractFont.php 0000644 00000004724 15073164707 0013640 0 ustar 00 size = $size;
return $this;
}
public function getSize(): float
{
return $this->size;
}
public function angle(float $angle): FontInterface
{
$this->angle = $angle;
return $this;
}
public function getAngle(): float
{
return $this->angle;
}
public function filename(string $filename): FontInterface
{
$this->filename = $filename;
return $this;
}
public function getFilename(): ?string
{
return $this->filename;
}
public function hasFilename(): bool
{
return !is_null($this->filename) && is_file($this->filename);
}
public function color($color): FontInterface
{
$this->color = $color;
return $this;
}
public function getColor(): ?ColorInterface
{
return $this->handleInput($this->color);
}
public function align(string $align): FontInterface
{
$this->align = $align;
return $this;
}
public function getValign(): string
{
return $this->valign;
}
public function valign(string $valign): FontInterface
{
$this->valign = $valign;
return $this;
}
public function getAlign(): string
{
return $this->align;
}
public function lineHeight(float $height): FontInterface
{
$this->lineHeight = $height;
return $this;
}
public function getLineHeight(): float
{
return $this->lineHeight;
}
public function leadingInPixels(): int
{
return intval(round($this->fontSizeInPixels() * $this->getLineHeight()));
}
public function capHeight(): int
{
return $this->getBoxSize('T')->getHeight();
}
public function fontSizeInPixels(): int
{
return $this->getBoxSize('Hy')->getHeight();
}
}
src/Drivers/Abstract/AbstractImage.php 0000644 00000023640 15073164707 0013752 0 ustar 00 getWidth(), $this->getHeight());
}
public function size(): SizeInterface
{
return $this->getSize();
}
public function modify(ModifierInterface $modifier): ImageInterface
{
return $modifier->apply($this);
}
public function encode(EncoderInterface $encoder): EncodedImage
{
return $encoder->encode($this);
}
public function toJpeg(int $quality = 75): EncodedImage
{
return $this->encode(
$this->resolveDriverClass('Encoders\JpegEncoder', $quality)
);
}
public function toWebp(int $quality = 75): EncodedImage
{
return $this->encode(
$this->resolveDriverClass('Encoders\WebpEncoder', $quality)
);
}
public function toGif(): EncodedImage
{
return $this->encode(
$this->resolveDriverClass('Encoders\GifEncoder')
);
}
public function toPng(): EncodedImage
{
return $this->encode(
$this->resolveDriverClass('Encoders\PngEncoder')
);
}
public function toBitmap(): EncodedImage
{
return $this->encode(
$this->resolveDriverClass('Encoders\BmpEncoder')
);
}
public function toBmp(): EncodedImage
{
return $this->toBitmap();
}
public function greyscale(): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\GreyscaleModifier')
);
}
public function invert(): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\InvertModifier')
);
}
public function brightness(int $level): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\BrightnessModifier', $level)
);
}
public function contrast(int $level): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\ContrastModifier', $level)
);
}
public function gamma(float $gamma): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\GammaModifier', $gamma)
);
}
public function blur(int $amount = 5): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\BlurModifier', $amount)
);
}
public function rotate(float $angle, $background = 'ffffff'): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\RotateModifier', $angle, $background)
);
}
/**
* Creates a vertical mirror image
*
* @return ImageInterface
*/
public function flip(): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\FlipModifier')
);
}
/**
* Creates a horizontal mirror image
*
* @return ImageInterface
*/
public function flop(): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\FlopModifier')
);
}
public function place($element, string $position = 'top-left', int $offset_x = 0, int $offset_y = 0): ImageInterface
{
return $this->modify(
$this->resolveDriverClass(
'Modifiers\PlaceModifier',
$element,
$position,
$offset_x,
$offset_y
)
);
}
public function fill($color, ?int $x = null, ?int $y = null): ImageInterface
{
$color = $this->handleInput($color);
$position = (is_null($x) && is_null($y)) ? null : new Point($x, $y);
return $this->modify(
$this->resolveDriverClass(
'Modifiers\FillModifier',
$color,
$position
)
);
}
public function pixelate(int $size): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\PixelateModifier', $size)
);
}
public function sharpen(int $amount = 10): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\SharpenModifier', $amount)
);
}
public function pickColors(int $x, int $y): CollectionInterface
{
$colors = new Collection();
foreach ($this as $key => $frame) {
$colors->push($this->pickColor($x, $y, $key));
}
return $colors;
}
public function text(string $text, int $x, int $y, ?callable $init = null): ImageInterface
{
$font = $this->runCallback($init, $this->resolveDriverClass('Font'));
$modifier = $this->resolveDriverClass('Modifiers\TextWriter', new Point($x, $y), $font, $text);
return $this->modify($modifier);
}
public function drawPixel(int $x, int $y, $color = null): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\DrawPixelModifier', new Point($x, $y), $color)
);
}
public function drawRectangle(int $x, int $y, ?callable $init = null): ImageInterface
{
$rectangle = $this->runCallback($init, new Rectangle(0, 0));
$modifier = $this->resolveDriverClass('Modifiers\DrawRectangleModifier', new Point($x, $y), $rectangle);
return $this->modify($modifier);
}
public function drawEllipse(int $x, int $y, ?callable $init = null): ImageInterface
{
$ellipse = $this->runCallback($init, new Ellipse(0, 0));
$modifier = $this->resolveDriverClass('Modifiers\DrawEllipseModifier', new Point($x, $y), $ellipse);
return $this->modify($modifier);
}
public function drawCircle(int $x, int $y, ?callable $init = null): ImageInterface
{
$circle = $this->runCallback($init, new Circle(0));
$modifier = $this->resolveDriverClass('Modifiers\DrawEllipseModifier', new Point($x, $y), $circle);
return $this->modify($modifier);
}
public function drawLine(callable $init = null): ImageInterface
{
$line = $this->runCallback($init, new Line(new Point(), new Point()));
$modifier = $this->resolveDriverClass('Modifiers\DrawLineModifier', $line->getStart(), $line);
return $this->modify($modifier);
}
public function drawPolygon(callable $init = null): ImageInterface
{
$polygon = $this->runCallback($init, new Polygon());
$modifier = $this->resolveDriverClass('Modifiers\DrawPolygonModifier', $polygon);
return $this->modify($modifier);
}
public function resize(?int $width = null, ?int $height = null): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\ResizeModifier', $width, $height)
);
}
public function resizeDown(?int $width = null, ?int $height = null): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\ResizeDownModifier', $width, $height)
);
}
public function scale(?int $width = null, ?int $height = null): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\ScaleModifier', $width, $height)
);
}
public function scaleDown(?int $width = null, ?int $height = null): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\ScaleDownModifier', $width, $height)
);
}
public function fit(int $width, int $height, string $position = 'center'): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\FitModifier', $width, $height, $position)
);
}
public function fitDown(int $width, int $height, string $position = 'center'): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\FitDownModifier', $width, $height, $position)
);
}
public function pad(int $width, int $height, $background = 'ffffff', string $position = 'center'): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\PadModifier', $width, $height, $background, $position)
);
}
public function padDown(
int $width,
int $height,
$background = 'ffffff',
string $position = 'center'
): ImageInterface {
return $this->modify(
$this->resolveDriverClass('Modifiers\PadDownModifier', $width, $height, $background, $position)
);
}
public function removeAnimation(int $position = 0): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\RemoveAnimationModifier', $position)
);
}
public function destroy(): void
{
$this->modify(
$this->resolveDriverClass('Modifiers\DestroyModifier')
);
}
}
src/Drivers/Abstract/AbstractInputHandler.php 0000644 00000002600 15073164707 0015316 0 ustar 00 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;
}
/**
* Try to decode the given input with each decoder of the the handler chain
*
* @param mixed $input
* @return ImageInterface|ColorInterface
*/
public function handle($input): ImageInterface|ColorInterface
{
return $this->chain()->handle($input);
}
}
src/Drivers/Abstract/AbstractTextWriter.php 0000644 00000003743 15073164707 0015053 0 ustar 00 font;
}
protected function getPosition(): Point
{
return $this->position;
}
/**
* Build TextBlock object from text string and align every line
* according to text writers font object and position.
*
* @return TextBlock
*/
public function getAlignedTextBlock(): TextBlock
{
$lines = new TextBlock($this->text);
$position = $this->getPosition();
$font = $this->getFont();
$boundingBox = $lines->getBoundingBox($font, $position);
$pivot = $boundingBox->last();
$leading = $font->leadingInPixels();
$blockWidth = $lines->longestLine()->widthInFont($font);
$x = $pivot->getX();
$y = $font->hasFilename() ? $pivot->getY() + $font->capHeight() : $pivot->getY();
$x_adjustment = 0;
foreach ($lines as $line) {
$x_adjustment = $font->getAlign() == 'left' ? 0 : $blockWidth - $line->widthInFont($font);
$x_adjustment = $font->getAlign() == 'right' ? intval(round($x_adjustment)) : $x_adjustment;
$x_adjustment = $font->getAlign() == 'center' ? intval(round($x_adjustment / 2)) : $x_adjustment;
$position = new Point($x + $x_adjustment, $y);
$position->rotate($font->getAngle(), $pivot);
$line->setPosition($position);
$y += $leading;
}
return $lines;
}
}
src/Drivers/Abstract/Decoders/AbstractDecoder.php 0000644 00000002167 15073164707 0016026 0 ustar 00 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;
}
protected function inputType($input): AbstractType
{
return MimeSniffer::createFromString($input)->getType();
}
}
src/Drivers/Abstract/Encoders/AbstractEncoder.php 0000644 00000001370 15073164707 0016045 0 ustar 00 quality = $quality;
return $this;
}
public function getQuality(): int
{
return $this->quality;
}
}
src/Drivers/Abstract/Modifiers/AbstractDrawModifier.php 0000644 00000005216 15073164707 0017224 0 ustar 00 drawable;
}
protected function getBackgroundColor(): ?ColorInterface
{
try {
$color = $this->handleInput($this->drawable->getBackgroundColor());
} catch (DecoderException $e) {
return $this->handleInput('transparent');
}
return $color;
}
protected function getBorderColor(): ?ColorInterface
{
try {
$color = $this->handleInput($this->drawable->getBorderColor());
} catch (DecoderException $e) {
return $this->handleInput('transparent');
}
return $color;
}
public function polygon(): Polygon
{
if (!is_a($this->drawable(), Polygon::class)) {
throw new GeometryException(
'Shape mismatch. Excepted Polygon::class, found ' . get_class($this->drawable())
);
}
return $this->drawable();
}
public function ellipse(): Ellipse
{
if (!is_a($this->drawable(), Ellipse::class)) {
throw new GeometryException(
'Shape mismatch. Excepted Ellipse::class, found ' . get_class($this->drawable())
);
}
return $this->drawable();
}
public function line(): Line
{
if (!is_a($this->drawable(), Line::class)) {
throw new GeometryException(
'Shape mismatch. Excepted Line::class, found ' . get_class($this->drawable())
);
}
return $this->drawable();
}
public function rectangle(): Rectangle
{
if (!is_a($this->drawable(), Rectangle::class)) {
throw new GeometryException(
'Shape mismatch. Excepted Rectangle::class, found ' . get_class($this->drawable())
);
}
return $this->drawable();
}
}
src/Drivers/Abstract/Modifiers/AbstractFitModifier.php 0000644 00000001634 15073164707 0017051 0 ustar 00 getSize();
$crop = new Rectangle($this->width, $this->height);
$crop = $crop->contain(
$imagesize->getWidth(),
$imagesize->getHeight()
)->alignPivotTo($imagesize, $this->position);
return $crop;
}
protected function getResizeSize(SizeInterface $size): SizeInterface
{
return $size->scale($this->width, $this->height);
}
}
src/Drivers/Abstract/Modifiers/AbstractPadModifier.php 0000644 00000001631 15073164707 0017030 0 ustar 00 getSize()
->contain($this->width, $this->height)
->alignPivotTo($this->getResizeSize($image), $this->position);
}
protected function getResizeSize(ImageInterface $image): SizeInterface
{
return new Rectangle($this->width, $this->height);
}
}
src/Drivers/Abstract/Modifiers/AbstractRotateModifier.php 0000644 00000001755 15073164707 0017571 0 ustar 00 angle, 360);
}
protected function backgroundColor(): ColorInterface
{
try {
return $this->handleInput($this->background);
} catch (DecoderException $e) {
throw new TypeException("rotate(): Argument #2 must be a color value.");
}
}
}
src/Drivers/Gd/Color.php 0000644 00000001736 15073164707 0011113 0 ustar 00 toArray()[0];
}
public function green(): int
{
return $this->toArray()[1];
}
public function blue(): int
{
return $this->toArray()[2];
}
public function alpha(): float
{
return $this->toArray()[3];
}
public function toArray(): array
{
$a = ($this->value >> 24) & 0x7F;
$r = ($this->value >> 16) & 0xFF;
$g = ($this->value >> 8) & 0xFF;
$b = $this->value & 0xFF;
$a = (float) round(1 - $a / 127, 2);
return [$r, $g, $b, $a];
}
public function toInt(): int
{
return $this->value;
}
}
src/Drivers/Gd/Decoders/ArrayColorDecoder.php 0000644 00000002102 15073164707 0015114 0 ustar 00 isValidColorArray($input)) {
throw new DecoderException('Unable to decode input');
}
if (count($input) === 3) {
$input[] = 1;
}
list($r, $g, $b, $a) = $input;
return new Color(
($this->opacityToGdAlpha($a) << 24) + ($r << 16) + ($g << 8) + $b
);
}
protected function opacityToGdAlpha(float $opacity): int
{
return intval(round($opacity * 127 * -1 + 127));
}
}
src/Drivers/Gd/Decoders/Base64ImageDecoder.php 0000644 00000001247 15073164707 0015037 0 ustar 00 isValidBase64($input)) {
throw new DecoderException('Unable to decode input');
}
return parent::decode(base64_decode($input));
}
}
src/Drivers/Gd/Decoders/BinaryImageDecoder.php 0000644 00000004076 15073164707 0015242 0 ustar 00 inputType($input)->isBinary()) {
throw new DecoderException('Unable to decode input');
}
if (is_a($this->inputType($input), ImageGif::class)) {
return $this->decodeGif($input); // decode (animated) gif
}
$gd = @imagecreatefromstring($input);
if ($gd === false) {
throw new DecoderException('Unable to decode input');
}
if (! imageistruecolor($gd)) {
imagepalettetotruecolor($gd);
}
imagesavealpha($gd, true);
return new Image(new Collection([new Frame($gd)]));
}
protected function decodeGif($input): ImageInterface
{
$image = new Image(new Collection());
$gif = GifDecoder::decode($input);
if (!$gif->isAnimated()) {
return $image->addFrame(new Frame(@imagecreatefromstring($input)));
}
$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));
}
return $image;
}
}
src/Drivers/Gd/Decoders/DataUriImageDecoder.php 0000644 00000001652 15073164707 0015344 0 ustar 00 decodeDataUri($input);
if (! $uri->isValid()) {
throw new DecoderException('Unable to decode input');
}
if ($uri->isBase64Encoded()) {
return parent::decode(base64_decode($uri->data()));
}
return parent::decode(urldecode($uri->data()));
}
}
src/Drivers/Gd/Decoders/FilePathImageDecoder.php 0000644 00000001532 15073164707 0015504 0 ustar 00 hexColorFromColorName($input);
if (empty($hexcolor)) {
throw new DecoderException('Unable to decode input');
}
return parent::decode($hexcolor);
}
}
src/Drivers/Gd/Decoders/ImageObjectDecoder.php 0000644 00000001201 15073164707 0015207 0 ustar 00 [0-9]{1,3}), ?(?P[0-9]{1,3}), ?(?P[0-9]{1,3})\)$/i";
if ((bool) preg_match($pattern, $input, $matches)) {
return parent::decode([$matches['r'], $matches['g'], $matches['b']]);
}
// rgba string like "rgba(200, 10, 30, 0.5)"
$pattern = "/^rgba ?\(((?P[0-9]{1,3})), ?((?P[0-9]{1,3})), ?((?P[0-9]{1,3})), ?(?P[0-9.]{1,4})\)$/i";
if ((bool) preg_match($pattern, $input, $matches)) {
return parent::decode([$matches['r'], $matches['g'], $matches['b'], $matches['a']]);
}
throw new DecoderException('Unable to decode input');
}
}
src/Drivers/Gd/Decoders/TransparentColorDecoder.php 0000644 00000001162 15073164707 0016344 0 ustar 00 getBuffered(function () use ($image) {
imagebmp($image->getFrame()->getCore(), null, false);
});
return new EncodedImage($data, 'image/bmp');
}
}
src/Drivers/Gd/Encoders/GifEncoder.php 0000644 00000002242 15073164707 0013575 0 ustar 00 isAnimated()) {
return $this->encodeAnimated($image);
}
$data = $this->getBuffered(function () use ($image) {
imagegif($image->getFrame()->getCore());
});
return new EncodedImage($data, 'image/gif');
}
protected function encodeAnimated($image): EncodedImage
{
$builder = GifBuilder::canvas(
$image->getWidth(),
$image->getHeight(),
$image->getLoops()
);
foreach ($image as $frame) {
$source = $this->encode($frame->toImage());
$builder->addFrame($source, $frame->getDelay());
}
return new EncodedImage($builder->encode(), 'image/gif');
}
}
src/Drivers/Gd/Encoders/JpegEncoder.php 0000644 00000001311 15073164707 0013751 0 ustar 00 quality = $quality;
}
public function encode(ImageInterface $image): EncodedImage
{
$data = $this->getBuffered(function () use ($image) {
imagejpeg($image->getFrame()->getCore(), null, $this->quality);
});
return new EncodedImage($data, 'image/jpeg');
}
}
src/Drivers/Gd/Encoders/PngEncoder.php 0000644 00000001134 15073164707 0013613 0 ustar 00 getBuffered(function () use ($image) {
imagepng($image->getFrame()->getCore(), null, -1);
});
return new EncodedImage($data, 'image/png');
}
}
src/Drivers/Gd/Encoders/WebpEncoder.php 0000644 00000001311 15073164707 0013761 0 ustar 00 quality = $quality;
}
public function encode(ImageInterface $image): EncodedImage
{
$data = $this->getBuffered(function () use ($image) {
imagewebp($image->getFrame()->getCore(), null, $this->quality);
});
return new EncodedImage($data, 'image/webp');
}
}
src/Drivers/Gd/Font.php 0000644 00000003773 15073164707 0010746 0 ustar 00 hasFilename()) {
// calculate box size from gd font
$box = new Rectangle(0, 0);
$chars = mb_strlen($text);
if ($chars > 0) {
$box->setWidth($chars * $this->getGdFontWidth());
$box->setHeight($this->getGdFontHeight());
}
return $box;
}
// calculate box size from font file with angle 0
$box = imageftbbox(
$this->getSize(),
0,
$this->getFilename(),
$text
);
// build polygon from points
$polygon = new Polygon();
$polygon->addPoint(new Point($box[6], $box[7]));
$polygon->addPoint(new Point($box[4], $box[5]));
$polygon->addPoint(new Point($box[2], $box[3]));
$polygon->addPoint(new Point($box[0], $box[1]));
return $polygon;
}
public function getGdFont(): int
{
if (is_numeric($this->filename)) {
return $this->filename;
}
return 1;
}
protected function getGdFontWidth(): int
{
return $this->getGdFont() + 4;
}
protected function getGdFontHeight(): int
{
switch ($this->getGdFont()) {
case 2:
return 14;
case 3:
return 14;
case 4:
return 16;
case 5:
return 16;
default:
case 1:
return 8;
}
}
}
src/Drivers/Gd/Frame.php 0000644 00000004123 15073164707 0011060 0 ustar 00 core = $core;
return $this;
}
public function getCore(): GdImage
{
return $this->core;
}
public function unsetCore(): void
{
unset($this->core);
}
public function getSize(): SizeInterface
{
return new Rectangle(imagesx($this->core), imagesy($this->core));
}
public function getDelay(): float
{
return $this->delay;
}
public function setDelay(float $delay): FrameInterface
{
$this->delay = $delay;
return $this;
}
public function getDispose(): int
{
return $this->dispose;
}
public function setDispose(int $dispose): FrameInterface
{
$this->dispose = $dispose;
return $this;
}
public function setOffset(int $left, int $top): FrameInterface
{
$this->offset_left = $left;
$this->offset_top = $top;
return $this;
}
public function getOffsetLeft(): int
{
return $this->offset_left;
}
public function setOffsetLeft(int $offset): FrameInterface
{
$this->offset_left = $offset;
return $this;
}
public function getOffsetTop(): int
{
return $this->offset_top;
}
public function setOffsetTop(int $offset): FrameInterface
{
$this->offset_top = $offset;
return $this;
}
public function toImage(): ImageInterface
{
return new Image(new Collection([$this]));
}
}
src/Drivers/Gd/Image.php 0000644 00000003245 15073164707 0011054 0 ustar 00 frames;
}
public function count(): int
{
return $this->frames->count();
}
public function isAnimated(): bool
{
return $this->count() > 1;
}
public function getLoops(): int
{
return $this->loops;
}
public function setLoops(int $count): self
{
$this->loops = $count;
return $this;
}
public function getFrame(int $position = 0): ?FrameInterface
{
return $this->frames->get($position);
}
public function addFrame(FrameInterface $frame): ImageInterface
{
$this->frames->push($frame);
return $this;
}
public function getWidth(): int
{
return imagesx($this->getFrame()->getCore());
}
public function getHeight(): int
{
return imagesy($this->getFrame()->getCore());
}
public function pickColor(int $x, int $y, int $frame_key = 0): ?ColorInterface
{
if ($frame = $this->getFrame($frame_key)) {
return new Color(imagecolorat($frame->getCore(), $x, $y));
}
return null;
}
}
src/Drivers/Gd/ImageFactory.php 0000644 00000001350 15073164707 0012377 0 ustar 00 newCore($width, $height))
])
);
}
public function newCore(int $width, int $height)
{
$core = imagecreatetruecolor($width, $height);
$color = imagecolorallocatealpha($core, 0, 0, 0, 127);
imagefill($core, 0, 0, $color);
imagesavealpha($core, true);
return $core;
}
}
src/Drivers/Gd/InputHandler.php 0000644 00000001210 15073164707 0012415 0 ustar 00 blurFrame($frame);
}
return $image;
}
protected function blurFrame(FrameInterface $frame): void
{
for ($i = 0; $i < $this->amount; $i++) {
imagefilter($frame->getCore(), IMG_FILTER_GAUSSIAN_BLUR);
}
}
}
src/Drivers/Gd/Modifiers/BrightnessModifier.php 0000644 00000001037 15073164707 0015537 0 ustar 00 getCore(), IMG_FILTER_BRIGHTNESS, intval($this->level * 2.55));
}
return $image;
}
}
src/Drivers/Gd/Modifiers/ContrastModifier.php 0000644 00000001023 15073164707 0015217 0 ustar 00 getCore(), IMG_FILTER_CONTRAST, ($this->level * -1));
}
return $image;
}
}
src/Drivers/Gd/Modifiers/DestroyModifier.php 0000644 00000000617 15073164707 0015063 0 ustar 00 unsetCore();
}
return $image;
}
}
src/Drivers/Gd/Modifiers/DrawEllipseModifier.php 0000644 00000003761 15073164707 0015650 0 ustar 00 eachFrame(function ($frame) {
if ($this->ellipse()->hasBorder()) {
// slightly smaller ellipse to keep 1px bordered edges clean
if ($this->ellipse()->hasBackgroundColor()) {
imagefilledellipse(
$frame->getCore(),
$this->position->getX(),
$this->position->getY(),
$this->ellipse()->getWidth() - 1,
$this->ellipse()->getHeight() - 1,
$this->getBackgroundColor()->toInt()
);
}
imagesetthickness($frame->getCore(), $this->ellipse()->getBorderSize());
// gd's imageellipse doesn't respect imagesetthickness so i use
// imagearc with 359.9 degrees here.
imagearc(
$frame->getCore(),
$this->position->getX(),
$this->position->getY(),
$this->ellipse()->getWidth(),
$this->ellipse()->getHeight(),
0,
359.99,
$this->getBorderColor()->toInt()
);
} else {
imagefilledellipse(
$frame->getCore(),
$this->position->getX(),
$this->position->getY(),
$this->ellipse()->getWidth(),
$this->ellipse()->getHeight(),
$this->getBackgroundColor()->toInt()
);
}
});
}
}
src/Drivers/Gd/Modifiers/DrawLineModifier.php 0000644 00000001424 15073164707 0015134 0 ustar 00 eachFrame(function ($frame) {
imageline(
$frame->getCore(),
$this->line()->getStart()->getX(),
$this->line()->getStart()->getY(),
$this->line()->getEnd()->getX(),
$this->line()->getEnd()->getY(),
$this->getBackgroundColor()->toInt()
);
});
}
}
src/Drivers/Gd/Modifiers/DrawPixelModifier.php 0000644 00000001516 15073164707 0015330 0 ustar 00 handleInput($this->color);
return $image->eachFrame(function ($frame) use ($color) {
imagesetpixel(
$frame->getCore(),
$this->position->getX(),
$this->position->getY(),
$color->toInt()
);
});
}
}
src/Drivers/Gd/Modifiers/DrawPolygonModifier.php 0000644 00000002405 15073164707 0015674 0 ustar 00 eachFrame(function ($frame) {
if ($this->polygon()->hasBackgroundColor()) {
imagefilledpolygon(
$frame->getCore(),
$this->polygon()->toArray(),
$this->getBackgroundColor()->toInt()
);
}
if ($this->polygon()->hasBorder()) {
imagesetthickness($frame->getCore(), $this->polygon()->getBorderSize());
imagepolygon(
$frame->getCore(),
$this->polygon()->toArray(),
$this->polygon()->count(),
$this->getBorderColor()->toInt()
);
}
});
}
}
src/Drivers/Gd/Modifiers/DrawRectangleModifier.php 0000644 00000003135 15073164707 0016152 0 ustar 00 eachFrame(function ($frame) {
// draw background
if ($this->rectangle()->hasBackgroundColor()) {
imagefilledrectangle(
$frame->getCore(),
$this->position->getX(),
$this->position->getY(),
$this->position->getX() + $this->rectangle()->bottomRightPoint()->getX(),
$this->position->getY() + $this->rectangle()->bottomRightPoint()->getY(),
$this->getBackgroundColor()->toInt()
);
}
if ($this->rectangle()->hasBorder()) {
// draw border
imagesetthickness($frame->getCore(), $this->rectangle()->getBorderSize());
imagerectangle(
$frame->getCore(),
$this->position->getX(),
$this->position->getY(),
$this->position->getX() + $this->rectangle()->bottomRightPoint()->getX(),
$this->position->getY() + $this->rectangle()->bottomRightPoint()->getY(),
$this->getBorderColor()->toInt()
);
}
});
return $image;
}
}
src/Drivers/Gd/Modifiers/FillModifier.php 0000644 00000002721 15073164707 0014316 0 ustar 00 hasPosition()) {
$this->floodFillWithColor($frame);
} else {
$this->fillAllWithColor($frame);
}
}
return $image;
}
protected function floodFillWithColor(Frame $frame): void
{
imagefill(
$frame->getCore(),
$this->position->getX(),
$this->position->getY(),
$this->color->toInt()
);
}
protected function fillAllWithColor(Frame $frame): void
{
imagealphablending($frame->getCore(), true);
imagefilledrectangle(
$frame->getCore(),
0,
0,
$frame->getSize()->getWidth() - 1,
$frame->getSize()->getHeight() - 1,
$this->color->toInt()
);
}
protected function hasPosition(): bool
{
return !empty($this->position);
}
}
src/Drivers/Gd/Modifiers/FitDownModifier.php 0000644 00000000456 15073164707 0015005 0 ustar 00 scaleDown($this->width, $this->height);
}
}
src/Drivers/Gd/Modifiers/FitModifier.php 0000644 00000005045 15073164707 0014154 0 ustar 00 getCropSize($image);
$resize = $this->getResizeSize($crop);
foreach ($image as $frame) {
$this->modifyFrame($frame, $crop, $resize);
}
return $image;
}
protected function modifyFrame(FrameInterface $frame, SizeInterface $crop, SizeInterface $resize): void
{
// create new image
$modified = imagecreatetruecolor(
$resize->getWidth(),
$resize->getHeight()
);
// get current image
$current = $frame->getCore();
// preserve transparency
imagealphablending($modified, false);
$transIndex = imagecolortransparent($current);
if ($transIndex != -1) {
$rgba = imagecolorsforindex($modified, $transIndex);
$transColor = imagecolorallocatealpha($modified, $rgba['red'], $rgba['green'], $rgba['blue'], 127);
imagefill($modified, 0, 0, $transColor);
} else {
imagesavealpha($modified, true);
}
// copy content from resource
imagecopyresampled(
$modified,
$current,
0,
0,
$crop->getPivot()->getX(),
$crop->getPivot()->getY(),
$resize->getWidth(),
$resize->getHeight(),
$crop->getWidth(),
$crop->getHeight()
);
imagedestroy($current);
if ($transIndex != -1) { // @todo refactor because of duplication
imagecolortransparent($modified, $transIndex);
for ($y = 0; $y < $resize->getHeight(); ++$y) {
for ($x = 0; $x < $resize->getWidth(); ++$x) {
if (((imagecolorat($modified, $x, $y) >> 24) & 0x7F) >= 100) {
imagesetpixel(
$modified,
$x,
$y,
$transIndex
);
}
}
}
}
// set new content as resource
$frame->setCore($modified);
}
}
src/Drivers/Gd/Modifiers/FlipModifier.php 0000644 00000000650 15073164707 0014321 0 ustar 00 getCore(), IMG_FLIP_VERTICAL);
}
return $image;
}
}
src/Drivers/Gd/Modifiers/FlopModifier.php 0000644 00000000652 15073164707 0014331 0 ustar 00 getCore(), IMG_FLIP_HORIZONTAL);
}
return $image;
}
}
src/Drivers/Gd/Modifiers/GammaModifier.php 0000644 00000000777 15073164707 0014463 0 ustar 00 getCore(), 1, $this->gamma);
}
return $image;
}
}
src/Drivers/Gd/Modifiers/GreyscaleModifier.php 0000644 00000000662 15073164707 0015350 0 ustar 00 getCore(), IMG_FILTER_GRAYSCALE);
}
return $image;
}
}
src/Drivers/Gd/Modifiers/InvertModifier.php 0000644 00000000654 15073164707 0014702 0 ustar 00 getCore(), IMG_FILTER_NEGATE);
}
return $image;
}
}
src/Drivers/Gd/Modifiers/PadDownModifier.php 0000644 00000001361 15073164707 0014763 0 ustar 00 getResizeSize($image);
return $image->getSize()
->contain($resize->getWidth(), $resize->getHeight())
->alignPivotTo($resize, $this->position);
}
protected function getResizeSize(ImageInterface $image): SizeInterface
{
return (new Rectangle($this->width, $this->height))
->resizeDown($image->getWidth(), $image->getHeight());
}
}
src/Drivers/Gd/Modifiers/PadModifier.php 0000644 00000003651 15073164707 0014137 0 ustar 00 getCropSize($image);
$resize = $this->getResizeSize($image);
$background = $this->handleInput($this->background);
foreach ($image as $frame) {
$this->modify($frame, $crop, $resize, $background);
}
return $image;
}
protected function modify(
FrameInterface $frame,
SizeInterface $crop,
SizeInterface $resize,
ColorInterface $background
): void {
// create new image
$modified = imagecreatetruecolor(
$resize->getWidth(),
$resize->getHeight()
);
imagefill($modified, 0, 0, $background->toInt());
// get current image
$current = $frame->getCore();
// preserve transparency
imagealphablending($modified, false);
imagesavealpha($modified, true);
// copy content from resource
imagecopyresampled(
$modified,
$current,
$crop->getPivot()->getX(),
$crop->getPivot()->getY(),
0,
0,
$crop->getWidth(),
$crop->getHeight(),
$frame->getSize()->getWidth(),
$frame->getSize()->getHeight()
);
imagedestroy($current);
// set new content as recource
$frame->setCore($modified);
}
}
src/Drivers/Gd/Modifiers/PixelateModifier.php 0000644 00000001102 15073164707 0015173 0 ustar 00 getCore(), IMG_FILTER_PIXELATE, $this->size, true);
}
return $image;
}
}
src/Drivers/Gd/Modifiers/PlaceModifier.php 0000644 00000003341 15073164707 0014453 0 ustar 00 decodeWatermark();
$position = $this->getPosition($image, $watermark);
foreach ($image as $frame) {
imagealphablending($frame->getCore(), true);
imagecopy(
$frame->getCore(),
$watermark->getFrame()->getCore(),
$position->getX(),
$position->getY(),
0,
0,
$watermark->getWidth(),
$watermark->getHeight()
);
}
return $image;
}
protected function decodeWatermark(): Image
{
return $this->resolveDriverClass('InputHandler')->handle($this->element);
}
protected function getPosition(ImageInterface $image, ImageInterface $watermark): PointInterface
{
$image_size = $image->getSize()->movePivot($this->position, $this->offset_x, $this->offset_y);
$watermark_size = $watermark->getSize()->movePivot($this->position);
return $image_size->getRelativePositionTo($watermark_size);
}
}
src/Drivers/Gd/Modifiers/RemoveAnimationModifier.php 0000644 00000001633 15073164707 0016526 0 ustar 00 isAnimated()) {
throw new RuntimeException('Image is not animated.');
}
$frames = new Collection();
foreach ($image as $key => $frame) {
if ($this->position == $key) {
$frames->push($frame);
} else {
imagedestroy($frame->getCore());
}
}
return new Image($frames);
}
}
src/Drivers/Gd/Modifiers/ResizeDownModifier.php 0000644 00000000567 15073164707 0015527 0 ustar 00 getSize()->resizeDown($this->width, $this->height);
}
}
src/Drivers/Gd/Modifiers/ResizeModifier.php 0000644 00000005310 15073164707 0014666 0 ustar 00 getAdjustedSize($image);
foreach ($image as $frame) {
$this->resizeFrame($frame, $resizeTo);
}
return $image;
}
protected function getAdjustedSize(ImageInterface $image): SizeInterface
{
return $image->getSize()->resize($this->width, $this->height);
}
protected function resizeFrame(FrameInterface $frame, SizeInterface $resizeTo): void
{
// create new image
$modified = imagecreatetruecolor(
$resizeTo->getWidth(),
$resizeTo->getHeight()
);
// get current image
$current = $frame->getCore();
// preserve transparency
imagealphablending($modified, false);
$transIndex = imagecolortransparent($current);
if ($transIndex != -1) {
$rgba = imagecolorsforindex($modified, $transIndex);
$transColor = imagecolorallocatealpha($modified, $rgba['red'], $rgba['green'], $rgba['blue'], 127);
imagefill($modified, 0, 0, $transColor);
} else {
imagesavealpha($modified, true);
}
// copy content from resource
imagecopyresampled(
$modified,
$current,
$resizeTo->getPivot()->getX(),
$resizeTo->getPivot()->getY(),
0,
0,
$resizeTo->getWidth(),
$resizeTo->getHeight(),
$frame->getSize()->getWidth(),
$frame->getSize()->getHeight()
);
imagedestroy($current);
if ($transIndex != -1) { // @todo refactor because of duplication
imagecolortransparent($modified, $transIndex);
for ($y = 0; $y < $resizeTo->getHeight(); ++$y) {
for ($x = 0; $x < $resizeTo->getWidth(); ++$x) {
if (((imagecolorat($modified, $x, $y) >> 24) & 0x7F) >= 100) {
imagesetpixel(
$modified,
$x,
$y,
$transIndex
);
}
}
}
}
// set new content as recource
$frame->setCore($modified);
}
}
src/Drivers/Gd/Modifiers/RotateModifier.php 0000644 00000001272 15073164707 0014666 0 ustar 00 setCore(
imagerotate(
$frame->getCore(),
$this->rotationAngle(),
$this->backgroundColor()->toInt()
)
);
}
return $image;
}
}
src/Drivers/Gd/Modifiers/ScaleDownModifier.php 0000644 00000000565 15073164707 0015313 0 ustar 00 getSize()->scaleDown($this->width, $this->height);
}
}
src/Drivers/Gd/Modifiers/ScaleModifier.php 0000644 00000000555 15073164707 0014462 0 ustar 00 getSize()->scale($this->width, $this->height);
}
}
src/Drivers/Gd/Modifiers/SharpenModifier.php 0000644 00000001550 15073164707 0015027 0 ustar 00 matrix();
foreach ($image as $frame) {
imageconvolution($frame->getCore(), $matrix, 1, 0);
}
return $image;
}
protected function matrix(): array
{
$min = $this->amount >= 10 ? $this->amount * -0.01 : 0;
$max = $this->amount * -0.025;
$abs = ((4 * $min + 4 * $max) * -1) + 1;
return [
[$min, $max, $min],
[$max, $abs, $max],
[$min, $max, $min]
];
}
}
src/Drivers/Gd/Modifiers/TextWriter.php 0000644 00000002730 15073164707 0014072 0 ustar 00 getAlignedTextBlock();
$font = $this->failIfNotClass($this->getFont(), Font::class);
foreach ($image as $frame) {
if ($this->font->hasFilename()) {
foreach ($lines as $line) {
imagettftext(
$frame->getCore(),
$font->getSize(),
$font->getAngle() * (-1),
$line->getPosition()->getX(),
$line->getPosition()->getY(),
$font->getColor()->toInt(),
$font->getFilename(),
$line
);
}
} else {
foreach ($lines as $line) {
imagestring(
$frame->getCore(),
$font->getGdFont(),
$line->getPosition()->getX(),
$line->getPosition()->getY(),
$line,
$this->font->getColor()->toInt()
);
}
}
}
return $image;
}
}
src/Drivers/Imagick/Color.php 0000644 00000002541 15073164707 0012120 0 ustar 00 pixel;
}
public function red(): int
{
return intval(round($this->pixel->getColorValue(Imagick::COLOR_RED) * 255));
}
public function green(): int
{
return intval(round($this->pixel->getColorValue(Imagick::COLOR_GREEN) * 255));
}
public function blue(): int
{
return intval(round($this->pixel->getColorValue(Imagick::COLOR_BLUE) * 255));
}
public function alpha(): float
{
return round($this->pixel->getColorValue(Imagick::COLOR_ALPHA), 2);
}
public function toArray(): array
{
return [
$this->red(),
$this->green(),
$this->blue(),
$this->alpha()
];
}
public function toInt(): int
{
$r = $this->red();
$g = $this->green();
$b = $this->blue();
$a = intval(round($this->alpha() * 255));
return intval(($a << 24) + ($r << 16) + ($g << 8) + $b);
}
}
src/Drivers/Imagick/Decoders/ArrayColorDecoder.php 0000644 00000001767 15073164707 0016146 0 ustar 00 isValidColorArray($input)) {
throw new DecoderException('Unable to decode input');
}
if (count($input) === 3) {
$input[] = 1;
}
list($r, $g, $b, $a) = $input;
$pixel = new ImagickPixel(
sprintf('rgba(%d, %d, %d, %.2F)', $r, $g, $b, $a)
);
return new Color($pixel);
}
}
src/Drivers/Imagick/Decoders/Base64ImageDecoder.php 0000644 00000001254 15073164707 0016047 0 ustar 00 isValidBase64($input)) {
throw new DecoderException('Unable to decode input');
}
return parent::decode(base64_decode($input));
}
}
src/Drivers/Imagick/Decoders/BinaryImageDecoder.php 0000644 00000002014 15073164707 0016242 0 ustar 00 inputType($input)->isBinary()) {
throw new DecoderException('Unable to decode input');
}
$imagick = new Imagick();
$imagick->readImageBlob($input);
$imagick = $imagick->coalesceImages();
$image = new Image($imagick);
$image->setLoops($imagick->getImageIterations());
return $image;
}
}
src/Drivers/Imagick/Decoders/DataUriImageDecoder.php 0000644 00000001657 15073164707 0016363 0 ustar 00 decodeDataUri($input);
if (! $uri->isValid()) {
throw new DecoderException('Unable to decode input');
}
if ($uri->isBase64Encoded()) {
return parent::decode(base64_decode($uri->data()));
}
return parent::decode(urldecode($uri->data()));
}
}
src/Drivers/Imagick/Decoders/FilePathImageDecoder.php 0000644 00000001537 15073164707 0016523 0 ustar 00 hexColorFromColorName($input);
if (empty($hexcolor)) {
throw new DecoderException('Unable to decode input');
}
return parent::decode($hexcolor);
}
}
src/Drivers/Imagick/Decoders/ImageObjectDecoder.php 0000644 00000001206 15073164707 0016226 0 ustar 00 getFrame()->getCore();
$imagick->setFormat($format);
$imagick->setImageFormat($format);
$imagick->setCompression($compression);
$imagick->setImageCompression($compression);
return new EncodedImage($imagick->getImagesBlob(), 'image/bmp');
}
}
src/Drivers/Imagick/Encoders/GifEncoder.php 0000644 00000002101 15073164707 0014601 0 ustar 00 getImagick();
$imagick->setFormat($format);
$imagick->setImageFormat($format);
$imagick->setCompression($compression);
$imagick->setImageCompression($compression);
$imagick = $imagick->deconstructImages();
return new EncodedImage($imagick->getImagesBlob(), 'image/gif');
}
}
src/Drivers/Imagick/Encoders/JpegEncoder.php 0000644 00000002150 15073164707 0014765 0 ustar 00 quality = $quality;
}
public function encode(ImageInterface $image): EncodedImage
{
$format = 'jpeg';
$compression = Imagick::COMPRESSION_JPEG;
$imagick = $image->getFrame()->getCore();
$imagick->setImageBackgroundColor('white');
$imagick->setBackgroundColor('white');
$imagick->setFormat($format);
$imagick->setImageFormat($format);
$imagick->setCompression($compression);
$imagick->setImageCompression($compression);
$imagick->setCompressionQuality($this->quality);
$imagick->setImageCompressionQuality($this->quality);
return new EncodedImage($imagick->getImagesBlob(), 'image/jpeg');
}
}
src/Drivers/Imagick/Encoders/PngEncoder.php 0000644 00000001454 15073164707 0014632 0 ustar 00 getFrame()->getCore();
$imagick->setFormat($format);
$imagick->setImageFormat($format);
$imagick->setCompression($compression);
$imagick->setImageCompression($compression);
return new EncodedImage($imagick->getImagesBlob(), 'image/png');
}
}
src/Drivers/Imagick/Encoders/WebpEncoder.php 0000644 00000002165 15073164707 0015003 0 ustar 00 quality = $quality;
}
public function encode(ImageInterface $image): EncodedImage
{
$format = 'webp';
$compression = Imagick::COMPRESSION_ZIP;
$imagick = $image->getFrame()->getCore();
$imagick->setImageBackgroundColor(new ImagickPixel('transparent'));
$imagick = $imagick->mergeImageLayers(Imagick::LAYERMETHOD_MERGE);
$imagick->setFormat($format);
$imagick->setImageFormat($format);
$imagick->setCompression($compression);
$imagick->setImageCompression($compression);
$imagick->setImageCompressionQuality($this->quality);
return new EncodedImage($imagick->getImagesBlob(), 'image/webp');
}
}
src/Drivers/Imagick/Font.php 0000644 00000002776 15073164707 0011762 0 ustar 00 hasFilename()) {
throw new FontException('No font file specified.');
}
$color = $this->failIfNotClass($this->getColor(), Color::class);
$draw = new ImagickDraw();
$draw->setStrokeAntialias(true);
$draw->setTextAntialias(true);
$draw->setFont($this->getFilename());
$draw->setFontSize($this->getSize());
$draw->setFillColor($color->getPixel());
$draw->setTextAlignment(Imagick::ALIGN_LEFT);
return $draw;
}
/**
* Calculate box size of current font
*
* @return Polygon
*/
public function getBoxSize(string $text): Polygon
{
// no text - no box size
if (mb_strlen($text) === 0) {
return (new Rectangle(0, 0));
}
$draw = $this->toImagickDraw();
$draw->setStrokeAntialias(true);
$draw->setTextAntialias(true);
$dimensions = (new Imagick())->queryFontMetrics($draw, $text);
return (new Rectangle(
intval(round($dimensions['textWidth'])),
intval(round($dimensions['ascender'] + $dimensions['descender'])),
));
}
}
src/Drivers/Imagick/Frame.php 0000644 00000004116 15073164707 0012074 0 ustar 00 core = $core;
return $this;
}
public function getCore(): Imagick
{
return $this->core;
}
public function getSize(): SizeInterface
{
return new Rectangle(
$this->core->getImageWidth(),
$this->core->getImageHeight()
);
}
public function getDelay(): float
{
return $this->core->getImageDelay() / 100;
}
public function setDelay(float $delay): FrameInterface
{
$this->core->setImageDelay(intval(round($delay * 100)));
return $this;
}
public function getDispose(): int
{
return $this->core->getImageDispose();
}
public function setDispose(int $dispose): FrameInterface
{
$this->core->setImageDispose($dispose);
return $this;
}
public function setOffset(int $left, int $top): FrameInterface
{
$this->core->setImagePage(
$this->core->getImageWidth(),
$this->core->getImageHeight(),
$left,
$top
);
return $this;
}
public function getOffsetLeft(): int
{
return $this->core->getImagePage()['x'];
}
public function setOffsetLeft(int $offset): FrameInterface
{
return $this->setOffset($offset, $this->getOffsetTop());
}
public function getOffsetTop(): int
{
return $this->core->getImagePage()['y'];
}
public function setOffsetTop(int $offset): FrameInterface
{
return $this->setOffset($this->getOffsetLeft(), $offset);
}
public function toImage(): ImageInterface
{
return new Image($this->getCore());
}
}
src/Drivers/Imagick/Image.php 0000644 00000005611 15073164707 0012065 0 ustar 00 imagick;
}
public function getFrame(int $position = 0): ?FrameInterface
{
foreach ($this->imagick as $core) {
if ($core->getIteratorIndex() == $position) {
return new Frame($core);
}
}
return null;
}
public function addFrame(FrameInterface $frame): ImageInterface
{
$imagick = $frame->getCore();
$imagick->setImageDelay($frame->getDelay());
$imagick->setImageDispose($frame->getDispose());
$size = $frame->getSize();
$imagick->setImagePage(
$size->getWidth(),
$size->getHeight(),
$frame->getOffsetLeft(),
$frame->getOffsetTop()
);
$this->imagick->addImage($imagick);
return $this;
}
public function setLoops(int $count): ImageInterface
{
$this->imagick->setImageIterations($count);
return $this;
}
public function getLoops(): int
{
return $this->imagick->getImageIterations();
}
public function isAnimated(): bool
{
return $this->count() > 1;
}
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 key(): mixed
{
return $this->iteratorIndex;
}
public function next(): void
{
$this->iteratorIndex = $this->iteratorIndex + 1;
}
public function rewind(): void
{
$this->iteratorIndex = 0;
}
public function valid(): bool
{
try {
$result = $this->imagick->setIteratorIndex($this->iteratorIndex);
} catch (ImagickException $e) {
return false;
}
return $result;
}
public function getWidth(): int
{
return $this->getFrame()->getCore()->getImageWidth();
}
public function getHeight(): int
{
return $this->getFrame()->getCore()->getImageHeight();
}
public function pickColor(int $x, int $y, int $frame_key = 0): ?ColorInterface
{
if ($frame = $this->getFrame($frame_key)) {
return new Color($frame->getCore()->getImagePixelColor($x, $y));
}
return null;
}
}
src/Drivers/Imagick/ImageFactory.php 0000644 00000001407 15073164707 0013414 0 ustar 00 newCore($width, $height));
}
public function newCore(int $width, int $height)
{
$imagick = new Imagick();
$imagick->newImage($width, $height, new ImagickPixel('rgba(0, 0, 0, 0)'), 'png');
$imagick->setType(Imagick::IMGTYPE_UNDEFINED);
$imagick->setImageType(Imagick::IMGTYPE_UNDEFINED);
$imagick->setColorspace(Imagick::COLORSPACE_UNDEFINED);
return $imagick;
}
}
src/Drivers/Imagick/InputHandler.php 0000644 00000001214 15073164707 0013433 0 ustar 00 getCore()->blurImage(1 * $this->amount, 0.5 * $this->amount);
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/BrightnessModifier.php 0000644 00000001020 15073164707 0016541 0 ustar 00 getCore()->modulateImage(100 + $this->level, 100, 100);
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/ContrastModifier.php 0000644 00000001045 15073164707 0016235 0 ustar 00 getCore()->sigmoidalContrastImage($this->level > 0, abs($this->level / 4), 0);
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/DestroyModifier.php 0000644 00000000633 15073164707 0016073 0 ustar 00 getCore()->clear();
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/DrawEllipseModifier.php 0000644 00000002562 15073164707 0016660 0 ustar 00 failIfNotClass($this->getBackgroundColor(), Color::class);
$border_color = $this->failIfNotClass($this->getBorderColor(), Color::class);
return $image->eachFrame(function ($frame) use ($background_color, $border_color) {
$drawing = new ImagickDraw();
$drawing->setFillColor($background_color->getPixel());
if ($this->ellipse()->hasBorder()) {
$drawing->setStrokeWidth($this->ellipse()->getBorderSize());
$drawing->setStrokeColor($border_color->getPixel());
}
$drawing->ellipse(
$this->position->getX(),
$this->position->getY(),
$this->ellipse()->getWidth() / 2,
$this->ellipse()->getHeight() / 2,
0,
360
);
$frame->getCore()->drawImage($drawing);
});
}
}
src/Drivers/Imagick/Modifiers/DrawLineModifier.php 0000644 00000002035 15073164707 0016145 0 ustar 00 failIfNotClass($this->getBackgroundColor(), Color::class);
$drawing->setStrokeColor($color->getPixel());
$drawing->setStrokeWidth($this->line()->getWidth());
$drawing->line(
$this->line()->getStart()->getX(),
$this->line()->getStart()->getY(),
$this->line()->getEnd()->getX(),
$this->line()->getEnd()->getY(),
);
return $image->eachFrame(function ($frame) use ($drawing) {
$frame->getCore()->drawImage($drawing);
});
}
}
src/Drivers/Imagick/Modifiers/DrawPixelModifier.php 0000644 00000002044 15073164707 0016337 0 ustar 00 failIfNotClass(
$this->handleInput($this->color),
Color::class,
);
$pixel = new ImagickDraw();
$pixel->setFillColor($color->getPixel());
$pixel->point($this->position->getX(), $this->position->getY());
return $image->eachFrame(function ($frame) use ($pixel) {
$frame->getCore()->drawImage($pixel);
});
}
}
src/Drivers/Imagick/Modifiers/DrawPolygonModifier.php 0000644 00000003046 15073164707 0016710 0 ustar 00 failIfNotClass($this->getBackgroundColor(), Color::class);
$border_color = $this->failIfNotClass($this->getBorderColor(), Color::class);
if ($this->polygon()->hasBackgroundColor()) {
$drawing->setFillColor($background_color->getPixel());
}
if ($this->polygon()->hasBorder()) {
$drawing->setStrokeColor($border_color->getPixel());
$drawing->setStrokeWidth($this->polygon()->getBorderSize());
}
$drawing->polygon($this->points());
return $image->eachFrame(function ($frame) use ($drawing) {
$frame->getCore()->drawImage($drawing);
});
}
private function points(): array
{
$points = [];
foreach ($this->polygon() as $point) {
$points[] = ['x' => $point->getX(), 'y' => $point->getY()];
}
return $points;
}
}
src/Drivers/Imagick/Modifiers/DrawRectangleModifier.php 0000644 00000002625 15073164707 0017167 0 ustar 00 failIfNotClass($this->getBackgroundColor(), Color::class);
$border_color = $this->failIfNotClass($this->getBorderColor(), Color::class);
$drawing->setFillColor($background_color->getPixel());
if ($this->rectangle()->hasBorder()) {
$drawing->setStrokeColor($border_color->getPixel());
$drawing->setStrokeWidth($this->rectangle()->getBorderSize());
}
// build rectangle
$drawing->rectangle(
$this->position->getX(),
$this->position->getY(),
$this->position->getX() + $this->rectangle()->bottomRightPoint()->getX(),
$this->position->getY() + $this->rectangle()->bottomRightPoint()->getY()
);
$image->eachFrame(function ($frame) use ($drawing) {
$frame->getCore()->drawImage($drawing);
});
return $image;
}
}
src/Drivers/Imagick/Modifiers/FillModifier.php 0000644 00000003366 15073164707 0015336 0 ustar 00 hasPosition()) {
$this->floodFillWithColor($frame);
} else {
$this->fillAllWithColor($frame);
}
}
return $image;
}
protected function floodFillWithColor(Frame $frame): void
{
$target = $frame->getCore()->getImagePixelColor(
$this->position->getX(),
$this->position->getY()
);
$frame->getCore()->floodfillPaintImage(
$this->color->getPixel(),
100,
$target,
$this->position->getX(),
$this->position->getY(),
false,
Imagick::CHANNEL_ALL
);
}
protected function fillAllWithColor(Frame $frame): void
{
$draw = new ImagickDraw();
$draw->setFillColor($this->color->getPixel());
$draw->rectangle(
0,
0,
$frame->getCore()->getImageWidth(),
$frame->getCore()->getImageHeight()
);
$frame->getCore()->drawImage($draw);
}
protected function hasPosition(): bool
{
return !empty($this->position);
}
}
src/Drivers/Imagick/Modifiers/FitDownModifier.php 0000644 00000000463 15073164707 0016015 0 ustar 00 scaleDown($this->width, $this->height);
}
}
src/Drivers/Imagick/Modifiers/FitModifier.php 0000644 00000001612 15073164707 0015162 0 ustar 00 getCropSize($image);
$resize = $this->getResizeSize($crop);
foreach ($image as $frame) {
$frame->getCore()->extentImage(
$crop->getWidth(),
$crop->getHeight(),
$crop->getPivot()->getX(),
$crop->getPivot()->getY()
);
$frame->getCore()->scaleImage(
$resize->getWidth(),
$resize->getHeight()
);
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/FlipModifier.php 0000644 00000000634 15073164707 0015335 0 ustar 00 getCore()->flipImage();
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/FlopModifier.php 0000644 00000000634 15073164707 0015343 0 ustar 00 getCore()->flopImage();
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/GammaModifier.php 0000644 00000000772 15073164707 0015470 0 ustar 00 getCore()->gammaImage($this->gamma);
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/GreyscaleModifier.php 0000644 00000000660 15073164707 0016360 0 ustar 00 getCore()->modulateImage(100, 0, 100);
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/InvertModifier.php 0000644 00000000645 15073164707 0015714 0 ustar 00 getCore()->negateImage(false);
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/PadDownModifier.php 0000644 00000001366 15073164707 0016002 0 ustar 00 getResizeSize($image);
return $image->getSize()
->contain($resize->getWidth(), $resize->getHeight())
->alignPivotTo($resize, $this->position);
}
protected function getResizeSize(ImageInterface $image): SizeInterface
{
return (new Rectangle($this->width, $this->height))
->resizeDown($image->getWidth(), $image->getHeight());
}
}
src/Drivers/Imagick/Modifiers/PadModifier.php 0000644 00000005344 15073164707 0015152 0 ustar 00 getResizeSize($image);
$crop = $this->getCropSize($image);
$background = $this->failIfNotClass($this->handleInput($this->background), Color::class);
foreach ($image as $frame) {
// resize current core
$frame->getCore()->scaleImage(
$crop->getWidth(),
$crop->getHeight()
);
// create new canvas, to get newly emerged background color
$canvas = $this->buildBaseCanvas($crop, $resize, $background);
// place current core onto canvas
$canvas->compositeImage(
$frame->getCore(),
Imagick::COMPOSITE_DEFAULT,
$crop->getPivot()->getX(),
$crop->getPivot()->getY()
);
// replace core
$frame->getCore()->destroy();
$frame->setCore($canvas);
}
return $image;
}
protected function buildBaseCanvas(SizeInterface $crop, SizeInterface $resize, Color $background): Imagick
{
// build base canvas in target size
$canvas = $this->imageFactory()->newCore(
$resize->getWidth(),
$resize->getHeight()
);
// draw background color on canvas
$draw = new ImagickDraw();
$draw->setFillColor($background->getPixel());
$draw->rectangle(0, 0, $canvas->getImageWidth(), $canvas->getImageHeight());
$canvas->drawImage($draw);
// make area where image is placed transparent to keep
// transparency even if background-color is set
$draw = new ImagickDraw();
$fill = $background->toHex('#') == '#ff0000' ? '#00ff00' : '#ff0000';
$draw->setFillColor($fill);
$draw->rectangle(
$crop->getPivot()->getX(),
$crop->getPivot()->getY(),
$crop->getPivot()->getX() + $crop->getWidth() - 1,
$crop->getPivot()->getY() + $crop->getHeight() - 1
);
$canvas->drawImage($draw);
$canvas->transparentPaintImage($fill, 0, 0, false);
return $canvas;
}
}
src/Drivers/Imagick/Modifiers/PixelateModifier.php 0000644 00000001562 15073164707 0016217 0 ustar 00 pixelateFrame($frame);
}
return $image;
}
protected function pixelateFrame(Frame $frame): void
{
$size = $frame->getSize();
$frame->getCore()->scaleImage(
max(1, ($size->getWidth() / $this->size)),
max(1, ($size->getHeight() / $this->size))
);
$frame->getCore()->scaleImage($size->getWidth(), $size->getHeight());
}
}
src/Drivers/Imagick/Modifiers/PlaceModifier.php 0000644 00000003125 15073164707 0015465 0 ustar 00 decodeWatermark();
$position = $this->getPosition($image, $watermark);
foreach ($image as $frame) {
$frame->getCore()->compositeImage(
$watermark->getFrame()->getCore(),
Imagick::COMPOSITE_DEFAULT,
$position->getX(),
$position->getY()
);
}
return $image;
}
protected function decodeWatermark(): Image
{
return $this->resolveDriverClass('InputHandler')->handle($this->element);
}
protected function getPosition(ImageInterface $image, Image $watermark): PointInterface
{
$image_size = $image->getSize()->movePivot($this->position, $this->offset_x, $this->offset_y);
$watermark_size = $watermark->getSize()->movePivot($this->position);
return $image_size->getRelativePositionTo($watermark_size);
}
}
src/Drivers/Imagick/Modifiers/RemoveAnimationModifier.php 0000644 00000001631 15073164707 0017536 0 ustar 00 isAnimated()) {
throw new RuntimeException('Image is not animated.');
}
$imagick = new Imagick();
foreach ($image as $frame) {
if ($frame->getCore()->getIteratorIndex() == $this->position) {
$imagick->addImage($frame->getCore()->getImage());
}
}
$image->destroy();
return new Image($imagick);
}
}
src/Drivers/Imagick/Modifiers/ResizeDownModifier.php 0000644 00000000574 15073164707 0016537 0 ustar 00 getSize()->resizeDown($this->width, $this->height);
}
}
src/Drivers/Imagick/Modifiers/ResizeModifier.php 0000644 00000001566 15073164707 0015711 0 ustar 00 getAdjustedSize($image);
foreach ($image as $frame) {
$frame->getCore()->scaleImage(
$resizeTo->getWidth(),
$resizeTo->getHeight()
);
}
return $image;
}
protected function getAdjustedSize(ImageInterface $image): SizeInterface
{
return $image->getSize()->resize($this->width, $this->height);
}
}
src/Drivers/Imagick/Modifiers/RotateModifier.php 0000644 00000001522 15073164707 0015676 0 ustar 00 failIfNotClass($this->backgroundColor(), Color::class);
foreach ($image as $frame) {
$frame->getCore()->rotateImage(
$background->getPixel(),
$this->rotationAngle()
);
}
return $image;
}
protected function rotationAngle(): float
{
return parent::rotationAngle() * -1;
}
}
src/Drivers/Imagick/Modifiers/ScaleDownModifier.php 0000644 00000000572 15073164707 0016323 0 ustar 00 getSize()->scaleDown($this->width, $this->height);
}
}
src/Drivers/Imagick/Modifiers/ScaleModifier.php 0000644 00000000562 15073164707 0015472 0 ustar 00 getSize()->scale($this->width, $this->height);
}
}
src/Drivers/Imagick/Modifiers/SharpenModifier.php 0000644 00000001022 15073164707 0016033 0 ustar 00 getCore()->unsharpMaskImage(1, 1, $this->amount / 6.25, 0);
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/TextWriter.php 0000644 00000001542 15073164707 0015104 0 ustar 00 getAlignedTextBlock();
$font = $this->failIfNotClass($this->getFont(), Font::class);
foreach ($image as $frame) {
foreach ($lines as $line) {
$frame->getCore()->annotateImage(
$font->toImagickDraw(),
$line->getPosition()->getX(),
$line->getPosition()->getY(),
$font->getAngle(),
$line
);
}
}
return $image;
}
}
src/EncodedImage.php 0000644 00000001676 15073164707 0010374 0 ustar 00 mimetype;
}
public function save(string $filepath): void
{
$saved = @file_put_contents($filepath, (string) $this);
if ($saved === false) {
throw new NotWritableException(
"Can't write image data to path ({$filepath})."
);
}
}
public function toDataUri(): string
{
return sprintf('data:%s;base64,%s', $this->mimetype, base64_encode($this->data));
}
public function toString(): string
{
return $this->data;
}
public function __toString(): string
{
return $this->toString();
}
}
src/Exceptions/DecoderException.php 0000644 00000000155 15073164707 0013424 0 ustar 00 setWidth($diameter);
$this->setHeight($diameter);
$this->pivot = $pivot ? $pivot : new Point();
}
public function diameter(int $diameter): self
{
return $this->setDiameter($diameter);
}
public function setDiameter(int $diameter): self
{
$this->setWidth($diameter);
$this->setHeight($diameter);
return $this;
}
public function getDiameter(): int
{
return $this->diameter;
}
public function radius(int $radius): self
{
return $this->setRadius($radius);
}
public function setRadius(int $radius): self
{
return $this->diameter(intval($radius * 2));
}
public function getRadius(): int
{
return intval($this->diameter / 2);
}
}
src/Geometry/Ellipse.php 0000644 00000002171 15073164707 0011247 0 ustar 00 pivot = $pivot ? $pivot : new Point();
}
public function size(int $width, int $height): self
{
return $this->setSize($width, $height);
}
public function setSize(int $width, int $height): self
{
return $this->setWidth($width)->setHeight($height);
}
public function setWidth(int $width): self
{
$this->width = $width;
return $this;
}
public function setHeight(int $height): self
{
$this->height = $height;
return $this;
}
public function getWidth(): int
{
return $this->width;
}
public function getHeight(): int
{
return $this->height;
}
}
src/Geometry/Line.php 0000644 00000003017 15073164707 0010541 0 ustar 00 width;
}
public function setWidth(int $width): self
{
$this->width = $width;
return $this;
}
public function width(int $width): self
{
return $this->setWidth($width);
}
public function color($color): self
{
$this->setBackgroundColor($color);
return $this;
}
public function getStart(): Point
{
return $this->start;
}
public function getEnd(): Point
{
return $this->end;
}
public function setStart(Point $start): self
{
$this->start = $start;
return $this;
}
public function from(int $x, int $y): self
{
$this->getStart()->setX($x);
$this->getStart()->setY($y);
return $this;
}
public function to(int $x, int $y): self
{
$this->getEnd()->setX($x);
$this->getEnd()->setY($y);
return $this;
}
public function setEnd(Point $end): self
{
$this->end = $end;
return $this;
}
}
src/Geometry/Pixel.php 0000644 00000001015 15073164707 0010727 0 ustar 00 background = $background;
return $this;
}
public function background(): ColorInterface
{
return $this->background;
}
}
src/Geometry/Point.php 0000644 00000004144 15073164707 0010745 0 ustar 00 x = $x;
return $this;
}
/**
* Get X coordinate
*
* @return integer
*/
public function getX(): int
{
return $this->x;
}
/**
* Sets Y coordinate
*
* @param integer $y
*/
public function setY(int $y): self
{
$this->y = $y;
return $this;
}
/**
* Get Y coordinate
*
* @return integer
*/
public function getY(): int
{
return $this->y;
}
/**
* Move X coordinate
*
* @param integer $value
*/
public function moveX(int $value): self
{
$this->x += $value;
return $this;
}
/**
* Move Y coordinate
*
* @param integer $value
*/
public function moveY(int $value): self
{
$this->y += $value;
return $this;
}
public function move(int $x, int $y): self
{
return $this->moveX($x)->moveY($y);
}
/**
* Sets both X and Y coordinate
*
* @param integer $x
* @param integer $y
* @return Point
*/
public function setPosition(int $x, int $y): self
{
$this->setX($x);
$this->setY($y);
return $this;
}
/**
* Rotate point ccw around pivot
*
* @param float $angle
* @param Point $pivot
* @return Point
*/
public function rotate(float $angle, Point $pivot): self
{
$sin = round(sin(deg2rad($angle)), 6);
$cos = round(cos(deg2rad($angle)), 6);
return $this->setPosition(
intval($cos * ($this->x - $pivot->x) - $sin * ($this->y - $pivot->y) + $pivot->x),
intval($sin * ($this->x - $pivot->x) + $cos * ($this->y - $pivot->y) + $pivot->y)
);
}
}
src/Geometry/Polygon.php 0000644 00000022534 15073164707 0011306 0 ustar 00 pivot = $pivot ? $pivot : new Point();
}
public function getIterator(): Traversable
{
return new ArrayIterator($this->points);
}
/**
* Return current pivot point
*
* @return Point
*/
public function getPivot(): Point
{
return $this->pivot;
}
/**
* Change pivot point to given point
*
* @param Point $pivot
* @return Polygon
*/
public function setPivot(Point $pivot): self
{
$this->pivot = $pivot;
return $this;
}
/**
* Return first point of polygon
*
* @return ?Point
*/
public function first(): ?Point
{
if ($point = reset($this->points)) {
return $point;
}
return null;
}
/**
* Return last point of polygon
*
* @return ?Point
*/
public function last(): ?Point
{
if ($point = end($this->points)) {
return $point;
}
return null;
}
/**
* Return polygon's point count
*
* @return int
*/
public function count(): int
{
return count($this->points);
}
/**
* Determine if point exists at given offset
*
* @param mixed $offset
* @return bool
*/
public function offsetExists($offset): bool
{
return array_key_exists($offset, $this->points);
}
/**
* Return point at given offset
*
* @param mixed $offset
* @return Point
*/
public function offsetGet($offset): mixed
{
return $this->points[$offset];
}
/**
* Set point at given offset
*
* @param mixed $offset
* @param Point $value
* @return void
*/
public function offsetSet($offset, $value): void
{
$this->points[$offset] = $value;
}
/**
* Unset offset at given offset
*
* @param mixed $offset
* @return void
*/
public function offsetUnset($offset): void
{
unset($this->points[$offset]);
}
/**
* Add given point to polygon
*
* @param Point $point
* @return Polygon
*/
public function addPoint(Point $point): self
{
$this->points[] = $point;
return $this;
}
public function point(int $x, int $y): self
{
$this->addPoint(new Point($x, $y));
return $this;
}
/**
* Calculate total horizontal span of polygon
*
* @return int
*/
public function getWidth(): int
{
return abs($this->getMostLeftPoint()->getX() - $this->getMostRightPoint()->getX());
}
/**
* Calculate total vertical span of polygon
*
* @return int
*/
public function getHeight(): int
{
return abs($this->getMostBottomPoint()->getY() - $this->getMostTopPoint()->getY());
}
/**
* Return most left point of all points in polygon
*
* @return Point
*/
public function getMostLeftPoint(): Point
{
$points = [];
foreach ($this->points as $point) {
$points[] = $point;
}
usort($points, function ($a, $b) {
if ($a->getX() === $b->getX()) {
return 0;
}
return ($a->getX() < $b->getX()) ? -1 : 1;
});
return $points[0];
}
/**
* Return most right point in polygon
*
* @return Point
*/
public function getMostRightPoint(): Point
{
$points = [];
foreach ($this->points as $point) {
$points[] = $point;
}
usort($points, function ($a, $b) {
if ($a->getX() === $b->getX()) {
return 0;
}
return ($a->getX() > $b->getX()) ? -1 : 1;
});
return $points[0];
}
/**
* Return most top point in polygon
*
* @return Point
*/
public function getMostTopPoint(): Point
{
$points = [];
foreach ($this->points as $point) {
$points[] = $point;
}
usort($points, function ($a, $b) {
if ($a->getY() === $b->getY()) {
return 0;
}
return ($a->getY() > $b->getY()) ? -1 : 1;
});
return $points[0];
}
/**
* Return most bottom point in polygon
*
* @return Point
*/
public function getMostBottomPoint(): Point
{
$points = [];
foreach ($this->points as $point) {
$points[] = $point;
}
usort($points, function ($a, $b) {
if ($a->getY() === $b->getY()) {
return 0;
}
return ($a->getY() < $b->getY()) ? -1 : 1;
});
return $points[0];
}
/**
* Create and return point in absolute center of the polygon
*
* @return Point
*/
public function getCenterPoint(): Point
{
return new Point(
$this->getMostRightPoint()->getX() - (intval(round($this->getWidth() / 2))),
$this->getMostTopPoint()->getY() - (intval(round($this->getHeight() / 2)))
);
}
/**
* Align all points of polygon horizontally to given position around pivot point
*
* @param string $position
* @return Polygon
*/
public function align(string $position): self
{
switch (strtolower($position)) {
case 'center':
case 'middle':
$diff = ($this->getCenterPoint()->getX() - $this->getPivot()->getX());
break;
case 'right':
$diff = ($this->getMostRightPoint()->getX() - $this->getPivot()->getX());
break;
default:
case 'left':
$diff = ($this->getMostLeftPoint()->getX() - $this->getPivot()->getX());
break;
}
foreach ($this->points as $point) {
$point->setX(
intval($point->getX() - $diff)
);
}
return $this;
}
/**
* Align all points of polygon vertically to given position around pivot point
*
* @param string $position
* @return Polygon
*/
public function valign(string $position): self
{
switch (strtolower($position)) {
case 'center':
case 'middle':
$diff = ($this->getCenterPoint()->getY() - $this->getPivot()->getY());
break;
case 'top':
$diff = ($this->getMostTopPoint()->getY() - $this->getPivot()->getY()) - $this->getHeight();
break;
default:
case 'bottom':
$diff = ($this->getMostBottomPoint()->getY() - $this->getPivot()->getY()) + $this->getHeight();
break;
}
foreach ($this->points as $point) {
$point->setY(
intval($point->getY() - $diff),
);
}
return $this;
}
/**
* Rotate points of polygon around pivot point with given angle
*
* @param float $angle
* @return Polygon
*/
public function rotate(float $angle): self
{
$sin = sin(deg2rad($angle));
$cos = cos(deg2rad($angle));
foreach ($this->points as $point) {
// translate point to pivot
$point->setX(
intval($point->getX() - $this->getPivot()->getX()),
);
$point->setY(
intval($point->getY() - $this->getPivot()->getY()),
);
// rotate point
$x = $point->getX() * $cos - $point->getY() * $sin;
$y = $point->getX() * $sin + $point->getY() * $cos;
// translate point back
$point->setX(
intval($x + $this->getPivot()->getX()),
);
$point->setY(
intval($y + $this->getPivot()->getY()),
);
}
return $this;
}
/**
* Move all points by given amount on the x-axis
*
* @param int $amount
* @return Polygon
*/
public function movePointsX(int $amount): self
{
foreach ($this->points as $point) {
$point->moveX($amount);
}
return $this;
}
/**
* Move all points by given amount on the y-axis
*
* @param int $amount
* @return Polygon
*/
public function movePointsY(int $amount): self
{
foreach ($this->points as $point) {
$point->moveY($amount);
}
return $this;
}
/**
* Return array of all x/y values of all points of polygon
*
* @return array
*/
public function toArray(): array
{
$coordinates = [];
foreach ($this->points as $point) {
$coordinates[] = $point->getX();
$coordinates[] = $point->getY();
}
return $coordinates;
}
}
src/Geometry/Rectangle.php 0000644 00000016605 15073164707 0011565 0 ustar 00 pivot = $pivot ? $pivot : new Point();
$this->addPoint(new Point($this->pivot->getX(), $this->pivot->getY()));
$this->addPoint(new Point($this->pivot->getX() + $width, $this->pivot->getY()));
$this->addPoint(new Point($this->pivot->getX() + $width, $this->pivot->getY() - $height));
$this->addPoint(new Point($this->pivot->getX(), $this->pivot->getY() - $height));
}
/**
* Set the rectangle dimensions to given width & height
*
* @param int $width
* @param int $height
* @return Rectangle
*/
public function setSize(int $width, int $height): self
{
return $this->setWidth($width)->setHeight($height);
}
/**
* Alias of self::setSize()
*/
public function size(int $width, int $height): self
{
return $this->setSize($width, $height);
}
public function setWidth(int $width): self
{
$this[1]->setX($this[0]->getX() + $width);
$this[2]->setX($this[3]->getX() + $width);
return $this;
}
public function setHeight(int $height): self
{
$this[2]->setY($this[1]->getY() + $height);
$this[3]->setY($this[0]->getY() + $height);
return $this;
}
public function getPivot(): Point
{
return $this->pivot;
}
public function setPivot(PointInterface $pivot): self
{
$this->pivot = $pivot;
return $this;
}
/**
* Move current pivot of current rectangle to given position
* and moves point automatically by offset.
*
* @param string $position
* @param int $offset_x
* @param int $offset_y
* @return Rectangle
*/
public function movePivot(string $position, int $offset_x = 0, int $offset_y = 0): self
{
switch (strtolower($position)) {
case 'top':
case 'top-center':
case 'top-middle':
case 'center-top':
case 'middle-top':
$x = intval($this->getWidth() / 2);
$y = 0 + $offset_y;
break;
case 'top-right':
case 'right-top':
$x = $this->getWidth() - $offset_x;
$y = 0 + $offset_y;
break;
case 'left':
case 'left-center':
case 'left-middle':
case 'center-left':
case 'middle-left':
$x = 0 + $offset_x;
$y = intval($this->getHeight() / 2);
break;
case 'right':
case 'right-center':
case 'right-middle':
case 'center-right':
case 'middle-right':
$x = $this->getWidth() - $offset_x;
$y = intval($this->getHeight() / 2);
break;
case 'bottom-left':
case 'left-bottom':
$x = 0 + $offset_x;
$y = $this->getHeight() - $offset_y;
break;
case 'bottom':
case 'bottom-center':
case 'bottom-middle':
case 'center-bottom':
case 'middle-bottom':
$x = intval($this->getWidth() / 2);
$y = $this->getHeight() - $offset_y;
break;
case 'bottom-right':
case 'right-bottom':
$x = $this->getWidth() - $offset_x;
$y = $this->getHeight() - $offset_y;
break;
case 'center':
case 'middle':
case 'center-center':
case 'middle-middle':
$x = intval($this->getWidth() / 2) + $offset_x;
$y = intval($this->getHeight() / 2) + $offset_y;
break;
default:
case 'top-left':
case 'left-top':
$x = 0 + $offset_x;
$y = 0 + $offset_y;
break;
}
$this->pivot->setPosition($x, $y);
return $this;
}
public function alignPivotTo(SizeInterface $size, string $position): self
{
$reference = new self($size->getWidth(), $size->getHeight());
$reference->movePivot($position);
$this->movePivot($position)->setPivot(
$reference->getRelativePositionTo($this)
);
return $this;
}
/**
* Calculate the relative position to another Size
* based on the pivot point settings of both sizes.
*
* @param SizeInterface $rectangle
* @return PointInterface
*/
public function getRelativePositionTo(SizeInterface $rectangle): PointInterface
{
return new Point(
$this->getPivot()->getX() - $rectangle->getPivot()->getX(),
$this->getPivot()->getY() - $rectangle->getPivot()->getY()
);
}
public function getAspectRatio(): float
{
return $this->getWidth() / $this->getHeight();
}
public function fitsInto(SizeInterface $size): bool
{
if ($this->getWidth() > $size->getWidth()) {
return false;
}
if ($this->getHeight() > $size->getHeight()) {
return false;
}
return true;
}
/**
* Determine if size is landscape format
*
* @return boolean
*/
public function isLandscape(): bool
{
return $this->getWidth() > $this->getHeight();
}
/**
* Determine if size is portrait format
*
* @return boolean
*/
public function isPortrait(): bool
{
return $this->getWidth() < $this->getHeight();
}
public function topLeftPoint(): PointInterface
{
return $this->points[0];
}
public function bottomRightPoint(): PointInterface
{
return $this->points[2];
}
protected function getResizer(?int $width = null, ?int $height = null): RectangleResizer
{
return new RectangleResizer($width, $height);
}
public function resize(?int $width = null, ?int $height = null): SizeInterface
{
return $this->getResizer($width, $height)->resize($this);
}
public function resizeDown(?int $width = null, ?int $height = null): SizeInterface
{
return $this->getResizer($width, $height)->resizeDown($this);
}
public function scale(?int $width = null, ?int $height = null): SizeInterface
{
return $this->getResizer($width, $height)->scale($this);
}
public function scaleDown(?int $width = null, ?int $height = null): SizeInterface
{
return $this->getResizer($width, $height)->scaleDown($this);
}
public function cover(int $width, int $height): SizeInterface
{
return $this->getResizer($width, $height)->cover($this);
}
public function contain(int $width, int $height): SizeInterface
{
return $this->getResizer($width, $height)->contain($this);
}
}
src/Geometry/Tools/RectangleResizer.php 0000644 00000015407 15073164707 0014230 0 ustar 00 width);
}
protected function getTargetWidth(): ?int
{
return $this->hasTargetWidth() ? $this->width : null;
}
protected function hasTargetHeight(): bool
{
return is_integer($this->height);
}
protected function getTargetHeight(): ?int
{
return $this->hasTargetHeight() ? $this->height : null;
}
protected function getTargetSize(): SizeInterface
{
if (!$this->hasTargetWidth() || !$this->hasTargetHeight()) {
throw new GeometryException('Target size needs width and height.');
}
return new Rectangle($this->width, $this->height);
}
public function toWidth(int $width): self
{
$this->width = $width;
return $this;
}
public function toHeight(int $height): self
{
$this->height = $height;
return $this;
}
public function toSize(SizeInterface $size): self
{
$this->width = $size->getWidth();
$this->height = $size->getHeight();
return $this;
}
protected function getProportionalWidth(SizeInterface $size): int
{
if (! $this->hasTargetHeight()) {
return $size->getWidth();
}
return (int) round($this->height * $size->getAspectRatio());
}
protected function getProportionalHeight(SizeInterface $size): int
{
if (! $this->hasTargetWidth()) {
return $size->getHeight();
}
return (int) round($this->width / $size->getAspectRatio());
}
public function resize(SizeInterface $size): SizeInterface
{
$resized = new Rectangle($size->getWidth(), $size->getHeight());
if ($width = $this->getTargetWidth()) {
$resized->setWidth($width);
}
if ($height = $this->getTargetHeight()) {
$resized->setHeight($height);
}
return $resized;
}
public function resizeDown(SizeInterface $size): SizeInterface
{
$resized = new Rectangle($size->getWidth(), $size->getHeight());
if ($width = $this->getTargetWidth()) {
$resized->setWidth(
min($width, $size->getWidth())
);
}
if ($height = $this->getTargetHeight()) {
$resized->setHeight(
min($height, $size->getHeight())
);
}
return $resized;
}
public function scale(SizeInterface $size): SizeInterface
{
$resized = new Rectangle($size->getWidth(), $size->getHeight());
if ($this->hasTargetWidth() && $this->hasTargetHeight()) {
$resized->setWidth(min(
$this->getProportionalWidth($size),
$this->getTargetWidth()
));
$resized->setHeight(min(
$this->getProportionalHeight($size),
$this->getTargetHeight()
));
} elseif ($this->hasTargetWidth()) {
$resized->setWidth($this->getTargetWidth());
$resized->setHeight($this->getProportionalHeight($size));
} elseif ($this->hasTargetHeight()) {
$resized->setWidth($this->getProportionalWidth($size));
$resized->setHeight($this->getTargetHeight());
}
return $resized;
}
public function scaleDown(SizeInterface $size): SizeInterface
{
$resized = new Rectangle($size->getWidth(), $size->getHeight());
if ($this->hasTargetWidth() && $this->hasTargetHeight()) {
$resized->setWidth(min(
$this->getProportionalWidth($size),
$this->getTargetWidth(),
$size->getWidth()
));
$resized->setHeight(min(
$this->getProportionalHeight($size),
$this->getTargetHeight(),
$size->getHeight()
));
} elseif ($this->hasTargetWidth()) {
$resized->setWidth(min(
$this->getTargetWidth(),
$size->getWidth()
));
$resized->setHeight(min(
$this->getProportionalHeight($size),
$size->getHeight()
));
} elseif ($this->hasTargetHeight()) {
$resized->setWidth(min(
$this->getProportionalWidth($size),
$size->getWidth()
));
$resized->setHeight(min(
$this->getTargetHeight(),
$size->getHeight()
));
}
return $resized;
}
/**
* Scale given size to cover target size
*
* @param SizeInterface $size Size to be resized
* @return SizeInterface
*/
public function cover(SizeInterface $size): SizeInterface
{
$resized = new Rectangle($size->getWidth(), $size->getHeight());
// auto height
$resized->setWidth($this->getTargetWidth());
$resized->setHeight($this->getProportionalHeight($size));
if ($resized->fitsInto($this->getTargetSize())) {
// auto width
$resized->setWidth($this->getProportionalWidth($size));
$resized->setHeight($this->getTargetHeight());
}
return $resized;
}
/**
* Scale given size to contain target size
*
* @param SizeInterface $size Size to be resized
* @return SizeInterface
*/
public function contain(SizeInterface $size): SizeInterface
{
$resized = new Rectangle($size->getWidth(), $size->getHeight());
// auto height
$resized->setWidth($this->getTargetWidth());
$resized->setHeight($this->getProportionalHeight($size));
if (!$resized->fitsInto($this->getTargetSize())) {
// auto width
$resized->setWidth($this->getProportionalWidth($size));
$resized->setHeight($this->getTargetHeight());
}
return $resized;
}
/**
* Crop target size out of given size at given position (i.e. move the pivot point)
*
* @param SizeInterface $size
* @param string $position
* @return SizeInterface
*/
public function crop(SizeInterface $size, string $position = 'top-left'): SizeInterface
{
return $this->resize($size)->alignPivotTo(
$size->movePivot($position),
$position
);
}
}
src/Geometry/Traits/HasBackgroundColor.php 0000644 00000001062 15073164707 0014630 0 ustar 00 setBackgroundColor($color);
}
public function setBackgroundColor($color): self
{
$this->backgroundColor = $color;
return $this;
}
public function getBackgroundColor()
{
return $this->backgroundColor;
}
public function hasBackgroundColor(): bool
{
return !is_null($this->backgroundColor);
}
}
src/Geometry/Traits/HasBorder.php 0000644 00000001457 15073164707 0012777 0 ustar 00 setBorderSize($size)->setBorderColor($color);
}
public function setBorderSize(int $size): self
{
$this->borderSize = $size;
return $this;
}
public function getBorderSize(): int
{
return $this->borderSize;
}
public function setBorderColor($color): self
{
$this->borderColor = $color;
return $this;
}
public function getBorderColor()
{
return $this->borderColor;
}
public function hasBorder(): bool
{
return $this->borderSize > 0 && !is_null($this->borderColor);
}
}
src/ImageManager.php 0000644 00000002043 15073164707 0010372 0 ustar 00 resolveDriverClass('ImageFactory')->newImage($width, $height);
}
/**
* Create new image instance from source
*
* @param mixed $source
* @return ImageInterface
*/
public function read($source): ImageInterface
{
return $this->resolveDriverClass('InputHandler')->handle($source);
}
/**
* Return id of current driver
*
* @return string
*/
protected function getCurrentDriver(): string
{
return strtolower($this->driver);
}
}
src/Interfaces/CollectionInterface.php 0000644 00000000541 15073164707 0014055 0 ustar 00 modifiers as $modifier) {
$modifier->apply($image);
}
return $image;
}
public function push(ModifierInterface $modifier): self
{
$this->modifiers[] = $modifier;
return $this;
}
}
src/Traits/CanBuildNewImage.php 0000644 00000000430 15073164707 0012417 0 ustar 00 resolveDriverClass('ImageFactory');
}
}
src/Traits/CanCheckType.php 0000644 00000000602 15073164707 0011623 0 ustar 00 \w+\/[-+.\w]+)?" .
"(?P(;[-\w]+=[-\w]+)*)(?P;base64)?,(?P.*)/";
$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;
}
};
}
}
src/Traits/CanHandleInput.php 0000644 00000001330 15073164707 0012156 0 ustar 00 resolveDriverClass('InputHandler')->handle($input);
if (!is_null($check_result_against_classname) && get_class($result) != $check_result_against_classname) {
throw new DecoderException('Decoded result is not an instance of ' . $check_result_against_classname);
}
return $result;
}
}
src/Traits/CanReadHtmlColorNames.php 0000644 00000012207 15073164707 0013433 0 ustar 00 '#FFA07A',
'salmon' => '#FA8072',
'darksalmon' => '#E9967A',
'lightcoral' => '#F08080',
'indianred' => '#CD5C5C',
'crimson' => '#DC143C',
'firebrick' => '#B22222',
'red' => '#FF0000',
'darkred' => '#8B0000',
'coral' => '#FF7F50',
'tomato' => '#FF6347',
'orangered' => '#FF4500',
'gold' => '#FFD700',
'orange' => '#FFA500',
'darkorange' => '#FF8C00',
'lightyellow' => '#FFFFE0',
'lemonchiffon' => '#FFFACD',
'lightgoldenrodyellow' => '#FAFAD2',
'papayawhip' => '#FFEFD5',
'moccasin' => '#FFE4B5',
'peachpuff' => '#FFDAB9',
'palegoldenrod' => '#EEE8AA',
'khaki' => '#F0E68C',
'darkkhaki' => '#BDB76B',
'yellow' => '#FFFF00',
'lawngreen' => '#7CFC00',
'chartreuse' => '#7FFF00',
'limegreen' => '#32CD32',
'lime' => '#00FF00',
'forestgreen' => '#228B22',
'green' => '#008000',
'darkgreen' => '#006400',
'greenyellow' => '#ADFF2F',
'yellowgreen' => '#9ACD32',
'springgreen' => '#00FF7F',
'mediumspringgreen' => '#00FA9A',
'lightgreen' => '#90EE90',
'palegreen' => '#98FB98',
'darkseagreen' => '#8FBC8F',
'mediumseagre' => 'en #3CB371',
'seagreen' => '#2E8B57',
'olive' => '#808000',
'darkolivegreen' => '#556B2F',
'olivedrab' => '#6B8E23',
'lightcyan' => '#E0FFFF',
'cyan' => '#00FFFF',
'aqua' => '#00FFFF',
'aquamarine' => '#7FFFD4',
'mediumaquamarine' => '#66CDAA',
'paleturquoise' => '#AFEEEE',
'turquoise' => '#40E0D0',
'mediumturquoise' => '#48D1CC',
'darkturquoise' => '#00CED1',
'lightseagreen' => '#20B2AA',
'cadetblue' => '#5F9EA0',
'darkcyan' => '#008B8B',
'teal' => '#008080',
'powderblue' => '#B0E0E6',
'lightblue' => '#ADD8E6',
'lightskyblue' => '#87CEFA',
'skyblue' => '#87CEEB',
'deepskyblue' => '#00BFFF',
'lightsteelblue' => '#B0C4DE',
'dodgerblue' => '#1E90FF',
'cornflowerblue' => '#6495ED',
'steelblue' => '#4682B4',
'royalblue' => '#4169E1',
'blue' => '#0000FF',
'mediumblue' => '#0000CD',
'darkblue' => '#00008B',
'navy' => '#000080',
'midnightblue' => '#191970',
'mediumslateblue' => '#7B68EE',
'slateblue' => '#6A5ACD',
'darkslateblue' => '#483D8B',
'lavender' => '#E6E6FA',
'thistle' => '#D8BFD8',
'plum' => '#DDA0DD',
'violet' => '#EE82EE',
'orchid' => '#DA70D6',
'fuchsia' => '#FF00FF',
'magenta' => '#FF00FF',
'mediumorchid' => '#BA55D3',
'mediumpurple' => '#9370DB',
'blueviolet' => '#8A2BE2',
'darkviolet' => '#9400D3',
'darkorchid' => '#9932CC',
'darkmagenta' => '#8B008B',
'purple' => '#800080',
'indigo' => '#4B0082',
'pink' => '#FFC0CB',
'lightpink' => '#FFB6C1',
'hotpink' => '#FF69B4',
'deeppink' => '#FF1493',
'palevioletred' => '#DB7093',
'mediumvioletred' => '#C71585',
'white' => '#FFFFFF',
'snow' => '#FFFAFA',
'honeydew' => '#F0FFF0',
'mintcream' => '#F5FFFA',
'azure' => '#F0FFFF',
'aliceblue' => '#F0F8FF',
'ghostwhite' => '#F8F8FF',
'whitesmoke' => '#F5F5F5',
'seashell' => '#FFF5EE',
'beige' => '#F5F5DC',
'oldlace' => '#FDF5E6',
'floralwhite' => '#FFFAF0',
'ivory' => '#FFFFF0',
'antiquewhite' => '#FAEBD7',
'linen' => '#FAF0E6',
'lavenderblush' => '#FFF0F5',
'mistyrose' => '#FFE4E1',
'gainsboro' => '#DCDCDC',
'lightgray' => '#D3D3D3',
'silver' => '#C0C0C0',
'darkgray' => '#A9A9A9',
'gray' => '#808080',
'dimgray' => '#696969',
'lightslategray' => '#778899',
'slategray' => '#708090',
'darkslategray' => '#2F4F4F',
'black' => '#000000',
'cornsilk' => '#FFF8DC',
'blanchedalmond' => '#FFEBCD',
'bisque' => '#FFE4C4',
'navajowhite' => '#FFDEAD',
'wheat' => '#F5DEB3',
'burlywood' => '#DEB887',
'tan' => '#D2B48C',
'rosybrown' => '#BC8F8F',
'sandybrown' => '#F4A460',
'goldenrod' => '#DAA520',
'peru' => '#CD853F',
'chocolate' => '#D2691E',
'saddlebrown' => '#8B4513',
'sienna' => '#A0522D',
'brown' => '#A52A2A',
'maroon' => '#800000',
];
/**
* Transform given html color name to hex color
* or return null, if color name doesn't exist.
*
* @param string $name
* @return null|string
*/
public function hexColorFromColorName(string $name): ?string
{
$name = strtolower($name);
if (!array_key_exists($name, $this->color_names)) {
return null;
}
return $this->color_names[$name];
}
}
src/Traits/CanResolveDriverClass.php 0000644 00000002656 15073164707 0013540 0 ustar 00 getCurrentDriver();
$classname = sprintf(
"Intervention\\Image\\Drivers\\%s\\%s",
ucfirst($driver_id),
$classname
);
try {
$reflection = new ReflectionClass($classname);
} catch (ReflectionException $e) {
throw new MissingDriverComponentException(
'Class (' . $classname . ') could not be resolved with driver ' . ucfirst($driver_id) . '.'
);
}
return $reflection->newInstanceArgs($arguments);
}
protected function getCurrentDriver(): string
{
$pattern = '/Intervention\\\Image\\\Drivers\\\(?P[A-Za-z]+)/';
preg_match($pattern, get_class($this), $matches);
if (! array_key_exists('driver', $matches)) {
throw new RuntimeException('Current driver could not be resolved.');
}
return strtolower($matches['driver']);
}
}
src/Traits/CanRunCallback.php 0000644 00000000413 15073164707 0012125 0 ustar 00 4) {
return false;
}
// validate rgb values
foreach ($input as $value) {
if ($value < 0 || $value > 255) {
return false;
}
}
// validate alpha value
if (isset($input[3]) && ($input[3] > 1 || $input[3] < 0)) {
return false;
}
return true;
}
}
src/Typography/Line.php 0000644 00000001302 15073164707 0011107 0 ustar 00 position = new Point();
}
public function getPosition(): Point
{
return $this->position;
}
public function setPosition(Point $point): self
{
$this->position = $point;
return $this;
}
public function widthInFont(FontInterface $font): int
{
return $font->getBoxSize($this->text)->getWidth();
}
public function __toString(): string
{
return $this->text;
}
}
src/Typography/TextBlock.php 0000644 00000003372 15073164707 0012130 0 ustar 00 push(new Line($line));
}
}
public function getBoundingBox(FontInterface $font, Point $pivot = null): Polygon
{
$pivot = $pivot ? $pivot : new Point();
// bounding box
$box = (new Rectangle(
$this->longestLine()->widthInFont($font),
$font->leadingInPixels() * ($this->count() - 1) + $font->capHeight()
));
// set pivot
$box->setPivot($pivot);
// align
$box->align($font->getAlign());
$box->valign($font->getValign());
$box->rotate($font->getAngle());
return $box;
}
/**
* Return array of lines in text block
*
* @return array
*/
public function lines(): array
{
return $this->items;
}
public function getLine($key): ?Line
{
if (!array_key_exists($key, $this->lines())) {
return null;
}
return $this->lines()[$key];
}
/**
* Return line with most characters of text block
*
* @return Line
*/
public function longestLine(): Line
{
$lines = $this->lines();
usort($lines, function ($a, $b) {
if (mb_strlen($a) === mb_strlen($b)) {
return 0;
}
return (mb_strlen($a) > mb_strlen($b)) ? -1 : 1;
});
return $lines[0];
}
}