1
0
mirror of https://github.com/Intervention/image.git synced 2025-08-28 16:19:50 +02:00

Modifier & tests

This commit is contained in:
Oliver Vogel
2021-11-05 15:48:16 +00:00
parent 0c3e08b46e
commit 0afda4b9e4
13 changed files with 245 additions and 6 deletions

View File

@@ -36,6 +36,11 @@ abstract class AbstractImage
return $this->frames;
}
public function getFrame(int $key = 0): ?FrameInterface
{
return $this->frames->get($key);
}
public function addFrame(FrameInterface $frame): ImageInterface
{
$this->frames->push($frame);
@@ -115,6 +120,16 @@ abstract class AbstractImage
);
}
public function pickColors(int $x, int $y): Collection
{
$colors = new Collection();
foreach ($this->getFrames() as $key => $frame) {
$colors->push($this->pickColor($x, $y, $key));
}
return $colors;
}
public function resize(...$arguments): ImageInterface
{
$size = $this->getResizer()->setTargetSizeByArray($arguments)->resize();
@@ -150,4 +165,17 @@ abstract class AbstractImage
$this->resolveDriverClass('Modifiers\ResizeModifier', $size)
);
}
public function place($element, string $position = 'top-left', int $offset_x = 0, int $offset_y = 0): ImageInterface
{
return $this->modify(
$this->resolveDriverClass(
'Modifiers\PlaceModifier',
$element,
$position,
$offset_x,
$offset_y
)
);
}
}

View File

@@ -2,6 +2,7 @@
namespace Intervention\Image\Drivers\Gd\Decoders;
use GdImage;
use Intervention\Image\Collection;
use Intervention\Image\Drivers\Abstract\Decoders\AbstractDecoder;
use Intervention\Image\Drivers\Gd\Frame;
@@ -26,13 +27,15 @@ class BinaryImageDecoder extends AbstractDecoder implements DecoderInterface
return $this->decodeGif($input); // decode (animated) gif
}
$resource = @imagecreatefromstring($input);
$gd = @imagecreatefromstring($input);
if ($resource === false) {
if ($gd === false) {
$this->fail();
}
return new Image(new Collection([new Frame($resource)]));
$gd = $this->gdImageToTruecolor($gd);
return new Image(new Collection([new Frame($gd)]));
}
protected function decodeGif($input): ImageInterface
@@ -55,4 +58,32 @@ class BinaryImageDecoder extends AbstractDecoder implements DecoderInterface
return $image;
}
/**
* Transform GD image into truecolor version
*
* @param GdImage $gd
* @return bool
*/
public function gdImageToTruecolor(GdImage $gd): GdImage
{
$width = imagesx($gd);
$height = imagesy($gd);
// new canvas
$canvas = imagecreatetruecolor($width, $height);
// fill with transparent color
imagealphablending($canvas, false);
$transparent = imagecolorallocatealpha($canvas, 255, 255, 255, 127);
imagefilledrectangle($canvas, 0, 0, $width, $height, $transparent);
imagecolortransparent($canvas, $transparent);
imagealphablending($canvas, true);
// copy original
imagecopy($canvas, $gd, 0, 0, 0, 0, $width, $height);
imagedestroy($gd);
return $canvas;
}
}

View File

@@ -8,6 +8,7 @@ use Intervention\Image\Drivers\Abstract\AbstractImage;
use Intervention\Image\Drivers\Gd\Frame;
use Intervention\Image\Geometry\Resizer;
use Intervention\Image\Geometry\Size;
use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\EncoderInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SizeInterface;
@@ -17,11 +18,20 @@ class Image extends AbstractImage implements ImageInterface, IteratorAggregate
{
public function width(): int
{
return imagesx($this->frames->first()->getCore());
return imagesx($this->getFrame()->getCore());
}
public function height(): int
{
return imagesy($this->frames->first()->getCore());
return imagesy($this->getFrame()->getCore());
}
public function pickColor(int $x, int $y, int $frame_key = 0): ?ColorInterface
{
if ($frame = $this->getFrame($frame_key)) {
return new Color(imagecolorat($frame->getCore(), $x, $y));
}
return null;
}
}

