Skip to content

Commit

Permalink
Merge branch 'develop' into feature/png-encoder-indexed-option
Browse files Browse the repository at this point in the history
  • Loading branch information
olivervogel committed Aug 11, 2024
2 parents 568444c + 9f5e062 commit 20dae08
Show file tree
Hide file tree
Showing 21 changed files with 260 additions and 5 deletions.
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
github: [Intervention]
ko_fi: interventionphp
custom: https://paypal.me/interventionio
24 changes: 24 additions & 0 deletions .github/images/support.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[![Latest Version](https://img.shields.io/packagist/v/intervention/image.svg)](https://packagist.org/packages/intervention/image)
[![Build Status](https://github.com/Intervention/image/actions/workflows/run-tests.yml/badge.svg)](https://github.com/Intervention/image/actions)
[![Monthly Downloads](https://img.shields.io/packagist/dm/intervention/image.svg)](https://packagist.org/packages/intervention/image/stats)
[![Support me on Ko-fi](https://raw.githubusercontent.com/Intervention/image/develop/.github/images/support.svg)](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 features a unified
Expand Down
10 changes: 10 additions & 0 deletions src/Colors/Cmyk/Color.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,14 @@ public function isTransparent(): bool
{
return false;
}

/**
* {@inheritdoc}
*
* @see ColorInterface::isClear()
*/
public function isClear(): bool
{
return false;
}
}
10 changes: 10 additions & 0 deletions src/Colors/Hsl/Color.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,14 @@ public function isTransparent(): bool
{
return false;
}

/**
* {@inheritdoc}
*
* @see ColorInterface::isClear()
*/
public function isClear(): bool
{
return false;
}
}
10 changes: 10 additions & 0 deletions src/Colors/Hsv/Color.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,14 @@ public function isTransparent(): bool
{
return false;
}

/**
* {@inheritdoc}
*
* @see ColorInterface::isClear()
*/
public function isClear(): bool
{
return false;
}
}
10 changes: 10 additions & 0 deletions src/Colors/Rgb/Color.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,14 @@ public function isTransparent(): bool
{
return $this->alpha()->value() < $this->alpha()->max();
}

/**
* {@inheritdoc}
*
* @see ColorInterface::isClear()
*/
public function isClear(): bool
{
return $this->alpha()->value() == 0;
}
}
11 changes: 11 additions & 0 deletions src/Decoders/EncodedImageObjectDecoder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Intervention\Image\Decoders;

use Intervention\Image\Drivers\SpecializableDecoder;

class EncodedImageObjectDecoder extends SpecializableDecoder
{
}
12 changes: 8 additions & 4 deletions src/Drivers/Gd/Cloner.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Intervention\Image\Drivers\Gd;

use GdImage;
use Intervention\Image\Colors\Rgb\Channels\Alpha;
use Intervention\Image\Colors\Rgb\Color;
use Intervention\Image\Exceptions\ColorException;
use Intervention\Image\Geometry\Rectangle;
Expand Down Expand Up @@ -50,10 +51,7 @@ public static function cloneEmpty(
ColorInterface $background = new Color(255, 255, 255, 0)
): GdImage {
// define size
$size = match (true) {
is_null($size) => new Rectangle(imagesx($gd), imagesy($gd)),
default => $size,
};
$size = $size ? $size : new Rectangle(imagesx($gd), imagesy($gd));

// create new gd image with same size or new given size
$clone = imagecreatetruecolor($size->width(), $size->height());
Expand All @@ -70,6 +68,12 @@ public static function cloneEmpty(
imagealphablending($clone, true);
imagesavealpha($clone, true);

// set background image as transparent if alpha channel value if color is below .5
// comes into effect when the end format only supports binary transparency (like GIF)
if ($background->channel(Alpha::class)->value() < 128) {
imagecolortransparent($clone, $processor->colorToNative($background));
}

return $clone;
}

Expand Down
27 changes: 27 additions & 0 deletions src/Drivers/Gd/Decoders/EncodedImageObjectDecoder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Intervention\Image\Drivers\Gd\Decoders;

use Intervention\Image\EncodedImage;
use Intervention\Image\Exceptions\DecoderException;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\ColorInterface;

class EncodedImageObjectDecoder extends BinaryImageDecoder
{
/**
* {@inheritdoc}
*
* @see DecoderInterface::decode()
*/
public function decode(mixed $input): ImageInterface|ColorInterface
{
if (!is_a($input, EncodedImage::class)) {
throw new DecoderException('Unable to decode input');
}

return parent::decode($input->toString());
}
}
27 changes: 27 additions & 0 deletions src/Drivers/Imagick/Decoders/EncodedImageObjectDecoder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Intervention\Image\Drivers\Imagick\Decoders;

use Intervention\Image\EncodedImage;
use Intervention\Image\Exceptions\DecoderException;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\ColorInterface;

class EncodedImageObjectDecoder extends BinaryImageDecoder
{
/**
* {@inheritdoc}
*
* @see DecoderInterface::decode()
*/
public function decode(mixed $input): ImageInterface|ColorInterface
{
if (!is_a($input, EncodedImage::class)) {
throw new DecoderException('Unable to decode input');
}

return parent::decode($input->toString());
}
}
14 changes: 14 additions & 0 deletions src/Drivers/Imagick/Decoders/NativeObjectDecoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@

class NativeObjectDecoder extends SpecializableDecoder implements SpecializedInterface
{
protected const SUPPORTED_COLORSPACES = [
Imagick::COLORSPACE_SRGB,
Imagick::COLORSPACE_CMYK,
Imagick::COLORSPACE_HSL,
Imagick::COLORSPACE_HSB,
];

public function decode(mixed $input): ImageInterface|ColorInterface
{
if (!is_object($input)) {
Expand All @@ -34,6 +41,13 @@ public function decode(mixed $input): ImageInterface|ColorInterface
$input = $input->coalesceImages();
}

// turn image into rgb if colorspace if other than CMYK, RGB, HSL or HSV.
// this prevents working on greyscale colorspace images when loading
// from PNG color type greyscale format.
if (!in_array($input->getImageColorspace(), self::SUPPORTED_COLORSPACES)) {
$input->setImageColorspace(Imagick::COLORSPACE_SRGB);
}

// create image object
$image = new Image(
$this->driver(),
Expand Down
2 changes: 2 additions & 0 deletions src/InputHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Intervention\Image\Decoders\BinaryImageDecoder;
use Intervention\Image\Decoders\ColorObjectDecoder;
use Intervention\Image\Decoders\DataUriImageDecoder;
use Intervention\Image\Decoders\EncodedImageObjectDecoder;
use Intervention\Image\Decoders\FilePathImageDecoder;
use Intervention\Image\Decoders\FilePointerImageDecoder;
use Intervention\Image\Decoders\ImageObjectDecoder;
Expand Down Expand Up @@ -53,6 +54,7 @@ class InputHandler implements InputHandlerInterface
BinaryImageDecoder::class,
DataUriImageDecoder::class,
Base64ImageDecoder::class,
EncodedImageObjectDecoder::class,
];

/**
Expand Down
7 changes: 7 additions & 0 deletions src/Interfaces/ColorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,11 @@ public function isGreyscale(): bool;
* @return bool
*/
public function isTransparent(): bool;

/**
* Determine whether the current color is completely transparent
*
* @return bool
*/
public function isClear(): bool;
}
6 changes: 6 additions & 0 deletions tests/Unit/Colors/Cmyk/ColorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,10 @@ public function testIsTransparent(): void
$color = new Color(100, 50, 50, 0);
$this->assertFalse($color->isTransparent());
}

public function testIsClear(): void
{
$color = new Color(0, 0, 0, 0);
$this->assertFalse($color->isClear());
}
}
6 changes: 6 additions & 0 deletions tests/Unit/Colors/Hsl/ColorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,10 @@ public function testIsTransparent(): void
$color = new Color(0, 1, 0);
$this->assertFalse($color->isTransparent());
}

public function testIsClear(): void
{
$color = new Color(0, 1, 0);
$this->assertFalse($color->isClear());
}
}
6 changes: 6 additions & 0 deletions tests/Unit/Colors/Hsv/ColorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,10 @@ public function testIsTransparent(): void
$color = new Color(1, 0, 0);
$this->assertFalse($color->isTransparent());
}

public function testIsClear(): void
{
$color = new Color(0, 1, 0);
$this->assertFalse($color->isClear());
}
}
15 changes: 15 additions & 0 deletions tests/Unit/Colors/Rgb/ColorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,19 @@ public function testIsTransparent(): void
$color = new Color(255, 255, 255, 0);
$this->assertTrue($color->isTransparent());
}

