LICENSE 0000644 00000002066 15073164665 0005572 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 00000001614 15073164665 0007305 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",
"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"
}
phpunit.xml.dist 0000644 00000001264 15073164665 0007737 0 ustar 00
./tests/
src
readme.md 0000644 00000003147 15073164665 0006345 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 **PHP image handling and manipulation** library providing an easier and expressive way to create, edit, and compose images.
- Simple interface for
- Driver agnostic
- Support for animated images
- Framework-agnostic, will work with any project
- PSR-12 compliant
## Code Examples
```php
// create image manager with desired driver
$manager = new ImageManager('gd')
// open an image file
$image = $manager->make('images/example.jpg');
// resize image instance
$image->resize(320, 240);
// 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.0
## Supported Image Libraries
- GD Library
- Imagick PHP extension
## Installation
```bash
composer require intervention/image
```
## Getting started
Learn the [basics](https://image.intervention.io/) on how to use Intervention Image and more with the [official documentation](https://image.intervention.io/).
## License
Intervention Image is licensed under the [MIT License](http://opensource.org/licenses/MIT).
Copyright 2021 Oliver Vogel
src/Collection.php 0000644 00000006624 15073164665 0010164 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);
}
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 15073164665 0014004 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 00000004771 15073164665 0013645 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_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')->height();
}
public function fontSizeInPixels(): int
{
return $this->getBoxSize('Hy')->height();
}
}
src/Drivers/Abstract/AbstractImage.php 0000644 00000016552 15073164665 0013761 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 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->resolveDriverClass('Font', $init);
$modifier = $this->resolveDriverClass('Modifiers\TextWriter', new Point($x, $y), $font, $text);
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 destroy(): void
{
$this->modify(
$this->resolveDriverClass('Modifiers\DestroyModifier')
);
}
}
src/Drivers/Abstract/AbstractInputHandler.php 0000644 00000000676 15073164665 0015334 0 ustar 00 chain()->handle($input);
}
}
src/Drivers/Abstract/AbstractTextWriter.php 0000644 00000003640 15073164665 0015052 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 15073164665 0016031 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 15073164665 0016050 0 ustar 00 quality = $quality;
return $this;
}
public function getQuality(): int
{
return $this->quality;
}
}
src/Drivers/Abstract/Modifiers/AbstractFitModifier.php 0000644 00000001622 15073164665 0017051 0 ustar 00 getSize();
$crop = new Size($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 00000001514 15073164665 0017033 0 ustar 00 getSize()
->contain($this->width, $this->height)
->alignPivotTo($this->getResizeSize($image), $this->position);
}
protected function getResizeSize(ImageInterface $image): SizeInterface
{
return new Size($this->width, $this->height);
}
}
src/Drivers/Abstract/Modifiers/AbstractRotateModifier.php 0000644 00000001653 15073164665 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 15073164665 0011116 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 15073164665 0015117 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 15073164665 0015042 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 15073164665 0015245 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 15073164665 0015347 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 15073164665 0015507 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 15073164665 0016347 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 15073164665 0013754 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 15073164665 0013616 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 15073164665 0013764 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 00000003776 15073164665 0010754 0 ustar 00 hasFilename()) {
// calculate box size from gd font
$box = new Size(0, 0);
$chars = mb_strlen($text);
if ($chars > 0) {
$box->setWidth($chars * $this->getGdFontWidth());
$box->setHeight($this->getGdFontHeight());
}
return $box->toPolygon();
}
// 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 00000004111 15073164665 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 Size(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 00000003233 15073164665 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 $key = 0): ?FrameInterface
{
return $this->frames->get($key);
}
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 15073164665 0012402 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 00000001763 15073164665 0012435 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 15073164665 0015542 0 ustar 00 getCore(), IMG_FILTER_BRIGHTNESS, intval($this->level * 2.55));
}
return $image;
}
}
src/Drivers/Gd/Modifiers/ContrastModifier.php 0000644 00000001023 15073164665 0015222 0 ustar 00 getCore(), IMG_FILTER_CONTRAST, ($this->level * -1));
}
return $image;
}
}
src/Drivers/Gd/Modifiers/DestroyModifier.php 0000644 00000000617 15073164665 0015066 0 ustar 00 unsetCore();
}
return $image;
}
}
src/Drivers/Gd/Modifiers/FillModifier.php 0000644 00000002721 15073164665 0014321 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 15073164665 0015010 0 ustar 00 scaleDown($this->width, $this->height);
}
}
src/Drivers/Gd/Modifiers/FitModifier.php 0000644 00000005045 15073164665 0014157 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 15073164665 0014324 0 ustar 00 getCore(), IMG_FLIP_VERTICAL);
}
return $image;
}
}
src/Drivers/Gd/Modifiers/FlopModifier.php 0000644 00000000652 15073164665 0014334 0 ustar 00 getCore(), IMG_FLIP_HORIZONTAL);
}
return $image;
}
}
src/Drivers/Gd/Modifiers/GammaModifier.php 0000644 00000000777 15073164665 0014466 0 ustar 00 getCore(), 1, $this->gamma);
}
return $image;
}
}
src/Drivers/Gd/Modifiers/GreyscaleModifier.php 0000644 00000000662 15073164665 0015353 0 ustar 00 getCore(), IMG_FILTER_GRAYSCALE);
}
return $image;
}
}
src/Drivers/Gd/Modifiers/InvertModifier.php 0000644 00000000654 15073164665 0014705 0 ustar 00 getCore(), IMG_FILTER_NEGATE);
}
return $image;
}
}
src/Drivers/Gd/Modifiers/PadDownModifier.php 0000644 00000001347 15073164665 0014772 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 Size($this->width, $this->height))
->resizeDown($image->getWidth(), $image->getHeight());
}
}
src/Drivers/Gd/Modifiers/PadModifier.php 0000644 00000003651 15073164665 0014142 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 15073164665 0015176 0 ustar 00 getCore(), IMG_FILTER_PIXELATE, $this->size, true);
}
return $image;
}
}
src/Drivers/Gd/Modifiers/PlaceModifier.php 0000644 00000003343 15073164665 0014460 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()->alignPivot($this->position, $this->offset_x, $this->offset_y);
$watermark_size = $watermark->getSize()->alignPivot($this->position);
return $image_size->getRelativePositionTo($watermark_size);
}
}
src/Drivers/Gd/Modifiers/ResizeDownModifier.php 0000644 00000000567 15073164665 0015532 0 ustar 00 getSize()->resizeDown($this->width, $this->height);
}
}
src/Drivers/Gd/Modifiers/ResizeModifier.php 0000644 00000005310 15073164665 0014671 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 15073164665 0014671 0 ustar 00 setCore(
imagerotate(
$frame->getCore(),
$this->rotationAngle(),
$this->backgroundColor()->toInt()
)
);
}
return $image;
}
}
src/Drivers/Gd/Modifiers/ScaleDownModifier.php 0000644 00000000565 15073164665 0015316 0 ustar 00 getSize()->scaleDown($this->width, $this->height);
}
}
src/Drivers/Gd/Modifiers/ScaleModifier.php 0000644 00000000555 15073164665 0014465 0 ustar 00 getSize()->scale($this->width, $this->height);
}
}
src/Drivers/Gd/Modifiers/SharpenModifier.php 0000644 00000001550 15073164665 0015032 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 00000003770 15073164665 0014102 0 ustar 00 getAlignedTextBlock();
foreach ($image as $frame) {
if ($this->font->hasFilename()) {
foreach ($lines as $line) {
imagettftext(
$frame->getCore(),
$this->getFont()->getSize(),
$this->getFont()->getAngle() * (-1),
$line->getPosition()->getX(),
$line->getPosition()->getY(),
$this->getFont()->getColor()->toInt(),
$this->getFont()->getFilename(),
$line
);
}
// debug
// $lines = new TextBlock($this->text);
// $box = $lines->getBoundingBox($this->font, $this->position);
// imagepolygon($frame->getCore(), $box->toArray(), 0);
} else {
foreach ($lines as $line) {
imagestring(
$frame->getCore(),
$this->getFont()->getGdFont(),
$line->getPosition()->getX(),
$line->getPosition()->getY(),
$line,
$this->font->getColor()->toInt()
);
}
}
}
return $image;
}
protected function getFont(): FontInterface
{
if (!is_a($this->font, Font::class)) {
throw new FontException('Font is not compatible to current driver.');
}
return $this->font;
}
}
src/Drivers/Imagick/Color.php 0000644 00000002541 15073164665 0012123 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 15073164665 0016151 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 15073164665 0016052 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 15073164665 0016245 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 15073164665 0016366 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 15073164665 0016526 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 15073164665 0014770 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 15073164665 0014635 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 15073164665 0015006 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 00000003376 15073164665 0011762 0 ustar 00 hasFilename()) {
throw new FontException('No font file specified.');
}
$draw = new ImagickDraw();
$draw->setStrokeAntialias(true);
$draw->setTextAntialias(true);
$draw->setFont($this->getFilename());
$draw->setFontSize($this->getSize());
$draw->setFillColor($this->getColor()->getPixel());
$draw->setTextAlignment(Imagick::ALIGN_LEFT);
return $draw;
}
public function getColor(): ?ColorInterface
{
$color = parent::getColor();
if (!is_a($color, Color::class)) {
throw new FontException('Font is not compatible to current driver.');
}
return $color;
}
/**
* 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 Size(0, 0))->toPolygon();
}
$draw = $this->toImagickDraw();
$draw->setStrokeAntialias(true);
$draw->setTextAntialias(true);
$dimensions = (new Imagick())->queryFontMetrics($draw, $text);
return (new Size(
intval(round($dimensions['textWidth'])),
intval(round($dimensions['ascender'] + $dimensions['descender'])),
))->toPolygon();
}
}
src/Drivers/Imagick/Frame.php 0000644 00000004042 15073164665 0012075 0 ustar 00 core = $core;
return $this;
}
public function getCore(): Imagick
{
return $this->core;
}
public function getSize(): SizeInterface
{
return new Size($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 00000005574 15073164665 0012100 0 ustar 00 imagick;
}
public function getFrame(int $key = 0): ?FrameInterface
{
try {
$this->imagick->setIteratorIndex($key);
} catch (ImagickException $e) {
return null;
}
return new Frame($this->imagick->current());
}
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()
{
$this->imagick->setIteratorIndex($this->iteratorIndex);
return new Frame($this->imagick->current());
}
public function key()
{
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 15073164665 0013417 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 00000001770 15073164665 0013445 0 ustar 00 getCore()->blurImage(1 * $this->amount, 0.5 * $this->amount);
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/BrightnessModifier.php 0000644 00000001020 15073164665 0016544 0 ustar 00 getCore()->modulateImage(100 + $this->level, 100, 100);
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/ContrastModifier.php 0000644 00000001045 15073164665 0016240 0 ustar 00 getCore()->sigmoidalContrastImage($this->level > 0, abs($this->level / 4), 0);
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/DestroyModifier.php 0000644 00000000633 15073164665 0016076 0 ustar 00 getCore()->clear();
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/FillModifier.php 0000644 00000003366 15073164665 0015341 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 15073164665 0016020 0 ustar 00 scaleDown($this->width, $this->height);
}
}
src/Drivers/Imagick/Modifiers/FitModifier.php 0000644 00000001612 15073164665 0015165 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 15073164665 0015340 0 ustar 00 getCore()->flipImage();
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/FlopModifier.php 0000644 00000000634 15073164665 0015346 0 ustar 00 getCore()->flopImage();
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/GammaModifier.php 0000644 00000000772 15073164665 0015473 0 ustar 00 getCore()->gammaImage($this->gamma);
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/GreyscaleModifier.php 0000644 00000000660 15073164665 0016363 0 ustar 00 getCore()->modulateImage(100, 0, 100);
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/InvertModifier.php 0000644 00000000645 15073164665 0015717 0 ustar 00 getCore()->negateImage(false);
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/PadDownModifier.php 0000644 00000001354 15073164665 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 Size($this->width, $this->height))
->resizeDown($image->getWidth(), $image->getHeight());
}
}
src/Drivers/Imagick/Modifiers/PadModifier.php 0000644 00000005573 15073164665 0015161 0 ustar 00 getResizeSize($image);
$crop = $this->getCropSize($image);
$background = $this->handleInput($this->background);
if (!is_a($background, Color::class)) {
throw new DecoderException('Unable to decode backgroud color.');
}
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 00000001644 15073164665 0016223 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 00000003127 15073164665 0015472 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()->alignPivot($this->position, $this->offset_x, $this->offset_y);
$watermark_size = $watermark->getSize()->alignPivot($this->position);
return $image_size->getRelativePositionTo($watermark_size);
}
}
src/Drivers/Imagick/Modifiers/ResizeDownModifier.php 0000644 00000000574 15073164665 0016542 0 ustar 00 getSize()->resizeDown($this->width, $this->height);
}
}
src/Drivers/Imagick/Modifiers/ResizeModifier.php 0000644 00000001650 15073164665 0015706 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 00000001757 15073164665 0015713 0 ustar 00 backgroundColor();
if (!is_a($background, Color::class)) {
throw new DecoderException('Unable to decode given background color.');
}
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 15073164665 0016326 0 ustar 00 getSize()->scaleDown($this->width, $this->height);
}
}
src/Drivers/Imagick/Modifiers/ScaleModifier.php 0000644 00000000562 15073164665 0015475 0 ustar 00 getSize()->scale($this->width, $this->height);
}
}
src/Drivers/Imagick/Modifiers/SharpenModifier.php 0000644 00000001022 15073164665 0016036 0 ustar 00 getCore()->unsharpMaskImage(1, 1, $this->amount / 6.25, 0);
}
return $image;
}
}
src/Drivers/Imagick/Modifiers/TextWriter.php 0000644 00000003332 15073164665 0015106 0 ustar 00 getAlignedTextBlock();
foreach ($image as $frame) {
foreach ($lines as $line) {
$frame->getCore()->annotateImage(
$this->getFont()->toImagickDraw(),
$line->getPosition()->getX(),
$line->getPosition()->getY(),
$this->getFont()->getAngle(),
$line
);
}
// debug
// $lines = new TextBlock($this->text);
// $box = $lines->getBoundingBox($this->font, $this->position);
// $points = [];
// foreach (array_chunk($box->toArray(), 2) as $p) {
// $points[] = ['x' => $p[0], 'y' => $p[1]];
// }
// $draw = new \ImagickDraw();
// $draw->setStrokeOpacity(1);
// $draw->setStrokeColor('black');
// $draw->setFillColor('transparent');
// $draw->polygon($points);
// $frame->getCore()->drawImage($draw);
}
return $image;
}
protected function getFont(): FontInterface
{
if (!is_a($this->font, Font::class)) {
throw new FontException('Font is not compatible to current driver.');
}
return $this->font;
}
}
src/EncodedImage.php 0000644 00000001676 15073164665 0010377 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 15073164665 0013427 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 00000024156 15073164665 0011313 0 ustar 00 pivot = $pivot ? $pivot : new Point();
}
/**
* Return current pivot point
*
* @return Point
*/
public function getPivotPoint(): Point
{
return $this->pivot;
}
/**
* Change pivot point to given point
*
* @param Point $pivot
* @return Polygon
*/
public function setPivotPoint(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)
{
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;
}
/**
* Calculate total horizontal span of polygon
*
* @return int
*/
public function width(): int
{
return abs($this->getMostLeftPoint()->getX() - $this->getMostRightPoint()->getX());
}
/**
* Calculate total vertical span of polygon
*
* @return int
*/
public function height(): 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->width() / 2))),
$this->getMostTopPoint()->getY() - (intval(round($this->height() / 2)))
);
}
/**
* Align pivot point to given horizontal position
*
* @param string $position
* @return Polygon
*/
public function alignPivot(string $position): self
{
switch (strtolower($position)) {
case 'center':
$this->pivot->setX(
intval(($this->getMostRightPoint()->getX() + $this->getMostLeftPoint()->getX()) / 2)
);
break;
case 'right':
$this->pivot->setX(
$this->getMostRightPoint()->getX()
);
break;
case 'left':
$this->pivot->setX(
$this->getMostLeftPoint()->getX()
);
break;
}
return $this;
}
/**
* Align pivot point to given vertical position
*
* @param string $position
* @return Polygon
*/
public function valignPivot(string $position): self
{
switch (strtolower($position)) {
case 'center':
case 'middle':
$this->pivot->setY(
intval(($this->getMostTopPoint()->getY() + $this->getMostBottomPoint()->getY()) / 2)
);
break;
case 'top':
$this->pivot->setY(
$this->getMostTopPoint()->getY()
);
break;
case 'bottom':
$this->pivot->setY(
$this->getMostBottomPoint()->getY()
);
break;
}
return $this;
}
/**
* 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->pivot->getX());
break;
case 'right':
$diff = ($this->getMostRightPoint()->getX() - $this->pivot->getX());
break;
default:
case 'left':
$diff = ($this->getMostLeftPoint()->getX() - $this->pivot->getX());
break;
}
foreach ($this->points as $point) {
$point->setX($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->pivot->getY());
break;
case 'top':
$diff = ($this->getMostTopPoint()->getY() - $this->pivot->getY()) - $this->height();
break;
default:
case 'bottom':
$diff = ($this->getMostBottomPoint()->getY() - $this->pivot->getY()) + $this->height();
break;
}
foreach ($this->points as $point) {
$point->setY($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($point->getX() - $this->pivot->getX());
$point->setY($point->getY() - $this->pivot->getY());
// rotate point
$x = $point->getX() * $cos - $point->getY() * $sin;
$y = $point->getX() * $sin + $point->getY() * $cos;
// translate point back
$point->setX($x + $this->pivot->getX());
$point->setY($y + $this->pivot->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/Resizer.php 0000644 00000015321 15073164665 0011301 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 Size($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 Size($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 Size($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 Size($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 Size($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 Size($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 Size($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->alignPivot($position),
$position
);
}
}
src/Geometry/Size.php 0000644 00000016534 15073164665 0010577 0 ustar 00 pivot = $pivot ? $pivot : new Point();
}
public function getWidth(): int
{
return $this->width;
}
public function getHeight(): int
{
return $this->height;
}
public function setWidth(int $width): SizeInterface
{
$this->width = $width;
return $this;
}
public function setHeight(int $height): SizeInterface
{
$this->height = $height;
return $this;
}
public function addWidth(int $value): SizeInterface
{
$this->width = $this->width + $value;
return $this;
}
public function subWidth(int $value): SizeInterface
{
$this->width = $this->width - $value;
return $this;
}
public function addHeight(int $value): SizeInterface
{
$this->height = $this->height + $value;
return $this;
}
public function subHeight(int $value): SizeInterface
{
$this->height = $this->height - $value;
return $this;
}
/**
* Get current pivot point
*
* @return Point
*/
public function getPivot(): PointInterface
{
return $this->pivot;
}
public function setPivot(PointInterface $pivot): SizeInterface
{
$this->pivot = $pivot;
return $this;
}
public function getAspectRatio(): float
{
return $this->width / $this->height;
}
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();
}
/**
* Aligns current size's pivot point to given position
* and moves point automatically by offset.
*
* @param string $position
* @param int $offset_x
* @param int $offset_y
* @return Size
*/
public function alignPivot(string $position, int $offset_x = 0, int $offset_y = 0): SizeInterface
{
switch (strtolower($position)) {
case 'top':
case 'top-center':
case 'top-middle':
case 'center-top':
case 'middle-top':
$x = intval($this->width / 2);
$y = 0 + $offset_y;
break;
case 'top-right':
case 'right-top':
$x = $this->width - $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->height / 2);
break;
case 'right':
case 'right-center':
case 'right-middle':
case 'center-right':
case 'middle-right':
$x = $this->width - $offset_x;
$y = intval($this->height / 2);
break;
case 'bottom-left':
case 'left-bottom':
$x = 0 + $offset_x;
$y = $this->height - $offset_y;
break;
case 'bottom':
case 'bottom-center':
case 'bottom-middle':
case 'center-bottom':
case 'middle-bottom':
$x = intval($this->width / 2);
$y = $this->height - $offset_y;
break;
case 'bottom-right':
case 'right-bottom':
$x = $this->width - $offset_x;
$y = $this->height - $offset_y;
break;
case 'center':
case 'middle':
case 'center-center':
case 'middle-middle':
$x = intval($this->width / 2) + $offset_x;
$y = intval($this->height / 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): SizeInterface
{
$reference = new Size($size->getWidth(), $size->getHeight());
$reference->alignPivot($position);
$this->alignPivot($position)->setPivot(
$reference->getRelativePositionTo($this)
);
return $this;
}
/**
* Calculate the relative position to another Size
* based on the pivot point settings of both sizes.
*
* @param Size $size
* @return Point
*/
public function getRelativePositionTo(SizeInterface $size): PointInterface
{
$x = $this->getPivot()->getX() - $size->getPivot()->getX();
$y = $this->getPivot()->getY() - $size->getPivot()->getY();
return new Point($x, $y);
}
public function toPolygon(): Polygon
{
$polygon = new Polygon([
$this->pivot // top/left
], $this->pivot);
// top/right
$polygon->addPoint(
new Point($this->pivot->getX() + $this->getWidth(), $this->pivot->getY())
);
// bottom/right
$polygon->addPoint(
new Point($this->pivot->getX() + $this->getWidth(), $this->pivot->getY() - $this->getHeight())
);
// bottom/left
$polygon->addPoint(
new Point($this->pivot->getX(), $this->pivot->getY() - $this->getHeight())
);
return $polygon;
}
protected function getResizer(?int $width = null, ?int $height = null): Resizer
{
return new Resizer($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/ImageManager.php 0000644 00000002043 15073164665 0010375 0 ustar 00 resolveDriverClass('ImageFactory')->newImage($width, $height);
}
/**
* Create new image instance from source
*
* @param mixed $source
* @return ImageInterface
*/
public function make($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 15073164665 0014060 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 15073164665 0012422 0 ustar 00 resolveDriverClass('ImageFactory');
}
}
src/Traits/CanDecodeDataUri.php 0000644 00000004033 15073164665 0012406 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 00000000550 15073164665 0012164 0 ustar 00 resolveDriverClass('InputHandler')->handle($input);
}
}
src/Traits/CanResizeGeometrically.php 0000644 00000000436 15073164665 0013736 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/CanValidateBase64.php 0000644 00000000457 15073164665 0012455 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 00000001277 15073164665 0011125 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)->width();
}
public function __toString(): string
{
return $this->text;
}
}
src/Typography/TextBlock.php 0000644 00000003402 15073164665 0012125 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 Size(
$this->longestLine()->widthInFont($font),
$font->leadingInPixels() * ($this->count() - 1) + $font->capHeight()
))->toPolygon();
// set pivot
$box->setPivotPoint($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];
}
}