View File

@@ -7,6 +7,7 @@ use Intervention\Image\Collection;
use Intervention\Image\Drivers\Abstract\AbstractImage;
use Intervention\Image\Drivers\Imagick\Frame;
use Intervention\Image\Geometry\Size;
use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SizeInterface;
use IteratorAggregate;
@@ -22,4 +23,13 @@ class Image extends AbstractImage implements ImageInterface, IteratorAggregate
{
return $this->frames->first()->getCore()->getImageHeight();
}
public function pickColor(int $x, int $y, int $frame_key = 0): ?ColorInterface
{
if ($frame = $this->getFrame($frame_key)) {
return new Color($frame->getCore()->getImagePixelColor($x, $y));
}
return null;
}
}

View File

@@ -2,6 +2,7 @@
namespace Intervention\Image\Interfaces;
use Intervention\Image\Collection;
use Intervention\Image\EncodedImage;
interface ImageInterface
@@ -14,4 +15,6 @@ interface ImageInterface
public function encode(EncoderInterface $encoder): EncodedImage;
public function setLoops(int $count): ImageInterface;
public function loops(): int;
public function pickColor(int $x, int $y, int $frame_key = 0): ?ColorInterface;
public function pickColors(int $x, int $y): Collection;
}

View File

@@ -3,6 +3,7 @@
namespace Intervention\Image\Tests\Drivers\Gd;
use Intervention\Image\Collection;
use Intervention\Image\Drivers\Gd\Color;
use Intervention\Image\Drivers\Gd\Frame;
use Intervention\Image\Drivers\Gd\Image;
use Intervention\Image\Geometry\Size;
@@ -14,7 +15,17 @@ class ImageTest extends TestCase
protected function setUp(): void
{
$this->image = new Image(new Collection([new Frame(imagecreatetruecolor(3, 2))]));
$gd1 = imagecreatetruecolor(3, 2);
imagefill($gd1, 0, 0, imagecolorallocate($gd1, 255, 0, 0));
$gd2 = imagecreatetruecolor(3, 2);
imagefill($gd2, 0, 0, imagecolorallocate($gd1, 0, 255, 0));
$gd3 = imagecreatetruecolor(3, 2);
imagefill($gd3, 0, 0, imagecolorallocate($gd1, 0, 0, 255));
$this->image = new Image(new Collection([
new Frame($gd1),
new Frame($gd2),
new Frame($gd3),
]));
}
public function testConstructor(): void
@@ -43,4 +54,47 @@ class ImageTest extends TestCase
{
$this->assertInstanceOf(Size::class, $this->image->getSize());
}
public function testPickColor(): void
{
$color = $this->image->pickColor(0, 0);
$this->assertInstanceOf(Color::class, $color);
$this->assertEquals(255, $color->red());
$this->assertEquals(0, $color->green());
$this->assertEquals(0, $color->blue());
$color = $this->image->pickColor(0, 0, 1);
$this->assertInstanceOf(Color::class, $color);
$this->assertEquals(0, $color->red());
$this->assertEquals(255, $color->green());
$this->assertEquals(0, $color->blue());
$color = $this->image->pickColor(0, 0, 2);
$this->assertInstanceOf(Color::class, $color);
$this->assertEquals(0, $color->red());
$this->assertEquals(0, $color->green());
$this->assertEquals(255, $color->blue());
$color = $this->image->pickColor(0, 0, 3);
$this->assertNull($color);
}
public function testPickColors(): void
{
$colors = $this->image->pickColors(0, 0);
$this->assertInstanceOf(Collection::class, $colors);
$this->assertCount(3, $colors);
$this->assertEquals(255, $colors->get(0)->red());
$this->assertEquals(0, $colors->get(0)->green());
$this->assertEquals(0, $colors->get(0)->blue());
$this->assertEquals(0, $colors->get(1)->red());
$this->assertEquals(255, $colors->get(1)->green());
$this->assertEquals(0, $colors->get(1)->blue());
$this->assertEquals(0, $colors->get(2)->red());
$this->assertEquals(0, $colors->get(2)->green());
$this->assertEquals(255, $colors->get(2)->blue());
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Intervention\Image\Tests\Drivers\Gd\Modifiers;
use Intervention\Image\Drivers\Gd\Image;
use Intervention\Image\Drivers\Gd\Modifiers\BlurModifier;
use Intervention\Image\Tests\TestCase;
use Intervention\Image\Tests\Traits\CanCreateGdTestImage;
class BlurModifierTest extends TestCase
{
use CanCreateGdTestImage;
public function testColorChange(): void
{
$image = $this->createTestImage('trim.png');
$this->assertEquals('00aef0', $image->pickColor(14, 14)->toHex());
$image->modify(new BlurModifier(30));
$this->assertEquals('4fa68d', $image->pickColor(14, 14)->toHex());
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Intervention\Image\Tests\Drivers\Imagick\Modifiers;
use Intervention\Image\Tests\TestCase;
use Intervention\Image\Drivers\Imagick\Image;
use Intervention\Image\Drivers\Imagick\Modifiers\BlurModifier;
use Intervention\Image\Tests\Traits\CanCreateImagickTestImage;
class BlurModifierTest extends TestCase
{
use CanCreateImagickTestImage;
public function testColorChange(): void
{
$image = $this->createTestImage('trim.png');
$this->assertEquals('00aef0', $image->pickColor(14, 14)->toHex());
$image->modify(new BlurModifier(30));
$this->assertEquals('42acb2', $image->pickColor(14, 14)->toHex());
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Intervention\Image\Tests\Traits;
use Intervention\Image\Collection;
use Intervention\Image\Drivers\Gd\Decoders\FilePathImageDecoder;
use Intervention\Image\Drivers\Gd\Frame;
use Intervention\Image\Drivers\Gd\Image;
trait CanCreateGdTestImage
{
public function createTestImage($filename = 'test.jpg'): Image
{
return $this->testImageDecoder()->handle(
sprintf('%s/../images/%s', __DIR__, $filename)
);
}
public function createTestAnimation(): Image
{
$gd1 = imagecreatetruecolor(3, 2);
imagefill($gd1, 0, 0, imagecolorallocate($gd1, 255, 0, 0));
$gd2 = imagecreatetruecolor(3, 2);
imagefill($gd2, 0, 0, imagecolorallocate($gd1, 0, 255, 0));
$gd3 = imagecreatetruecolor(3, 2);
imagefill($gd3, 0, 0, imagecolorallocate($gd1, 0, 0, 255));
return new Image(new Collection([
new Frame($gd1),
new Frame($gd2),
new Frame($gd3),
]));
}
protected function testImageDecoder(): FilePathImageDecoder
{
return new FilePathImageDecoder();
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Intervention\Image\Tests\Traits;
use Intervention\Image\Collection;
use Intervention\Image\Drivers\Imagick\Decoders\FilePathImageDecoder;
use Intervention\Image\Drivers\Imagick\Frame;
use Intervention\Image\Drivers\Imagick\Image;
trait CanCreateImagickTestImage
{
public function createTestImage($filename = 'test.jpg'): Image
{
return $this->testImageDecoder()->handle(
sprintf('%s/../images/%s', __DIR__, $filename)
);
}
protected function testImageDecoder(): FilePathImageDecoder
{
return new FilePathImageDecoder();
}
}

BIN
tests/images/circle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

BIN
tests/images/test.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
tests/images/trim.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B