public function testIsClear(): void
{
$color = new Color(255, 255, 255);
$this->assertFalse($color->isClear());

$color = new Color(255, 255, 255, 255);
$this->assertFalse($color->isClear());

$color = new Color(255, 255, 255, 85);
$this->assertFalse($color->isClear());

$color = new Color(255, 255, 255, 0);
$this->assertTrue($color->isClear());
}
}
2 changes: 1 addition & 1 deletion tests/Unit/Drivers/Gd/ClonerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function testCloneEmpty(): void
);
}

public function testCLoneBlended(): void
public function testCloneBlended(): void
{
$gd = imagecreatefromgif($this->getTestResourcePath('gradient.gif'));
$clone = Cloner::cloneBlended($gd, new Color(255, 0, 255, 255));
Expand Down
32 changes: 32 additions & 0 deletions tests/Unit/Drivers/Gd/Decoders/EncodedImageObjectDecoderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Intervention\Image\Tests\Unit\Drivers\Gd\Decoders;

use Intervention\Image\Drivers\Gd\Decoders\EncodedImageObjectDecoder;
use Intervention\Image\Drivers\Gd\Driver;
use Intervention\Image\EncodedImage;
use Intervention\Image\Image;
use Intervention\Image\Tests\ImagickTestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\RequiresPhpExtension;

#[RequiresPhpExtension('gd')]
#[CoversClass(EncodedImageObjectDecoder::class)]
class EncodedImageObjectDecoderTest extends ImagickTestCase
{
protected EncodedImageObjectDecoder $decoder;

protected function setUp(): void
{
$this->decoder = new EncodedImageObjectDecoder();
$this->decoder->setDriver(new Driver());
}

public function testDecode(): void
{
$result = $this->decoder->decode(new EncodedImage($this->getTestResourceData()));
$this->assertInstanceOf(Image::class, $result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Decoders;

use Intervention\Image\Drivers\Imagick\Decoders\EncodedImageObjectDecoder;
use Intervention\Image\Drivers\Imagick\Driver;
use Intervention\Image\EncodedImage;
use Intervention\Image\Image;
use Intervention\Image\Tests\ImagickTestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\RequiresPhpExtension;

#[RequiresPhpExtension('imagick')]
#[CoversClass(EncodedImageObjectDecoder::class)]
class EncodedImageObjectDecoderTest extends ImagickTestCase
{
protected EncodedImageObjectDecoder $decoder;

protected function setUp(): void
{
$this->decoder = new EncodedImageObjectDecoder();
$this->decoder->setDriver(new Driver());
}

public function testDecode(): void
{
$result = $this->decoder->decode(new EncodedImage($this->getTestResourceData()));
$this->assertInstanceOf(Image::class, $result);
}
}

0 comments on commit 20dae08

Please sign in to comment.