charger une image
This commit is contained in:
21
upLoadImage/vendor/intervention/gif/LICENSE
vendored
Executable file
21
upLoadImage/vendor/intervention/gif/LICENSE
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020-present 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.
|
||||
101
upLoadImage/vendor/intervention/gif/README.md
vendored
Executable file
101
upLoadImage/vendor/intervention/gif/README.md
vendored
Executable file
@@ -0,0 +1,101 @@
|
||||
# Intervention GIF
|
||||
## Native PHP GIF Encoder/Decoder
|
||||
|
||||
[](https://packagist.org/packages/intervention/gif)
|
||||

|
||||
[](https://packagist.org/packages/intervention/gif/stats)
|
||||
[](https://ko-fi.com/interventionphp)
|
||||
|
||||
Intervention GIF is a PHP encoder and decoder for the GIF image format that
|
||||
does not depend on any image processing extension.
|
||||
|
||||
Only the special `Splitter::class` class divides the data stream of an animated
|
||||
GIF into individual `GDImage` objects for each frame and is therefore dependent
|
||||
on the GD library.
|
||||
|
||||
The library is the main component of [Intervention
|
||||
Image](https://github.com/Intervention/image) for processing animated GIF files
|
||||
with the GD library, but also works independently.
|
||||
|
||||
## Installation
|
||||
|
||||
You can easily install this package using [Composer](https://getcomposer.org).
|
||||
Just request the package with the following command:
|
||||
|
||||
```bash
|
||||
composer require intervention/gif
|
||||
```
|
||||
|
||||
## Code Examples
|
||||
|
||||
### Decoding
|
||||
|
||||
```php
|
||||
use Intervention\Gif\Decoder;
|
||||
|
||||
// Decode filepath to Intervention\Gif\GifDataStream::class
|
||||
$gif = Decoder::decode('images/animation.gif');
|
||||
|
||||
// Decoder can also handle binary content directly
|
||||
$gif = Decoder::decode($contents);
|
||||
```
|
||||
|
||||
### Encoding
|
||||
|
||||
Use the Builder class to create a new GIF image.
|
||||
|
||||
```php
|
||||
use Intervention\Gif\Builder;
|
||||
|
||||
// create new gif canvas
|
||||
$gif = Builder::canvas(width: 32, height: 32);
|
||||
|
||||
// add animation frames to canvas
|
||||
$delay = .25; // delay in seconds after next frame is displayed
|
||||
$left = 0; // position offset (left)
|
||||
$top = 0; // position offset (top)
|
||||
|
||||
// add animation frames with optional delay in seconds
|
||||
// and optional position offset for each frame
|
||||
$gif->addFrame('images/frame01.gif', $delay, $left, $top);
|
||||
$gif->addFrame('images/frame02.gif', $delay, $left);
|
||||
$gif->addFrame('images/frame03.gif', $delay);
|
||||
$gif->addFrame('images/frame04.gif');
|
||||
|
||||
// set loop count; 0 for infinite looping
|
||||
$gif->setLoops(12);
|
||||
|
||||
// encode
|
||||
$data = $gif->encode();
|
||||
```
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
- PHP >= 8.1
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
## Authors
|
||||
|
||||
This library is developed and maintained by [Oliver Vogel](https://intervention.io)
|
||||
|
||||
Thanks to the community of [contributors](https://github.com/Intervention/gif/graphs/contributors) who have helped to improve this project.
|
||||
|
||||
## License
|
||||
|
||||
Intervention GIF is licensed under the [MIT License](LICENSE).
|
||||
44
upLoadImage/vendor/intervention/gif/composer.json
vendored
Executable file
44
upLoadImage/vendor/intervention/gif/composer.json
vendored
Executable file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "intervention/gif",
|
||||
"description": "Native PHP GIF Encoder/Decoder",
|
||||
"homepage": "https://github.com/intervention/gif",
|
||||
"keywords": [
|
||||
"image",
|
||||
"gd",
|
||||
"gif",
|
||||
"animation"
|
||||
],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Oliver Vogel",
|
||||
"email": "oliver@intervention.io",
|
||||
"homepage": "https://intervention.io/"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10.0 || ^11.0 || ^12.0",
|
||||
"phpstan/phpstan": "^2.1",
|
||||
"squizlabs/php_codesniffer": "^3.8",
|
||||
"slevomat/coding-standard": "~8.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Intervention\\Gif\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Intervention\\Gif\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
}
|
||||
}
|
||||
}
|
||||
13
upLoadImage/vendor/intervention/gif/phpunit.xml.dist
vendored
Executable file
13
upLoadImage/vendor/intervention/gif/phpunit.xml.dist
vendored
Executable file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" bootstrap="vendor/autoload.php" colors="true" processIsolation="false" stopOnFailure="false" beStrictAboutTestsThatDoNotTestAnything="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" cacheDirectory=".phpunit.cache" backupStaticProperties="false">
|
||||
<testsuites>
|
||||
<testsuite name="Unit Tests">
|
||||
<directory suffix=".php">./tests/Unit/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<source>
|
||||
<include>
|
||||
<directory suffix=".php">src</directory>
|
||||
</include>
|
||||
</source>
|
||||
</phpunit>
|
||||
37
upLoadImage/vendor/intervention/gif/src/AbstractEntity.php
vendored
Normal file
37
upLoadImage/vendor/intervention/gif/src/AbstractEntity.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif;
|
||||
|
||||
use Intervention\Gif\Exceptions\EncoderException;
|
||||
use Intervention\Gif\Traits\CanDecode;
|
||||
use Intervention\Gif\Traits\CanEncode;
|
||||
use ReflectionClass;
|
||||
use Stringable;
|
||||
|
||||
abstract class AbstractEntity implements Stringable
|
||||
{
|
||||
use CanEncode;
|
||||
use CanDecode;
|
||||
|
||||
public const TERMINATOR = "\x00";
|
||||
|
||||
/**
|
||||
* Get short classname of current instance
|
||||
*/
|
||||
public static function getShortClassname(): string
|
||||
{
|
||||
return (new ReflectionClass(static::class))->getShortName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast object to string
|
||||
*
|
||||
* @throws EncoderException
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->encode();
|
||||
}
|
||||
}
|
||||
10
upLoadImage/vendor/intervention/gif/src/AbstractExtension.php
vendored
Normal file
10
upLoadImage/vendor/intervention/gif/src/AbstractExtension.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif;
|
||||
|
||||
abstract class AbstractExtension extends AbstractEntity
|
||||
{
|
||||
public const MARKER = "\x21";
|
||||
}
|
||||
97
upLoadImage/vendor/intervention/gif/src/Blocks/ApplicationExtension.php
vendored
Normal file
97
upLoadImage/vendor/intervention/gif/src/Blocks/ApplicationExtension.php
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractExtension;
|
||||
use Intervention\Gif\Exceptions\RuntimeException;
|
||||
|
||||
class ApplicationExtension extends AbstractExtension
|
||||
{
|
||||
public const LABEL = "\xFF";
|
||||
|
||||
/**
|
||||
* Application Identifier & Auth Code
|
||||
*/
|
||||
protected string $application = '';
|
||||
|
||||
/**
|
||||
* Data Sub Blocks
|
||||
*
|
||||
* @var array<DataSubBlock>
|
||||
*/
|
||||
protected array $blocks = [];
|
||||
|
||||
/**
|
||||
* Get size of block
|
||||
*/
|
||||
public function getBlockSize(): int
|
||||
{
|
||||
return strlen($this->application);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set application name
|
||||
*/
|
||||
public function setApplication(string $value): self
|
||||
{
|
||||
$this->application = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get application name
|
||||
*/
|
||||
public function getApplication(): string
|
||||
{
|
||||
return $this->application;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add block to application extension
|
||||
*/
|
||||
public function addBlock(DataSubBlock $block): self
|
||||
{
|
||||
$this->blocks[] = $block;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set data sub blocks of instance
|
||||
*
|
||||
* @param array<DataSubBlock> $blocks
|
||||
*/
|
||||
public function setBlocks(array $blocks): self
|
||||
{
|
||||
$this->blocks = $blocks;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get blocks of ApplicationExtension
|
||||
*
|
||||
* @return array<DataSubBlock>
|
||||
*/
|
||||
public function getBlocks(): array
|
||||
{
|
||||
return $this->blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first block of ApplicationExtension
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function getFirstBlock(): DataSubBlock
|
||||
{
|
||||
if (!array_key_exists(0, $this->blocks)) {
|
||||
throw new RuntimeException('Unable to retrieve data sub block.');
|
||||
}
|
||||
|
||||
return $this->blocks[0];
|
||||
}
|
||||
}
|
||||
83
upLoadImage/vendor/intervention/gif/src/Blocks/Color.php
vendored
Normal file
83
upLoadImage/vendor/intervention/gif/src/Blocks/Color.php
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class Color extends AbstractEntity
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(
|
||||
protected int $r = 0,
|
||||
protected int $g = 0,
|
||||
protected int $b = 0
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get red value
|
||||
*/
|
||||
public function getRed(): int
|
||||
{
|
||||
return $this->r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set red value
|
||||
*/
|
||||
public function setRed(int $value): self
|
||||
{
|
||||
$this->r = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get green value
|
||||
*/
|
||||
public function getGreen(): int
|
||||
{
|
||||
return $this->g;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set green value
|
||||
*/
|
||||
public function setGreen(int $value): self
|
||||
{
|
||||
$this->g = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get blue value
|
||||
*/
|
||||
public function getBlue(): int
|
||||
{
|
||||
return $this->b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set blue value
|
||||
*/
|
||||
public function setBlue(int $value): self
|
||||
{
|
||||
$this->b = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return hash value of current color
|
||||
*/
|
||||
public function getHash(): string
|
||||
{
|
||||
return md5($this->r . $this->g . $this->b);
|
||||
}
|
||||
}
|
||||
121
upLoadImage/vendor/intervention/gif/src/Blocks/ColorTable.php
vendored
Normal file
121
upLoadImage/vendor/intervention/gif/src/Blocks/ColorTable.php
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class ColorTable extends AbstractEntity
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param array<Color> $colors
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(protected array $colors = [])
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of current colors
|
||||
*
|
||||
* @return array<Color>
|
||||
*/
|
||||
public function getColors(): array
|
||||
{
|
||||
return array_values($this->colors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add color to table
|
||||
*/
|
||||
public function addRgb(int $r, int $g, int $b): self
|
||||
{
|
||||
$this->addColor(new Color($r, $g, $b));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add color to table
|
||||
*/
|
||||
public function addColor(Color $color): self
|
||||
{
|
||||
$this->colors[] = $color;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset colors to array of color objects
|
||||
*
|
||||
* @param array<Color> $colors
|
||||
*/
|
||||
public function setColors(array $colors): self
|
||||
{
|
||||
$this->empty();
|
||||
foreach ($colors as $color) {
|
||||
$this->addColor($color);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count colors of current instance
|
||||
*/
|
||||
public function countColors(): int
|
||||
{
|
||||
return count($this->colors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if any colors are present on the current table
|
||||
*/
|
||||
public function hasColors(): bool
|
||||
{
|
||||
return $this->countColors() >= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty color table
|
||||
*/
|
||||
public function empty(): self
|
||||
{
|
||||
$this->colors = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size of color table in logical screen descriptor
|
||||
*/
|
||||
public function getLogicalSize(): int
|
||||
{
|
||||
return match ($this->countColors()) {
|
||||
4 => 1,
|
||||
8 => 2,
|
||||
16 => 3,
|
||||
32 => 4,
|
||||
64 => 5,
|
||||
128 => 6,
|
||||
256 => 7,
|
||||
default => 0,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the number of bytes contained by the current table
|
||||
*/
|
||||
public function getByteSize(): int
|
||||
{
|
||||
if (!$this->hasColors()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 3 * pow(2, $this->getLogicalSize() + 1);
|
||||
}
|
||||
}
|
||||
47
upLoadImage/vendor/intervention/gif/src/Blocks/CommentExtension.php
vendored
Normal file
47
upLoadImage/vendor/intervention/gif/src/Blocks/CommentExtension.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractExtension;
|
||||
|
||||
class CommentExtension extends AbstractExtension
|
||||
{
|
||||
public const LABEL = "\xFE";
|
||||
|
||||
/**
|
||||
* Comment blocks
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected array $comments = [];
|
||||
|
||||
/**
|
||||
* Get all or one comment
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
public function getComments(): array
|
||||
{
|
||||
return $this->comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get one comment by key
|
||||
*/
|
||||
public function getComment(int $key): mixed
|
||||
{
|
||||
return $this->comments[$key] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set comment text
|
||||
*/
|
||||
public function addComment(string $value): self
|
||||
{
|
||||
$this->comments[] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
41
upLoadImage/vendor/intervention/gif/src/Blocks/DataSubBlock.php
vendored
Normal file
41
upLoadImage/vendor/intervention/gif/src/Blocks/DataSubBlock.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
use Intervention\Gif\Exceptions\FormatException;
|
||||
|
||||
class DataSubBlock extends AbstractEntity
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @throws FormatException
|
||||
*/
|
||||
public function __construct(protected string $value)
|
||||
{
|
||||
if ($this->getSize() > 255) {
|
||||
throw new FormatException(
|
||||
'Data Sub-Block can not have a block size larger than 255 bytes.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return size of current block
|
||||
*/
|
||||
public function getSize(): int
|
||||
{
|
||||
return strlen($this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return block value
|
||||
*/
|
||||
public function getValue(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
250
upLoadImage/vendor/intervention/gif/src/Blocks/FrameBlock.php
vendored
Normal file
250
upLoadImage/vendor/intervention/gif/src/Blocks/FrameBlock.php
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
/**
|
||||
* The GIF files that can be found on the Internet come in a wide variety
|
||||
* of forms. Some strictly adhere to the original specification, others do
|
||||
* not and differ in the actual sequence of blocks or their number.
|
||||
*
|
||||
* For this reason, this libary has this (kind of "virtual") FrameBlock,
|
||||
* which can contain all possible blocks in different order that occur in
|
||||
* a GIF animation.
|
||||
*
|
||||
* - Image Description
|
||||
* - Local Color Table
|
||||
* - Image Data Block
|
||||
* - Plain Text Extension
|
||||
* - Application Extension
|
||||
* - Comment Extension
|
||||
*
|
||||
* The TableBasedImage block, which is a chain of ImageDescriptor, (Local
|
||||
* Color Table) and ImageData, is used as a marker for terminating a
|
||||
* FrameBlock.
|
||||
*
|
||||
* So far I have only seen GIF files that follow this scheme. However, there are
|
||||
* examples which have one (or more) comment extensions added before the end. So
|
||||
* there can be additional "global comments" that are not part of the FrameBlock
|
||||
* and are appended to the GifDataStream afterwards.
|
||||
*/
|
||||
class FrameBlock extends AbstractEntity
|
||||
{
|
||||
protected ?GraphicControlExtension $graphicControlExtension = null;
|
||||
|
||||
protected ?ColorTable $colorTable = null;
|
||||
|
||||
protected ?PlainTextExtension $plainTextExtension = null;
|
||||
|
||||
/**
|
||||
* @var array<ApplicationExtension> $applicationExtensions
|
||||
*/
|
||||
protected array $applicationExtensions = [];
|
||||
|
||||
/**
|
||||
* @var array<CommentExtension> $commentExtensions
|
||||
*/
|
||||
protected array $commentExtensions = [];
|
||||
|
||||
public function __construct(
|
||||
protected ImageDescriptor $imageDescriptor = new ImageDescriptor(),
|
||||
protected ImageData $imageData = new ImageData()
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
public function addEntity(AbstractEntity $entity): self
|
||||
{
|
||||
return match (true) {
|
||||
$entity instanceof TableBasedImage => $this->setTableBasedImage($entity),
|
||||
$entity instanceof GraphicControlExtension => $this->setGraphicControlExtension($entity),
|
||||
$entity instanceof ImageDescriptor => $this->setImageDescriptor($entity),
|
||||
$entity instanceof ColorTable => $this->setColorTable($entity),
|
||||
$entity instanceof ImageData => $this->setImageData($entity),
|
||||
$entity instanceof PlainTextExtension => $this->setPlainTextExtension($entity),
|
||||
$entity instanceof NetscapeApplicationExtension,
|
||||
$entity instanceof ApplicationExtension => $this->addApplicationExtension($entity),
|
||||
$entity instanceof CommentExtension => $this->addCommentExtension($entity),
|
||||
default => $this,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return application extensions of current frame block
|
||||
*
|
||||
* @return array<ApplicationExtension>
|
||||
*/
|
||||
public function getApplicationExtensions(): array
|
||||
{
|
||||
return $this->applicationExtensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return comment extensions of current frame block
|
||||
*
|
||||
* @return array<CommentExtension>
|
||||
*/
|
||||
public function getCommentExtensions(): array
|
||||
{
|
||||
return $this->commentExtensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the graphic control extension
|
||||
*/
|
||||
public function setGraphicControlExtension(GraphicControlExtension $extension): self
|
||||
{
|
||||
$this->graphicControlExtension = $extension;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the graphic control extension of the current frame block
|
||||
*/
|
||||
public function getGraphicControlExtension(): ?GraphicControlExtension
|
||||
{
|
||||
return $this->graphicControlExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the image descriptor
|
||||
*/
|
||||
public function setImageDescriptor(ImageDescriptor $descriptor): self
|
||||
{
|
||||
$this->imageDescriptor = $descriptor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image descriptor of the frame block
|
||||
*/
|
||||
public function getImageDescriptor(): ImageDescriptor
|
||||
{
|
||||
return $this->imageDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the color table of the current frame block
|
||||
*/
|
||||
public function setColorTable(ColorTable $table): self
|
||||
{
|
||||
$this->colorTable = $table;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get color table
|
||||
*/
|
||||
public function getColorTable(): ?ColorTable
|
||||
{
|
||||
return $this->colorTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if frame block has color table
|
||||
*/
|
||||
public function hasColorTable(): bool
|
||||
{
|
||||
return !is_null($this->colorTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set image data of frame block
|
||||
*/
|
||||
public function setImageData(ImageData $data): self
|
||||
{
|
||||
$this->imageData = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image data of current frame block
|
||||
*/
|
||||
public function getImageData(): ImageData
|
||||
{
|
||||
return $this->imageData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set plain text extension
|
||||
*/
|
||||
public function setPlainTextExtension(PlainTextExtension $extension): self
|
||||
{
|
||||
$this->plainTextExtension = $extension;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plain text extension
|
||||
*/
|
||||
public function getPlainTextExtension(): ?PlainTextExtension
|
||||
{
|
||||
return $this->plainTextExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given application extension to the current frame block
|
||||
*/
|
||||
public function addApplicationExtension(ApplicationExtension $extension): self
|
||||
{
|
||||
$this->applicationExtensions[] = $extension;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all application extensions from the current frame block.
|
||||
*/
|
||||
public function clearApplicationExtensions(): self
|
||||
{
|
||||
$this->applicationExtensions = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given comment extension to the current frame block
|
||||
*/
|
||||
public function addCommentExtension(CommentExtension $extension): self
|
||||
{
|
||||
$this->commentExtensions[] = $extension;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return netscape extension of the frame block if available
|
||||
*/
|
||||
public function getNetscapeExtension(): ?NetscapeApplicationExtension
|
||||
{
|
||||
$extensions = array_filter(
|
||||
$this->applicationExtensions,
|
||||
fn(ApplicationExtension $extension): bool => $extension instanceof NetscapeApplicationExtension,
|
||||
);
|
||||
|
||||
return count($extensions) ? reset($extensions) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the table based image of the current frame block
|
||||
*/
|
||||
public function setTableBasedImage(TableBasedImage $tableBasedImage): self
|
||||
{
|
||||
$this->setImageDescriptor($tableBasedImage->getImageDescriptor());
|
||||
|
||||
if ($colorTable = $tableBasedImage->getColorTable()) {
|
||||
$this->setColorTable($colorTable);
|
||||
}
|
||||
|
||||
$this->setImageData($tableBasedImage->getImageData());
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
129
upLoadImage/vendor/intervention/gif/src/Blocks/GraphicControlExtension.php
vendored
Normal file
129
upLoadImage/vendor/intervention/gif/src/Blocks/GraphicControlExtension.php
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractExtension;
|
||||
use Intervention\Gif\DisposalMethod;
|
||||
|
||||
class GraphicControlExtension extends AbstractExtension
|
||||
{
|
||||
public const LABEL = "\xF9";
|
||||
public const BLOCKSIZE = "\x04";
|
||||
|
||||
/**
|
||||
* Existance flag of transparent color
|
||||
*/
|
||||
protected bool $transparentColorExistance = false;
|
||||
|
||||
/**
|
||||
* Transparent color index
|
||||
*/
|
||||
protected int $transparentColorIndex = 0;
|
||||
|
||||
/**
|
||||
* User input flag
|
||||
*/
|
||||
protected bool $userInput = false;
|
||||
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(
|
||||
protected int $delay = 0,
|
||||
protected DisposalMethod $disposalMethod = DisposalMethod::UNDEFINED,
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Set delay time (1/100 second)
|
||||
*/
|
||||
public function setDelay(int $value): self
|
||||
{
|
||||
$this->delay = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return delay time (1/100 second)
|
||||
*/
|
||||
public function getDelay(): int
|
||||
{
|
||||
return $this->delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set disposal method
|
||||
*/
|
||||
public function setDisposalMethod(DisposalMethod $method): self
|
||||
{
|
||||
$this->disposalMethod = $method;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get disposal method
|
||||
*/
|
||||
public function getDisposalMethod(): DisposalMethod
|
||||
{
|
||||
return $this->disposalMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get transparent color index
|
||||
*/
|
||||
public function getTransparentColorIndex(): int
|
||||
{
|
||||
return $this->transparentColorIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set transparent color index
|
||||
*/
|
||||
public function setTransparentColorIndex(int $index): self
|
||||
{
|
||||
$this->transparentColorIndex = $index;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current transparent color existance
|
||||
*/
|
||||
public function getTransparentColorExistance(): bool
|
||||
{
|
||||
return $this->transparentColorExistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set existance flag of transparent color
|
||||
*/
|
||||
public function setTransparentColorExistance(bool $existance = true): self
|
||||
{
|
||||
$this->transparentColorExistance = $existance;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user input flag
|
||||
*/
|
||||
public function getUserInput(): bool
|
||||
{
|
||||
return $this->userInput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user input flag
|
||||
*/
|
||||
public function setUserInput(bool $value = true): self
|
||||
{
|
||||
$this->userInput = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
38
upLoadImage/vendor/intervention/gif/src/Blocks/Header.php
vendored
Normal file
38
upLoadImage/vendor/intervention/gif/src/Blocks/Header.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class Header extends AbstractEntity
|
||||
{
|
||||
/**
|
||||
* Header signature
|
||||
*/
|
||||
public const SIGNATURE = 'GIF';
|
||||
|
||||
/**
|
||||
* Current GIF version
|
||||
*/
|
||||
protected string $version = '89a';
|
||||
|
||||
/**
|
||||
* Set GIF version
|
||||
*/
|
||||
public function setVersion(string $value): self
|
||||
{
|
||||
$this->version = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return current version
|
||||
*/
|
||||
public function getVersion(): string
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
}
|
||||
68
upLoadImage/vendor/intervention/gif/src/Blocks/ImageData.php
vendored
Normal file
68
upLoadImage/vendor/intervention/gif/src/Blocks/ImageData.php
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class ImageData extends AbstractEntity
|
||||
{
|
||||
/**
|
||||
* LZW min. code size
|
||||
*/
|
||||
protected int $lzw_min_code_size;
|
||||
|
||||
/**
|
||||
* Sub blocks
|
||||
*
|
||||
* @var array<DataSubBlock>
|
||||
*/
|
||||
protected array $blocks = [];
|
||||
|
||||
/**
|
||||
* Get LZW min. code size
|
||||
*/
|
||||
public function getLzwMinCodeSize(): int
|
||||
{
|
||||
return $this->lzw_min_code_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set lzw min. code size
|
||||
*/
|
||||
public function setLzwMinCodeSize(int $size): self
|
||||
{
|
||||
$this->lzw_min_code_size = $size;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current data sub blocks
|
||||
*
|
||||
* @return array<DataSubBlock>
|
||||
*/
|
||||
public function getBlocks(): array
|
||||
{
|
||||
return $this->blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Addd sub block
|
||||
*/
|
||||
public function addBlock(DataSubBlock $block): self
|
||||
{
|
||||
$this->blocks[] = $block;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if data sub blocks are present
|
||||
*/
|
||||
public function hasBlocks(): bool
|
||||
{
|
||||
return count($this->blocks) >= 1;
|
||||
}
|
||||
}
|
||||
194
upLoadImage/vendor/intervention/gif/src/Blocks/ImageDescriptor.php
vendored
Normal file
194
upLoadImage/vendor/intervention/gif/src/Blocks/ImageDescriptor.php
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class ImageDescriptor extends AbstractEntity
|
||||
{
|
||||
public const SEPARATOR = "\x2C";
|
||||
|
||||
/**
|
||||
* Width of frame
|
||||
*/
|
||||
protected int $width = 0;
|
||||
|
||||
/**
|
||||
* Height of frame
|
||||
*/
|
||||
protected int $height = 0;
|
||||
|
||||
/**
|
||||
* Left position of frame
|
||||
*/
|
||||
protected int $left = 0;
|
||||
|
||||
/**
|
||||
* Top position of frame
|
||||
*/
|
||||
protected int $top = 0;
|
||||
|
||||
/**
|
||||
* Determine if frame is interlaced
|
||||
*/
|
||||
protected bool $interlaced = false;
|
||||
|
||||
/**
|
||||
* Local color table flag
|
||||
*/
|
||||
protected bool $localColorTableExistance = false;
|
||||
|
||||
/**
|
||||
* Sort flag of local color table
|
||||
*/
|
||||
protected bool $localColorTableSorted = false;
|
||||
|
||||
/**
|
||||
* Size of local color table
|
||||
*/
|
||||
protected int $localColorTableSize = 0;
|
||||
|
||||
/**
|
||||
* Get current width
|
||||
*/
|
||||
public function getWidth(): int
|
||||
{
|
||||
return intval($this->width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current width
|
||||
*/
|
||||
public function getHeight(): int
|
||||
{
|
||||
return intval($this->height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current Top
|
||||
*/
|
||||
public function getTop(): int
|
||||
{
|
||||
return intval($this->top);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current Left
|
||||
*/
|
||||
public function getLeft(): int
|
||||
{
|
||||
return intval($this->left);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set size of current instance
|
||||
*/
|
||||
public function setSize(int $width, int $height): self
|
||||
{
|
||||
$this->width = $width;
|
||||
$this->height = $height;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set position of current instance
|
||||
*/
|
||||
public function setPosition(int $left, int $top): self
|
||||
{
|
||||
$this->left = $left;
|
||||
$this->top = $top;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if frame is interlaced
|
||||
*/
|
||||
public function isInterlaced(): bool
|
||||
{
|
||||
return $this->interlaced;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or unset interlaced value
|
||||
*/
|
||||
public function setInterlaced(bool $value = true): self
|
||||
{
|
||||
$this->interlaced = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if local color table is present
|
||||
*/
|
||||
public function getLocalColorTableExistance(): bool
|
||||
{
|
||||
return $this->localColorTableExistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for getLocalColorTableExistance
|
||||
*/
|
||||
public function hasLocalColorTable(): bool
|
||||
{
|
||||
return $this->getLocalColorTableExistance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set local color table flag
|
||||
*/
|
||||
public function setLocalColorTableExistance(bool $existance = true): self
|
||||
{
|
||||
$this->localColorTableExistance = $existance;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get local color table sorted flag
|
||||
*/
|
||||
public function getLocalColorTableSorted(): bool
|
||||
{
|
||||
return $this->localColorTableSorted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set local color table sorted flag
|
||||
*/
|
||||
public function setLocalColorTableSorted(bool $sorted = true): self
|
||||
{
|
||||
$this->localColorTableSorted = $sorted;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size of local color table
|
||||
*/
|
||||
public function getLocalColorTableSize(): int
|
||||
{
|
||||
return $this->localColorTableSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get byte size of global color table
|
||||
*/
|
||||
public function getLocalColorTableByteSize(): int
|
||||
{
|
||||
return 3 * pow(2, $this->getLocalColorTableSize() + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set size of local color table
|
||||
*/
|
||||
public function setLocalColorTableSize(int $size): self
|
||||
{
|
||||
$this->localColorTableSize = $size;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
201
upLoadImage/vendor/intervention/gif/src/Blocks/LogicalScreenDescriptor.php
vendored
Normal file
201
upLoadImage/vendor/intervention/gif/src/Blocks/LogicalScreenDescriptor.php
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class LogicalScreenDescriptor extends AbstractEntity
|
||||
{
|
||||
/**
|
||||
* Width
|
||||
*/
|
||||
protected int $width;
|
||||
|
||||
/**
|
||||
* Height
|
||||
*/
|
||||
protected int $height;
|
||||
|
||||
/**
|
||||
* Global color table flag
|
||||
*/
|
||||
protected bool $globalColorTableExistance = false;
|
||||
|
||||
/**
|
||||
* Sort flag of global color table
|
||||
*/
|
||||
protected bool $globalColorTableSorted = false;
|
||||
|
||||
/**
|
||||
* Size of global color table
|
||||
*/
|
||||
protected int $globalColorTableSize = 0;
|
||||
|
||||
/**
|
||||
* Background color index
|
||||
*/
|
||||
protected int $backgroundColorIndex = 0;
|
||||
|
||||
/**
|
||||
* Color resolution
|
||||
*/
|
||||
protected int $bitsPerPixel = 8;
|
||||
|
||||
/**
|
||||
* Pixel aspect ration
|
||||
*/
|
||||
protected int $pixelAspectRatio = 0;
|
||||
|
||||
/**
|
||||
* Set size
|
||||
*/
|
||||
public function setSize(int $width, int $height): self
|
||||
{
|
||||
$this->width = $width;
|
||||
$this->height = $height;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get width of current instance
|
||||
*/
|
||||
public function getWidth(): int
|
||||
{
|
||||
return intval($this->width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get height of current instance
|
||||
*/
|
||||
public function getHeight(): int
|
||||
{
|
||||
return intval($this->height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if global color table is present
|
||||
*/
|
||||
public function getGlobalColorTableExistance(): bool
|
||||
{
|
||||
return $this->globalColorTableExistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of getGlobalColorTableExistance
|
||||
*/
|
||||
public function hasGlobalColorTable(): bool
|
||||
{
|
||||
return $this->getGlobalColorTableExistance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set global color table flag
|
||||
*/
|
||||
public function setGlobalColorTableExistance(bool $existance = true): self
|
||||
{
|
||||
$this->globalColorTableExistance = $existance;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get global color table sorted flag
|
||||
*/
|
||||
public function getGlobalColorTableSorted(): bool
|
||||
{
|
||||
return $this->globalColorTableSorted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set global color table sorted flag
|
||||
*/
|
||||
public function setGlobalColorTableSorted(bool $sorted = true): self
|
||||
{
|
||||
$this->globalColorTableSorted = $sorted;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size of global color table
|
||||
*/
|
||||
public function getGlobalColorTableSize(): int
|
||||
{
|
||||
return $this->globalColorTableSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get byte size of global color table
|
||||
*/
|
||||
public function getGlobalColorTableByteSize(): int
|
||||
{
|
||||
return 3 * pow(2, $this->getGlobalColorTableSize() + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set size of global color table
|
||||
*/
|
||||
public function setGlobalColorTableSize(int $size): self
|
||||
{
|
||||
$this->globalColorTableSize = $size;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get background color index
|
||||
*/
|
||||
public function getBackgroundColorIndex(): int
|
||||
{
|
||||
return $this->backgroundColorIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color index
|
||||
*/
|
||||
public function setBackgroundColorIndex(int $index): self
|
||||
{
|
||||
$this->backgroundColorIndex = $index;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current pixel aspect ration
|
||||
*/
|
||||
public function getPixelAspectRatio(): int
|
||||
{
|
||||
return $this->pixelAspectRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set pixel aspect ratio
|
||||
*/
|
||||
public function setPixelAspectRatio(int $ratio): self
|
||||
{
|
||||
$this->pixelAspectRatio = $ratio;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get color resolution
|
||||
*/
|
||||
public function getBitsPerPixel(): int
|
||||
{
|
||||
return $this->bitsPerPixel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set color resolution
|
||||
*/
|
||||
public function setBitsPerPixel(int $value): self
|
||||
{
|
||||
$this->bitsPerPixel = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
56
upLoadImage/vendor/intervention/gif/src/Blocks/NetscapeApplicationExtension.php
vendored
Normal file
56
upLoadImage/vendor/intervention/gif/src/Blocks/NetscapeApplicationExtension.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\Exceptions\FormatException;
|
||||
use Intervention\Gif\Exceptions\RuntimeException;
|
||||
|
||||
class NetscapeApplicationExtension extends ApplicationExtension
|
||||
{
|
||||
public const IDENTIFIER = "NETSCAPE";
|
||||
public const AUTH_CODE = "2.0";
|
||||
public const SUB_BLOCK_PREFIX = "\x01";
|
||||
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @throws FormatException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->setApplication(self::IDENTIFIER . self::AUTH_CODE);
|
||||
$this->setBlocks([new DataSubBlock(self::SUB_BLOCK_PREFIX . "\x00\x00")]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of loops
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function getLoops(): int
|
||||
{
|
||||
$unpacked = unpack('v*', substr($this->getFirstBlock()->getValue(), 1));
|
||||
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new RuntimeException('Unable to get loop count.');
|
||||
}
|
||||
|
||||
return $unpacked[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set number of loops
|
||||
*
|
||||
* @throws FormatException
|
||||
*/
|
||||
public function setLoops(int $loops): self
|
||||
{
|
||||
$this->setBlocks([
|
||||
new DataSubBlock(self::SUB_BLOCK_PREFIX . pack('v*', $loops))
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
59
upLoadImage/vendor/intervention/gif/src/Blocks/PlainTextExtension.php
vendored
Normal file
59
upLoadImage/vendor/intervention/gif/src/Blocks/PlainTextExtension.php
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractExtension;
|
||||
|
||||
class PlainTextExtension extends AbstractExtension
|
||||
{
|
||||
public const LABEL = "\x01";
|
||||
|
||||
/**
|
||||
* Array of text
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected array $text = [];
|
||||
|
||||
/**
|
||||
* Get current text
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
public function getText(): array
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add text
|
||||
*/
|
||||
public function addText(string $text): self
|
||||
{
|
||||
$this->text[] = $text;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text array of extension
|
||||
*
|
||||
* @param array<string> $text
|
||||
*/
|
||||
public function setText(array $text): self
|
||||
{
|
||||
$this->text = $text;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if any text is present
|
||||
*/
|
||||
public function hasText(): bool
|
||||
{
|
||||
return $this->text !== [];
|
||||
}
|
||||
}
|
||||
50
upLoadImage/vendor/intervention/gif/src/Blocks/TableBasedImage.php
vendored
Normal file
50
upLoadImage/vendor/intervention/gif/src/Blocks/TableBasedImage.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class TableBasedImage extends AbstractEntity
|
||||
{
|
||||
protected ImageDescriptor $imageDescriptor;
|
||||
protected ?ColorTable $colorTable = null;
|
||||
protected ImageData $imageData;
|
||||
|
||||
public function getImageDescriptor(): ImageDescriptor
|
||||
{
|
||||
return $this->imageDescriptor;
|
||||
}
|
||||
|
||||
public function setImageDescriptor(ImageDescriptor $descriptor): self
|
||||
{
|
||||
$this->imageDescriptor = $descriptor;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getImageData(): ImageData
|
||||
{
|
||||
return $this->imageData;
|
||||
}
|
||||
|
||||
public function setImageData(ImageData $data): self
|
||||
{
|
||||
$this->imageData = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getColorTable(): ?ColorTable
|
||||
{
|
||||
return $this->colorTable;
|
||||
}
|
||||
|
||||
public function setColorTable(ColorTable $table): self
|
||||
{
|
||||
$this->colorTable = $table;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
12
upLoadImage/vendor/intervention/gif/src/Blocks/Trailer.php
vendored
Normal file
12
upLoadImage/vendor/intervention/gif/src/Blocks/Trailer.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class Trailer extends AbstractEntity
|
||||
{
|
||||
public const MARKER = "\x3b";
|
||||
}
|
||||
204
upLoadImage/vendor/intervention/gif/src/Builder.php
vendored
Normal file
204
upLoadImage/vendor/intervention/gif/src/Builder.php
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif;
|
||||
|
||||
use Exception;
|
||||
use Intervention\Gif\Blocks\FrameBlock;
|
||||
use Intervention\Gif\Blocks\GraphicControlExtension;
|
||||
use Intervention\Gif\Blocks\ImageDescriptor;
|
||||
use Intervention\Gif\Blocks\NetscapeApplicationExtension;
|
||||
use Intervention\Gif\Blocks\TableBasedImage;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
use Intervention\Gif\Exceptions\EncoderException;
|
||||
use Intervention\Gif\Traits\CanHandleFiles;
|
||||
|
||||
class Builder
|
||||
{
|
||||
use CanHandleFiles;
|
||||
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(protected GifDataStream $gif = new GifDataStream())
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new canvas
|
||||
*/
|
||||
public static function canvas(int $width, int $height): self
|
||||
{
|
||||
return (new self())->setSize($width, $height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get GifDataStream object we're currently building
|
||||
*/
|
||||
public function getGifDataStream(): GifDataStream
|
||||
{
|
||||
return $this->gif;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set canvas size of gif
|
||||
*/
|
||||
public function setSize(int $width, int $height): self
|
||||
{
|
||||
$this->gif->getLogicalScreenDescriptor()->setSize($width, $height);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set loop count
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setLoops(int $loops): self
|
||||
{
|
||||
if ($loops < 0) {
|
||||
throw new Exception('The loop count must be equal to or greater than 0');
|
||||
}
|
||||
|
||||
if ($this->gif->getFrames() === []) {
|
||||
throw new Exception('Add at least one frame before setting the loop count');
|
||||
}
|
||||
|
||||
// with one single loop the netscape extension must be removed otherwise the
|
||||
// gif is looped twice because the first repetition always takes place
|
||||
if ($loops === 1) {
|
||||
$this->gif->getFirstFrame()?->clearApplicationExtensions();
|
||||
return $this;
|
||||
}
|
||||
|
||||
// make sure a netscape extension is present to store the loop count
|
||||
if (!$this->gif->getFirstFrame()?->getNetscapeExtension()) {
|
||||
$this->gif->getFirstFrame()?->addApplicationExtension(
|
||||
new NetscapeApplicationExtension()
|
||||
);
|
||||
}
|
||||
|
||||
// the loop count is reduced by one because what is referred to here as
|
||||
// the “loop count” actually means repetitions in GIF format, and thus
|
||||
// the first repetition always takes place. A loop count of 0 howerver
|
||||
// means infinite repetitions and remains unaltered.
|
||||
$loops = $loops === 0 ? $loops : $loops - 1;
|
||||
|
||||
// add loop count to netscape extension on first frame
|
||||
$this->gif->getFirstFrame()?->getNetscapeExtension()?->setLoops($loops);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new animation frame from given source
|
||||
* which can be path to a file or GIF image data
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public function addFrame(
|
||||
mixed $source,
|
||||
float $delay = 0,
|
||||
int $left = 0,
|
||||
int $top = 0,
|
||||
bool $interlaced = false
|
||||
): self {
|
||||
$frame = new FrameBlock();
|
||||
$source = Decoder::decode($source);
|
||||
|
||||
// store delay
|
||||
$frame->setGraphicControlExtension(
|
||||
$this->buildGraphicControlExtension(
|
||||
$source,
|
||||
intval($delay * 100)
|
||||
)
|
||||
);
|
||||
|
||||
// store image
|
||||
$frame->setTableBasedImage(
|
||||
$this->buildTableBasedImage($source, $left, $top, $interlaced)
|
||||
);
|
||||
|
||||
// add frame
|
||||
$this->gif->addFrame($frame);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build new graphic control extension with given delay & disposal method
|
||||
*/
|
||||
protected function buildGraphicControlExtension(
|
||||
GifDataStream $source,
|
||||
int $delay,
|
||||
DisposalMethod $disposalMethod = DisposalMethod::BACKGROUND
|
||||
): GraphicControlExtension {
|
||||
// create extension
|
||||
$extension = new GraphicControlExtension($delay, $disposalMethod);
|
||||
|
||||
// set transparency index
|
||||
$control = $source->getFirstFrame()->getGraphicControlExtension();
|
||||
if ($control && $control->getTransparentColorExistance()) {
|
||||
$extension->setTransparentColorExistance();
|
||||
$extension->setTransparentColorIndex(
|
||||
$control->getTransparentColorIndex()
|
||||
);
|
||||
}
|
||||
|
||||
return $extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build table based image object from given source
|
||||
*/
|
||||
protected function buildTableBasedImage(
|
||||
GifDataStream $source,
|
||||
int $left,
|
||||
int $top,
|
||||
bool $interlaced
|
||||
): TableBasedImage {
|
||||
$block = new TableBasedImage();
|
||||
$block->setImageDescriptor(new ImageDescriptor());
|
||||
|
||||
// set global color table from source as local color table
|
||||
$block->getImageDescriptor()->setLocalColorTableExistance();
|
||||
$block->setColorTable($source->getGlobalColorTable());
|
||||
|
||||
$block->getImageDescriptor()->setLocalColorTableSorted(
|
||||
$source->getLogicalScreenDescriptor()->getGlobalColorTableSorted()
|
||||
);
|
||||
|
||||
$block->getImageDescriptor()->setLocalColorTableSize(
|
||||
$source->getLogicalScreenDescriptor()->getGlobalColorTableSize()
|
||||
);
|
||||
|
||||
$block->getImageDescriptor()->setSize(
|
||||
$source->getLogicalScreenDescriptor()->getWidth(),
|
||||
$source->getLogicalScreenDescriptor()->getHeight()
|
||||
);
|
||||
|
||||
// set position
|
||||
$block->getImageDescriptor()->setPosition($left, $top);
|
||||
|
||||
// set interlaced flag
|
||||
$block->getImageDescriptor()->setInterlaced($interlaced);
|
||||
|
||||
// add image data from source
|
||||
$block->setImageData($source->getFirstFrame()->getImageData());
|
||||
|
||||
return $block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the current build
|
||||
*
|
||||
* @throws EncoderException
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return $this->gif->encode();
|
||||
}
|
||||
}
|
||||
47
upLoadImage/vendor/intervention/gif/src/Decoder.php
vendored
Normal file
47
upLoadImage/vendor/intervention/gif/src/Decoder.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif;
|
||||
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
use Intervention\Gif\Exceptions\RuntimeException;
|
||||
use Intervention\Gif\Traits\CanHandleFiles;
|
||||
|
||||
class Decoder
|
||||
{
|
||||
use CanHandleFiles;
|
||||
|
||||
/**
|
||||
* Decode given input
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public static function decode(mixed $input): GifDataStream
|
||||
{
|
||||
try {
|
||||
$handle = match (true) {
|
||||
self::isFilePath($input) => self::getHandleFromFilePath($input),
|
||||
is_string($input) => self::getHandleFromData($input),
|
||||
self::isFileHandle($input) => $input,
|
||||
default => throw new DecoderException(
|
||||
'Decoder input must be either file path, file pointer resource or binary data.'
|
||||
)
|
||||
};
|
||||
} catch (RuntimeException $e) {
|
||||
throw new DecoderException($e->getMessage());
|
||||
}
|
||||
|
||||
rewind($handle);
|
||||
|
||||
return GifDataStream::decode($handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if input is file pointer resource
|
||||
*/
|
||||
private static function isFileHandle(mixed $input): bool
|
||||
{
|
||||
return is_resource($input) && get_resource_type($input) === 'stream';
|
||||
}
|
||||
}
|
||||
159
upLoadImage/vendor/intervention/gif/src/Decoders/AbstractDecoder.php
vendored
Normal file
159
upLoadImage/vendor/intervention/gif/src/Decoders/AbstractDecoder.php
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
|
||||
abstract class AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current source
|
||||
*/
|
||||
abstract public function decode(): mixed;
|
||||
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(protected mixed $handle, protected ?int $length = null)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Set source to decode
|
||||
*/
|
||||
public function setHandle(mixed $handle): self
|
||||
{
|
||||
$this->handle = $handle;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read given number of bytes and move file pointer
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function getNextBytesOrFail(int $length): string
|
||||
{
|
||||
if ($length < 1) {
|
||||
throw new DecoderException('The length passed must be at least one byte.');
|
||||
}
|
||||
|
||||
$bytes = fread($this->handle, $length);
|
||||
if ($bytes === false || strlen($bytes) !== $length) {
|
||||
throw new DecoderException('Unexpected end of file.');
|
||||
}
|
||||
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read given number of bytes and move pointer back to previous position
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function viewNextBytesOrFail(int $length): string
|
||||
{
|
||||
$bytes = $this->getNextBytesOrFail($length);
|
||||
$this->movePointer($length * -1);
|
||||
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read next byte and move pointer back to previous position
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function viewNextByteOrFail(): string
|
||||
{
|
||||
return $this->viewNextBytesOrFail(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all remaining bytes from file handler
|
||||
*/
|
||||
protected function getRemainingBytes(): string
|
||||
{
|
||||
$all = '';
|
||||
do {
|
||||
$byte = fread($this->handle, 1);
|
||||
$all .= $byte;
|
||||
} while (!feof($this->handle));
|
||||
|
||||
return $all;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next byte in stream and move file pointer
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function getNextByteOrFail(): string
|
||||
{
|
||||
return $this->getNextBytesOrFail(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move file pointer on handle by given offset
|
||||
*/
|
||||
protected function movePointer(int $offset): self
|
||||
{
|
||||
fseek($this->handle, $offset, SEEK_CUR);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode multi byte value
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeMultiByte(string $bytes): int
|
||||
{
|
||||
$unpacked = unpack('v*', $bytes);
|
||||
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to decode given bytes.');
|
||||
}
|
||||
|
||||
return $unpacked[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set length
|
||||
*/
|
||||
public function setLength(int $length): self
|
||||
{
|
||||
$this->length = $length;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get length
|
||||
*/
|
||||
public function getLength(): ?int
|
||||
{
|
||||
return $this->length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current handle position
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public function getPosition(): int
|
||||
{
|
||||
$position = ftell($this->handle);
|
||||
|
||||
if ($position === false) {
|
||||
throw new DecoderException('Unable to read current position from handle.');
|
||||
}
|
||||
|
||||
return $position;
|
||||
}
|
||||
}
|
||||
47
upLoadImage/vendor/intervention/gif/src/Decoders/AbstractPackedBitDecoder.php
vendored
Normal file
47
upLoadImage/vendor/intervention/gif/src/Decoders/AbstractPackedBitDecoder.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
|
||||
abstract class AbstractPackedBitDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode packed byte
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodePackedByte(string $byte): int
|
||||
{
|
||||
$unpacked = unpack('C', $byte);
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to get info block size.');
|
||||
}
|
||||
|
||||
return intval($unpacked[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if packed bit is set
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function hasPackedBit(string $byte, int $num): bool
|
||||
{
|
||||
return (bool) $this->getPackedBits($byte)[$num];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get packed bits
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function getPackedBits(string $byte, int $start = 0, int $length = 8): string
|
||||
{
|
||||
$bits = str_pad(decbin($this->decodePackedByte($byte)), 8, '0', STR_PAD_LEFT);
|
||||
|
||||
return substr($bits, $start, $length);
|
||||
}
|
||||
}
|
||||
75
upLoadImage/vendor/intervention/gif/src/Decoders/ApplicationExtensionDecoder.php
vendored
Normal file
75
upLoadImage/vendor/intervention/gif/src/Decoders/ApplicationExtensionDecoder.php
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\ApplicationExtension;
|
||||
use Intervention\Gif\Blocks\DataSubBlock;
|
||||
use Intervention\Gif\Blocks\NetscapeApplicationExtension;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
use Intervention\Gif\Exceptions\FormatException;
|
||||
|
||||
class ApplicationExtensionDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current source
|
||||
*
|
||||
* @throws FormatException
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public function decode(): ApplicationExtension
|
||||
{
|
||||
$result = new ApplicationExtension();
|
||||
|
||||
$this->getNextByteOrFail(); // marker
|
||||
$this->getNextByteOrFail(); // label
|
||||
$blocksize = $this->decodeBlockSize($this->getNextByteOrFail());
|
||||
$application = $this->getNextBytesOrFail($blocksize);
|
||||
|
||||
if ($application === NetscapeApplicationExtension::IDENTIFIER . NetscapeApplicationExtension::AUTH_CODE) {
|
||||
$result = new NetscapeApplicationExtension();
|
||||
|
||||
// skip length
|
||||
$this->getNextByteOrFail();
|
||||
|
||||
$result->setBlocks([
|
||||
new DataSubBlock(
|
||||
$this->getNextBytesOrFail(3)
|
||||
)
|
||||
]);
|
||||
|
||||
// skip terminator
|
||||
$this->getNextByteOrFail();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result->setApplication($application);
|
||||
|
||||
// decode data sub blocks
|
||||
$blocksize = $this->decodeBlockSize($this->getNextByteOrFail());
|
||||
while ($blocksize > 0) {
|
||||
$result->addBlock(new DataSubBlock($this->getNextBytesOrFail($blocksize)));
|
||||
$blocksize = $this->decodeBlockSize($this->getNextByteOrFail());
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode block size of ApplicationExtension from given byte
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeBlockSize(string $byte): int
|
||||
{
|
||||
$unpacked = @unpack('C', $byte);
|
||||
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to decode application extension block size.');
|
||||
}
|
||||
|
||||
return intval($unpacked[1]);
|
||||
}
|
||||
}
|
||||
42
upLoadImage/vendor/intervention/gif/src/Decoders/ColorDecoder.php
vendored
Normal file
42
upLoadImage/vendor/intervention/gif/src/Decoders/ColorDecoder.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\Color;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
|
||||
class ColorDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current source to Color
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public function decode(): Color
|
||||
{
|
||||
$color = new Color();
|
||||
|
||||
$color->setRed($this->decodeColorValue($this->getNextByteOrFail()));
|
||||
$color->setGreen($this->decodeColorValue($this->getNextByteOrFail()));
|
||||
$color->setBlue($this->decodeColorValue($this->getNextByteOrFail()));
|
||||
|
||||
return $color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode red value from source
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeColorValue(string $byte): int
|
||||
{
|
||||
$unpacked = unpack('C', $byte);
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to decode color value.');
|
||||
}
|
||||
|
||||
return $unpacked[1];
|
||||
}
|
||||
}
|
||||
27
upLoadImage/vendor/intervention/gif/src/Decoders/ColorTableDecoder.php
vendored
Normal file
27
upLoadImage/vendor/intervention/gif/src/Decoders/ColorTableDecoder.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\Color;
|
||||
use Intervention\Gif\Blocks\ColorTable;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
|
||||
class ColorTableDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode given string to ColorTable
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public function decode(): ColorTable
|
||||
{
|
||||
$table = new ColorTable();
|
||||
for ($i = 0; $i < ($this->getLength() / 3); $i++) {
|
||||
$table->addColor(Color::decode($this->handle));
|
||||
}
|
||||
|
||||
return $table;
|
||||
}
|
||||
}
|
||||
65
upLoadImage/vendor/intervention/gif/src/Decoders/CommentExtensionDecoder.php
vendored
Normal file
65
upLoadImage/vendor/intervention/gif/src/Decoders/CommentExtensionDecoder.php
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\CommentExtension;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
|
||||
class CommentExtensionDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current source
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public function decode(): CommentExtension
|
||||
{
|
||||
$this->getNextBytesOrFail(2); // skip marker & label
|
||||
|
||||
$extension = new CommentExtension();
|
||||
foreach ($this->decodeComments() as $comment) {
|
||||
$extension->addComment($comment);
|
||||
}
|
||||
|
||||
return $extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode comment from current source
|
||||
*
|
||||
* @throws DecoderException
|
||||
* @return array<string>
|
||||
*/
|
||||
protected function decodeComments(): array
|
||||
{
|
||||
$comments = [];
|
||||
|
||||
do {
|
||||
$byte = $this->getNextByteOrFail();
|
||||
$size = $this->decodeBlocksize($byte);
|
||||
if ($size > 0) {
|
||||
$comments[] = $this->getNextBytesOrFail($size);
|
||||
}
|
||||
} while ($byte !== CommentExtension::TERMINATOR);
|
||||
|
||||
return $comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode blocksize of following comment
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeBlocksize(string $byte): int
|
||||
{
|
||||
$unpacked = @unpack('C', $byte);
|
||||
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to decode comment extension block size.');
|
||||
}
|
||||
|
||||
return intval($unpacked[1]);
|
||||
}
|
||||
}
|
||||
31
upLoadImage/vendor/intervention/gif/src/Decoders/DataSubBlockDecoder.php
vendored
Normal file
31
upLoadImage/vendor/intervention/gif/src/Decoders/DataSubBlockDecoder.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\DataSubBlock;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
use Intervention\Gif\Exceptions\FormatException;
|
||||
|
||||
class DataSubBlockDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current sourc
|
||||
*
|
||||
* @throws FormatException
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public function decode(): DataSubBlock
|
||||
{
|
||||
$char = $this->getNextByteOrFail();
|
||||
$unpacked = unpack('C', $char);
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to decode data sub block.');
|
||||
}
|
||||
|
||||
$size = (int) $unpacked[1];
|
||||
|
||||
return new DataSubBlock($this->getNextBytesOrFail($size));
|
||||
}
|
||||
}
|
||||
52
upLoadImage/vendor/intervention/gif/src/Decoders/FrameBlockDecoder.php
vendored
Normal file
52
upLoadImage/vendor/intervention/gif/src/Decoders/FrameBlockDecoder.php
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\AbstractExtension;
|
||||
use Intervention\Gif\Blocks\ApplicationExtension;
|
||||
use Intervention\Gif\Blocks\CommentExtension;
|
||||
use Intervention\Gif\Blocks\FrameBlock;
|
||||
use Intervention\Gif\Blocks\GraphicControlExtension;
|
||||
use Intervention\Gif\Blocks\ImageDescriptor;
|
||||
use Intervention\Gif\Blocks\NetscapeApplicationExtension;
|
||||
use Intervention\Gif\Blocks\PlainTextExtension;
|
||||
use Intervention\Gif\Blocks\TableBasedImage;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
|
||||
class FrameBlockDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode FrameBlock
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public function decode(): FrameBlock
|
||||
{
|
||||
$frame = new FrameBlock();
|
||||
|
||||
do {
|
||||
$block = match ($this->viewNextBytesOrFail(2)) {
|
||||
AbstractExtension::MARKER . GraphicControlExtension::LABEL
|
||||
=> GraphicControlExtension::decode($this->handle),
|
||||
AbstractExtension::MARKER . NetscapeApplicationExtension::LABEL
|
||||
=> NetscapeApplicationExtension::decode($this->handle),
|
||||
AbstractExtension::MARKER . ApplicationExtension::LABEL
|
||||
=> ApplicationExtension::decode($this->handle),
|
||||
AbstractExtension::MARKER . PlainTextExtension::LABEL
|
||||
=> PlainTextExtension::decode($this->handle),
|
||||
AbstractExtension::MARKER . CommentExtension::LABEL
|
||||
=> CommentExtension::decode($this->handle),
|
||||
default => match ($this->viewNextByteOrFail()) {
|
||||
ImageDescriptor::SEPARATOR => TableBasedImage::decode($this->handle),
|
||||
default => throw new DecoderException('Unable to decode Data Block'),
|
||||
}
|
||||
};
|
||||
|
||||
$frame->addEntity($block);
|
||||
} while (!($block instanceof TableBasedImage));
|
||||
|
||||
return $frame;
|
||||
}
|
||||
}
|
||||
58
upLoadImage/vendor/intervention/gif/src/Decoders/GifDataStreamDecoder.php
vendored
Normal file
58
upLoadImage/vendor/intervention/gif/src/Decoders/GifDataStreamDecoder.php
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\AbstractExtension;
|
||||
use Intervention\Gif\Blocks\ColorTable;
|
||||
use Intervention\Gif\Blocks\CommentExtension;
|
||||
use Intervention\Gif\Blocks\FrameBlock;
|
||||
use Intervention\Gif\Blocks\Header;
|
||||
use Intervention\Gif\Blocks\LogicalScreenDescriptor;
|
||||
use Intervention\Gif\Blocks\Trailer;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
use Intervention\Gif\GifDataStream;
|
||||
|
||||
class GifDataStreamDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current source to GifDataStream
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public function decode(): GifDataStream
|
||||
{
|
||||
$gif = new GifDataStream();
|
||||
|
||||
$gif->setHeader(
|
||||
Header::decode($this->handle),
|
||||
);
|
||||
|
||||
$gif->setLogicalScreenDescriptor(
|
||||
LogicalScreenDescriptor::decode($this->handle),
|
||||
);
|
||||
|
||||
if ($gif->getLogicalScreenDescriptor()->hasGlobalColorTable()) {
|
||||
$length = $gif->getLogicalScreenDescriptor()->getGlobalColorTableByteSize();
|
||||
$gif->setGlobalColorTable(
|
||||
ColorTable::decode($this->handle, $length)
|
||||
);
|
||||
}
|
||||
|
||||
while ($this->viewNextByteOrFail() !== Trailer::MARKER) {
|
||||
match ($this->viewNextBytesOrFail(2)) {
|
||||
// trailing "global" comment blocks which are not part of "FrameBlock"
|
||||
AbstractExtension::MARKER . CommentExtension::LABEL
|
||||
=> $gif->addComment(
|
||||
CommentExtension::decode($this->handle)
|
||||
),
|
||||
default => $gif->addFrame(
|
||||
FrameBlock::decode($this->handle)
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
return $gif;
|
||||
}
|
||||
}
|
||||
106
upLoadImage/vendor/intervention/gif/src/Decoders/GraphicControlExtensionDecoder.php
vendored
Normal file
106
upLoadImage/vendor/intervention/gif/src/Decoders/GraphicControlExtensionDecoder.php
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\GraphicControlExtension;
|
||||
use Intervention\Gif\DisposalMethod;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
|
||||
class GraphicControlExtensionDecoder extends AbstractPackedBitDecoder
|
||||
{
|
||||
/**
|
||||
* Decode given string to current instance
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public function decode(): GraphicControlExtension
|
||||
{
|
||||
$result = new GraphicControlExtension();
|
||||
|
||||
// bytes 1-3
|
||||
$this->getNextBytesOrFail(3); // skip marker, label & bytesize
|
||||
|
||||
// byte #4
|
||||
$packedField = $this->getNextByteOrFail();
|
||||
$result->setDisposalMethod($this->decodeDisposalMethod($packedField));
|
||||
$result->setUserInput($this->decodeUserInput($packedField));
|
||||
$result->setTransparentColorExistance($this->decodeTransparentColorExistance($packedField));
|
||||
|
||||
// bytes 5-6
|
||||
$result->setDelay($this->decodeDelay($this->getNextBytesOrFail(2)));
|
||||
|
||||
// byte #7
|
||||
$result->setTransparentColorIndex($this->decodeTransparentColorIndex(
|
||||
$this->getNextByteOrFail()
|
||||
));
|
||||
|
||||
// byte #8 (terminator)
|
||||
$this->getNextByteOrFail();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode disposal method
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeDisposalMethod(string $byte): DisposalMethod
|
||||
{
|
||||
return DisposalMethod::from(
|
||||
intval(bindec($this->getPackedBits($byte, 3, 3)))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode user input flag
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeUserInput(string $byte): bool
|
||||
{
|
||||
return $this->hasPackedBit($byte, 6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode transparent color existance
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeTransparentColorExistance(string $byte): bool
|
||||
{
|
||||
return $this->hasPackedBit($byte, 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode delay value
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeDelay(string $bytes): int
|
||||
{
|
||||
$unpacked = unpack('v*', $bytes);
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to decode animation delay.');
|
||||
}
|
||||
|
||||
return $unpacked[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode transparent color index
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeTransparentColorIndex(string $byte): int
|
||||
{
|
||||
$unpacked = unpack('C', $byte);
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to decode transparent color index.');
|
||||
}
|
||||
|
||||
return $unpacked[1];
|
||||
}
|
||||
}
|
||||
40
upLoadImage/vendor/intervention/gif/src/Decoders/HeaderDecoder.php
vendored
Normal file
40
upLoadImage/vendor/intervention/gif/src/Decoders/HeaderDecoder.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
use Intervention\Gif\Blocks\Header;
|
||||
|
||||
class HeaderDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current sourc
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public function decode(): Header
|
||||
{
|
||||
$header = new Header();
|
||||
$header->setVersion($this->decodeVersion());
|
||||
|
||||
return $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode version string
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeVersion(): string
|
||||
{
|
||||
$parsed = (bool) preg_match("/^GIF(?P<version>[0-9]{2}[a-z])$/", $this->getNextBytesOrFail(6), $matches);
|
||||
|
||||
if ($parsed === false) {
|
||||
throw new DecoderException('Unable to parse file header.');
|
||||
}
|
||||
|
||||
return $matches['version'];
|
||||
}
|
||||
}
|
||||
51
upLoadImage/vendor/intervention/gif/src/Decoders/ImageDataDecoder.php
vendored
Normal file
51
upLoadImage/vendor/intervention/gif/src/Decoders/ImageDataDecoder.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
use Intervention\Gif\Blocks\DataSubBlock;
|
||||
use Intervention\Gif\Blocks\ImageData;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
use Intervention\Gif\Exceptions\FormatException;
|
||||
|
||||
class ImageDataDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current source
|
||||
*
|
||||
* @throws DecoderException
|
||||
* @throws FormatException
|
||||
*/
|
||||
public function decode(): ImageData
|
||||
{
|
||||
$data = new ImageData();
|
||||
|
||||
// LZW min. code size
|
||||
$char = $this->getNextByteOrFail();
|
||||
$unpacked = unpack('C', $char);
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to decode lzw min. code size.');
|
||||
}
|
||||
|
||||
$data->setLzwMinCodeSize(intval($unpacked[1]));
|
||||
|
||||
do {
|
||||
// decode sub blocks
|
||||
$char = $this->getNextByteOrFail();
|
||||
$unpacked = unpack('C', $char);
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to decode image data sub block.');
|
||||
}
|
||||
|
||||
$size = intval($unpacked[1]);
|
||||
|
||||
if ($size > 0) {
|
||||
$data->addBlock(new DataSubBlock($this->getNextBytesOrFail($size)));
|
||||
}
|
||||
} while ($char !== AbstractEntity::TERMINATOR);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
93
upLoadImage/vendor/intervention/gif/src/Decoders/ImageDescriptorDecoder.php
vendored
Normal file
93
upLoadImage/vendor/intervention/gif/src/Decoders/ImageDescriptorDecoder.php
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\ImageDescriptor;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
|
||||
class ImageDescriptorDecoder extends AbstractPackedBitDecoder
|
||||
{
|
||||
/**
|
||||
* Decode given string to current instance
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public function decode(): ImageDescriptor
|
||||
{
|
||||
$descriptor = new ImageDescriptor();
|
||||
|
||||
$this->getNextByteOrFail(); // skip separator
|
||||
|
||||
$descriptor->setPosition(
|
||||
$this->decodeMultiByte($this->getNextBytesOrFail(2)),
|
||||
$this->decodeMultiByte($this->getNextBytesOrFail(2))
|
||||
);
|
||||
|
||||
$descriptor->setSize(
|
||||
$this->decodeMultiByte($this->getNextBytesOrFail(2)),
|
||||
$this->decodeMultiByte($this->getNextBytesOrFail(2))
|
||||
);
|
||||
|
||||
$packedField = $this->getNextByteOrFail();
|
||||
|
||||
$descriptor->setLocalColorTableExistance(
|
||||
$this->decodeLocalColorTableExistance($packedField)
|
||||
);
|
||||
|
||||
$descriptor->setLocalColorTableSorted(
|
||||
$this->decodeLocalColorTableSorted($packedField)
|
||||
);
|
||||
|
||||
$descriptor->setLocalColorTableSize(
|
||||
$this->decodeLocalColorTableSize($packedField)
|
||||
);
|
||||
|
||||
$descriptor->setInterlaced(
|
||||
$this->decodeInterlaced($packedField)
|
||||
);
|
||||
|
||||
return $descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode local color table existance
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeLocalColorTableExistance(string $byte): bool
|
||||
{
|
||||
return $this->hasPackedBit($byte, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode local color table sort method
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeLocalColorTableSorted(string $byte): bool
|
||||
{
|
||||
return $this->hasPackedBit($byte, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode local color table size
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeLocalColorTableSize(string $byte): int
|
||||
{
|
||||
return (int) bindec($this->getPackedBits($byte, 5, 3));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode interlaced flag
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeInterlaced(string $byte): bool
|
||||
{
|
||||
return $this->hasPackedBit($byte, 1);
|
||||
}
|
||||
}
|
||||
162
upLoadImage/vendor/intervention/gif/src/Decoders/LogicalScreenDescriptorDecoder.php
vendored
Normal file
162
upLoadImage/vendor/intervention/gif/src/Decoders/LogicalScreenDescriptorDecoder.php
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\LogicalScreenDescriptor;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
|
||||
class LogicalScreenDescriptorDecoder extends AbstractPackedBitDecoder
|
||||
{
|
||||
/**
|
||||
* Decode given string to current instance
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public function decode(): LogicalScreenDescriptor
|
||||
{
|
||||
$logicalScreenDescriptor = new LogicalScreenDescriptor();
|
||||
|
||||
// bytes 1-4
|
||||
$logicalScreenDescriptor->setSize(
|
||||
$this->decodeWidth($this->getNextBytesOrFail(2)),
|
||||
$this->decodeHeight($this->getNextBytesOrFail(2))
|
||||
);
|
||||
|
||||
// byte 5
|
||||
$packedField = $this->getNextByteOrFail();
|
||||
|
||||
$logicalScreenDescriptor->setGlobalColorTableExistance(
|
||||
$this->decodeGlobalColorTableExistance($packedField)
|
||||
);
|
||||
|
||||
$logicalScreenDescriptor->setBitsPerPixel(
|
||||
$this->decodeBitsPerPixel($packedField)
|
||||
);
|
||||
|
||||
$logicalScreenDescriptor->setGlobalColorTableSorted(
|
||||
$this->decodeGlobalColorTableSorted($packedField)
|
||||
);
|
||||
|
||||
$logicalScreenDescriptor->setGlobalColorTableSize(
|
||||
$this->decodeGlobalColorTableSize($packedField)
|
||||
);
|
||||
|
||||
// byte 6
|
||||
$logicalScreenDescriptor->setBackgroundColorIndex(
|
||||
$this->decodeBackgroundColorIndex($this->getNextByteOrFail())
|
||||
);
|
||||
|
||||
// byte 7
|
||||
$logicalScreenDescriptor->setPixelAspectRatio(
|
||||
$this->decodePixelAspectRatio($this->getNextByteOrFail())
|
||||
);
|
||||
|
||||
return $logicalScreenDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode width
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeWidth(string $source): int
|
||||
{
|
||||
$unpacked = unpack('v*', $source);
|
||||
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to decode width.');
|
||||
}
|
||||
|
||||
return $unpacked[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode height
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeHeight(string $source): int
|
||||
{
|
||||
$unpacked = unpack('v*', $source);
|
||||
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to decode height.');
|
||||
}
|
||||
|
||||
return $unpacked[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode existance of global color table
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeGlobalColorTableExistance(string $byte): bool
|
||||
{
|
||||
return $this->hasPackedBit($byte, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode color resolution in bits per pixel
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeBitsPerPixel(string $byte): int
|
||||
{
|
||||
return intval(bindec($this->getPackedBits($byte, 1, 3))) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode global color table sorted status
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeGlobalColorTableSorted(string $byte): bool
|
||||
{
|
||||
return $this->hasPackedBit($byte, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode size of global color table
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeGlobalColorTableSize(string $byte): int
|
||||
{
|
||||
return intval(bindec($this->getPackedBits($byte, 5, 3)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode background color index
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodeBackgroundColorIndex(string $source): int
|
||||
{
|
||||
$unpacked = unpack('C', $source);
|
||||
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to decode background color index.');
|
||||
}
|
||||
|
||||
return $unpacked[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode pixel aspect ratio
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function decodePixelAspectRatio(string $source): int
|
||||
{
|
||||
$unpacked = unpack('C', $source);
|
||||
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to decode pixel aspect ratio.');
|
||||
}
|
||||
|
||||
return $unpacked[1];
|
||||
}
|
||||
}
|
||||
9
upLoadImage/vendor/intervention/gif/src/Decoders/NetscapeApplicationExtensionDecoder.php
vendored
Normal file
9
upLoadImage/vendor/intervention/gif/src/Decoders/NetscapeApplicationExtensionDecoder.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
class NetscapeApplicationExtensionDecoder extends ApplicationExtensionDecoder
|
||||
{
|
||||
}
|
||||
74
upLoadImage/vendor/intervention/gif/src/Decoders/PlainTextExtensionDecoder.php
vendored
Normal file
74
upLoadImage/vendor/intervention/gif/src/Decoders/PlainTextExtensionDecoder.php
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\PlainTextExtension;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
|
||||
class PlainTextExtensionDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current source
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public function decode(): PlainTextExtension
|
||||
{
|
||||
$extension = new PlainTextExtension();
|
||||
|
||||
// skip marker & label
|
||||
$this->getNextBytesOrFail(2);
|
||||
|
||||
// skip info block
|
||||
$this->getNextBytesOrFail($this->getInfoBlockSize());
|
||||
|
||||
// text blocks
|
||||
$extension->setText($this->decodeTextBlocks());
|
||||
|
||||
return $extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of bytes in header block
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected function getInfoBlockSize(): int
|
||||
{
|
||||
$unpacked = unpack('C', $this->getNextByteOrFail());
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to decode info block size.');
|
||||
}
|
||||
|
||||
return $unpacked[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode text sub blocks
|
||||
*
|
||||
* @throws DecoderException
|
||||
* @return array<string>
|
||||
*/
|
||||
protected function decodeTextBlocks(): array
|
||||
{
|
||||
$blocks = [];
|
||||
|
||||
do {
|
||||
$char = $this->getNextByteOrFail();
|
||||
$unpacked = unpack('C', $char);
|
||||
if ($unpacked === false || !array_key_exists(1, $unpacked)) {
|
||||
throw new DecoderException('Unable to decode text block.');
|
||||
}
|
||||
|
||||
$size = (int) $unpacked[1];
|
||||
|
||||
if ($size > 0) {
|
||||
$blocks[] = $this->getNextBytesOrFail($size);
|
||||
}
|
||||
} while ($char !== PlainTextExtension::TERMINATOR);
|
||||
|
||||
return $blocks;
|
||||
}
|
||||
}
|
||||
41
upLoadImage/vendor/intervention/gif/src/Decoders/TableBasedImageDecoder.php
vendored
Normal file
41
upLoadImage/vendor/intervention/gif/src/Decoders/TableBasedImageDecoder.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\ColorTable;
|
||||
use Intervention\Gif\Blocks\ImageData;
|
||||
use Intervention\Gif\Blocks\ImageDescriptor;
|
||||
use Intervention\Gif\Blocks\TableBasedImage;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
|
||||
class TableBasedImageDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode TableBasedImage
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public function decode(): TableBasedImage
|
||||
{
|
||||
$block = new TableBasedImage();
|
||||
|
||||
$block->setImageDescriptor(ImageDescriptor::decode($this->handle));
|
||||
|
||||
if ($block->getImageDescriptor()->hasLocalColorTable()) {
|
||||
$block->setColorTable(
|
||||
ColorTable::decode(
|
||||
$this->handle,
|
||||
$block->getImageDescriptor()->getLocalColorTableByteSize()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$block->setImageData(
|
||||
ImageData::decode($this->handle)
|
||||
);
|
||||
|
||||
return $block;
|
||||
}
|
||||
}
|
||||
13
upLoadImage/vendor/intervention/gif/src/DisposalMethod.php
vendored
Normal file
13
upLoadImage/vendor/intervention/gif/src/DisposalMethod.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif;
|
||||
|
||||
enum DisposalMethod: int
|
||||
{
|
||||
case UNDEFINED = 0;
|
||||
case NONE = 1; // overlay each frame in sequence
|
||||
case BACKGROUND = 2; // clear to background (as indicated by the logical screen descriptor)
|
||||
case PREVIOUS = 3; // restore the canvas to its previous state
|
||||
}
|
||||
21
upLoadImage/vendor/intervention/gif/src/Encoders/AbstractEncoder.php
vendored
Normal file
21
upLoadImage/vendor/intervention/gif/src/Encoders/AbstractEncoder.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
abstract class AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Encode current source
|
||||
*/
|
||||
abstract public function encode(): string;
|
||||
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(protected mixed $source)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
37
upLoadImage/vendor/intervention/gif/src/Encoders/ApplicationExtensionEncoder.php
vendored
Normal file
37
upLoadImage/vendor/intervention/gif/src/Encoders/ApplicationExtensionEncoder.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\ApplicationExtension;
|
||||
use Intervention\Gif\Blocks\DataSubBlock;
|
||||
use Intervention\Gif\Exceptions\EncoderException;
|
||||
|
||||
class ApplicationExtensionEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new decoder instance
|
||||
*/
|
||||
public function __construct(ApplicationExtension $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @throws EncoderException
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
ApplicationExtension::MARKER,
|
||||
ApplicationExtension::LABEL,
|
||||
pack('C', $this->source->getBlockSize()),
|
||||
$this->source->getApplication(),
|
||||
implode('', array_map(fn(DataSubBlock $block): string => $block->encode(), $this->source->getBlocks())),
|
||||
ApplicationExtension::TERMINATOR,
|
||||
]);
|
||||
}
|
||||
}
|
||||
38
upLoadImage/vendor/intervention/gif/src/Encoders/ColorEncoder.php
vendored
Normal file
38
upLoadImage/vendor/intervention/gif/src/Encoders/ColorEncoder.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\Color;
|
||||
|
||||
class ColorEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(Color $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
$this->encodeColorValue($this->source->getRed()),
|
||||
$this->encodeColorValue($this->source->getGreen()),
|
||||
$this->encodeColorValue($this->source->getBlue()),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode color value
|
||||
*/
|
||||
protected function encodeColorValue(int $value): string
|
||||
{
|
||||
return pack('C', $value);
|
||||
}
|
||||
}
|
||||
33
upLoadImage/vendor/intervention/gif/src/Encoders/ColorTableEncoder.php
vendored
Normal file
33
upLoadImage/vendor/intervention/gif/src/Encoders/ColorTableEncoder.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\Color;
|
||||
use Intervention\Gif\Blocks\ColorTable;
|
||||
use Intervention\Gif\Exceptions\EncoderException;
|
||||
|
||||
class ColorTableEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(ColorTable $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @throws EncoderException
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', array_map(
|
||||
fn(Color $color): string => $color->encode(),
|
||||
$this->source->getColors(),
|
||||
));
|
||||
}
|
||||
}
|
||||
41
upLoadImage/vendor/intervention/gif/src/Encoders/CommentExtensionEncoder.php
vendored
Normal file
41
upLoadImage/vendor/intervention/gif/src/Encoders/CommentExtensionEncoder.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\CommentExtension;
|
||||
|
||||
class CommentExtensionEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new decoder instance
|
||||
*/
|
||||
public function __construct(CommentExtension $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
CommentExtension::MARKER,
|
||||
CommentExtension::LABEL,
|
||||
$this->encodeComments(),
|
||||
CommentExtension::TERMINATOR,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode comment blocks
|
||||
*/
|
||||
protected function encodeComments(): string
|
||||
{
|
||||
return implode('', array_map(function (string $comment): string {
|
||||
return pack('C', strlen($comment)) . $comment;
|
||||
}, $this->source->getComments()));
|
||||
}
|
||||
}
|
||||
26
upLoadImage/vendor/intervention/gif/src/Encoders/DataSubBlockEncoder.php
vendored
Normal file
26
upLoadImage/vendor/intervention/gif/src/Encoders/DataSubBlockEncoder.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\DataSubBlock;
|
||||
|
||||
class DataSubBlockEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(DataSubBlock $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return pack('C', $this->source->getSize()) . $this->source->getValue();
|
||||
}
|
||||
}
|
||||
47
upLoadImage/vendor/intervention/gif/src/Encoders/FrameBlockEncoder.php
vendored
Normal file
47
upLoadImage/vendor/intervention/gif/src/Encoders/FrameBlockEncoder.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\ApplicationExtension;
|
||||
use Intervention\Gif\Blocks\CommentExtension;
|
||||
use Intervention\Gif\Blocks\FrameBlock;
|
||||
use Intervention\Gif\Exceptions\EncoderException;
|
||||
|
||||
class FrameBlockEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new decoder instance
|
||||
*/
|
||||
public function __construct(FrameBlock $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws EncoderException
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
$graphicControlExtension = $this->source->getGraphicControlExtension();
|
||||
$colorTable = $this->source->getColorTable();
|
||||
$plainTextExtension = $this->source->getPlainTextExtension();
|
||||
|
||||
return implode('', [
|
||||
implode('', array_map(
|
||||
fn(ApplicationExtension $extension): string => $extension->encode(),
|
||||
$this->source->getApplicationExtensions(),
|
||||
)),
|
||||
implode('', array_map(
|
||||
fn(CommentExtension $extension): string => $extension->encode(),
|
||||
$this->source->getCommentExtensions(),
|
||||
)),
|
||||
$plainTextExtension ? $plainTextExtension->encode() : '',
|
||||
$graphicControlExtension ? $graphicControlExtension->encode() : '',
|
||||
$this->source->getImageDescriptor()->encode(),
|
||||
$colorTable ? $colorTable->encode() : '',
|
||||
$this->source->getImageData()->encode(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
73
upLoadImage/vendor/intervention/gif/src/Encoders/GifDataStreamEncoder.php
vendored
Normal file
73
upLoadImage/vendor/intervention/gif/src/Encoders/GifDataStreamEncoder.php
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\CommentExtension;
|
||||
use Intervention\Gif\Blocks\FrameBlock;
|
||||
use Intervention\Gif\Exceptions\EncoderException;
|
||||
use Intervention\Gif\GifDataStream;
|
||||
|
||||
class GifDataStreamEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(GifDataStream $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @throws EncoderException
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
$this->source->getHeader()->encode(),
|
||||
$this->source->getLogicalScreenDescriptor()->encode(),
|
||||
$this->maybeEncodeGlobalColorTable(),
|
||||
$this->encodeFrames(),
|
||||
$this->encodeComments(),
|
||||
$this->source->getTrailer()->encode(),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function maybeEncodeGlobalColorTable(): string
|
||||
{
|
||||
if (!$this->source->hasGlobalColorTable()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->source->getGlobalColorTable()->encode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode data blocks of source
|
||||
*
|
||||
* @throws EncoderException
|
||||
*/
|
||||
protected function encodeFrames(): string
|
||||
{
|
||||
return implode('', array_map(
|
||||
fn(FrameBlock $frame): string => $frame->encode(),
|
||||
$this->source->getFrames(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode comment extension blocks of source
|
||||
*
|
||||
* @throws EncoderException
|
||||
*/
|
||||
protected function encodeComments(): string
|
||||
{
|
||||
return implode('', array_map(
|
||||
fn(CommentExtension $commentExtension): string => $commentExtension->encode(),
|
||||
$this->source->getComments()
|
||||
));
|
||||
}
|
||||
}
|
||||
63
upLoadImage/vendor/intervention/gif/src/Encoders/GraphicControlExtensionEncoder.php
vendored
Normal file
63
upLoadImage/vendor/intervention/gif/src/Encoders/GraphicControlExtensionEncoder.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\GraphicControlExtension;
|
||||
|
||||
class GraphicControlExtensionEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(GraphicControlExtension $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
GraphicControlExtension::MARKER,
|
||||
GraphicControlExtension::LABEL,
|
||||
GraphicControlExtension::BLOCKSIZE,
|
||||
$this->encodePackedField(),
|
||||
$this->encodeDelay(),
|
||||
$this->encodeTransparentColorIndex(),
|
||||
GraphicControlExtension::TERMINATOR,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode delay time
|
||||
*/
|
||||
protected function encodeDelay(): string
|
||||
{
|
||||
return pack('v*', $this->source->getDelay());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode transparent color index
|
||||
*/
|
||||
protected function encodeTransparentColorIndex(): string
|
||||
{
|
||||
return pack('C', $this->source->getTransparentColorIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode packed field
|
||||
*/
|
||||
protected function encodePackedField(): string
|
||||
{
|
||||
return pack('C', bindec(implode('', [
|
||||
str_pad('0', 3, '0', STR_PAD_LEFT),
|
||||
str_pad(decbin($this->source->getDisposalMethod()->value), 3, '0', STR_PAD_LEFT),
|
||||
(int) $this->source->getUserInput(),
|
||||
(int) $this->source->getTransparentColorExistance(),
|
||||
])));
|
||||
}
|
||||
}
|
||||
26
upLoadImage/vendor/intervention/gif/src/Encoders/HeaderEncoder.php
vendored
Normal file
26
upLoadImage/vendor/intervention/gif/src/Encoders/HeaderEncoder.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\Header;
|
||||
|
||||
class HeaderEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(Header $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return Header::SIGNATURE . $this->source->getVersion();
|
||||
}
|
||||
}
|
||||
42
upLoadImage/vendor/intervention/gif/src/Encoders/ImageDataEncoder.php
vendored
Normal file
42
upLoadImage/vendor/intervention/gif/src/Encoders/ImageDataEncoder.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
use Intervention\Gif\Blocks\DataSubBlock;
|
||||
use Intervention\Gif\Exceptions\EncoderException;
|
||||
use Intervention\Gif\Blocks\ImageData;
|
||||
|
||||
class ImageDataEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(ImageData $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @throws EncoderException
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
if (!$this->source->hasBlocks()) {
|
||||
throw new EncoderException("No data blocks in ImageData.");
|
||||
}
|
||||
|
||||
return implode('', [
|
||||
pack('C', $this->source->getLzwMinCodeSize()),
|
||||
implode('', array_map(
|
||||
fn(DataSubBlock $block): string => $block->encode(),
|
||||
$this->source->getBlocks(),
|
||||
)),
|
||||
AbstractEntity::TERMINATOR,
|
||||
]);
|
||||
}
|
||||
}
|
||||
95
upLoadImage/vendor/intervention/gif/src/Encoders/ImageDescriptorEncoder.php
vendored
Normal file
95
upLoadImage/vendor/intervention/gif/src/Encoders/ImageDescriptorEncoder.php
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\ImageDescriptor;
|
||||
|
||||
class ImageDescriptorEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(ImageDescriptor $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
ImageDescriptor::SEPARATOR,
|
||||
$this->encodeLeft(),
|
||||
$this->encodeTop(),
|
||||
$this->encodeWidth(),
|
||||
$this->encodeHeight(),
|
||||
$this->encodePackedField(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode left value
|
||||
*/
|
||||
protected function encodeLeft(): string
|
||||
{
|
||||
return pack('v*', $this->source->getLeft());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode top value
|
||||
*/
|
||||
protected function encodeTop(): string
|
||||
{
|
||||
return pack('v*', $this->source->getTop());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode width value
|
||||
*/
|
||||
protected function encodeWidth(): string
|
||||
{
|
||||
return pack('v*', $this->source->getWidth());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode height value
|
||||
*/
|
||||
protected function encodeHeight(): string
|
||||
{
|
||||
return pack('v*', $this->source->getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode size of local color table
|
||||
*/
|
||||
protected function encodeLocalColorTableSize(): string
|
||||
{
|
||||
return str_pad(decbin($this->source->getLocalColorTableSize()), 3, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode reserved field
|
||||
*/
|
||||
protected function encodeReservedField(): string
|
||||
{
|
||||
return str_pad('0', 2, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode packed field
|
||||
*/
|
||||
protected function encodePackedField(): string
|
||||
{
|
||||
return pack('C', bindec(implode('', [
|
||||
(int) $this->source->getLocalColorTableExistance(),
|
||||
(int) $this->source->isInterlaced(),
|
||||
(int) $this->source->getLocalColorTableSorted(),
|
||||
$this->encodeReservedField(),
|
||||
$this->encodeLocalColorTableSize(),
|
||||
])));
|
||||
}
|
||||
}
|
||||
93
upLoadImage/vendor/intervention/gif/src/Encoders/LogicalScreenDescriptorEncoder.php
vendored
Normal file
93
upLoadImage/vendor/intervention/gif/src/Encoders/LogicalScreenDescriptorEncoder.php
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\LogicalScreenDescriptor;
|
||||
|
||||
class LogicalScreenDescriptorEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(LogicalScreenDescriptor $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
$this->encodeWidth(),
|
||||
$this->encodeHeight(),
|
||||
$this->encodePackedField(),
|
||||
$this->encodeBackgroundColorIndex(),
|
||||
$this->encodePixelAspectRatio(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode width of current instance
|
||||
*/
|
||||
protected function encodeWidth(): string
|
||||
{
|
||||
return pack('v*', $this->source->getWidth());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode height of current instance
|
||||
*/
|
||||
protected function encodeHeight(): string
|
||||
{
|
||||
return pack('v*', $this->source->getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode background color index of global color table
|
||||
*/
|
||||
protected function encodeBackgroundColorIndex(): string
|
||||
{
|
||||
return pack('C', $this->source->getBackgroundColorIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode pixel aspect ratio
|
||||
*/
|
||||
protected function encodePixelAspectRatio(): string
|
||||
{
|
||||
return pack('C', $this->source->getPixelAspectRatio());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return color resolution for encoding
|
||||
*/
|
||||
protected function encodeColorResolution(): string
|
||||
{
|
||||
return str_pad(decbin($this->source->getBitsPerPixel() - 1), 3, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode size of global color table
|
||||
*/
|
||||
protected function encodeGlobalColorTableSize(): string
|
||||
{
|
||||
return str_pad(decbin($this->source->getGlobalColorTableSize()), 3, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode packed field of current instance
|
||||
*/
|
||||
protected function encodePackedField(): string
|
||||
{
|
||||
return pack('C', bindec(implode('', [
|
||||
(int) $this->source->getGlobalColorTableExistance(),
|
||||
$this->encodeColorResolution(),
|
||||
(int) $this->source->getGlobalColorTableSorted(),
|
||||
$this->encodeGlobalColorTableSize(),
|
||||
])));
|
||||
}
|
||||
}
|
||||
35
upLoadImage/vendor/intervention/gif/src/Encoders/NetscapeApplicationExtensionEncoder.php
vendored
Normal file
35
upLoadImage/vendor/intervention/gif/src/Encoders/NetscapeApplicationExtensionEncoder.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\ApplicationExtension;
|
||||
use Intervention\Gif\Blocks\DataSubBlock;
|
||||
use Intervention\Gif\Blocks\NetscapeApplicationExtension;
|
||||
|
||||
class NetscapeApplicationExtensionEncoder extends ApplicationExtensionEncoder
|
||||
{
|
||||
/**
|
||||
* Create new decoder instance
|
||||
*/
|
||||
public function __construct(NetscapeApplicationExtension $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
ApplicationExtension::MARKER,
|
||||
ApplicationExtension::LABEL,
|
||||
pack('C', $this->source->getBlockSize()),
|
||||
$this->source->getApplication(),
|
||||
implode('', array_map(fn(DataSubBlock $block): string => $block->encode(), $this->source->getBlocks())),
|
||||
ApplicationExtension::TERMINATOR,
|
||||
]);
|
||||
}
|
||||
}
|
||||
55
upLoadImage/vendor/intervention/gif/src/Encoders/PlainTextExtensionEncoder.php
vendored
Normal file
55
upLoadImage/vendor/intervention/gif/src/Encoders/PlainTextExtensionEncoder.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\PlainTextExtension;
|
||||
|
||||
class PlainTextExtensionEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(PlainTextExtension $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
if (!$this->source->hasText()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return implode('', [
|
||||
PlainTextExtension::MARKER,
|
||||
PlainTextExtension::LABEL,
|
||||
$this->encodeHead(),
|
||||
$this->encodeTexts(),
|
||||
PlainTextExtension::TERMINATOR,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode head block
|
||||
*/
|
||||
protected function encodeHead(): string
|
||||
{
|
||||
return "\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode text chunks
|
||||
*/
|
||||
protected function encodeTexts(): string
|
||||
{
|
||||
return implode('', array_map(
|
||||
fn(string $text): string => pack('C', strlen($text)) . $text,
|
||||
$this->source->getText(),
|
||||
));
|
||||
}
|
||||
}
|
||||
24
upLoadImage/vendor/intervention/gif/src/Encoders/TableBasedImageEncoder.php
vendored
Normal file
24
upLoadImage/vendor/intervention/gif/src/Encoders/TableBasedImageEncoder.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\TableBasedImage;
|
||||
|
||||
class TableBasedImageEncoder extends AbstractEncoder
|
||||
{
|
||||
public function __construct(TableBasedImage $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
$this->source->getImageDescriptor()->encode(),
|
||||
$this->source->getColorTable() ? $this->source->getColorTable()->encode() : '',
|
||||
$this->source->getImageData()->encode(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
26
upLoadImage/vendor/intervention/gif/src/Encoders/TrailerEncoder.php
vendored
Normal file
26
upLoadImage/vendor/intervention/gif/src/Encoders/TrailerEncoder.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\Trailer;
|
||||
|
||||
class TrailerEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(Trailer $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return Trailer::MARKER;
|
||||
}
|
||||
}
|
||||
10
upLoadImage/vendor/intervention/gif/src/Exceptions/DecoderException.php
vendored
Normal file
10
upLoadImage/vendor/intervention/gif/src/Exceptions/DecoderException.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Exceptions;
|
||||
|
||||
class DecoderException extends RuntimeException
|
||||
{
|
||||
//
|
||||
}
|
||||
10
upLoadImage/vendor/intervention/gif/src/Exceptions/EncoderException.php
vendored
Normal file
10
upLoadImage/vendor/intervention/gif/src/Exceptions/EncoderException.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Exceptions;
|
||||
|
||||
class EncoderException extends RuntimeException
|
||||
{
|
||||
//
|
||||
}
|
||||
10
upLoadImage/vendor/intervention/gif/src/Exceptions/FormatException.php
vendored
Normal file
10
upLoadImage/vendor/intervention/gif/src/Exceptions/FormatException.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Exceptions;
|
||||
|
||||
class FormatException extends RuntimeException
|
||||
{
|
||||
//
|
||||
}
|
||||
10
upLoadImage/vendor/intervention/gif/src/Exceptions/NotReadableException.php
vendored
Normal file
10
upLoadImage/vendor/intervention/gif/src/Exceptions/NotReadableException.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Exceptions;
|
||||
|
||||
class NotReadableException extends RuntimeException
|
||||
{
|
||||
//
|
||||
}
|
||||
10
upLoadImage/vendor/intervention/gif/src/Exceptions/RuntimeException.php
vendored
Normal file
10
upLoadImage/vendor/intervention/gif/src/Exceptions/RuntimeException.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Exceptions;
|
||||
|
||||
class RuntimeException extends \RuntimeException
|
||||
{
|
||||
//
|
||||
}
|
||||
192
upLoadImage/vendor/intervention/gif/src/GifDataStream.php
vendored
Normal file
192
upLoadImage/vendor/intervention/gif/src/GifDataStream.php
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif;
|
||||
|
||||
use Intervention\Gif\Blocks\ColorTable;
|
||||
use Intervention\Gif\Blocks\CommentExtension;
|
||||
use Intervention\Gif\Blocks\FrameBlock;
|
||||
use Intervention\Gif\Blocks\Header;
|
||||
use Intervention\Gif\Blocks\LogicalScreenDescriptor;
|
||||
use Intervention\Gif\Blocks\NetscapeApplicationExtension;
|
||||
use Intervention\Gif\Blocks\Trailer;
|
||||
|
||||
class GifDataStream extends AbstractEntity
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param array<FrameBlock> $frames
|
||||
* @param array<CommentExtension> $comments
|
||||
*/
|
||||
public function __construct(
|
||||
protected Header $header = new Header(),
|
||||
protected LogicalScreenDescriptor $logicalScreenDescriptor = new LogicalScreenDescriptor(),
|
||||
protected ?ColorTable $globalColorTable = null,
|
||||
protected array $frames = [],
|
||||
protected array $comments = []
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get header
|
||||
*/
|
||||
public function getHeader(): Header
|
||||
{
|
||||
return $this->header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set header
|
||||
*/
|
||||
public function setHeader(Header $header): self
|
||||
{
|
||||
$this->header = $header;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get logical screen descriptor
|
||||
*/
|
||||
public function getLogicalScreenDescriptor(): LogicalScreenDescriptor
|
||||
{
|
||||
return $this->logicalScreenDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set logical screen descriptor
|
||||
*/
|
||||
public function setLogicalScreenDescriptor(LogicalScreenDescriptor $descriptor): self
|
||||
{
|
||||
$this->logicalScreenDescriptor = $descriptor;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return global color table if available else null
|
||||
*/
|
||||
public function getGlobalColorTable(): ?ColorTable
|
||||
{
|
||||
return $this->globalColorTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set global color table
|
||||
*/
|
||||
public function setGlobalColorTable(ColorTable $table): self
|
||||
{
|
||||
$this->globalColorTable = $table;
|
||||
$this->logicalScreenDescriptor->setGlobalColorTableExistance(true);
|
||||
$this->logicalScreenDescriptor->setGlobalColorTableSize(
|
||||
$table->getLogicalSize()
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get main graphic control extension
|
||||
*/
|
||||
public function getMainApplicationExtension(): ?NetscapeApplicationExtension
|
||||
{
|
||||
foreach ($this->frames as $frame) {
|
||||
if ($extension = $frame->getNetscapeExtension()) {
|
||||
return $extension;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of frames
|
||||
*
|
||||
* @return array<FrameBlock>
|
||||
*/
|
||||
public function getFrames(): array
|
||||
{
|
||||
return $this->frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of "global" comments
|
||||
*
|
||||
* @return array<CommentExtension>
|
||||
*/
|
||||
public function getComments(): array
|
||||
{
|
||||
return $this->comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return first frame
|
||||
*/
|
||||
public function getFirstFrame(): ?FrameBlock
|
||||
{
|
||||
if (!array_key_exists(0, $this->frames)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->frames[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add frame
|
||||
*/
|
||||
public function addFrame(FrameBlock $frame): self
|
||||
{
|
||||
$this->frames[] = $frame;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add comment extension
|
||||
*/
|
||||
public function addComment(CommentExtension $comment): self
|
||||
{
|
||||
$this->comments[] = $comment;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current data
|
||||
*
|
||||
* @param array<FrameBlock> $frames
|
||||
*/
|
||||
public function setFrames(array $frames): self
|
||||
{
|
||||
$this->frames = $frames;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get trailer
|
||||
*/
|
||||
public function getTrailer(): Trailer
|
||||
{
|
||||
return new Trailer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if gif is animated
|
||||
*/
|
||||
public function isAnimated(): bool
|
||||
{
|
||||
return count($this->getFrames()) > 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if global color table is set
|
||||
*/
|
||||
public function hasGlobalColorTable(): bool
|
||||
{
|
||||
return !is_null($this->globalColorTable);
|
||||
}
|
||||
}
|
||||
281
upLoadImage/vendor/intervention/gif/src/Splitter.php
vendored
Normal file
281
upLoadImage/vendor/intervention/gif/src/Splitter.php
vendored
Normal file
@@ -0,0 +1,281 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif;
|
||||
|
||||
use ArrayIterator;
|
||||
use GdImage;
|
||||
use Intervention\Gif\Exceptions\EncoderException;
|
||||
use IteratorAggregate;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* @implements IteratorAggregate<GifDataStream>
|
||||
*/
|
||||
class Splitter implements IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* Single frames resolved to GifDataStream
|
||||
*
|
||||
* @var array<GifDataStream>
|
||||
*/
|
||||
protected array $frames = [];
|
||||
|
||||
/**
|
||||
* Delays of each frame
|
||||
*
|
||||
* @var array<int>
|
||||
*/
|
||||
protected array $delays = [];
|
||||
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(protected GifDataStream $stream)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Static constructor method
|
||||
*/
|
||||
public static function create(GifDataStream $stream): self
|
||||
{
|
||||
return new self($stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator
|
||||
*/
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
return new ArrayIterator($this->frames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get frames
|
||||
*
|
||||
* @return array<GifDataStream>
|
||||
*/
|
||||
public function getFrames(): array
|
||||
{
|
||||
return $this->frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get delays
|
||||
*
|
||||
* @return array<int>
|
||||
*/
|
||||
public function getDelays(): array
|
||||
{
|
||||
return $this->delays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set stream of instance
|
||||
*/
|
||||
public function setStream(GifDataStream $stream): self
|
||||
{
|
||||
$this->stream = $stream;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split current stream into array of seperate streams for each frame
|
||||
*/
|
||||
public function split(): self
|
||||
{
|
||||
$this->frames = [];
|
||||
|
||||
foreach ($this->stream->getFrames() as $frame) {
|
||||
// create separate stream for each frame
|
||||
$gif = Builder::canvas(
|
||||
$this->stream->getLogicalScreenDescriptor()->getWidth(),
|
||||
$this->stream->getLogicalScreenDescriptor()->getHeight()
|
||||
)->getGifDataStream();
|
||||
|
||||
// check if working stream has global color table
|
||||
if ($this->stream->hasGlobalColorTable()) {
|
||||
$gif->setGlobalColorTable($this->stream->getGlobalColorTable());
|
||||
$gif->getLogicalScreenDescriptor()->setGlobalColorTableExistance(true);
|
||||
|
||||
$gif->getLogicalScreenDescriptor()->setGlobalColorTableSorted(
|
||||
$this->stream->getLogicalScreenDescriptor()->getGlobalColorTableSorted()
|
||||
);
|
||||
|
||||
$gif->getLogicalScreenDescriptor()->setGlobalColorTableSize(
|
||||
$this->stream->getLogicalScreenDescriptor()->getGlobalColorTableSize()
|
||||
);
|
||||
|
||||
$gif->getLogicalScreenDescriptor()->setBackgroundColorIndex(
|
||||
$this->stream->getLogicalScreenDescriptor()->getBackgroundColorIndex()
|
||||
);
|
||||
|
||||
$gif->getLogicalScreenDescriptor()->setPixelAspectRatio(
|
||||
$this->stream->getLogicalScreenDescriptor()->getPixelAspectRatio()
|
||||
);
|
||||
|
||||
$gif->getLogicalScreenDescriptor()->setBitsPerPixel(
|
||||
$this->stream->getLogicalScreenDescriptor()->getBitsPerPixel()
|
||||
);
|
||||
}
|
||||
|
||||
// copy original frame
|
||||
$gif->addFrame($frame);
|
||||
|
||||
$this->frames[] = $gif;
|
||||
$this->delays[] = match (is_object($frame->getGraphicControlExtension())) {
|
||||
true => $frame->getGraphicControlExtension()->getDelay(),
|
||||
default => 0,
|
||||
};
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of GD library resources for each frame
|
||||
*
|
||||
* @throws EncoderException
|
||||
* @return array<GdImage>
|
||||
*/
|
||||
public function toResources(): array
|
||||
{
|
||||
$resources = [];
|
||||
|
||||
foreach ($this->frames as $frame) {
|
||||
$resource = imagecreatefromstring($frame->encode());
|
||||
if ($resource === false) {
|
||||
throw new EncoderException('Unable to extract animation frames.');
|
||||
}
|
||||
|
||||
imagepalettetotruecolor($resource);
|
||||
imagesavealpha($resource, true);
|
||||
$resources[] = $resource;
|
||||
}
|
||||
|
||||
return $resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of coalesced GD library resources for each frame
|
||||
*
|
||||
* @throws EncoderException
|
||||
* @return array<GdImage>
|
||||
*/
|
||||
public function coalesceToResources(): array
|
||||
{
|
||||
$resources = $this->toResources();
|
||||
|
||||
// static gif files don't need to be coalesced
|
||||
if (count($resources) === 1) {
|
||||
return $resources;
|
||||
}
|
||||
|
||||
$width = imagesx($resources[0]);
|
||||
$height = imagesy($resources[0]);
|
||||
$transparent = imagecolortransparent($resources[0]);
|
||||
|
||||
foreach ($resources as $key => $resource) {
|
||||
// get meta data
|
||||
$gif = $this->frames[$key];
|
||||
$descriptor = $gif->getFirstFrame()->getImageDescriptor();
|
||||
$offset_x = $descriptor->getLeft();
|
||||
$offset_y = $descriptor->getTop();
|
||||
$w = $descriptor->getWidth();
|
||||
$h = $descriptor->getHeight();
|
||||
|
||||
if (in_array($this->getDisposalMethod($gif), [DisposalMethod::NONE, DisposalMethod::PREVIOUS])) {
|
||||
if ($key >= 1) {
|
||||
// create normalized gd image
|
||||
$canvas = imagecreatetruecolor($width, $height);
|
||||
if (imagecolortransparent($resource) != -1) {
|
||||
$transparent = imagecolortransparent($resource);
|
||||
} else {
|
||||
$transparent = imagecolorallocatealpha($resource, 255, 0, 255, 127);
|
||||
}
|
||||
|
||||
if (!is_int($transparent)) {
|
||||
throw new EncoderException('Animation frames cannot be converted into resources.');
|
||||
}
|
||||
|
||||
// fill with transparent
|
||||
imagefill($canvas, 0, 0, $transparent);
|
||||
imagecolortransparent($canvas, $transparent);
|
||||
imagealphablending($canvas, true);
|
||||
|
||||
// insert last as base
|
||||
imagecopy(
|
||||
$canvas,
|
||||
$resources[$key - 1],
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
$width,
|
||||
$height
|
||||
);
|
||||
|
||||
// insert resource
|
||||
imagecopy(
|
||||
$canvas,
|
||||
$resource,
|
||||
$offset_x,
|
||||
$offset_y,
|
||||
0,
|
||||
0,
|
||||
$w,
|
||||
$h
|
||||
);
|
||||
} else {
|
||||
imagealphablending($resource, true);
|
||||
$canvas = $resource;
|
||||
}
|
||||
} else {
|
||||
// create normalized gd image
|
||||
$canvas = imagecreatetruecolor($width, $height);
|
||||
if (imagecolortransparent($resource) != -1) {
|
||||
$transparent = imagecolortransparent($resource);
|
||||
} else {
|
||||
$transparent = imagecolorallocatealpha($resource, 255, 0, 255, 127);
|
||||
}
|
||||
|
||||
if (!is_int($transparent)) {
|
||||
throw new EncoderException('Animation frames cannot be converted into resources.');
|
||||
}
|
||||
|
||||
// fill with transparent
|
||||
imagefill($canvas, 0, 0, $transparent);
|
||||
imagecolortransparent($canvas, $transparent);
|
||||
imagealphablending($canvas, true);
|
||||
|
||||
// insert frame resource
|
||||
imagecopy(
|
||||
$canvas,
|
||||
$resource,
|
||||
$offset_x,
|
||||
$offset_y,
|
||||
0,
|
||||
0,
|
||||
$w,
|
||||
$h
|
||||
);
|
||||
}
|
||||
|
||||
$resources[$key] = $canvas;
|
||||
}
|
||||
|
||||
return $resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and return disposal method of given gif data stream
|
||||
*/
|
||||
private function getDisposalMethod(GifDataStream $gif): DisposalMethod
|
||||
{
|
||||
return $gif->getFirstFrame()->getGraphicControlExtension()->getDisposalMethod();
|
||||
}
|
||||
}
|
||||
43
upLoadImage/vendor/intervention/gif/src/Traits/CanDecode.php
vendored
Normal file
43
upLoadImage/vendor/intervention/gif/src/Traits/CanDecode.php
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Traits;
|
||||
|
||||
use Intervention\Gif\Decoders\AbstractDecoder;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
|
||||
trait CanDecode
|
||||
{
|
||||
/**
|
||||
* Decode current instance
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public static function decode(mixed $source, ?int $length = null): mixed
|
||||
{
|
||||
return self::getDecoder($source, $length)->decode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get decoder for current instance
|
||||
*
|
||||
* @throws DecoderException
|
||||
*/
|
||||
protected static function getDecoder(mixed $source, ?int $length = null): AbstractDecoder
|
||||
{
|
||||
$classname = sprintf('Intervention\Gif\Decoders\%sDecoder', self::getShortClassname());
|
||||
|
||||
if (!class_exists($classname)) {
|
||||
throw new DecoderException("Decoder for '" . static::class . "' not found.");
|
||||
}
|
||||
|
||||
$decoder = new $classname($source, $length);
|
||||
|
||||
if (!($decoder instanceof AbstractDecoder)) {
|
||||
throw new DecoderException("Decoder for '" . static::class . "' not found.");
|
||||
}
|
||||
|
||||
return $decoder;
|
||||
}
|
||||
}
|
||||
43
upLoadImage/vendor/intervention/gif/src/Traits/CanEncode.php
vendored
Normal file
43
upLoadImage/vendor/intervention/gif/src/Traits/CanEncode.php
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Traits;
|
||||
|
||||
use Intervention\Gif\Encoders\AbstractEncoder;
|
||||
use Intervention\Gif\Exceptions\EncoderException;
|
||||
|
||||
trait CanEncode
|
||||
{
|
||||
/**
|
||||
* Encode current entity
|
||||
*
|
||||
* @throws EncoderException
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return $this->getEncoder()->encode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get encoder object for current entity
|
||||
*
|
||||
* @throws EncoderException
|
||||
*/
|
||||
protected function getEncoder(): AbstractEncoder
|
||||
{
|
||||
$classname = sprintf('Intervention\Gif\Encoders\%sEncoder', $this->getShortClassname());
|
||||
|
||||
if (!class_exists($classname)) {
|
||||
throw new EncoderException("Encoder for '" . $this::class . "' not found.");
|
||||
}
|
||||
|
||||
$encoder = new $classname($this);
|
||||
|
||||
if (!($encoder instanceof AbstractEncoder)) {
|
||||
throw new EncoderException("Encoder for '" . $this::class . "' not found.");
|
||||
}
|
||||
|
||||
return $encoder;
|
||||
}
|
||||
}
|
||||
53
upLoadImage/vendor/intervention/gif/src/Traits/CanHandleFiles.php
vendored
Normal file
53
upLoadImage/vendor/intervention/gif/src/Traits/CanHandleFiles.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Traits;
|
||||
|
||||
use Intervention\Gif\Exceptions\RuntimeException;
|
||||
|
||||
trait CanHandleFiles
|
||||
{
|
||||
/**
|
||||
* Determines if input is file path
|
||||
*/
|
||||
private static function isFilePath(mixed $input): bool
|
||||
{
|
||||
return is_string($input) && !self::hasNullBytes($input) && @is_file($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if given string contains null bytes
|
||||
*/
|
||||
private static function hasNullBytes(string $string): bool
|
||||
{
|
||||
return str_contains($string, chr(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create file pointer from given gif image data
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
private static function getHandleFromData(string $data): mixed
|
||||
{
|
||||
$handle = fopen('php://temp', 'r+');
|
||||
|
||||
if ($handle === false) {
|
||||
throw new RuntimeException('Unable to create tempory file handle.');
|
||||
}
|
||||
|
||||
fwrite($handle, $data);
|
||||
rewind($handle);
|
||||
|
||||
return $handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create file pounter from given file path
|
||||
*/
|
||||
private static function getHandleFromFilePath(string $path): mixed
|
||||
{
|
||||
return fopen($path, 'rb');
|
||||
}
|
||||
}
|
||||
21
upLoadImage/vendor/intervention/image/LICENSE
vendored
Normal file
21
upLoadImage/vendor/intervention/image/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-present 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.
|
||||
51
upLoadImage/vendor/intervention/image/composer.json
vendored
Normal file
51
upLoadImage/vendor/intervention/image/composer.json
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "intervention/image",
|
||||
"description": "PHP Image Processing",
|
||||
"homepage": "https://image.intervention.io",
|
||||
"keywords": [
|
||||
"image",
|
||||
"gd",
|
||||
"imagick",
|
||||
"watermark",
|
||||
"thumbnail",
|
||||
"resize"
|
||||
],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Oliver Vogel",
|
||||
"email": "oliver@intervention.io",
|
||||
"homepage": "https://intervention.io"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.1",
|
||||
"ext-mbstring": "*",
|
||||
"intervention/gif": "^4.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10.0 || ^11.0 || ^12.0",
|
||||
"mockery/mockery": "^1.6",
|
||||
"phpstan/phpstan": "^2.1",
|
||||
"squizlabs/php_codesniffer": "^3.8",
|
||||
"slevomat/coding-standard": "~8.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-exif": "Recommended to be able to read EXIF data properly."
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Intervention\\Image\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Intervention\\Image\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
}
|
||||
}
|
||||
}
|
||||
91
upLoadImage/vendor/intervention/image/readme.md
vendored
Normal file
91
upLoadImage/vendor/intervention/image/readme.md
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
# Intervention Image
|
||||
## PHP Image Processing
|
||||
|
||||
[](https://packagist.org/packages/intervention/image)
|
||||
[](https://github.com/Intervention/image/actions)
|
||||
[](https://packagist.org/packages/intervention/image/stats)
|
||||
[](https://ko-fi.com/interventionphp)
|
||||
|
||||
Intervention Image is a **PHP image processing library** that provides a simple
|
||||
and expressive way to create, edit, and compose images. It comes with a universal
|
||||
interface for the two most popular PHP image manipulation extensions. You can
|
||||
choose between the GD library or Imagick as the base layer for all operations.
|
||||
|
||||
- Simple interface for common image editing tasks
|
||||
- Interchangeable driver architecture
|
||||
- Support for animated images
|
||||
- Framework-agnostic
|
||||
- PSR-12 compliant
|
||||
|
||||
## Installation
|
||||
|
||||
You can easily install this library using [Composer](https://getcomposer.org).
|
||||
Simply request the package with the following command:
|
||||
|
||||
```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/).
|
||||
|
||||
## Code Examples
|
||||
|
||||
```php
|
||||
use Intervention\Image\ImageManager;
|
||||
|
||||
// create image manager with desired driver
|
||||
$manager = new ImageManager(
|
||||
new Intervention\Image\Drivers\Gd\Driver()
|
||||
);
|
||||
|
||||
// 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
|
||||
|
||||
Before you begin with the installation make sure that your server environment
|
||||
supports the following requirements.
|
||||
|
||||
- PHP >= 8.1
|
||||
- Mbstring PHP Extension
|
||||
- Image Processing PHP Extension
|
||||
|
||||
## Supported Image Libraries
|
||||
|
||||
Depending on your environment Intervention Image lets you choose between
|
||||
different image processing extensions.
|
||||
|
||||
- GD Library
|
||||
- Imagick PHP extension
|
||||
- [libvips](https://github.com/Intervention/image-driver-vips)
|
||||
|
||||
## Security
|
||||
|
||||
If you discover any security related issues, please email oliver@intervention.io directly.
|
||||
|
||||
## Authors
|
||||
|
||||
This library is developed and maintained by [Oliver Vogel](https://intervention.io)
|
||||
|
||||
Thanks to the community of [contributors](https://github.com/Intervention/image/graphs/contributors) who have helped to improve this project.
|
||||
|
||||
## License
|
||||
|
||||
Intervention Image is licensed under the [MIT License](LICENSE).
|
||||
12
upLoadImage/vendor/intervention/image/src/Analyzers/ColorspaceAnalyzer.php
vendored
Normal file
12
upLoadImage/vendor/intervention/image/src/Analyzers/ColorspaceAnalyzer.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Analyzers;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableAnalyzer;
|
||||
|
||||
class ColorspaceAnalyzer extends SpecializableAnalyzer
|
||||
{
|
||||
//
|
||||
}
|
||||
12
upLoadImage/vendor/intervention/image/src/Analyzers/HeightAnalyzer.php
vendored
Normal file
12
upLoadImage/vendor/intervention/image/src/Analyzers/HeightAnalyzer.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Analyzers;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableAnalyzer;
|
||||
|
||||
class HeightAnalyzer extends SpecializableAnalyzer
|
||||
{
|
||||
//
|
||||
}
|
||||
18
upLoadImage/vendor/intervention/image/src/Analyzers/PixelColorAnalyzer.php
vendored
Normal file
18
upLoadImage/vendor/intervention/image/src/Analyzers/PixelColorAnalyzer.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Analyzers;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableAnalyzer;
|
||||
|
||||
class PixelColorAnalyzer extends SpecializableAnalyzer
|
||||
{
|
||||
public function __construct(
|
||||
public int $x,
|
||||
public int $y,
|
||||
public int $frame_key = 0
|
||||
) {
|
||||
//
|
||||
}
|
||||
}
|
||||
17
upLoadImage/vendor/intervention/image/src/Analyzers/PixelColorsAnalyzer.php
vendored
Normal file
17
upLoadImage/vendor/intervention/image/src/Analyzers/PixelColorsAnalyzer.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Analyzers;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableAnalyzer;
|
||||
|
||||
class PixelColorsAnalyzer extends SpecializableAnalyzer
|
||||
{
|
||||
public function __construct(
|
||||
public int $x,
|
||||
public int $y
|
||||
) {
|
||||
//
|
||||
}
|
||||
}
|
||||
12
upLoadImage/vendor/intervention/image/src/Analyzers/ProfileAnalyzer.php
vendored
Normal file
12
upLoadImage/vendor/intervention/image/src/Analyzers/ProfileAnalyzer.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Analyzers;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableAnalyzer;
|
||||
|
||||
class ProfileAnalyzer extends SpecializableAnalyzer
|
||||
{
|
||||
//
|
||||
}
|
||||
12
upLoadImage/vendor/intervention/image/src/Analyzers/ResolutionAnalyzer.php
vendored
Normal file
12
upLoadImage/vendor/intervention/image/src/Analyzers/ResolutionAnalyzer.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Analyzers;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableAnalyzer;
|
||||
|
||||
class ResolutionAnalyzer extends SpecializableAnalyzer
|
||||
{
|
||||
//
|
||||
}
|
||||
12
upLoadImage/vendor/intervention/image/src/Analyzers/WidthAnalyzer.php
vendored
Normal file
12
upLoadImage/vendor/intervention/image/src/Analyzers/WidthAnalyzer.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Analyzers;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableAnalyzer;
|
||||
|
||||
class WidthAnalyzer extends SpecializableAnalyzer
|
||||
{
|
||||
//
|
||||
}
|
||||
217
upLoadImage/vendor/intervention/image/src/Collection.php
vendored
Normal file
217
upLoadImage/vendor/intervention/image/src/Collection.php
vendored
Normal file
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image;
|
||||
|
||||
use Intervention\Image\Interfaces\CollectionInterface;
|
||||
use ArrayIterator;
|
||||
use Countable;
|
||||
use Traversable;
|
||||
use IteratorAggregate;
|
||||
|
||||
/**
|
||||
* @implements IteratorAggregate<int|string, mixed>
|
||||
*/
|
||||
class Collection implements CollectionInterface, IteratorAggregate, Countable
|
||||
{
|
||||
/**
|
||||
* Create new collection object
|
||||
*
|
||||
* @param array<int|string, mixed> $items
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(protected array $items = [])
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Static constructor
|
||||
*
|
||||
* @param array<int|string, mixed> $items
|
||||
* @return self<int|string, mixed>
|
||||
*/
|
||||
public static function create(array $items = []): self
|
||||
{
|
||||
return new self($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see CollectionInterface::has()
|
||||
*/
|
||||
public function has(int|string $key): bool
|
||||
{
|
||||
return array_key_exists($key, $this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Iterator
|
||||
*
|
||||
* @return Traversable<int|string, mixed>
|
||||
*/
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
return new ArrayIterator($this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see CollectionInterface::toArray()
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count items in collection
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append new item to collection
|
||||
*
|
||||
* @return CollectionInterface<int|string, mixed>
|
||||
*/
|
||||
public function push(mixed $item): CollectionInterface
|
||||
{
|
||||
$this->items[] = $item;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return first item in collection
|
||||
*/
|
||||
public function first(): mixed
|
||||
{
|
||||
if ($item = reset($this->items)) {
|
||||
return $item;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns last item in collection
|
||||
*/
|
||||
public function last(): mixed
|
||||
{
|
||||
if ($item = end($this->items)) {
|
||||
return $item;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return item at given position starting at 0
|
||||
*/
|
||||
public function getAtPosition(int $key = 0, mixed $default = null): mixed
|
||||
{
|
||||
if ($this->count() == 0) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$positions = array_values($this->items);
|
||||
if (!array_key_exists($key, $positions)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $positions[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see CollectionInterface::get()
|
||||
*/
|
||||
public function get(int|string $query, mixed $default = null): mixed
|
||||
{
|
||||
if ($this->count() == 0) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if (is_int($query) && array_key_exists($query, $this->items)) {
|
||||
return $this->items[$query];
|
||||
}
|
||||
|
||||
if (is_string($query) && !str_contains($query, '.')) {
|
||||
return array_key_exists($query, $this->items) ? $this->items[$query] : $default;
|
||||
}
|
||||
|
||||
$query = explode('.', (string) $query);
|
||||
|
||||
$result = $default;
|
||||
$items = $this->items;
|
||||
foreach ($query as $key) {
|
||||
if (!is_array($items) || !array_key_exists($key, $items)) {
|
||||
$result = $default;
|
||||
break;
|
||||
}
|
||||
|
||||
$result = $items[$key];
|
||||
$items = $result;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map each item of collection by given callback
|
||||
*/
|
||||
public function map(callable $callback): self
|
||||
{
|
||||
|
||||
return new self(
|
||||
array_map(
|
||||
fn(mixed $item) => $callback($item),
|
||||
$this->items,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run callback on each item of the collection an remove it if it does not return true
|
||||
*/
|
||||
public function filter(callable $callback): self
|
||||
{
|
||||
return new self(
|
||||
array_filter(
|
||||
$this->items,
|
||||
fn(mixed $item) => $callback($item),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see CollectionInterface::empty()
|
||||
*/
|
||||
public function empty(): CollectionInterface
|
||||
{
|
||||
$this->items = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see CollectionInterface::slice()
|
||||
*/
|
||||
public function slice(int $offset, ?int $length = null): CollectionInterface
|
||||
{
|
||||
$this->items = array_slice($this->items, $offset, $length);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
116
upLoadImage/vendor/intervention/image/src/Colors/AbstractColor.php
vendored
Normal file
116
upLoadImage/vendor/intervention/image/src/Colors/AbstractColor.php
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors;
|
||||
|
||||
use Intervention\Image\Exceptions\ColorException;
|
||||
use Intervention\Image\Interfaces\ColorChannelInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
use ReflectionClass;
|
||||
use Stringable;
|
||||
|
||||
abstract class AbstractColor implements ColorInterface, Stringable
|
||||
{
|
||||
/**
|
||||
* Color channels
|
||||
*
|
||||
* @var array<ColorChannelInterface>
|
||||
*/
|
||||
protected array $channels;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::channels()
|
||||
*/
|
||||
public function channels(): array
|
||||
{
|
||||
return $this->channels;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::channel()
|
||||
*/
|
||||
public function channel(string $classname): ColorChannelInterface
|
||||
{
|
||||
$channels = array_filter(
|
||||
$this->channels(),
|
||||
fn(ColorChannelInterface $channel): bool => $channel::class === $classname,
|
||||
);
|
||||
|
||||
if (count($channels) == 0) {
|
||||
throw new ColorException('Color channel ' . $classname . ' could not be found.');
|
||||
}
|
||||
|
||||
return reset($channels);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::normalize()
|
||||
*/
|
||||
public function normalize(): array
|
||||
{
|
||||
return array_map(
|
||||
fn(ColorChannelInterface $channel): float => $channel->normalize(),
|
||||
$this->channels(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::toArray()
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return array_map(
|
||||
fn(ColorChannelInterface $channel): int => $channel->value(),
|
||||
$this->channels()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::convertTo()
|
||||
*/
|
||||
public function convertTo(string|ColorspaceInterface $colorspace): ColorInterface
|
||||
{
|
||||
$colorspace = match (true) {
|
||||
is_object($colorspace) => $colorspace,
|
||||
default => new $colorspace(),
|
||||
};
|
||||
|
||||
return $colorspace->importColor($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show debug info for the current color
|
||||
*
|
||||
* @return array<string, int>
|
||||
*/
|
||||
public function __debugInfo(): array
|
||||
{
|
||||
return array_reduce($this->channels(), function (array $result, ColorChannelInterface $item) {
|
||||
$key = strtolower((new ReflectionClass($item))->getShortName());
|
||||
$result[$key] = $item->value();
|
||||
return $result;
|
||||
}, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::__toString()
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
}
|
||||
92
upLoadImage/vendor/intervention/image/src/Colors/AbstractColorChannel.php
vendored
Normal file
92
upLoadImage/vendor/intervention/image/src/Colors/AbstractColorChannel.php
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors;
|
||||
|
||||
use Intervention\Image\Exceptions\ColorException;
|
||||
use Intervention\Image\Interfaces\ColorChannelInterface;
|
||||
use Stringable;
|
||||
|
||||
abstract class AbstractColorChannel implements ColorChannelInterface, Stringable
|
||||
{
|
||||
protected int $value;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::__construct()
|
||||
*/
|
||||
public function __construct(?int $value = null, ?float $normalized = null)
|
||||
{
|
||||
$this->value = $this->validate(
|
||||
match (true) {
|
||||
is_null($value) && is_numeric($normalized) => intval(round($normalized * $this->max())),
|
||||
is_numeric($value) && is_null($normalized) => $value,
|
||||
default => throw new ColorException('Color channels must either have a value or a normalized value')
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of value()
|
||||
*/
|
||||
public function toInt(): int
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::value()
|
||||
*/
|
||||
public function value(): int
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::normalize()
|
||||
*/
|
||||
public function normalize(int $precision = 32): float
|
||||
{
|
||||
return round(($this->value() - $this->min()) / ($this->max() - $this->min()), $precision);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::validate()
|
||||
*/
|
||||
public function validate(mixed $value): mixed
|
||||
{
|
||||
if ($value < $this->min() || $value > $this->max()) {
|
||||
throw new ColorException('Color channel value must be in range ' . $this->min() . ' to ' . $this->max());
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::toString()
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
return (string) $this->value();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::__toString()
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
}
|
||||
20
upLoadImage/vendor/intervention/image/src/Colors/Cmyk/Channels/Cyan.php
vendored
Normal file
20
upLoadImage/vendor/intervention/image/src/Colors/Cmyk/Channels/Cyan.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Cmyk\Channels;
|
||||
|
||||
use Intervention\Image\Colors\AbstractColorChannel;
|
||||
|
||||
class Cyan extends AbstractColorChannel
|
||||
{
|
||||
public function min(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function max(): int
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
10
upLoadImage/vendor/intervention/image/src/Colors/Cmyk/Channels/Key.php
vendored
Normal file
10
upLoadImage/vendor/intervention/image/src/Colors/Cmyk/Channels/Key.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Cmyk\Channels;
|
||||
|
||||
class Key extends Cyan
|
||||
{
|
||||
//
|
||||
}
|
||||
10
upLoadImage/vendor/intervention/image/src/Colors/Cmyk/Channels/Magenta.php
vendored
Normal file
10
upLoadImage/vendor/intervention/image/src/Colors/Cmyk/Channels/Magenta.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Cmyk\Channels;
|
||||
|
||||
class Magenta extends Cyan
|
||||
{
|
||||
//
|
||||
}
|
||||
10
upLoadImage/vendor/intervention/image/src/Colors/Cmyk/Channels/Yellow.php
vendored
Normal file
10
upLoadImage/vendor/intervention/image/src/Colors/Cmyk/Channels/Yellow.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Cmyk\Channels;
|
||||
|
||||
class Yellow extends Cyan
|
||||
{
|
||||
//
|
||||
}
|
||||
153
upLoadImage/vendor/intervention/image/src/Colors/Cmyk/Color.php
vendored
Normal file
153
upLoadImage/vendor/intervention/image/src/Colors/Cmyk/Color.php
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Cmyk;
|
||||
|
||||
use Intervention\Image\Colors\AbstractColor;
|
||||
use Intervention\Image\Colors\Cmyk\Channels\Cyan;
|
||||
use Intervention\Image\Colors\Cmyk\Channels\Magenta;
|
||||
use Intervention\Image\Colors\Cmyk\Channels\Yellow;
|
||||
use Intervention\Image\Colors\Cmyk\Channels\Key;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\InputHandler;
|
||||
use Intervention\Image\Interfaces\ColorChannelInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
|
||||
class Color extends AbstractColor
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(int $c, int $m, int $y, int $k)
|
||||
{
|
||||
/** @throws void */
|
||||
$this->channels = [
|
||||
new Cyan($c),
|
||||
new Magenta($m),
|
||||
new Yellow($y),
|
||||
new Key($k),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::create()
|
||||
*/
|
||||
public static function create(mixed $input): ColorInterface
|
||||
{
|
||||
return InputHandler::withDecoders([
|
||||
Decoders\StringColorDecoder::class,
|
||||
])->handle($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::colorspace()
|
||||
*/
|
||||
public function colorspace(): ColorspaceInterface
|
||||
{
|
||||
return new Colorspace();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::toHex()
|
||||
*/
|
||||
public function toHex(string $prefix = ''): string
|
||||
{
|
||||
return $this->convertTo(RgbColorspace::class)->toHex($prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CMYK cyan channel
|
||||
*/
|
||||
public function cyan(): ColorChannelInterface
|
||||
{
|
||||
/** @throws void */
|
||||
return $this->channel(Cyan::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CMYK magenta channel
|
||||
*/
|
||||
public function magenta(): ColorChannelInterface
|
||||
{
|
||||
/** @throws void */
|
||||
return $this->channel(Magenta::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CMYK yellow channel
|
||||
*/
|
||||
public function yellow(): ColorChannelInterface
|
||||
{
|
||||
/** @throws void */
|
||||
return $this->channel(Yellow::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CMYK key channel
|
||||
*/
|
||||
public function key(): ColorChannelInterface
|
||||
{
|
||||
/** @throws void */
|
||||
return $this->channel(Key::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::toString()
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
return sprintf(
|
||||
'cmyk(%d%%, %d%%, %d%%, %d%%)',
|
||||
$this->cyan()->value(),
|
||||
$this->magenta()->value(),
|
||||
$this->yellow()->value(),
|
||||
$this->key()->value()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::isGreyscale()
|
||||
*/
|
||||
public function isGreyscale(): bool
|
||||
{
|
||||
return 0 === array_sum([
|
||||
$this->cyan()->value(),
|
||||
$this->magenta()->value(),
|
||||
$this->yellow()->value(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::isTransparent()
|
||||
*/
|
||||
public function isTransparent(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::isClear()
|
||||
*/
|
||||
public function isClear(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
77
upLoadImage/vendor/intervention/image/src/Colors/Cmyk/Colorspace.php
vendored
Normal file
77
upLoadImage/vendor/intervention/image/src/Colors/Cmyk/Colorspace.php
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Cmyk;
|
||||
|
||||
use Intervention\Image\Colors\Rgb\Color as RgbColor;
|
||||
use Intervention\Image\Colors\Cmyk\Color as CmykColor;
|
||||
use Intervention\Image\Colors\Hsv\Color as HsvColor;
|
||||
use Intervention\Image\Colors\Hsl\Color as HslColor;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\Exceptions\ColorException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
|
||||
class Colorspace implements ColorspaceInterface
|
||||
{
|
||||
/**
|
||||
* Channel class names of colorspace
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
public static array $channels = [
|
||||
Channels\Cyan::class,
|
||||
Channels\Magenta::class,
|
||||
Channels\Yellow::class,
|
||||
Channels\Key::class
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorspaceInterface::createColor()
|
||||
*/
|
||||
public function colorFromNormalized(array $normalized): ColorInterface
|
||||
{
|
||||
return new Color(...array_map(
|
||||
fn(string $classname, float $value_normalized) => (new $classname(normalized: $value_normalized))->value(),
|
||||
self::$channels,
|
||||
$normalized,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ColorException
|
||||
*/
|
||||
public function importColor(ColorInterface $color): ColorInterface
|
||||
{
|
||||
return match ($color::class) {
|
||||
RgbColor::class => $this->importRgbColor($color),
|
||||
HsvColor::class => $this->importRgbColor($color->convertTo(RgbColorspace::class)),
|
||||
HslColor::class => $this->importRgbColor($color->convertTo(RgbColorspace::class)),
|
||||
default => $color,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ColorException
|
||||
*/
|
||||
protected function importRgbColor(ColorInterface $color): CmykColor
|
||||
{
|
||||
if (!($color instanceof RgbColor)) {
|
||||
throw new ColorException('Unabled to import color of type ' . $color::class . '.');
|
||||
}
|
||||
|
||||
$c = (255 - $color->red()->value()) / 255.0 * 100;
|
||||
$m = (255 - $color->green()->value()) / 255.0 * 100;
|
||||
$y = (255 - $color->blue()->value()) / 255.0 * 100;
|
||||
$k = intval(round(min([$c, $m, $y])));
|
||||
|
||||
$c = intval(round($c - $k));
|
||||
$m = intval(round($m - $k));
|
||||
$y = intval(round($y - $k));
|
||||
|
||||
return new CmykColor($c, $m, $y, $k);
|
||||
}
|
||||
}
|
||||
36
upLoadImage/vendor/intervention/image/src/Colors/Cmyk/Decoders/StringColorDecoder.php
vendored
Normal file
36
upLoadImage/vendor/intervention/image/src/Colors/Cmyk/Decoders/StringColorDecoder.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Cmyk\Decoders;
|
||||
|
||||
use Intervention\Image\Colors\Cmyk\Color;
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class StringColorDecoder extends AbstractDecoder implements DecoderInterface
|
||||
{
|
||||
/**
|
||||
* Decode CMYK color strings
|
||||
*/
|
||||
public function decode(mixed $input): ImageInterface|ColorInterface
|
||||
{
|
||||
if (!is_string($input)) {
|
||||
throw new DecoderException('Unable to decode input');
|
||||
}
|
||||
|
||||
$pattern = '/^cmyk\((?P<c>[0-9\.]+%?), ?(?P<m>[0-9\.]+%?), ?(?P<y>[0-9\.]+%?), ?(?P<k>[0-9\.]+%?)\)$/i';
|
||||
if (preg_match($pattern, $input, $matches) != 1) {
|
||||
throw new DecoderException('Unable to decode input');
|
||||
}
|
||||
|
||||
$values = array_map(function (string $value): int {
|
||||
return intval(round(floatval(trim(str_replace('%', '', $value)))));
|
||||
}, [$matches['c'], $matches['m'], $matches['y'], $matches['k']]);
|
||||
|
||||
return new Color(...$values);
|
||||
}
|
||||
}
|
||||
30
upLoadImage/vendor/intervention/image/src/Colors/Hsl/Channels/Hue.php
vendored
Normal file
30
upLoadImage/vendor/intervention/image/src/Colors/Hsl/Channels/Hue.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Hsl\Channels;
|
||||
|
||||
use Intervention\Image\Colors\AbstractColorChannel;
|
||||
|
||||
class Hue extends AbstractColorChannel
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::min()
|
||||
*/
|
||||
public function min(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::max()
|
||||
*/
|
||||
public function max(): int
|
||||
{
|
||||
return 360;
|
||||
}
|
||||
}
|
||||
30
upLoadImage/vendor/intervention/image/src/Colors/Hsl/Channels/Luminance.php
vendored
Normal file
30
upLoadImage/vendor/intervention/image/src/Colors/Hsl/Channels/Luminance.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Hsl\Channels;
|
||||
|
||||
use Intervention\Image\Colors\AbstractColorChannel;
|
||||
|
||||
class Luminance extends AbstractColorChannel
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::min()
|
||||
*/
|
||||
public function min(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::max()
|
||||
*/
|
||||
public function max(): int
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
30
upLoadImage/vendor/intervention/image/src/Colors/Hsl/Channels/Saturation.php
vendored
Normal file
30
upLoadImage/vendor/intervention/image/src/Colors/Hsl/Channels/Saturation.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Hsl\Channels;
|
||||
|
||||
use Intervention\Image\Colors\AbstractColorChannel;
|
||||
|
||||
class Saturation extends AbstractColorChannel
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::min()
|
||||
*/
|
||||
public function min(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::max()
|
||||
*/
|
||||
public function max(): int
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
132
upLoadImage/vendor/intervention/image/src/Colors/Hsl/Color.php
vendored
Normal file
132
upLoadImage/vendor/intervention/image/src/Colors/Hsl/Color.php
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Hsl;
|
||||
|
||||
use Intervention\Image\Colors\AbstractColor;
|
||||
use Intervention\Image\Colors\Hsl\Channels\Hue;
|
||||
use Intervention\Image\Colors\Hsl\Channels\Luminance;
|
||||
use Intervention\Image\Colors\Hsl\Channels\Saturation;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\InputHandler;
|
||||
use Intervention\Image\Interfaces\ColorChannelInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
|
||||
class Color extends AbstractColor
|
||||
{
|
||||
/**
|
||||
* Create new color object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(int $h, int $s, int $l)
|
||||
{
|
||||
/** @throws void */
|
||||
$this->channels = [
|
||||
new Hue($h),
|
||||
new Saturation($s),
|
||||
new Luminance($l),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::colorspace()
|
||||
*/
|
||||
public function colorspace(): ColorspaceInterface
|
||||
{
|
||||
return new Colorspace();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::create()
|
||||
*/
|
||||
public static function create(mixed $input): ColorInterface
|
||||
{
|
||||
return InputHandler::withDecoders([
|
||||
Decoders\StringColorDecoder::class,
|
||||
])->handle($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Hue channel
|
||||
*/
|
||||
public function hue(): ColorChannelInterface
|
||||
{
|
||||
/** @throws void */
|
||||
return $this->channel(Hue::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Saturation channel
|
||||
*/
|
||||
public function saturation(): ColorChannelInterface
|
||||
{
|
||||
/** @throws void */
|
||||
return $this->channel(Saturation::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Luminance channel
|
||||
*/
|
||||
public function luminance(): ColorChannelInterface
|
||||
{
|
||||
/** @throws void */
|
||||
return $this->channel(Luminance::class);
|
||||
}
|
||||
|
||||
public function toHex(string $prefix = ''): string
|
||||
{
|
||||
return $this->convertTo(RgbColorspace::class)->toHex($prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::toString()
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
return sprintf(
|
||||
'hsl(%d, %d%%, %d%%)',
|
||||
$this->hue()->value(),
|
||||
$this->saturation()->value(),
|
||||
$this->luminance()->value()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::isGreyscale()
|
||||
*/
|
||||
public function isGreyscale(): bool
|
||||
{
|
||||
return $this->saturation()->value() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::isTransparent()
|
||||
*/
|
||||
public function isTransparent(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::isClear()
|
||||
*/
|
||||
public function isClear(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
137
upLoadImage/vendor/intervention/image/src/Colors/Hsl/Colorspace.php
vendored
Normal file
137
upLoadImage/vendor/intervention/image/src/Colors/Hsl/Colorspace.php
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Hsl;
|
||||
|
||||
use Intervention\Image\Colors\Cmyk\Color as CmykColor;
|
||||
use Intervention\Image\Colors\Rgb\Color as RgbColor;
|
||||
use Intervention\Image\Colors\Hsv\Color as HsvColor;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\Exceptions\ColorException;
|
||||
use Intervention\Image\Interfaces\ColorChannelInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
|
||||
class Colorspace implements ColorspaceInterface
|
||||
{
|
||||
/**
|
||||
* Channel class names of colorspace
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
public static array $channels = [
|
||||
Channels\Hue::class,
|
||||
Channels\Saturation::class,
|
||||
Channels\Luminance::class
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorspaceInterface::colorFromNormalized()
|
||||
*/
|
||||
public function colorFromNormalized(array $normalized): ColorInterface
|
||||
{
|
||||
return new Color(...array_map(
|
||||
fn(string $classname, float $value_normalized) => (new $classname(normalized: $value_normalized))->value(),
|
||||
self::$channels,
|
||||
$normalized
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ColorException
|
||||
*/
|
||||
public function importColor(ColorInterface $color): ColorInterface
|
||||
{
|
||||
return match ($color::class) {
|
||||
CmykColor::class => $this->importRgbColor($color->convertTo(RgbColorspace::class)),
|
||||
RgbColor::class => $this->importRgbColor($color),
|
||||
HsvColor::class => $this->importHsvColor($color),
|
||||
default => $color,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ColorException
|
||||
*/
|
||||
protected function importRgbColor(ColorInterface $color): ColorInterface
|
||||
{
|
||||
if (!($color instanceof RgbColor)) {
|
||||
throw new ColorException('Unabled to import color of type ' . $color::class . '.');
|
||||
}
|
||||
|
||||
// normalized values of rgb channels
|
||||
$values = array_map(
|
||||
fn(ColorChannelInterface $channel): float => $channel->normalize(),
|
||||
$color->channels(),
|
||||
);
|
||||
|
||||
// take only RGB
|
||||
$values = array_slice($values, 0, 3);
|
||||
|
||||
// calculate Luminance
|
||||
$min = min(...$values);
|
||||
$max = max(...$values);
|
||||
$luminance = ($max + $min) / 2;
|
||||
$delta = $max - $min;
|
||||
|
||||
// calculate saturation
|
||||
$saturation = match (true) {
|
||||
$delta == 0 => 0,
|
||||
default => $delta / (1 - abs(2 * $luminance - 1)),
|
||||
};
|
||||
|
||||
// calculate hue
|
||||
[$r, $g, $b] = $values;
|
||||
$hue = match (true) {
|
||||
($delta == 0) => 0,
|
||||
($max == $r) => 60 * fmod((($g - $b) / $delta), 6),
|
||||
($max == $g) => 60 * ((($b - $r) / $delta) + 2),
|
||||
($max == $b) => 60 * ((($r - $g) / $delta) + 4),
|
||||
default => 0,
|
||||
};
|
||||
|
||||
$hue = ($hue + 360) % 360; // normalize hue
|
||||
|
||||
return new Color(
|
||||
intval(round($hue)),
|
||||
intval(round($saturation * 100)),
|
||||
intval(round($luminance * 100)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ColorException
|
||||
*/
|
||||
protected function importHsvColor(ColorInterface $color): ColorInterface
|
||||
{
|
||||
if (!($color instanceof HsvColor)) {
|
||||
throw new ColorException('Unabled to import color of type ' . $color::class . '.');
|
||||
}
|
||||
|
||||
// normalized values of hsv channels
|
||||
[$h, $s, $v] = array_map(
|
||||
fn(ColorChannelInterface $channel): float => $channel->normalize(),
|
||||
$color->channels(),
|
||||
);
|
||||
|
||||
// calculate Luminance
|
||||
$luminance = (2 - $s) * $v / 2;
|
||||
|
||||
// calculate Saturation
|
||||
$saturation = match (true) {
|
||||
$luminance == 0 => $s,
|
||||
$luminance == 1 => 0,
|
||||
$luminance < .5 => $s * $v / ($luminance * 2),
|
||||
default => $s * $v / (2 - $luminance * 2),
|
||||
};
|
||||
|
||||
return new Color(
|
||||
intval(round($h * 360)),
|
||||
intval(round($saturation * 100)),
|
||||
intval(round($luminance * 100)),
|
||||
);
|
||||
}
|
||||
}
|
||||
39
upLoadImage/vendor/intervention/image/src/Colors/Hsl/Decoders/StringColorDecoder.php
vendored
Normal file
39
upLoadImage/vendor/intervention/image/src/Colors/Hsl/Decoders/StringColorDecoder.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Hsl\Decoders;
|
||||
|
||||
use Intervention\Image\Colors\Hsl\Color;
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class StringColorDecoder extends AbstractDecoder implements DecoderInterface
|
||||
{
|
||||
/**
|
||||
* Decode hsl color strings
|
||||
*/
|
||||
public function decode(mixed $input): ImageInterface|ColorInterface
|
||||
{
|
||||
if (!is_string($input)) {
|
||||
throw new DecoderException('Unable to decode input');
|
||||
}
|
||||
|
||||
$pattern = '/^hsl\((?P<h>[0-9\.]+), ?(?P<s>[0-9\.]+%?), ?(?P<l>[0-9\.]+%?)\)$/i';
|
||||
if (preg_match($pattern, $input, $matches) != 1) {
|
||||
throw new DecoderException('Unable to decode input');
|
||||
}
|
||||
|
||||
$values = array_map(function (string $value): int {
|
||||
return match (strpos($value, '%')) {
|
||||
false => intval(trim($value)),
|
||||
default => intval(trim(str_replace('%', '', $value))),
|
||||
};
|
||||
}, [$matches['h'], $matches['s'], $matches['l']]);
|
||||
|
||||
return new Color(...$values);
|
||||
}
|
||||
}
|
||||
30
upLoadImage/vendor/intervention/image/src/Colors/Hsv/Channels/Hue.php
vendored
Normal file
30
upLoadImage/vendor/intervention/image/src/Colors/Hsv/Channels/Hue.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Hsv\Channels;
|
||||
|
||||
use Intervention\Image\Colors\AbstractColorChannel;
|
||||
|
||||
class Hue extends AbstractColorChannel
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::min()
|
||||
*/
|
||||
public function min(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::max()
|
||||
*/
|
||||
public function max(): int
|
||||
{
|
||||
return 360;
|
||||
}
|
||||
}
|
||||
30
upLoadImage/vendor/intervention/image/src/Colors/Hsv/Channels/Saturation.php
vendored
Normal file
30
upLoadImage/vendor/intervention/image/src/Colors/Hsv/Channels/Saturation.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Hsv\Channels;
|
||||
|
||||
use Intervention\Image\Colors\AbstractColorChannel;
|
||||
|
||||
class Saturation extends AbstractColorChannel
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::min()
|
||||
*/
|
||||
public function min(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::max()
|
||||
*/
|
||||
public function max(): int
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
30
upLoadImage/vendor/intervention/image/src/Colors/Hsv/Channels/Value.php
vendored
Normal file
30
upLoadImage/vendor/intervention/image/src/Colors/Hsv/Channels/Value.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Hsv\Channels;
|
||||
|
||||
use Intervention\Image\Colors\AbstractColorChannel;
|
||||
|
||||
class Value extends AbstractColorChannel
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::min()
|
||||
*/
|
||||
public function min(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::max()
|
||||
*/
|
||||
public function max(): int
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
132
upLoadImage/vendor/intervention/image/src/Colors/Hsv/Color.php
vendored
Normal file
132
upLoadImage/vendor/intervention/image/src/Colors/Hsv/Color.php
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Hsv;
|
||||
|
||||
use Intervention\Image\Colors\AbstractColor;
|
||||
use Intervention\Image\Colors\Hsv\Channels\Hue;
|
||||
use Intervention\Image\Colors\Hsv\Channels\Saturation;
|
||||
use Intervention\Image\Colors\Hsv\Channels\Value;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\InputHandler;
|
||||
use Intervention\Image\Interfaces\ColorChannelInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
|
||||
class Color extends AbstractColor
|
||||
{
|
||||
/**
|
||||
* Create new color object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(int $h, int $s, int $v)
|
||||
{
|
||||
/** @throws void */
|
||||
$this->channels = [
|
||||
new Hue($h),
|
||||
new Saturation($s),
|
||||
new Value($v),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::colorspace()
|
||||
*/
|
||||
public function colorspace(): ColorspaceInterface
|
||||
{
|
||||
return new Colorspace();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::create()
|
||||
*/
|
||||
public static function create(mixed $input): ColorInterface
|
||||
{
|
||||
return InputHandler::withDecoders([
|
||||
Decoders\StringColorDecoder::class,
|
||||
])->handle($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Hue channel
|
||||
*/
|
||||
public function hue(): ColorChannelInterface
|
||||
{
|
||||
/** @throws void */
|
||||
return $this->channel(Hue::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Saturation channel
|
||||
*/
|
||||
public function saturation(): ColorChannelInterface
|
||||
{
|
||||
/** @throws void */
|
||||
return $this->channel(Saturation::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Value channel
|
||||
*/
|
||||
public function value(): ColorChannelInterface
|
||||
{
|
||||
/** @throws void */
|
||||
return $this->channel(Value::class);
|
||||
}
|
||||
|
||||
public function toHex(string $prefix = ''): string
|
||||
{
|
||||
return $this->convertTo(RgbColorspace::class)->toHex($prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::toString()
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
return sprintf(
|
||||
'hsv(%d, %d%%, %d%%)',
|
||||
$this->hue()->value(),
|
||||
$this->saturation()->value(),
|
||||
$this->value()->value()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::isGreyscale()
|
||||
*/
|
||||
public function isGreyscale(): bool
|
||||
{
|
||||
return $this->saturation()->value() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::isTransparent()
|
||||
*/
|
||||
public function isTransparent(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::isClear()
|
||||
*/
|
||||
public function isClear(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
122
upLoadImage/vendor/intervention/image/src/Colors/Hsv/Colorspace.php
vendored
Normal file
122
upLoadImage/vendor/intervention/image/src/Colors/Hsv/Colorspace.php
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Hsv;
|
||||
|
||||
use Intervention\Image\Colors\Cmyk\Color as CmykColor;
|
||||
use Intervention\Image\Colors\Rgb\Color as RgbColor;
|
||||
use Intervention\Image\Colors\Hsl\Color as HslColor;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\Exceptions\ColorException;
|
||||
use Intervention\Image\Interfaces\ColorChannelInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
|
||||
class Colorspace implements ColorspaceInterface
|
||||
{
|
||||
/**
|
||||
* Channel class names of colorspace
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
public static array $channels = [
|
||||
Channels\Hue::class,
|
||||
Channels\Saturation::class,
|
||||
Channels\Value::class
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorspaceInterface::colorFromNormalized()
|
||||
*/
|
||||
public function colorFromNormalized(array $normalized): ColorInterface
|
||||
{
|
||||
return new Color(...array_map(
|
||||
fn(string $classname, float $value_normalized) => (new $classname(normalized: $value_normalized))->value(),
|
||||
self::$channels,
|
||||
$normalized
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ColorException
|
||||
*/
|
||||
public function importColor(ColorInterface $color): ColorInterface
|
||||
{
|
||||
return match ($color::class) {
|
||||
CmykColor::class => $this->importRgbColor($color->convertTo(RgbColorspace::class)),
|
||||
RgbColor::class => $this->importRgbColor($color),
|
||||
HslColor::class => $this->importHslColor($color),
|
||||
default => $color,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ColorException
|
||||
*/
|
||||
protected function importRgbColor(ColorInterface $color): ColorInterface
|
||||
{
|
||||
if (!($color instanceof RgbColor)) {
|
||||
throw new ColorException('Unabled to import color of type ' . $color::class . '.');
|
||||
}
|
||||
|
||||
// normalized values of rgb channels
|
||||
$values = array_map(fn(ColorChannelInterface $channel): float => $channel->normalize(), $color->channels());
|
||||
|
||||
// take only RGB
|
||||
$values = array_slice($values, 0, 3);
|
||||
|
||||
// calculate chroma
|
||||
$min = min(...$values);
|
||||
$max = max(...$values);
|
||||
$chroma = $max - $min;
|
||||
|
||||
// calculate value
|
||||
$v = 100 * $max;
|
||||
|
||||
if ($chroma == 0) {
|
||||
// greyscale color
|
||||
return new Color(0, 0, intval(round($v)));
|
||||
}
|
||||
|
||||
// calculate saturation
|
||||
$s = 100 * ($chroma / $max);
|
||||
|
||||
// calculate hue
|
||||
[$r, $g, $b] = $values;
|
||||
$h = match (true) {
|
||||
($r == $min) => 3 - (($g - $b) / $chroma),
|
||||
($b == $min) => 1 - (($r - $g) / $chroma),
|
||||
default => 5 - (($b - $r) / $chroma),
|
||||
} * 60;
|
||||
|
||||
return new Color(
|
||||
intval(round($h)),
|
||||
intval(round($s)),
|
||||
intval(round($v))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ColorException
|
||||
*/
|
||||
protected function importHslColor(ColorInterface $color): ColorInterface
|
||||
{
|
||||
if (!($color instanceof HslColor)) {
|
||||
throw new ColorException('Unabled to import color of type ' . $color::class . '.');
|
||||
}
|
||||
|
||||
// normalized values of hsl channels
|
||||
[$h, $s, $l] = array_map(
|
||||
fn(ColorChannelInterface $channel): float => $channel->normalize(),
|
||||
$color->channels()
|
||||
);
|
||||
|
||||
$v = $l + $s * min($l, 1 - $l);
|
||||
$s = ($v == 0) ? 0 : 2 * (1 - $l / $v);
|
||||
|
||||
return $this->colorFromNormalized([$h, $s, $v]);
|
||||
}
|
||||
}
|
||||
39
upLoadImage/vendor/intervention/image/src/Colors/Hsv/Decoders/StringColorDecoder.php
vendored
Normal file
39
upLoadImage/vendor/intervention/image/src/Colors/Hsv/Decoders/StringColorDecoder.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Hsv\Decoders;
|
||||
|
||||
use Intervention\Image\Colors\Hsv\Color;
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class StringColorDecoder extends AbstractDecoder implements DecoderInterface
|
||||
{
|
||||
/**
|
||||
* Decode hsv/hsb color strings
|
||||
*/
|
||||
public function decode(mixed $input): ImageInterface|ColorInterface
|
||||
{
|
||||
if (!is_string($input)) {
|
||||
throw new DecoderException('Unable to decode input');
|
||||
}
|
||||
|
||||
$pattern = '/^hs(v|b)\((?P<h>[0-9\.]+), ?(?P<s>[0-9\.]+%?), ?(?P<v>[0-9\.]+%?)\)$/i';
|
||||
if (preg_match($pattern, $input, $matches) != 1) {
|
||||
throw new DecoderException('Unable to decode input');
|
||||
}
|
||||
|
||||
$values = array_map(function (string $value): int {
|
||||
return match (strpos($value, '%')) {
|
||||
false => intval(trim($value)),
|
||||
default => intval(trim(str_replace('%', '', $value))),
|
||||
};
|
||||
}, [$matches['h'], $matches['s'], $matches['v']]);
|
||||
|
||||
return new Color(...$values);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user