1
0
mirror of https://github.com/Intervention/image.git synced 2025-08-19 12:11:26 +02:00

Merge branch 'feature/image-cloning'

This commit is contained in:
Oliver Vogel
2023-12-14 15:46:20 +01:00
7 changed files with 117 additions and 0 deletions

View File

@@ -55,4 +55,11 @@ class Core extends Collection implements CoreInterface
{
return parent::last();
}
public function __clone(): void
{
foreach ($this->items as $key => $frame) {
$this->items[$key] = clone $frame;
}
}
}

View File

@@ -2,6 +2,7 @@
namespace Intervention\Image\Drivers\Gd;
use GdImage;
use Intervention\Image\Drivers\AbstractDriver;
use Intervention\Image\Image;
use Intervention\Image\Interfaces\ColorInterface;

View File

@@ -99,4 +99,43 @@ class Frame implements FrameInterface
return $this;
}
/**
* This workaround helps cloning GdImages which is currently not possible.
*
* @return void
*/
public function __clone(): void
{
// create new clone image
$width = imagesx($this->native);
$height = imagesy($this->native);
$clone = match (imageistruecolor($this->native)) {
true => imagecreatetruecolor($width, $height),
default => imagecreate($width, $height),
};
// transfer resolution to clone
$resolution = imageresolution($this->native);
if (is_array($resolution) && array_key_exists(0, $resolution) && array_key_exists(1, $resolution)) {
imageresolution($clone, $resolution[0], $resolution[1]);
}
// transfer transparency to clone
$transIndex = imagecolortransparent($this->native);
if ($transIndex != -1) {
$rgba = imagecolorsforindex($clone, $transIndex);
$transColor = imagecolorallocatealpha($clone, $rgba['red'], $rgba['green'], $rgba['blue'], 127);
imagefill($clone, 0, 0, $transColor);
imagecolortransparent($clone, $transColor);
} else {
imagealphablending($clone, false);
imagesavealpha($clone, true);
}
// transfer actual image to clone
imagecopy($clone, $this->native, 0, 0, 0, 0, $width, $height);
$this->native = $clone;
}
}

View File

@@ -120,4 +120,9 @@ class Core implements CoreInterface, Iterator
{
return $this->frame($this->count());
}
public function __clone(): void
{
$this->imagick = clone $this->imagick;
}
}

View File

@@ -774,4 +774,16 @@ final class Image implements ImageInterface, Countable
{
return $this->encode(new AvifEncoder($quality));
}
/**
* Clone image
*
* @return void
*/
public function __clone(): void
{
$this->driver = clone $this->driver;
$this->core = clone $this->core;
$this->exif = clone $this->exif;
}
}

View File

@@ -4,6 +4,10 @@ namespace Intervention\Image\Tests\Drivers\Gd;
use Intervention\Image\Analyzers\WidthAnalyzer;
use Intervention\Image\Collection;
use Intervention\Image\Colors\Rgb\Channels\Alpha;
use Intervention\Image\Colors\Rgb\Channels\Blue;
use Intervention\Image\Colors\Rgb\Channels\Green;
use Intervention\Image\Colors\Rgb\Channels\Red;
use Intervention\Image\Drivers\Gd\Core;
use Intervention\Image\Drivers\Gd\Driver;
use Intervention\Image\Drivers\Gd\Frame;
@@ -17,10 +21,13 @@ use Intervention\Image\Interfaces\ResolutionInterface;
use Intervention\Image\Interfaces\SizeInterface;
use Intervention\Image\Modifiers\GreyscaleModifier;
use Intervention\Image\Tests\TestCase;
use Intervention\Image\Tests\Traits\CanCreateGdTestImage;
use Intervention\Image\Typography\Font;
class ImageTest extends TestCase
{
use CanCreateGdTestImage;
protected Image $image;
public function setUp(): void
@@ -37,6 +44,25 @@ class ImageTest extends TestCase
);
}
public function testClone(): void
{
$image = $this->readTestImage('gradient.gif');
$clone = clone $image;
$this->assertEquals(16, $image->width());
$this->assertEquals(16, $clone->width());
$result = $clone->crop(4, 4);
$this->assertEquals(16, $image->width());
$this->assertEquals(4, $clone->width());
$this->assertEquals(4, $result->width());
$this->assertEquals('ff0000', $image->pickColor(0, 0)->toHex());
$this->assertEquals('00000000', $image->pickColor(1, 0)->toHex());
$this->assertEquals('ff0000', $clone->pickColor(0, 0)->toHex());
$this->assertEquals('00000000', $clone->pickColor(1, 0)->toHex());
}
public function testDriver(): void
{
$this->assertInstanceOf(Driver::class, $this->image->driver());

View File

@@ -3,6 +3,11 @@
namespace Intervention\Image\Tests\Drivers\Imagick;
use Imagick;
use ImagickPixel;
use Intervention\Image\Colors\Rgb\Channels\Alpha;
use Intervention\Image\Colors\Rgb\Channels\Blue;
use Intervention\Image\Colors\Rgb\Channels\Green;
use Intervention\Image\Colors\Rgb\Channels\Red;
use Intervention\Image\Analyzers\WidthAnalyzer;
use Intervention\Image\Collection;
use Intervention\Image\Drivers\Imagick\Core;
@@ -18,9 +23,12 @@ use Intervention\Image\Interfaces\ResolutionInterface;
use Intervention\Image\Interfaces\SizeInterface;
use Intervention\Image\Modifiers\GreyscaleModifier;
use Intervention\Image\Tests\TestCase;
use Intervention\Image\Tests\Traits\CanCreateImagickTestImage;
class ImageTest extends TestCase
{
use CanCreateImagickTestImage;
protected Image $image;
public function setUp(): void
@@ -36,6 +44,25 @@ class ImageTest extends TestCase
);
}
public function testClone(): void
{
$image = $this->readTestImage('gradient.gif');
$clone = clone $image;
$this->assertEquals(16, $image->width());
$this->assertEquals(16, $clone->width());
$result = $clone->crop(4, 4);
$this->assertEquals(16, $image->width());
$this->assertEquals(4, $clone->width());
$this->assertEquals(4, $result->width());
$this->assertEquals('ff0000', $image->pickColor(0, 0)->toHex());
$this->assertEquals('00000000', $image->pickColor(1, 0)->toHex());
$this->assertEquals('ff0000', $clone->pickColor(0, 0)->toHex());
$this->assertEquals('00000000', $clone->pickColor(1, 0)->toHex());
}
public function testDriver(): void
{
$this->assertInstanceOf(Driver::class, $this->image->driver());