mirror of
https://github.com/Intervention/image.git
synced 2025-08-11 16:34:00 +02:00
Add CropModifier
This commit is contained in:
@@ -345,6 +345,18 @@ abstract class AbstractImage implements ImageInterface
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function crop(
|
||||||
|
int $width,
|
||||||
|
int $height,
|
||||||
|
string $position = 'center',
|
||||||
|
int $offset_x = 0,
|
||||||
|
int $offset_y = 0
|
||||||
|
): ImageInterface {
|
||||||
|
return $this->modify(
|
||||||
|
$this->resolveDriverClass('Modifiers\CropModifier', $width, $height, $position, $offset_x, $offset_y)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function removeAnimation(int $position = 0): ImageInterface
|
public function removeAnimation(int $position = 0): ImageInterface
|
||||||
{
|
{
|
||||||
return $this->modify(
|
return $this->modify(
|
||||||
|
94
src/Drivers/Gd/Modifiers/CropModifier.php
Normal file
94
src/Drivers/Gd/Modifiers/CropModifier.php
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||||
|
|
||||||
|
use Intervention\Image\Geometry\Rectangle;
|
||||||
|
use Intervention\Image\Interfaces\FrameInterface;
|
||||||
|
use Intervention\Image\Interfaces\ImageInterface;
|
||||||
|
use Intervention\Image\Interfaces\ModifierInterface;
|
||||||
|
use Intervention\Image\Interfaces\SizeInterface;
|
||||||
|
|
||||||
|
class CropModifier implements ModifierInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
protected int $width,
|
||||||
|
protected int $height,
|
||||||
|
protected string $position = 'center',
|
||||||
|
protected int $offset_x = 0,
|
||||||
|
protected int $offset_y = 0
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public function apply(ImageInterface $image): ImageInterface
|
||||||
|
{
|
||||||
|
$crop = new Rectangle($this->width, $this->height);
|
||||||
|
$crop->align($this->position);
|
||||||
|
$crop->alignPivotTo($image->getSize(), $this->position);
|
||||||
|
|
||||||
|
foreach ($image as $frame) {
|
||||||
|
$this->cropFrame($frame, $crop);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $image;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function cropFrame(FrameInterface $frame, SizeInterface $resizeTo): void
|
||||||
|
{
|
||||||
|
// create new image
|
||||||
|
$modified = imagecreatetruecolor(
|
||||||
|
$resizeTo->getWidth(),
|
||||||
|
$resizeTo->getHeight()
|
||||||
|
);
|
||||||
|
|
||||||
|
// get current image
|
||||||
|
$current = $frame->getCore();
|
||||||
|
|
||||||
|
// preserve transparency
|
||||||
|
imagealphablending($modified, false);
|
||||||
|
$transIndex = imagecolortransparent($current);
|
||||||
|
|
||||||
|
if ($transIndex != -1) {
|
||||||
|
$rgba = imagecolorsforindex($modified, $transIndex);
|
||||||
|
$transColor = imagecolorallocatealpha($modified, $rgba['red'], $rgba['green'], $rgba['blue'], 127);
|
||||||
|
imagefill($modified, 0, 0, $transColor);
|
||||||
|
} else {
|
||||||
|
imagesavealpha($modified, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy content from resource
|
||||||
|
imagecopyresampled(
|
||||||
|
$modified,
|
||||||
|
$current,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
$resizeTo->getPivot()->getX(),
|
||||||
|
$resizeTo->getPivot()->getY(),
|
||||||
|
$resizeTo->getWidth(),
|
||||||
|
$resizeTo->getHeight(),
|
||||||
|
$resizeTo->getWidth(),
|
||||||
|
$resizeTo->getHeight(),
|
||||||
|
);
|
||||||
|
|
||||||
|
imagedestroy($current);
|
||||||
|
|
||||||
|
if ($transIndex != -1) { // @todo refactor because of duplication
|
||||||
|
imagecolortransparent($modified, $transIndex);
|
||||||
|
for ($y = 0; $y < $resizeTo->getHeight(); ++$y) {
|
||||||
|
for ($x = 0; $x < $resizeTo->getWidth(); ++$x) {
|
||||||
|
if (((imagecolorat($modified, $x, $y) >> 24) & 0x7F) >= 100) {
|
||||||
|
imagesetpixel(
|
||||||
|
$modified,
|
||||||
|
$x,
|
||||||
|
$y,
|
||||||
|
$transIndex
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set new content as recource
|
||||||
|
$frame->setCore($modified);
|
||||||
|
}
|
||||||
|
}
|
38
src/Drivers/Imagick/Modifiers/CropModifier.php
Normal file
38
src/Drivers/Imagick/Modifiers/CropModifier.php
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||||
|
|
||||||
|
use Intervention\Image\Geometry\Rectangle;
|
||||||
|
use Intervention\Image\Interfaces\ImageInterface;
|
||||||
|
use Intervention\Image\Interfaces\ModifierInterface;
|
||||||
|
|
||||||
|
class CropModifier implements ModifierInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
protected int $width,
|
||||||
|
protected int $height,
|
||||||
|
protected string $position = 'center',
|
||||||
|
protected int $offset_x = 0,
|
||||||
|
protected int $offset_y = 0
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public function apply(ImageInterface $image): ImageInterface
|
||||||
|
{
|
||||||
|
$crop = new Rectangle($this->width, $this->height);
|
||||||
|
$crop->align($this->position);
|
||||||
|
$crop->alignPivotTo($image->getSize(), $this->position);
|
||||||
|
|
||||||
|
foreach ($image as $frame) {
|
||||||
|
$frame->getCore()->extentImage(
|
||||||
|
$crop->getWidth(),
|
||||||
|
$crop->getHeight(),
|
||||||
|
$crop->getPivot()->getX() + $this->offset_x,
|
||||||
|
$crop->getPivot()->getY() + $this->offset_y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $image;
|
||||||
|
}
|
||||||
|
}
|
28
tests/Drivers/Gd/Modifiers/CropModifierTest.php
Normal file
28
tests/Drivers/Gd/Modifiers/CropModifierTest.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Intervention\Image\Tests\Drivers\Gd\Modifiers;
|
||||||
|
|
||||||
|
use Intervention\Image\Drivers\Gd\Modifiers\CropModifier;
|
||||||
|
use Intervention\Image\Tests\TestCase;
|
||||||
|
use Intervention\Image\Tests\Traits\CanCreateGdTestImage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires extension gd
|
||||||
|
* @covers \Intervention\Image\Drivers\Gd\Modifiers\CropModifier
|
||||||
|
*/
|
||||||
|
class CropModifierTest extends TestCase
|
||||||
|
{
|
||||||
|
use CanCreateGdTestImage;
|
||||||
|
|
||||||
|
public function testModify(): void
|
||||||
|
{
|
||||||
|
$image = $this->createTestImage('blocks.png');
|
||||||
|
$image = $image->modify(new CropModifier(200, 200, 'bottom-right'));
|
||||||
|
$image->toPng()->save('./test.png');
|
||||||
|
$this->assertEquals(200, $image->getWidth());
|
||||||
|
$this->assertEquals(200, $image->getHeight());
|
||||||
|
$this->assertColor(255, 0, 0, 255, $image->pickColor(5, 5));
|
||||||
|
$this->assertColor(255, 0, 0, 255, $image->pickColor(100, 100));
|
||||||
|
$this->assertColor(255, 0, 0, 255, $image->pickColor(190, 190));
|
||||||
|
}
|
||||||
|
}
|
28
tests/Drivers/Imagick/Modifiers/CropModifierTest.php
Normal file
28
tests/Drivers/Imagick/Modifiers/CropModifierTest.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Intervention\Image\Tests\Drivers\Imagick\Modifiers;
|
||||||
|
|
||||||
|
use Intervention\Image\Drivers\Imagick\Modifiers\CropModifier;
|
||||||
|
use Intervention\Image\Tests\TestCase;
|
||||||
|
use Intervention\Image\Tests\Traits\CanCreateImagickTestImage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires extension gd
|
||||||
|
* @covers \Intervention\Image\Drivers\Imagick\Modifiers\CropModifier
|
||||||
|
*/
|
||||||
|
class CropModifierTest extends TestCase
|
||||||
|
{
|
||||||
|
use CanCreateImagickTestImage;
|
||||||
|
|
||||||
|
public function testModify(): void
|
||||||
|
{
|
||||||
|
$image = $this->createTestImage('blocks.png');
|
||||||
|
$image = $image->modify(new CropModifier(200, 200, 'bottom-right'));
|
||||||
|
$image->toPng()->save('./test.png');
|
||||||
|
$this->assertEquals(200, $image->getWidth());
|
||||||
|
$this->assertEquals(200, $image->getHeight());
|
||||||
|
$this->assertColor(255, 0, 0, 255, $image->pickColor(5, 5));
|
||||||
|
$this->assertColor(255, 0, 0, 255, $image->pickColor(100, 100));
|
||||||
|
$this->assertColor(255, 0, 0, 255, $image->pickColor(190, 190));
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user