Skip to content

Commit

Permalink
fixed crop for animations (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
deluxetom authored Jan 8, 2025
1 parent a024a7b commit f0307ce
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 19 deletions.
60 changes: 41 additions & 19 deletions src/Modifiers/CropModifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
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\Vips\Core;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Interfaces\FrameInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SizeInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
Expand Down Expand Up @@ -48,27 +50,14 @@ public function apply(ImageInterface $image): ImageInterface
)
);
} else {
$offset_x = $crop->pivot()->x() + $this->offset_x;
$offset_y = $crop->pivot()->y() + $this->offset_y;

$targetWidth = min($crop->width(), $originalSize->width());
$targetHeight = min($crop->height(), $originalSize->height());

$targetWidth = $targetWidth > $originalSize->width() ? $targetWidth + $offset_x : $targetWidth;
$targetHeight = $targetHeight > $originalSize->height() ? $targetHeight + $offset_y : $targetHeight;

$cropped = $image->core()->native()->crop(
max($offset_x, 0),
max($offset_y, 0),
$targetWidth,
$targetHeight
);

if ($crop->width() > $originalSize->width() || $cropped->height < $crop->height()) {
$cropped = $background->insert($cropped, max($offset_x * -1, 0), max($offset_y * -1, 0));
$frames = [];
foreach ($image as $frame) {
$frames[] = $frame->setNative($this->cropFrame($frame, $crop, $originalSize, $background));
}

$image->core()->setNative($cropped);
$image->core()->setNative(
Core::replaceFrames($image->core()->native(), $frames)
);
}

return $image;
Expand Down Expand Up @@ -116,4 +105,37 @@ private function getInterestingPositions(): array
Interesting::ALL,
]);
}

private function cropFrame(
FrameInterface $frame,
SizeInterface $crop,
SizeInterface $originalSize,
VipsImage $background
): VipsImage {
$offset_x = $crop->pivot()->x() + $this->offset_x;
$offset_y = $crop->pivot()->y() + $this->offset_y;

$targetWidth = min($crop->width(), $originalSize->width());
$targetHeight = min($crop->height(), $originalSize->height());

$targetWidth = $targetWidth > $originalSize->width() ? $targetWidth + $offset_x : $targetWidth;
$targetHeight = $targetHeight > $originalSize->height() ? $targetHeight + $offset_y : $targetHeight;

$cropped = $frame->native()->crop(
max($offset_x, 0),
max($offset_y, 0),
$targetWidth,
$targetHeight
);

if ($crop->width() > $originalSize->width() || $cropped->height < $crop->height()) {
$cropped = $background->insert(
$cropped,
max($offset_x * -1, 0),
max($offset_y * -1, 0)
);
}

return $cropped;
}
}
23 changes: 23 additions & 0 deletions tests/Unit/Modifiers/CropModifierTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Intervention\Image\Drivers\Vips\Tests\Unit\Modifiers;

use Intervention\Image\Colors\Rgb\Color;
use Intervention\Image\Drivers\Vips\Driver;
use Intervention\Image\Drivers\Vips\Tests\BaseTestCase;
use Intervention\Image\Modifiers\CropModifier;
Expand Down Expand Up @@ -65,4 +66,26 @@ public function testModifyCropSmart(): void
$this->assertEquals(50, $image->height());
$this->assertColor(255, 219, 154, 255, $image->pickColor(25, 25));
}

public function testModifyCropAnimated(): void
{
$image = $this->readTestImage('animation.gif');
$image = $image->modify(new CropModifier(15, 15, 0, 0, position: 'center'));
$this->assertEquals(15, $image->width());
$this->assertEquals(15, $image->height());

$this->assertEquals(
array_map(fn(Color $color): string => $color->toHex(), $image->pickColors(8, 8)->toArray()),
['ffa601', 'ffa601', 'ffa601', 'ffa601', '394b63', '394b63', '394b63', '394b63']
);
}

public function testModifyCropAnimatedSmart(): void
{
$image = $this->readTestImage('animation.gif');
$image = $image->modify(new CropModifier(15, 15, 0, 0, 'ff0000', 'interesting-attention'));
$this->assertEquals(15, $image->width());
$this->assertEquals(15, $image->height());
$this->assertColor(255, 166, 1, 255, $image->pickColor(8, 8));
}
}

0 comments on commit f0307ce

Please sign in to comment.