Skip to content

Commit

Permalink
Fix bug in Imagick PadModifier
Browse files Browse the repository at this point in the history
  • Loading branch information
olivervogel committed Dec 3, 2023
1 parent 84d2aaa commit 6354c37
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 53 deletions.
103 changes: 53 additions & 50 deletions src/Drivers/Imagick/Modifiers/PadModifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,11 @@

namespace Intervention\Image\Drivers\Imagick\Modifiers;

use Imagick;
use ImagickDraw;
use ImagickPixel;
use Intervention\Image\Colors\Rgb\Color;
use Intervention\Image\Drivers\DriverModifier;
use Intervention\Image\Drivers\Imagick\Core;
use Intervention\Image\Image;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SizeInterface;
use Intervention\Image\Modifiers\FillModifier;

/**
* @method SizeInterface getCropSize(ImageInterface $image)
Expand All @@ -25,63 +20,71 @@ class PadModifier extends DriverModifier
{
public function apply(ImageInterface $image): ImageInterface
{

$crop = $this->getCropSize($image);
$resize = $this->getResizeSize($image);
$background = $this->driver()->handleInput($this->background);
$transparent = new ImagickPixel('transparent');
$background = $this->driver()->colorProcessor($image->colorspace())->colorToNative(
$this->driver()->handleInput($this->background)
);

$imagick = new Imagick();
foreach ($image as $frame) {
// resize current core
$frame->native()->scaleImage(
$crop->width(),
$crop->height()
$crop->height(),
);

// create new canvas, to get newly emerged background color
$canvas = $this->buildBaseCanvas($crop, $resize, $background);
$frame->native()->setBackgroundColor($transparent);
$frame->native()->setImageBackgroundColor($transparent);

// place current core onto canvas
$canvas->compositeImage(
$frame->native(),
Imagick::COMPOSITE_DEFAULT,
$crop->pivot()->x(),
$crop->pivot()->y()
$frame->native()->extentImage(
$resize->width(),
$resize->height(),
$crop->pivot()->x() * -1,
$crop->pivot()->y() * -1
);

$imagick->addImage($canvas);
}

return new Image(
$image->driver(),
new Core($imagick),
$image->exif()
);
}

protected function buildBaseCanvas(SizeInterface $crop, SizeInterface $resize, Color $background): Imagick
{
// build base canvas in target size
$canvas = $this->driver()->createImage(
$resize->width(),
$resize->height()
)->modify(
new FillModifier($background)
)->core()->native();
if ($resize->width() > $crop->width()) {
// fill new emerged background
$draw = new ImagickDraw();
$draw->setFillColor($background);
$draw->rectangle(
0,
0,
$crop->pivot()->x() - 1,
$resize->height()
);
$frame->native()->drawImage($draw);
$draw->rectangle(
$crop->pivot()->x() + $crop->width(),
0,
$resize->width(),
$resize->height()
);
$frame->native()->drawImage($draw);
}

// make area where image is placed transparent to keep
// transparency even if background-color is set
$draw = new ImagickDraw();
$fill = $background->toHex('#') == '#ff0000' ? '#00ff00' : '#ff0000';
$draw->setFillColor(new ImagickPixel($fill));
$draw->rectangle(
$crop->pivot()->x(),
$crop->pivot()->y(),
$crop->pivot()->x() + $crop->width() - 1,
$crop->pivot()->y() + $crop->height() - 1
);
$canvas->drawImage($draw);
$canvas->transparentPaintImage($fill, 0, 0, false);
if ($resize->height() > $crop->height()) {
// fill new emerged background
$draw = new ImagickDraw();
$draw->setFillColor($background);
$draw->rectangle(
0,
0,
$crop->width(),
$crop->pivot()->y() - 1
);
$frame->native()->drawImage($draw);
$draw->rectangle(
0,
$crop->pivot()->y() + $crop->height(),
$resize->width(),
$resize->height()
);
$frame->native()->drawImage($draw);
}
}

return $canvas;
return $image;
}
}
7 changes: 6 additions & 1 deletion src/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,12 @@ public function place(
*/
public function fill(mixed $color, ?int $x = null, ?int $y = null): ImageInterface
{
return $this->modify(new FillModifier($color, new Point($x, $y)));
return $this->modify(
new FillModifier(
$color,
(is_null($x) || is_null($y)) ? null : new Point($x, $y),
),
);
}

/**
Expand Down
9 changes: 7 additions & 2 deletions tests/Drivers/Imagick/Modifiers/PadModifierTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,16 @@ public function testModify(): void
$image = $this->createTestImage('blocks.png');
$this->assertEquals(640, $image->width());
$this->assertEquals(480, $image->height());
$image->modify(new PadModifier(200, 100, 'ff0'));
$result = $image->modify(new PadModifier(200, 100, 'ff0'));
$this->assertEquals(200, $image->width());
$this->assertEquals(100, $image->height());
$this->assertColor(255, 255, 0, 255, $image->pickColor(0, 0));
$this->assertColor(255, 0, 255, 0, $image->pickColor(140, 10));
$this->assertColor(0, 0, 0, 0, $image->pickColor(140, 10));
$this->assertColor(255, 255, 0, 255, $image->pickColor(175, 10));
$this->assertEquals(200, $result->width());
$this->assertEquals(100, $result->height());
$this->assertColor(255, 255, 0, 255, $result->pickColor(0, 0));
$this->assertColor(0, 0, 0, 0, $result->pickColor(140, 10));
$this->assertColor(255, 255, 0, 255, $result->pickColor(175, 10));
}
}

0 comments on commit 6354c37

Please sign in to comment.