Skip to content

Commit

Permalink
added runCoverResize
Browse files Browse the repository at this point in the history
  • Loading branch information
deluxetom committed Jan 2, 2025
1 parent 463f9c5 commit 1b38a04
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 7 deletions.
93 changes: 91 additions & 2 deletions src/Manipulators/Size.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,11 @@ public function getFit(): string
return $fit;
}

if (preg_match('/^(crop)(-top-left|-top|-top-right|-left|-center|-right|-bottom-left|-bottom|-bottom-right|-[\d]{1,3}-[\d]{1,3}(?:-[\d]{1,3}(?:\.\d+)?)?)*$/', $fit)) {
if (preg_match('/^(crop)(-top-left|-top|-top-right|-left|-center|-right|-bottom-left|-bottom|-bottom-right?)*$/', $fit)) {
return 'cover';
}

if (preg_match('/^(crop)(-[\d]{1,3}-[\d]{1,3}(?:-[\d]{1,3}(?:\.\d+)?)?)*$/', $fit)) {
return 'crop';
}

Expand Down Expand Up @@ -245,6 +249,10 @@ public function runResize(ImageInterface $image, string $fit, int $width, int $h
return $this->runStretchResize($image, $width, $height);
}

if ('cover' === $fit) {
return $this->runCoverResize($image, $width, $height);
}

if ('crop' === $fit) {
return $this->runCropResize($image, $width, $height);
}
Expand Down Expand Up @@ -333,7 +341,88 @@ public function runStretchResize(ImageInterface $image, int $width, int $height)
*/
public function runCropResize(ImageInterface $image, int $width, int $height): ImageInterface
{
return $image->cover($width, $height);
[$resize_width, $resize_height] = $this->resolveCropResizeDimensions($image, $width, $height);

$zoom = $this->getCrop()[2];

$image->scale((int) round($resize_width * $zoom), (int) round($resize_height * $zoom));

[$offset_x, $offset_y] = $this->resolveCropOffset($image, $width, $height);

return $image->crop($width, $height, $offset_x, $offset_y);
}

/**
* Perform crop resize image manipulation.
*
* @param ImageInterface $image The source image.
* @param int $width The width.
* @param int $height The height.
* @param ?string $position The position of the crop
*
* @return ImageInterface The manipulated image.
*/
public function runCoverResize(ImageInterface $image, int $width, int $height, ?string $position = null): ImageInterface
{
$position ??= str_replace('crop-', '', (string) $this->getParam('fit'));

return $image->cover($width, $height, $position ?? 'center');

Check failure on line 369 in src/Manipulators/Size.php

View workflow job for this annotation

GitHub Actions / static-analysis

RedundantConditionGivenDocblockType

src/Manipulators/Size.php:369:47: RedundantConditionGivenDocblockType: Docblock-defined type string for $position is never null (see https://psalm.dev/156)

Check failure on line 369 in src/Manipulators/Size.php

View workflow job for this annotation

GitHub Actions / static-analysis

DocblockTypeContradiction

src/Manipulators/Size.php:369:60: DocblockTypeContradiction: Cannot resolve types for $position - docblock-defined type string does not contain null (see https://psalm.dev/155)

Check failure on line 369 in src/Manipulators/Size.php

View workflow job for this annotation

GitHub Actions / static-analysis

Variable $position on left side of ?? always exists and is not nullable.
}

/**
* Resolve the crop resize dimensions.
*
* @param ImageInterface $image The source image.
* @param int $width The width.
* @param int $height The height.
*
* @return array The resize dimensions.
*/
public function resolveCropResizeDimensions(ImageInterface $image, int $width, int $height): array
{
if ($height > $width * ($image->height() / $image->width())) {
return [$height * ($image->width() / $image->height()), $height];
}

return [$width, $width * ($image->height() / $image->width())];
}

/**
* Resolve the crop offset.
*
* @param ImageInterface $image The source image.
* @param int $width The width.
* @param int $height The height.
*
* @return array The crop offset.
*/
public function resolveCropOffset(ImageInterface $image, int $width, int $height): array
{
[$offset_percentage_x, $offset_percentage_y] = $this->getCrop();

$offset_x = (int) (($image->width() * $offset_percentage_x / 100) - ($width / 2));
$offset_y = (int) (($image->height() * $offset_percentage_y / 100) - ($height / 2));

$max_offset_x = $image->width() - $width;
$max_offset_y = $image->height() - $height;

if ($offset_x < 0) {
$offset_x = 0;
}

if ($offset_y < 0) {
$offset_y = 0;
}

if ($offset_x > $max_offset_x) {
$offset_x = $max_offset_x;
}

if ($offset_y > $max_offset_y) {
$offset_y = $max_offset_y;
}

return [$offset_x, $offset_y];
}

/**
Expand Down
32 changes: 27 additions & 5 deletions tests/Manipulators/SizeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

class SizeTest extends TestCase
{
private $manipulator;
private Size $manipulator;

public function setUp(): void
{
Expand All @@ -21,9 +21,9 @@ public function tearDown(): void
\Mockery::close();
}

public function testCreateInstance()
public function testCreateInstance(): void
{
$this->assertInstanceOf('League\Glide\Manipulators\Size', $this->manipulator);
$this->assertInstanceOf(Size::class, $this->manipulator);
}

public function testSetMaxImageSize()
Expand Down Expand Up @@ -76,7 +76,8 @@ public function testGetFit()
$this->assertSame('fill-max', $this->manipulator->setParams(['fit' => 'fill-max'])->getFit());
$this->assertSame('max', $this->manipulator->setParams(['fit' => 'max'])->getFit());
$this->assertSame('stretch', $this->manipulator->setParams(['fit' => 'stretch'])->getFit());
$this->assertSame('crop', $this->manipulator->setParams(['fit' => 'crop'])->getFit());
$this->assertSame('cover', $this->manipulator->setParams(['fit' => 'crop'])->getFit());
$this->assertSame('crop', $this->manipulator->setParams(['fit' => 'crop-27-75'])->getFit());
$this->assertSame('contain', $this->manipulator->setParams(['fit' => 'invalid'])->getFit());
}

Expand Down Expand Up @@ -186,6 +187,11 @@ public function testRunResize()
$this->manipulator->runResize($image, 'crop', 100, 100)
);

$this->assertInstanceOf(
ImageInterface::class,
$this->manipulator->runResize($image, 'crop-top-right', 100, 100)
);

$this->assertInstanceOf(
ImageInterface::class,
$this->manipulator->runResize($image, 'invalid', 100, 100)
Expand Down Expand Up @@ -251,7 +257,23 @@ public function testRunCropResize()

$this->assertInstanceOf(
ImageInterface::class,
$this->manipulator->runCropResize($image, 100, 100, 'center')
$this->manipulator->runCropResize($image, 100, 100)
);
}

public function testRunCoverResizePosition()
{
$image = \Mockery::mock(ImageInterface::class, function ($mock) {
$mock->shouldReceive('width')->andReturn(100);
$mock->shouldReceive('height')->andReturn(100);
$mock->shouldReceive('cover')->with(50, 50, 'top-left')->andReturn($mock)->once();
});

$this->manipulator->setParams(['w' => 50, 'h' => 50, 'fit' => 'crop-top-left']);

$this->assertInstanceOf(
ImageInterface::class,
$this->manipulator->run($image)
);
}

Expand Down

0 comments on commit 1b38a04

Please sign in to comment.