fjffk简单的咖啡店科开发2方法2
环滁皆山也。其西南诸峰,林壑尤美,望之蔚然而深秀者,琅琊也。山行六七里,渐闻水声潺潺,而泻出于两峰之间者,酿泉也
???????????????????????????????
??????????????/?????????????????
............/...................
.........................../...
???????????????????????????????
>>>>>>>>>>>>>/>>>>>>>>>>>>>>>>>
ÿØÿà JFIF ÿÛ „ ( %!1!%)+//.383,7(-.+
-%%-////---/-.+/--+------/------/--0+--/-/-----.-----ÿÀ ¥2" ÿÄ ÿÄ J ! 1AQ"aq2‘#BR‚¡ÁÑ3br’¢±Âð$CSƒ²á4c“%DsÓñÿÄ ÿÄ * !1AQa‘"2q3±ð#b¡ÿÚ ? ¼QxJQaÍuò¸Zö Úü8,ÐÚú
"SSn<rçù–´âE—^ªBÖ9À\†¸ÔÁTÃÛ5
ëd´³Í#Ý;Þ38œî ¶H£M:wÎ3…³…âpÔF&‚FK¸9„â4àGEõªfÿ ‘ñ(ßwpŽF|È¥ù®häðÍѶ¹‘[ÒinÙW¶ùñY˜Q{›K"išÒ[Ú8žë\F¹@-?v"ÔU”,ìöžkÿ {I‡£šÍ?e
ríV
?>
.........................................
.............................................................................
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
>>>>>>>>>>>>>/>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
dsdfgif/LICENSE 0000644 00000002077 15266563364 0006344 0 ustar 00 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.
gif/phpunit.xml.dist 0000644 00000001215 15266563364 0010503 0 ustar 00
./tests/Unit/
src
gif/README.md 0000644 00000005632 15266563364 0006616 0 ustar 00 # 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).
gif/src/Exceptions/EncoderException.php 0000644 00000000176 15266563364 0014214 0 ustar 00 $frames
* @param array $comments
* @return void
*/
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
*
* @return Header
*/
public function getHeader(): Header
{
return $this->header;
}
/**
* Set header
*
* @param Header $header
*/
public function setHeader(Header $header): self
{
$this->header = $header;
return $this;
}
/**
* Get logical screen descriptor
*
* @return LogicalScreenDescriptor
*/
public function getLogicalScreenDescriptor(): LogicalScreenDescriptor
{
return $this->logicalScreenDescriptor;
}
/**
* Set logical screen descriptor
*
* @param LogicalScreenDescriptor $descriptor
* @return GifDataStream
*/
public function setLogicalScreenDescriptor(LogicalScreenDescriptor $descriptor): self
{
$this->logicalScreenDescriptor = $descriptor;
return $this;
}
/**
* Return global color table if available else null
*
* @return null|ColorTable
*/
public function getGlobalColorTable(): ?ColorTable
{
return $this->globalColorTable;
}
/**
* Set global color table
*
* @param ColorTable $table
* @return GifDataStream
*/
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
*
* @return NetscapeApplicationExtension
*/
public function getMainApplicationExtension(): ?NetscapeApplicationExtension
{
foreach ($this->frames as $frame) {
if ($extension = $frame->getNetscapeExtension()) {
return $extension;
}
}
return null;
}
/**
* Get array of frames
*
* @return array
*/
public function getFrames(): array
{
return $this->frames;
}
/**
* Return array of "global" comments
*
* @return array
*/
public function getComments(): array
{
return $this->comments;
}
/**
* Return first frame
*
* @return null|FrameBlock
*/
public function getFirstFrame(): ?FrameBlock
{
if (!array_key_exists(0, $this->frames)) {
return null;
}
return $this->frames[0];
}
/**
* Add frame
*
* @param FrameBlock $frame
* @return GifDataStream
*/
public function addFrame(FrameBlock $frame): self
{
$this->frames[] = $frame;
return $this;
}
/**
* Add comment extension
*
* @param CommentExtension $comment
* @return GifDataStream
*/
public function addComment(CommentExtension $comment): self
{
$this->comments[] = $comment;
return $this;
}
/**
* Set the current data
*
* @param array $frames
*/
public function setFrames(array $frames): self
{
$this->frames = $frames;
return $this;
}
/**
* Get trailer
*
* @return Trailer
*/
public function getTrailer(): Trailer
{
return new Trailer();
}
/**
* Determine if gif is animated
*
* @return bool
*/
public function isAnimated(): bool
{
return count($this->getFrames()) > 1;
}
/**
* Determine if global color table is set
*
* @return bool
*/
public function hasGlobalColorTable(): bool
{
return !is_null($this->globalColorTable);
}
}
gif/src/Decoders/LogicalScreenDescriptorDecoder.php 0000644 00000006360 15266563364 0016425 0 ustar 00 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
*
* @return int
*/
protected function decodeWidth(string $source): int
{
return unpack('v*', $source)[1];
}
/**
* Decode height
*
* @return int
*/
protected function decodeHeight(string $source): int
{
return unpack('v*', $source)[1];
}
/**
* Decode existance of global color table
*
* @return bool
*/
protected function decodeGlobalColorTableExistance(string $byte): bool
{
return $this->hasPackedBit($byte, 0);
}
/**
* Decode color resolution in bits per pixel
*
* @return int
*/
protected function decodeBitsPerPixel(string $byte): int
{
return bindec($this->getPackedBits($byte, 1, 3)) + 1;
}
/**
* Decode global color table sorted status
*
* @return bool
*/
protected function decodeGlobalColorTableSorted(string $byte): bool
{
return $this->hasPackedBit($byte, 4);
}
/**
* Decode size of global color table
*
* @return int
*/
protected function decodeGlobalColorTableSize(string $byte): int
{
return bindec($this->getPackedBits($byte, 5, 3));
}
/**
* Decode background color index
*
* @return int
*/
protected function decodeBackgroundColorIndex(string $source): int
{
return unpack('C', $source)[1];
}
/**
* Decode pixel aspect ratio
*
* @return int
*/
protected function decodePixelAspectRatio(string $source): int
{
return unpack('C', $source)[1];
}
}
gif/src/Decoders/GraphicControlExtensionDecoder.php 0000644 00000004464 15266563364 0016472 0 ustar 00 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
*
* @return DisposalMethod
*/
protected function decodeDisposalMethod(string $byte): DisposalMethod
{
return DisposalMethod::from(
bindec($this->getPackedBits($byte, 3, 3))
);
}
/**
* Decode user input flag
*
* @return bool
*/
protected function decodeUserInput(string $byte): bool
{
return $this->hasPackedBit($byte, 6);
}
/**
* Decode transparent color existance
*
* @return bool
*/
protected function decodeTransparentColorExistance(string $byte): bool
{
return $this->hasPackedBit($byte, 7);
}
/**
* Decode delay value
*
* @return int
*/
protected function decodeDelay(string $bytes): int
{
return unpack('v*', $bytes)[1];
}
/**
* Decode transparent color index
*
* @return int
*/
protected function decodeTransparentColorIndex(string $byte): int
{
return unpack('C', $byte)[1];
}
}
gif/src/Decoders/ColorDecoder.php 0000644 00000001513 15266563364 0012725 0 ustar 00 setRed($this->decodeColorValue($this->getNextByteOrFail()));
$color->setGreen($this->decodeColorValue($this->getNextByteOrFail()));
$color->setBlue($this->decodeColorValue($this->getNextByteOrFail()));
return $color;
}
/**
* Decode red value from source
*
* @return int
*/
protected function decodeColorValue(string $byte): int
{
return unpack('C', $byte)[1];
}
}
gif/src/Decoders/ColorTableDecoder.php 0000644 00000001145 15266563364 0013676 0 ustar 00 getLength() / 3); $i++) {
$table->addColor(Color::decode($this->handle));
}
return $table;
}
}
gif/src/Decoders/NetscapeApplicationExtensionDecoder.php 0000644 00000000231 15266563364 0017466 0 ustar 00 setVersion($this->decodeVersion());
return $header;
}
/**
* Decode version string
*
* @throws DecoderException
* @return string
*/
protected function decodeVersion(): string
{
$parsed = (bool) preg_match("/^GIF(?P[0-9]{2}[a-z])$/", $this->getNextBytesOrFail(6), $matches);
if ($parsed === false) {
throw new DecoderException('Unable to parse file header.');
}
return $matches['version'];
}
}
gif/src/Decoders/PlainTextExtensionDecoder.php 0000644 00000002663 15266563364 0015463 0 ustar 00 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
* @return int
*/
protected function getInfoBlockSize(): int
{
return unpack('C', $this->getNextByteOrFail())[1];
}
/**
* Decode text sub blocks
*
* @throws DecoderException
* @return array
*/
protected function decodeTextBlocks(): array
{
$blocks = [];
do {
$char = $this->getNextByteOrFail();
$size = (int) unpack('C', $char)[1];
if ($size > 0) {
$blocks[] = $this->getNextBytesOrFail($size);
}
} while ($char !== PlainTextExtension::TERMINATOR);
return $blocks;
}
}
gif/src/Decoders/ImageDescriptorDecoder.php 0000644 00000004324 15266563364 0014733 0 ustar 00 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
*
* @return bool
*/
protected function decodeLocalColorTableExistance(string $byte): bool
{
return $this->hasPackedBit($byte, 0);
}
/**
* Decode local color table sort method
*
* @return bool
*/
protected function decodeLocalColorTableSorted(string $byte): bool
{
return $this->hasPackedBit($byte, 2);
}
/**
* Decode local color table size
*
* @return int
*/
protected function decodeLocalColorTableSize(string $byte): int
{
return bindec($this->getPackedBits($byte, 5, 3));
}
/**
* Decode interlaced flag
*
* @return bool
*/
protected function decodeInterlaced(string $byte): bool
{
return $this->hasPackedBit($byte, 1);
}
}
gif/src/Decoders/CommentExtensionDecoder.php 0000644 00000002561 15266563364 0015152 0 ustar 00 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
*/
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
*
* @param string $byte
* @return int
*/
protected function decodeBlocksize(string $byte): int
{
return (int) @unpack('C', $byte)[1];
}
}
gif/src/Decoders/AbstractDecoder.php 0000644 00000006250 15266563364 0013415 0 ustar 00 handle = $handle;
return $this;
}
/**
* Read given number of bytes and move file pointer
*
* @param int $length
* @throws DecoderException
* @return string
*/
protected function getNextBytesOrFail(int $length): string
{
$bytes = fread($this->handle, $length);
if (strlen($bytes) !== $length) {
throw new DecoderException('Unexpected end of file.');
}
return $bytes;
}
/**
* Read given number of bytes and move pointer back to previous position
*
* @param int $length
* @throws DecoderException
* @return string
*/
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
* @return string
*/
protected function viewNextByteOrFail(): string
{
return $this->viewNextBytesOrFail(1);
}
/**
* Read all remaining bytes from file handler
*
* @return string
*/
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
* @return string
*/
protected function getNextByteOrFail(): string
{
return $this->getNextBytesOrFail(1);
}
/**
* Move file pointer on handle by given offset
*
* @param int $offset
* @return self
*/
protected function movePointer(int $offset): self
{
fseek($this->handle, $offset, SEEK_CUR);
return $this;
}
/**
* Decode multi byte value
*
* @return int
*/
protected function decodeMultiByte(string $bytes): int
{
return unpack('v*', $bytes)[1];
}
/**
* Set length
*
* @param int $length
*/
public function setLength(int $length): self
{
$this->length = $length;
return $this;
}
/**
* Get length
*
* @return null|int
*/
public function getLength(): ?int
{
return $this->length;
}
/**
* Get current handle position
*
* @return int
*/
public function getPosition(): int
{
return ftell($this->handle);
}
}
gif/src/Decoders/DataSubBlockDecoder.php 0000644 00000001155 15266563364 0014147 0 ustar 00 getNextByteOrFail();
$size = (int) unpack('C', $char)[1];
return new DataSubBlock($this->getNextBytesOrFail($size));
}
}
gif/src/Decoders/AbstractPackedBitDecoder.php 0000644 00000001667 15266563364 0015173 0 ustar 00 getPackedBits($byte)[$num];
}
/**
* Get packed bits
*
* @param int $start
* @param int $length
* @return string
*/
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);
}
}
gif/src/Decoders/GifDataStreamDecoder.php 0000644 00000003340 15266563364 0014322 0 ustar 00 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;
}
}
gif/src/Decoders/ApplicationExtensionDecoder.php 0000644 00000003735 15266563364 0016017 0 ustar 00 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
*
* @param string $byte
* @return int
*/
protected function decodeBlockSize(string $byte): int
{
return (int) @unpack('C', $byte)[1];
}
}
gif/src/Decoders/TableBasedImageDecoder.php 0000644 00000002025 15266563364 0014577 0 ustar 00 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;
}
}
gif/src/Decoders/ImageDataDecoder.php 0000644 00000002065 15266563364 0013466 0 ustar 00 getNextByteOrFail();
$size = (int) unpack('C', $char)[1];
$data->setLzwMinCodeSize($size);
do {
// decode sub blocks
$char = $this->getNextByteOrFail();
$size = (int) unpack('C', $char)[1];
if ($size > 0) {
$data->addBlock(new DataSubBlock($this->getNextBytesOrFail($size)));
}
} while ($char !== AbstractEntity::TERMINATOR);
return $data;
}
}
gif/src/Decoders/FrameBlockDecoder.php 0000644 00000003644 15266563364 0013663 0 ustar 00 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;
}
}
gif/src/Traits/CanEncode.php 0000644 00000002052 15266563364 0011715 0 ustar 00 getEncoder()->encode();
}
/**
* Get encoder object for current entity
*
* @throws EncoderException
* @return AbstractEncoder
*/
protected function getEncoder(): AbstractEncoder
{
$classname = $this->getEncoderClassname();
if (!class_exists($classname)) {
throw new EncoderException("Encoder for '" . $this::class . "' not found.");
}
return new $classname($this);
}
/**
* Get encoder classname for current entity
*
* @return string
*/
protected function getEncoderClassname(): string
{
return sprintf('Intervention\Gif\Encoders\%sEncoder', $this->getShortClassname());
}
}
gif/src/Traits/CanHandleFiles.php 0000644 00000002212 15266563364 0012674 0 ustar 00 decode();
}
/**
* Get decoder for current instance
*
* @param resource $source
* @param null|int $length
* @throws DecoderException
* @return AbstractDecoder
*/
protected static function getDecoder($source, ?int $length = null): AbstractDecoder
{
$classname = self::getDecoderClassname();
if (!class_exists($classname)) {
throw new DecoderException("Decoder for '" . static::class . "' not found.");
}
return new $classname($source, $length);
}
/**
* Get classname of decoder for current classname
*
* @return string
*/
protected static function getDecoderClassname(): string
{
return sprintf('Intervention\Gif\Decoders\%sDecoder', self::getShortClassname());
}
}
gif/src/AbstractExtension.php 0000644 00000000234 15266563364 0012270 0 ustar 00 getShortName();
}
/**
* Cast object to string
*
* @throws EncoderException
* @return string
*/
public function __toString(): string
{
return $this->encode();
}
}
gif/src/Splitter.php 0000644 00000017636 15266563364 0010454 0 ustar 00
*/
class Splitter implements IteratorAggregate
{
/**
* Single frames resolved to GifDataStream
*
* @var array
*/
protected array $frames = [];
/**
* Delays of each frame
*
* @var array
*/
protected array $delays = [];
/**
* Create new instance
*
* @param GifDataStream $stream
*/
public function __construct(protected GifDataStream $stream)
{
//
}
/**
* Iterator
*
* @return Traversable
*/
public function getIterator(): Traversable
{
return new ArrayIterator($this->frames);
}
/**
* Get frames
*
* @return array
*/
public function getFrames(): array
{
return $this->frames;
}
/**
* Get delays
*
* @return array
*/
public function getDelays(): array
{
return $this->delays;
}
/**
* Set stream of instance
*
* @param GifDataStream $stream
*/
public function setStream(GifDataStream $stream): self
{
$this->stream = $stream;
return $this;
}
/**
* Static constructor method
*
* @param GifDataStream $stream
* @return Splitter
*/
public static function create(GifDataStream $stream): self
{
return new self($stream);
}
/**
* Split current stream into array of seperate streams for each frame
*
* @return Splitter
*/
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
*/
public function toResources(): array
{
$resources = [];
foreach ($this->frames as $frame) {
$resource = imagecreatefromstring($frame->encode());
imagepalettetotruecolor($resource);
imagesavealpha($resource, true);
$resources[] = $resource;
}
return $resources;
}
/**
* Return array of coalesced GD library resources for each frame
*
* @throws EncoderException
* @return array
*/
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);
}
// 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);
}
// 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
*
* @param GifDataStream $gif
* @return DisposalMethod
*/
private function getDisposalMethod(GifDataStream $gif): DisposalMethod
{
return $gif->getFirstFrame()->getGraphicControlExtension()->getDisposalMethod();
}
}
gif/src/Blocks/Header.php 0000644 00000001225 15266563364 0011236 0 ustar 00 version = $value;
return $this;
}
/**
* Return current version
*
* @return string
*/
public function getVersion(): string
{
return $this->version;
}
}
gif/src/Blocks/ImageData.php 0000644 00000002514 15266563364 0011664 0 ustar 00
*/
protected array $blocks = [];
/**
* Get LZW min. code size
*
* @return int
*/
public function getLzwMinCodeSize(): int
{
return $this->lzw_min_code_size;
}
/**
* Set lzw min. code size
*
* @param int $size
* @return ImageData
*/
public function setLzwMinCodeSize(int $size): self
{
$this->lzw_min_code_size = $size;
return $this;
}
/**
* Get current data sub blocks
*
* @return array
*/
public function getBlocks(): array
{
return $this->blocks;
}
/**
* Addd sub block
*
* @param DataSubBlock $block
* @return ImageData
*/
public function addBlock(DataSubBlock $block): self
{
$this->blocks[] = $block;
return $this;
}
/**
* Determine if data sub blocks are present
*
* @return bool
*/
public function hasBlocks(): bool
{
return count($this->blocks) >= 1;
}
}
gif/src/Blocks/DataSubBlock.php 0000644 00000001603 15266563364 0012344 0 ustar 00 getSize() > 255) {
throw new FormatException(
'Data Sub-Block can not have a block size larger than 255 bytes.'
);
}
}
/**
* Return size of current block
*
* @return int
*/
public function getSize(): int
{
return strlen($this->value);
}
/**
* Return block value
*
* @return string
*/
public function getValue(): string
{
return $this->value;
}
}
gif/src/Blocks/Color.php 0000644 00000002775 15266563364 0011137 0 ustar 00 r;
}
/**
* Set red value
*
* @param int $value
*/
public function setRed(int $value): self
{
$this->r = $value;
return $this;
}
/**
* Get green value
*
* @return int
*/
public function getGreen(): int
{
return $this->g;
}
/**
* Set green value
*
* @param int $value
*/
public function setGreen(int $value): self
{
$this->g = $value;
return $this;
}
/**
* Get blue value
*
* @return int
*/
public function getBlue(): int
{
return $this->b;
}
/**
* Set blue value
*
* @param int $value
*/
public function setBlue(int $value): self
{
$this->b = $value;
return $this;
}
/**
* Return hash value of current color
*
* @return string
*/
public function getHash(): string
{
return md5($this->r . $this->g . $this->b);
}
}
gif/src/Blocks/LogicalScreenDescriptor.php 0000644 00000010734 15266563364 0014624 0 ustar 00 width = $width;
$this->height = $height;
return $this;
}
/**
* Get width of current instance
*
* @return int
*/
public function getWidth(): int
{
return intval($this->width);
}
/**
* Get height of current instance
*
* @return int
*/
public function getHeight(): int
{
return intval($this->height);
}
/**
* Determine if global color table is present
*
* @return bool
*/
public function getGlobalColorTableExistance(): bool
{
return $this->globalColorTableExistance;
}
/**
* Alias of getGlobalColorTableExistance
*
* @return bool
*/
public function hasGlobalColorTable(): bool
{
return $this->getGlobalColorTableExistance();
}
/**
* Set global color table flag
*
* @param bool $existance
* @return self
*/
public function setGlobalColorTableExistance(bool $existance = true): self
{
$this->globalColorTableExistance = $existance;
return $this;
}
/**
* Get global color table sorted flag
*
* @return bool
*/
public function getGlobalColorTableSorted(): bool
{
return $this->globalColorTableSorted;
}
/**
* Set global color table sorted flag
*
* @param bool $sorted
* @return self
*/
public function setGlobalColorTableSorted(bool $sorted = true): self
{
$this->globalColorTableSorted = $sorted;
return $this;
}
/**
* Get size of global color table
*
* @return int
*/
public function getGlobalColorTableSize(): int
{
return $this->globalColorTableSize;
}
/**
* Get byte size of global color table
*
* @return int
*/
public function getGlobalColorTableByteSize(): int
{
return 3 * pow(2, $this->getGlobalColorTableSize() + 1);
}
/**
* Set size of global color table
*
* @param int $size
*/
public function setGlobalColorTableSize(int $size): self
{
$this->globalColorTableSize = $size;
return $this;
}
/**
* Get background color index
*
* @return int
*/
public function getBackgroundColorIndex(): int
{
return $this->backgroundColorIndex;
}
/**
* Set background color index
*
* @param int $index
*/
public function setBackgroundColorIndex(int $index): self
{
$this->backgroundColorIndex = $index;
return $this;
}
/**
* Get current pixel aspect ration
*
* @return int
*/
public function getPixelAspectRatio(): int
{
return $this->pixelAspectRatio;
}
/**
* Set pixel aspect ratio
*
* @param int $ratio
*/
public function setPixelAspectRatio(int $ratio): self
{
$this->pixelAspectRatio = $ratio;
return $this;
}
/**
* Get color resolution
*
* @return int
*/
public function getBitsPerPixel(): int
{
return $this->bitsPerPixel;
}
/**
* Set color resolution
*
* @param int $value
*/
public function setBitsPerPixel(int $value): self
{
$this->bitsPerPixel = $value;
return $this;
}
}
gif/src/Blocks/GraphicControlExtension.php 0000644 00000005660 15266563364 0014670 0 ustar 00 delay = $value;
return $this;
}
/**
* Return delay time (1/100 second)
*
* @return int
*/
public function getDelay(): int
{
return $this->delay;
}
/**
* Set disposal method
*
* @param DisposalMethod $method
* @return self
*/
public function setDisposalMethod(DisposalMethod $method): self
{
$this->disposalMethod = $method;
return $this;
}
/**
* Get disposal method
*
* @return DisposalMethod
*/
public function getDisposalMethod(): DisposalMethod
{
return $this->disposalMethod;
}
/**
* Get transparent color index
*
* @return int
*/
public function getTransparentColorIndex(): int
{
return $this->transparentColorIndex;
}
/**
* Set transparent color index
*
* @param int $index
*/
public function setTransparentColorIndex(int $index): self
{
$this->transparentColorIndex = $index;
return $this;
}
/**
* Get current transparent color existance
*
* @return bool
*/
public function getTransparentColorExistance(): bool
{
return $this->transparentColorExistance;
}
/**
* Set existance flag of transparent color
*
* @param bool $existance
*/
public function setTransparentColorExistance(bool $existance = true): self
{
$this->transparentColorExistance = $existance;
return $this;
}
/**
* Get user input flag
*
* @return bool
*/
public function getUserInput(): bool
{
return $this->userInput;
}
/**
* Set user input flag
*
* @param bool $value
*/
public function setUserInput(bool $value = true): self
{
$this->userInput = $value;
return $this;
}
}
gif/src/Blocks/PlainTextExtension.php 0000644 00000001757 15266563364 0013665 0 ustar 00
*/
protected array $text = [];
/**
* Get current text
*
* @return array
*/
public function getText(): array
{
return $this->text;
}
/**
* Add text
*
* @param string $text
*/
public function addText(string $text): self
{
$this->text[] = $text;
return $this;
}
/**
* Set text array of extension
*
* @param array $text
*/
public function setText(array $text): self
{
$this->text = $text;
return $this;
}
/**
* Determine if any text is present
*
* @return bool
*/
public function hasText(): bool
{
return $this->text !== [];
}
}
gif/src/Blocks/CommentExtension.php 0000644 00000001624 15266563364 0013350 0 ustar 00
*/
protected array $comments = [];
/**
* Get all or one comment
*
* @return array
*/
public function getComments(): array
{
return $this->comments;
}
/**
* Get one comment by key
*
* @param int $key
* @return mixed
*/
public function getComment(int $key): mixed
{
return array_key_exists($key, $this->comments) ? $this->comments[$key] : null;
}
/**
* Set comment text
*
* @param string $value
*/
public function addComment(string $value): self
{
$this->comments[] = $value;
return $this;
}
}
gif/src/Blocks/ImageDescriptor.php 0000644 00000010414 15266563364 0013127 0 ustar 00 width);
}
/**
* Get current width
*
* @return int
*/
public function getHeight(): int
{
return intval($this->height);
}
/**
* Get current Top
*
* @return int
*/
public function getTop(): int
{
return intval($this->top);
}
/**
* Get current Left
*
* @return int
*/
public function getLeft(): int
{
return intval($this->left);
}
/**
* Set size of current instance
*
* @param int $width
* @param int $height
*/
public function setSize(int $width, int $height): self
{
$this->width = $width;
$this->height = $height;
return $this;
}
/**
* Set position of current instance
*
* @param int $left
* @param int $top
*/
public function setPosition(int $left, int $top): self
{
$this->left = $left;
$this->top = $top;
return $this;
}
/**
* Determine if frame is interlaced
*
* @return bool
*/
public function isInterlaced(): bool
{
return $this->interlaced;
}
/**
* Set or unset interlaced value
*
* @param bool $value
*/
public function setInterlaced(bool $value = true): self
{
$this->interlaced = $value;
return $this;
}
/**
* Determine if local color table is present
*
* @return bool
*/
public function getLocalColorTableExistance(): bool
{
return $this->localColorTableExistance;
}
/**
* Alias for getLocalColorTableExistance
*
* @return bool
*/
public function hasLocalColorTable(): bool
{
return $this->getLocalColorTableExistance();
}
/**
* Set local color table flag
*
* @param bool $existance
* @return self
*/
public function setLocalColorTableExistance(bool $existance = true): self
{
$this->localColorTableExistance = $existance;
return $this;
}
/**
* Get local color table sorted flag
*
* @return bool
*/
public function getLocalColorTableSorted(): bool
{
return $this->localColorTableSorted;
}
/**
* Set local color table sorted flag
*
* @param bool $sorted
* @return self
*/
public function setLocalColorTableSorted(bool $sorted = true): self
{
$this->localColorTableSorted = $sorted;
return $this;
}
/**
* Get size of local color table
*
* @return int
*/
public function getLocalColorTableSize(): int
{
return $this->localColorTableSize;
}
/**
* Get byte size of global color table
*
* @return int
*/
public function getLocalColorTableByteSize(): int
{
return 3 * pow(2, $this->getLocalColorTableSize() + 1);
}
/**
* Set size of local color table
*
* @param int $size
*/
public function setLocalColorTableSize(int $size): self
{
$this->localColorTableSize = $size;
return $this;
}
}
gif/src/Blocks/ApplicationExtension.php 0000644 00000003263 15266563364 0014212 0 ustar 00
*/
protected array $blocks = [];
/**
* Get size of block
*
* @return int
*/
public function getBlockSize(): int
{
return strlen($this->application);
}
/**
* Set application name
*
* @param string $value
* @return ApplicationExtension
*/
public function setApplication(string $value): self
{
$this->application = $value;
return $this;
}
/**
* Get application name
*
* @return string
*/
public function getApplication(): string
{
return $this->application;
}
/**
* Add block to application extension
*
* @param DataSubBlock $block
* @return ApplicationExtension
*/
public function addBlock(DataSubBlock $block): self
{
$this->blocks[] = $block;
return $this;
}
/**
* Set data sub blocks of instance
*
* @param array $blocks
* @return ApplicationExtension
*/
public function setBlocks(array $blocks): self
{
$this->blocks = $blocks;
return $this;
}
/**
* Get blocks of ApplicationExtension
*
* @return array
*/
public function getBlocks(): array
{
return $this->blocks;
}
}
gif/src/Blocks/Trailer.php 0000644 00000000266 15266563364 0011454 0 ustar 00 $applicationExtensions
*/
protected array $applicationExtensions = [];
/**
* @var array $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
*/
public function getApplicationExtensions(): array
{
return $this->applicationExtensions;
}
/**
* Return comment extensions of current frame block
*
* @return array
*/
public function getCommentExtensions(): array
{
return $this->commentExtensions;
}
/**
* Set the graphic control extension
*
* @param GraphicControlExtension $extension
* @return self
*/
public function setGraphicControlExtension(GraphicControlExtension $extension): self
{
$this->graphicControlExtension = $extension;
return $this;
}
/**
* Get the graphic control extension of the current frame block
*
* @return null|GraphicControlExtension
*/
public function getGraphicControlExtension(): ?GraphicControlExtension
{
return $this->graphicControlExtension;
}
/**
* Set the image descriptor
*
* @param ImageDescriptor $descriptor
* @return self
*/
public function setImageDescriptor(ImageDescriptor $descriptor): self
{
$this->imageDescriptor = $descriptor;
return $this;
}
/**
* Get the image descriptor of the frame block
*
* @return ImageDescriptor
*/
public function getImageDescriptor(): ImageDescriptor
{
return $this->imageDescriptor;
}
/**
* Set the color table of the current frame block
*
* @param ColorTable $table
* @return FrameBlock
*/
public function setColorTable(ColorTable $table): self
{
$this->colorTable = $table;
return $this;
}
/**
* Get color table
*
* @return null|ColorTable
*/
public function getColorTable(): ?ColorTable
{
return $this->colorTable;
}
/**
* Determine if frame block has color table
*
* @return bool
*/
public function hasColorTable(): bool
{
return !is_null($this->colorTable);
}
/**
* Set image data of frame block
*
* @param ImageData $data
* @return self
*/
public function setImageData(ImageData $data): self
{
$this->imageData = $data;
return $this;
}
/**
* Get image data of current frame block
*
* @return ImageData
*/
public function getImageData(): ImageData
{
return $this->imageData;
}
/**
* Set plain text extension
*
* @param PlainTextExtension $extension
* @return self
*/
public function setPlainTextExtension(PlainTextExtension $extension): self
{
$this->plainTextExtension = $extension;
return $this;
}
/**
* Get plain text extension
*
* @return null|PlainTextExtension
*/
public function getPlainTextExtension(): ?PlainTextExtension
{
return $this->plainTextExtension;
}
/**
* Add given application extension to the current frame block
*
* @param ApplicationExtension $extension
* @return self
*/
public function addApplicationExtension(ApplicationExtension $extension): self
{
$this->applicationExtensions[] = $extension;
return $this;
}
/**
* Add given comment extension to the current frame block
*
* @param CommentExtension $extension
* @return self
*/
public function addCommentExtension(CommentExtension $extension): self
{
$this->commentExtensions[] = $extension;
return $this;
}
/**
* Return netscape extension of the frame block if available
*
* @return null|NetscapeApplicationExtension
*/
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
*
* @param TableBasedImage $tableBasedImage
* @return self
*/
public function setTableBasedImage(TableBasedImage $tableBasedImage): self
{
$this->setImageDescriptor($tableBasedImage->getImageDescriptor());
if ($colorTable = $tableBasedImage->getColorTable()) {
$this->setColorTable($colorTable);
}
$this->setImageData($tableBasedImage->getImageData());
return $this;
}
}
gif/src/Blocks/ColorTable.php 0000644 00000004760 15266563364 0012103 0 ustar 00 $colors
* @return void
*/
public function __construct(protected array $colors = [])
{
//
}
/**
* Return array of current colors
*
* @return array
*/
public function getColors(): array
{
return array_values($this->colors);
}
/**
* Add color to table
*
* @param int $r
* @param int $g
* @param int $b
* @return self
*/
public function addRgb(int $r, int $g, int $b): self
{
$this->addColor(new Color($r, $g, $b));
return $this;
}
/**
* Add color to table
*
* @param Color $color
* @return self
*/
public function addColor(Color $color): self
{
$this->colors[] = $color;
return $this;
}
/**
* Reset colors to array of color objects
*
* @param array $colors
* @return self
*/
public function setColors(array $colors): self
{
$this->empty();
foreach ($colors as $color) {
$this->addColor($color);
}
return $this;
}
/**
* Count colors of current instance
*
* @return int
*/
public function countColors(): int
{
return count($this->colors);
}
/**
* Determine if any colors are present on the current table
*
* @return bool
*/
public function hasColors(): bool
{
return $this->countColors() >= 1;
}
/**
* Empty color table
*
* @return self
*/
public function empty(): self
{
$this->colors = [];
return $this;
}
/**
* Get size of color table in logical screen descriptor
*
* @return int
*/
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
*
* @return int
*/
public function getByteSize(): int
{
if (!$this->hasColors()) {
return 0;
}
return 3 * pow(2, $this->getLogicalSize() + 1);
}
}
gif/src/Blocks/TableBasedImage.php 0000644 00000001745 15266563364 0013006 0 ustar 00 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;
}
}
gif/src/Blocks/NetscapeApplicationExtension.php 0000644 00000002145 15266563364 0015673 0 ustar 00 setApplication(self::IDENTIFIER . self::AUTH_CODE);
$this->setBlocks([new DataSubBlock(self::SUB_BLOCK_PREFIX . "\x00\x00")]);
}
/**
* Get number of loops
*
* @return int
*/
public function getLoops(): int
{
return unpack('v*', substr($this->getBlocks()[0]->getValue(), 1))[1];
}
/**
* Set number of loops
*
* @param int $loops
* @throws FormatException
* @return self
*/
public function setLoops(int $loops): self
{
$this->setBlocks([
new DataSubBlock(self::SUB_BLOCK_PREFIX . pack('v*', $loops))
]);
return $this;
}
}
gif/src/Builder.php 0000644 00000013561 15266563364 0010225 0 ustar 00 gif;
}
/**
* Set canvas size of gif
*
* @param int $width
* @param int $height
* @return Builder
*/
public function setSize(int $width, int $height): self
{
$this->gif->getLogicalScreenDescriptor()->setSize($width, $height);
return $this;
}
/**
* Create new canvas
*
* @param int $width
* @param int $height
* @return self
*/
public static function canvas(int $width, int $height): self
{
return (new self())->setSize($width, $height);
}
/**
* Set loop count
*
* @param int $loops
* @return Builder
* @throws Exception
*/
public function setLoops(int $loops): self
{
if ($this->gif->getFrames() === []) {
throw new Exception('Add at least one frame before setting the loop count');
}
if ($loops >= 0) {
// add frame count to existing or new netscape extension on first frame
if (!$this->gif->getFirstFrame()->getNetscapeExtension()) {
$this->gif->getFirstFrame()->addApplicationExtension(
new NetscapeApplicationExtension()
);
}
$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
*
* @param string|resource $source
* @param float $delay time delay in seconds
* @param int $left position offset in pixels from left
* @param int $top position offset in pixels from top
* @param bool $interlaced
* @throws DecoderException
* @return Builder
*/
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
*
* @param GifDataStream $source
* @param int $delay
* @param DisposalMethod $disposalMethod
* @return GraphicControlExtension
*/
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
*
* @param GifDataStream $source
* @param int $left
* @param int $top
* @param bool $interlaced
* @return TableBasedImage
*/
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
* @return string
*/
public function encode(): string
{
return $this->gif->encode();
}
}
gif/src/Encoders/ImageDescriptorEncoder.php 0000644 00000004504 15266563364 0014757 0 ustar 00 source = $source;
}
/**
* Encode current source
*
* @return string
*/
public function encode(): string
{
return implode('', [
ImageDescriptor::SEPARATOR,
$this->encodeLeft(),
$this->encodeTop(),
$this->encodeWidth(),
$this->encodeHeight(),
$this->encodePackedField(),
]);
}
/**
* Encode left value
*
* @return string
*/
protected function encodeLeft(): string
{
return pack('v*', $this->source->getLeft());
}
/**
* Encode top value
*
* @return string
*/
protected function encodeTop(): string
{
return pack('v*', $this->source->getTop());
}
/**
* Encode width value
*
* @return string
*/
protected function encodeWidth(): string
{
return pack('v*', $this->source->getWidth());
}
/**
* Encode height value
*
* @return string
*/
protected function encodeHeight(): string
{
return pack('v*', $this->source->getHeight());
}
/**
* Encode size of local color table
*
* @return string
*/
protected function encodeLocalColorTableSize(): string
{
return str_pad(decbin($this->source->getLocalColorTableSize()), 3, '0', STR_PAD_LEFT);
}
/**
* Encode reserved field
*
* @return string
*/
protected function encodeReservedField(): string
{
return str_pad('0', 2, '0', STR_PAD_LEFT);
}
/**
* Encode packed field
*
* @return string
*/
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(),
])));
}
}
gif/src/Encoders/TableBasedImageEncoder.php 0000644 00000001223 15266563364 0014622 0 ustar 00 source = $source;
}
public function encode(): string
{
return implode('', [
$this->source->getImageDescriptor()->encode(),
$this->source->getColorTable() ? $this->source->getColorTable()->encode() : '',
$this->source->getImageData()->encode(),
]);
}
}
gif/src/Encoders/FrameBlockEncoder.php 0000644 00000003004 15266563364 0013675 0 ustar 00 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(),
]);
}
}
gif/src/Encoders/CommentExtensionEncoder.php 0000644 00000001756 15266563364 0015203 0 ustar 00 source = $source;
}
/**
* Encode current source
*
* @return string
*/
public function encode(): string
{
return implode('', [
CommentExtension::MARKER,
CommentExtension::LABEL,
$this->encodeComments(),
CommentExtension::TERMINATOR,
]);
}
/**
* Encode comment blocks
*
* @return string
*/
protected function encodeComments(): string
{
return implode('', array_map(function (string $comment): string {
return pack('C', strlen($comment)) . $comment;
}, $this->source->getComments()));
}
}
gif/src/Encoders/LogicalScreenDescriptorEncoder.php 0000644 00000004775 15266563364 0016461 0 ustar 00 source = $source;
}
/**
* Encode current source
*
* @return string
*/
public function encode(): string
{
return implode('', [
$this->encodeWidth(),
$this->encodeHeight(),
$this->encodePackedField(),
$this->encodeBackgroundColorIndex(),
$this->encodePixelAspectRatio(),
]);
}
/**
* Encode width of current instance
*
* @return string
*/
protected function encodeWidth(): string
{
return pack('v*', $this->source->getWidth());
}
/**
* Encode height of current instance
*
* @return string
*/
protected function encodeHeight(): string
{
return pack('v*', $this->source->getHeight());
}
/**
* Encode background color index of global color table
*
* @return string
*/
protected function encodeBackgroundColorIndex(): string
{
return pack('C', $this->source->getBackgroundColorIndex());
}
/**
* Encode pixel aspect ratio
*
* @return string
*/
protected function encodePixelAspectRatio(): string
{
return pack('C', $this->source->getPixelAspectRatio());
}
/**
* Return color resolution for encoding
*
* @return string
*/
protected function encodeColorResolution(): string
{
return str_pad(decbin($this->source->getBitsPerPixel() - 1), 3, '0', STR_PAD_LEFT);
}
/**
* Encode size of global color table
*
* @return string
*/
protected function encodeGlobalColorTableSize(): string
{
return str_pad(decbin($this->source->getGlobalColorTableSize()), 3, '0', STR_PAD_LEFT);
}
/**
* Encode packed field of current instance
*
* @return string
*/
protected function encodePackedField(): string
{
return pack('C', bindec(implode('', [
(int) $this->source->getGlobalColorTableExistance(),
$this->encodeColorResolution(),
(int) $this->source->getGlobalColorTableSorted(),
$this->encodeGlobalColorTableSize(),
])));
}
}
gif/src/Encoders/ColorTableEncoder.php 0000644 00000001335 15266563364 0013723 0 ustar 00 source = $source;
}
/**
* Encode current source
*
* @throws EncoderException
* @return string
*/
public function encode(): string
{
return implode('', array_map(
fn(Color $color): string => $color->encode(),
$this->source->getColors(),
));
}
}
gif/src/Encoders/DataSubBlockEncoder.php 0000644 00000001054 15266563364 0014171 0 ustar 00 source = $source;
}
/**
* Encode current source
*
* @return string
*/
public function encode(): string
{
return pack('C', $this->source->getSize()) . $this->source->getValue();
}
}
gif/src/Encoders/GraphicControlExtensionEncoder.php 0000644 00000003303 15266563364 0016505 0 ustar 00 source = $source;
}
/**
* Encode current source
*
* @return string
*/
public function encode(): string
{
return implode('', [
GraphicControlExtension::MARKER,
GraphicControlExtension::LABEL,
GraphicControlExtension::BLOCKSIZE,
$this->encodePackedField(),
$this->encodeDelay(),
$this->encodeTransparentColorIndex(),
GraphicControlExtension::TERMINATOR,
]);
}
/**
* Encode delay time
*
* @return string
*/
protected function encodeDelay(): string
{
return pack('v*', $this->source->getDelay());
}
/**
* Encode transparent color index
*
* @return string
*/
protected function encodeTransparentColorIndex(): string
{
return pack('C', $this->source->getTransparentColorIndex());
}
/**
* Encode packed field
*
* @return string
*/
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(),
])));
}
}
gif/src/Encoders/ApplicationExtensionEncoder.php 0000644 00000002002 15266563364 0016025 0 ustar 00 source = $source;
}
/**
* Encode current source
*
* @throws EncoderException
* @return string
*/
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,
]);
}
}
gif/src/Encoders/HeaderEncoder.php 0000644 00000001004 15266563364 0013056 0 ustar 00 source = $source;
}
/**
* Encode current source
*
* @return string
*/
public function encode(): string
{
return Header::SIGNATURE . $this->source->getVersion();
}
}
gif/src/Encoders/PlainTextExtensionEncoder.php 0000644 00000002417 15266563364 0015504 0 ustar 00 source = $source;
}
/**
* Encode current source
*
* @return string
*/
public function encode(): string
{
if (!$this->source->hasText()) {
return '';
}
return implode('', [
PlainTextExtension::MARKER,
PlainTextExtension::LABEL,
$this->encodeHead(),
$this->encodeTexts(),
PlainTextExtension::TERMINATOR,
]);
}
/**
* Encode head block
*
* @return string
*/
protected function encodeHead(): string
{
return "\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
}
/**
* Encode text chunks
*
* @return string
*/
protected function encodeTexts(): string
{
return implode('', array_map(
fn(string $text): string => pack('C', strlen($text)) . $text,
$this->source->getText(),
));
}
}
gif/src/Encoders/NetscapeApplicationExtensionEncoder.php 0000644 00000002016 15266563364 0017515 0 ustar 00 source = $source;
}
/**
* Encode current source
*
* @return string
*/
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,
]);
}
}
gif/src/Encoders/ColorEncoder.php 0000644 00000001530 15266563364 0012750 0 ustar 00 source = $source;
}
/**
* Encode current source
*
* @return string
*/
public function encode(): string
{
return implode('', [
$this->encodeColorValue($this->source->getRed()),
$this->encodeColorValue($this->source->getGreen()),
$this->encodeColorValue($this->source->getBlue()),
]);
}
/**
* Encode color value
*
* @return string
*/
protected function encodeColorValue(int $value): string
{
return pack('C', $value);
}
}
gif/src/Encoders/GifDataStreamEncoder.php 0000644 00000003542 15266563364 0014352 0 ustar 00 source = $source;
}
/**
* Encode current source
*
* @throws EncoderException
* @return string
*/
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
* @return string
*/
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
* @return string
*/
protected function encodeComments(): string
{
return implode('', array_map(
fn(CommentExtension $commentExtension): string => $commentExtension->encode(),
$this->source->getComments()
));
}
}
gif/src/Encoders/AbstractEncoder.php 0000644 00000000567 15266563364 0013446 0 ustar 00 source = $source;
}
/**
* Encode current source
*
* @throws EncoderException
* @return string
*/
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,
]);
}
}
gif/src/Encoders/TrailerEncoder.php 0000644 00000000750 15266563364 0013277 0 ustar 00 source = $source;
}
/**
* Encode current source
*
* @return string
*/
public function encode(): string
{
return Trailer::MARKER;
}
}
gif/src/Decoder.php 0000644 00000002217 15266563364 0010200 0 ustar 00 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.'
)
};
rewind($handle);
return GifDataStream::decode($handle);
}
/**
* Determine if input is file pointer resource
*
* @param mixed $input
* @return bool
*/
private static function isFileHandle(mixed $input): bool
{
return is_resource($input) && get_resource_type($input) === 'stream';
}
}
gif/composer.json 0000644 00000002033 15266563364 0010051 0 ustar 00 {
"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
}
}
}
image/readme.md 0000644 00000005456 15266563364 0007437 0 ustar 00 # 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).
image/LICENSE 0000644 00000002077 15266563364 0006661 0 ustar 00 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.
image/src/ModifierStack.php 0000644 00000001646 15266563364 0011701 0 ustar 00 $modifiers
* @return void
*/
public function __construct(protected array $modifiers)
{
//
}
/**
* Apply all modifiers in stack to the given image
*/
public function apply(ImageInterface $image): ImageInterface
{
foreach ($this->modifiers as $modifier) {
$modifier->apply($image);
}
return $image;
}
/**
* Append new modifier to the stack
*/
public function push(ModifierInterface $modifier): self
{
$this->modifiers[] = $modifier;
return $this;
}
}
image/src/Analyzers/PixelColorsAnalyzer.php 0000644 00000000444 15266563364 0015071 0 ustar 00 mediaType;
}
/**
* {@inheritdoc}
*
* @see EncodedImageInterface::mimetype()
*/
public function mimetype(): string
{
return $this->mediaType();
}
/**
* {@inheritdoc}
*
* @see EncodedImageInterface::toDataUri()
*/
public function toDataUri(): string
{
return sprintf('data:%s;base64,%s', $this->mediaType(), base64_encode((string) $this));
}
/**
* Show debug info for the current image
*
* @return array
*/
public function __debugInfo(): array
{
return [
'mediaType' => $this->mediaType(),
'size' => $this->size(),
];
}
}
image/src/Modifiers/PixelateModifier.php 0000644 00000000403 15266563364 0014316 0 ustar 00 size()
->contain(
$this->width,
$this->height
)
->alignPivotTo(
$this->getResizeSize($image),
$this->position
);
}
public function getResizeSize(ImageInterface $image): SizeInterface
{
return new Rectangle($this->width, $this->height);
}
}
image/src/Modifiers/SliceAnimationModifier.php 0000644 00000000453 15266563364 0015447 0 ustar 00 new Rectangle(
is_null($this->width) ? $image->width() : $image->width() + $this->width,
is_null($this->height) ? $image->height() : $image->height() + $this->height,
),
default => new Rectangle(
is_null($this->width) ? $image->width() : $this->width,
is_null($this->height) ? $image->height() : $this->height,
),
};
return $size->alignPivotTo($image->size(), $this->position);
}
}
image/src/Modifiers/BlurModifier.php 0000644 00000000401 15266563364 0013445 0 ustar 00 core()->frame($this->normalizePosition($image));
}
/**
* Return the position of the selected frame as integer
*
* @throws InputException
*/
protected function normalizePosition(ImageInterface $image): int
{
if (is_int($this->position)) {
return $this->position;
}
if (is_numeric($this->position)) {
return (int) $this->position;
}
// calculate position from percentage value
if (preg_match("/^(?P[0-9]{1,3})%$/", $this->position, $matches) != 1) {
throw new InputException(
'Position must be either integer or a percent value as string.'
);
}
$total = count($image);
$position = intval(round($total / 100 * intval($matches['percent'])));
return $position == $total ? $position - 1 : $position;
}
}
image/src/Modifiers/ScaleDownModifier.php 0000644 00000000203 15266563364 0014420 0 ustar 00 size()
->containMax(
$this->width,
$this->height
)
->alignPivotTo(
$this->getResizeSize($image),
$this->position
);
}
}
image/src/Modifiers/RotateModifier.php 0000644 00000000745 15266563364 0014012 0 ustar 00 angle, 360);
}
}
image/src/Modifiers/DrawPolygonModifier.php 0000644 00000000624 15266563364 0015015 0 ustar 00 drawable;
}
}
image/src/Modifiers/AbstractDrawModifier.php 0000644 00000002307 15266563364 0015131 0 ustar 00 driver()->handleInput($this->drawable()->backgroundColor());
} catch (DecoderException) {
return $this->driver()->handleInput('transparent');
}
return $color;
}
/**
* @throws RuntimeException
*/
public function borderColor(): ColorInterface
{
try {
$color = $this->driver()->handleInput($this->drawable()->borderColor());
} catch (DecoderException) {
return $this->driver()->handleInput('transparent');
}
return $color;
}
}
image/src/Modifiers/FlopModifier.php 0000644 00000000275 15266563364 0013452 0 ustar 00 handleInput(
$this->color ?: $driver->config()->blendingColor
);
// replace alpha channel value with opaque value
if ($color->isTransparent()) {
return new Color(
$color->channel(Red::class)->value(),
$color->channel(Green::class)->value(),
$color->channel(Blue::class)->value(),
);
}
return $color;
}
}
image/src/Modifiers/TrimModifier.php 0000644 00000000525 15266563364 0013463 0 ustar 00 driver()->handleInput($this->font->color());
if ($this->font->hasStrokeEffect() && $color->isTransparent()) {
throw new ColorException(
'The text color must be fully opaque when using the stroke effect.'
);
}
return $color;
}
/**
* Decode outline stroke color
*
* @throws RuntimeException
* @throws ColorException
*/
protected function strokeColor(): ColorInterface
{
$color = $this->driver()->handleInput($this->font->strokeColor());
if ($color->isTransparent()) {
throw new ColorException(
'The stroke color must be fully opaque.'
);
}
return $color;
}
/**
* Return array of offset points to draw text stroke effect below the actual text
*
* @return array
*/
protected function strokeOffsets(FontInterface $font): array
{
$offsets = [];
if ($font->strokeWidth() <= 0) {
return $offsets;
}
for ($x = $font->strokeWidth() * -1; $x <= $font->strokeWidth(); $x++) {
for ($y = $font->strokeWidth() * -1; $y <= $font->strokeWidth(); $y++) {
$offsets[] = new Point($x, $y);
}
}
return $offsets;
}
}
image/src/Modifiers/DrawEllipseModifier.php 0000644 00000000624 15266563364 0014763 0 ustar 00 drawable;
}
}
image/src/Modifiers/ColorspaceModifier.php 0000644 00000002064 15266563364 0014642 0 ustar 00 target)) {
return $this->target;
}
if (in_array($this->target, ['rgb', 'RGB', RgbColorspace::class])) {
return new RgbColorspace();
}
if (in_array($this->target, ['cmyk', 'CMYK', CmykColorspace::class])) {
return new CmykColorspace();
}
throw new NotSupportedException('Given colorspace is not supported.');
}
}
image/src/Modifiers/ResizeModifier.php 0000644 00000000563 15266563364 0014013 0 ustar 00 drawable;
}
}
image/src/Modifiers/ResizeDownModifier.php 0000644 00000000205 15266563364 0014634 0 ustar 00 drawable;
}
}
image/src/Modifiers/InvertModifier.php 0000644 00000000277 15266563364 0014023 0 ustar 00 drawable;
}
}
image/src/Modifiers/CoverModifier.php 0000644 00000002234 15266563364 0013625 0 ustar 00 size();
$crop = new Rectangle($this->width, $this->height);
return $crop->contain(
$imagesize->width(),
$imagesize->height()
)->alignPivotTo($imagesize, $this->position);
}
/**
* @throws RuntimeException
*/
public function getResizeSize(SizeInterface $size): SizeInterface
{
return $size->resize($this->width, $this->height);
}
}
image/src/Modifiers/ResizeCanvasRelativeModifier.php 0000644 00000000225 15266563364 0016636 0 ustar 00 position instanceof PointInterface;
}
}
image/src/Modifiers/BrightnessModifier.php 0000644 00000000406 15266563364 0014656 0 ustar 00 width, $this->height);
$crop->align($this->position);
return $crop->alignPivotTo(
$image->size(),
$this->position
);
}
}
image/src/Modifiers/PlaceModifier.php 0000644 00000002135 15266563364 0013573 0 ustar 00 size()->movePivot(
$this->position,
$this->offset_x,
$this->offset_y
);
$watermark_size = $watermark->size()->movePivot(
$this->position
);
return $image_size->relativePositionTo($watermark_size);
}
}
image/src/Modifiers/ProfileModifier.php 0000644 00000000506 15266563364 0014147 0 ustar 00
*/
public function specializable(): array;
/**
* Set the driver for which the object is specialized
*
* @throws DriverException
*/
public function setDriver(DriverInterface $driver): self;
/**
* Return the driver for which the object was specialized
*/
public function driver(): DriverInterface;
}
image/src/Interfaces/FileInterface.php 0000644 00000001301 15266563364 0013724 0 ustar 00 $objects
* @throws NotSupportedException
* @throws DriverException
* @return array