From 463f9c5581e737eb2262f032edf9c42d31a6ee9e Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 2 Jan 2025 15:32:03 -0600 Subject: [PATCH 1/8] use cover method from Intervention --- src/Manipulators/Size.php | 66 +-------------------------------------- 1 file changed, 1 insertion(+), 65 deletions(-) diff --git a/src/Manipulators/Size.php b/src/Manipulators/Size.php index ac4a12a..6934e61 100644 --- a/src/Manipulators/Size.php +++ b/src/Manipulators/Size.php @@ -333,71 +333,7 @@ public function runStretchResize(ImageInterface $image, int $width, int $height) */ public function runCropResize(ImageInterface $image, int $width, int $height): ImageInterface { - [$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); - } - - /** - * 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]; + return $image->cover($width, $height); } /** From 1b38a04f071ce5b5379a10d5515ffd6c1a39532f Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 2 Jan 2025 16:21:09 -0600 Subject: [PATCH 2/8] added runCoverResize --- src/Manipulators/Size.php | 93 ++++++++++++++++++++++++++++++++- tests/Manipulators/SizeTest.php | 32 ++++++++++-- 2 files changed, 118 insertions(+), 7 deletions(-) diff --git a/src/Manipulators/Size.php b/src/Manipulators/Size.php index 6934e61..9f75a4b 100644 --- a/src/Manipulators/Size.php +++ b/src/Manipulators/Size.php @@ -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'; } @@ -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); } @@ -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'); + } + + /** + * 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]; } /** diff --git a/tests/Manipulators/SizeTest.php b/tests/Manipulators/SizeTest.php index 1153f9b..4f0bfc3 100644 --- a/tests/Manipulators/SizeTest.php +++ b/tests/Manipulators/SizeTest.php @@ -9,7 +9,7 @@ class SizeTest extends TestCase { - private $manipulator; + private Size $manipulator; public function setUp(): void { @@ -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() @@ -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()); } @@ -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) @@ -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) ); } From b5b02719e4ebfdd3c717768ad36a44e9754f70c6 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 2 Jan 2025 16:24:33 -0600 Subject: [PATCH 3/8] added fit=cover --- src/Manipulators/Size.php | 2 +- tests/Manipulators/SizeTest.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Manipulators/Size.php b/src/Manipulators/Size.php index 9f75a4b..3dd38cf 100644 --- a/src/Manipulators/Size.php +++ b/src/Manipulators/Size.php @@ -107,7 +107,7 @@ public function getFit(): string { $fit = (string) $this->getParam('fit'); - if (in_array($fit, ['contain', 'fill', 'max', 'stretch', 'fill-max'], true)) { + if (in_array($fit, ['contain', 'fill', 'max', 'stretch', 'fill-max', 'cover'], true)) { return $fit; } diff --git a/tests/Manipulators/SizeTest.php b/tests/Manipulators/SizeTest.php index 4f0bfc3..c7198f6 100644 --- a/tests/Manipulators/SizeTest.php +++ b/tests/Manipulators/SizeTest.php @@ -76,7 +76,10 @@ 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('cover', $this->manipulator->setParams(['fit' => 'cover'])->getFit()); $this->assertSame('cover', $this->manipulator->setParams(['fit' => 'crop'])->getFit()); + $this->assertSame('cover', $this->manipulator->setParams(['fit' => 'crop-top-left'])->getFit()); + $this->assertSame('cover', $this->manipulator->setParams(['fit' => 'crop-center'])->getFit()); $this->assertSame('crop', $this->manipulator->setParams(['fit' => 'crop-27-75'])->getFit()); $this->assertSame('contain', $this->manipulator->setParams(['fit' => 'invalid'])->getFit()); } From b89b65883fdf96b553877d7e3948d35d6da5c318 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 2 Jan 2025 17:50:28 -0600 Subject: [PATCH 4/8] fixed position --- src/Manipulators/Size.php | 4 +++- tests/Manipulators/SizeTest.php | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Manipulators/Size.php b/src/Manipulators/Size.php index 3dd38cf..3613ed1 100644 --- a/src/Manipulators/Size.php +++ b/src/Manipulators/Size.php @@ -366,7 +366,9 @@ public function runCoverResize(ImageInterface $image, int $width, int $height, ? { $position ??= str_replace('crop-', '', (string) $this->getParam('fit')); - return $image->cover($width, $height, $position ?? 'center'); + $position = empty($position) || in_array($position, ['crop', 'cover']) ? 'center' : $position; + + return $image->cover($width, $height, $position); } /** diff --git a/tests/Manipulators/SizeTest.php b/tests/Manipulators/SizeTest.php index c7198f6..ba718f3 100644 --- a/tests/Manipulators/SizeTest.php +++ b/tests/Manipulators/SizeTest.php @@ -264,6 +264,22 @@ public function testRunCropResize() ); } + public function testRunCoverResize() + { + $image = \Mockery::mock(ImageInterface::class, function ($mock) { + $mock->shouldReceive('width')->andReturn(100); + $mock->shouldReceive('height')->andReturn(100); + $mock->shouldReceive('cover')->with(50, 50, 'center')->andReturn($mock)->once(); + }); + + $this->manipulator->setParams(['w' => 50, 'h' => 50, 'fit' => 'crop']); + + $this->assertInstanceOf( + ImageInterface::class, + $this->manipulator->run($image) + ); + } + public function testRunCoverResizePosition() { $image = \Mockery::mock(ImageInterface::class, function ($mock) { From 03c3805adb4aa55f7638e7c509ef825016d2c645 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 2 Jan 2025 17:53:37 -0600 Subject: [PATCH 5/8] added tests --- tests/Manipulators/SizeTest.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/Manipulators/SizeTest.php b/tests/Manipulators/SizeTest.php index ba718f3..1afd6b9 100644 --- a/tests/Manipulators/SizeTest.php +++ b/tests/Manipulators/SizeTest.php @@ -78,9 +78,10 @@ public function testGetFit() $this->assertSame('stretch', $this->manipulator->setParams(['fit' => 'stretch'])->getFit()); $this->assertSame('cover', $this->manipulator->setParams(['fit' => 'cover'])->getFit()); $this->assertSame('cover', $this->manipulator->setParams(['fit' => 'crop'])->getFit()); + $this->assertSame('cover', $this->manipulator->setParams(['fit' => 'crop-bottom'])->getFit()); $this->assertSame('cover', $this->manipulator->setParams(['fit' => 'crop-top-left'])->getFit()); $this->assertSame('cover', $this->manipulator->setParams(['fit' => 'crop-center'])->getFit()); - $this->assertSame('crop', $this->manipulator->setParams(['fit' => 'crop-27-75'])->getFit()); + $this->assertSame('crop', $this->manipulator->setParams(['fit' => 'crop-25-75'])->getFit()); $this->assertSame('contain', $this->manipulator->setParams(['fit' => 'invalid'])->getFit()); } @@ -286,13 +287,23 @@ public function testRunCoverResizePosition() $mock->shouldReceive('width')->andReturn(100); $mock->shouldReceive('height')->andReturn(100); $mock->shouldReceive('cover')->with(50, 50, 'top-left')->andReturn($mock)->once(); + $mock->shouldReceive('cover')->with(50, 50, 'bottom')->andReturn($mock)->once(); + $mock->shouldReceive('cover')->with(50, 50, 'bottom-right')->andReturn($mock)->once(); }); $this->manipulator->setParams(['w' => 50, 'h' => 50, 'fit' => 'crop-top-left']); $this->assertInstanceOf( ImageInterface::class, - $this->manipulator->run($image) + $this->manipulator->setParams(['w' => 50, 'h' => 50, 'fit' => 'crop-top-left'])->run($image) + ); + $this->assertInstanceOf( + ImageInterface::class, + $this->manipulator->setParams(['w' => 50, 'h' => 50, 'fit' => 'crop-bottom'])->run($image) + ); + $this->assertInstanceOf( + ImageInterface::class, + $this->manipulator->setParams(['w' => 50, 'h' => 50, 'fit' => 'crop-bottom-right'])->run($image) ); } From 2ddea0f9aaf0cd84f87ecd0758e24ff22918a334 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 2 Jan 2025 17:55:57 -0600 Subject: [PATCH 6/8] fixed return types --- tests/Manipulators/SizeTest.php | 44 ++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/Manipulators/SizeTest.php b/tests/Manipulators/SizeTest.php index 1afd6b9..d7f51ff 100644 --- a/tests/Manipulators/SizeTest.php +++ b/tests/Manipulators/SizeTest.php @@ -26,18 +26,18 @@ public function testCreateInstance(): void $this->assertInstanceOf(Size::class, $this->manipulator); } - public function testSetMaxImageSize() + public function testSetMaxImageSize(): void { $this->manipulator->setMaxImageSize(500 * 500); $this->assertSame(500 * 500, $this->manipulator->getMaxImageSize()); } - public function testGetMaxImageSize() + public function testGetMaxImageSize(): void { $this->assertNull($this->manipulator->getMaxImageSize()); } - public function testRun() + public function testRun(): void { $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('width')->andReturn('200')->twice(); @@ -51,7 +51,7 @@ public function testRun() ); } - public function testGetWidth() + public function testGetWidth(): void { $this->assertSame(100, $this->manipulator->setParams(['w' => 100])->getWidth()); $this->assertSame(100, $this->manipulator->setParams(['w' => 100.1])->getWidth()); @@ -60,7 +60,7 @@ public function testGetWidth() $this->assertSame(null, $this->manipulator->setParams(['w' => '-100'])->getWidth()); } - public function testGetHeight() + public function testGetHeight(): void { $this->assertSame(100, $this->manipulator->setParams(['h' => 100])->getHeight()); $this->assertSame(100, $this->manipulator->setParams(['h' => 100.1])->getHeight()); @@ -69,7 +69,7 @@ public function testGetHeight() $this->assertSame(null, $this->manipulator->setParams(['h' => '-100'])->getHeight()); } - public function testGetFit() + public function testGetFit(): void { $this->assertSame('contain', $this->manipulator->setParams(['fit' => 'contain'])->getFit()); $this->assertSame('fill', $this->manipulator->setParams(['fit' => 'fill'])->getFit()); @@ -85,7 +85,7 @@ public function testGetFit() $this->assertSame('contain', $this->manipulator->setParams(['fit' => 'invalid'])->getFit()); } - public function testGetCrop() + public function testGetCrop(): void { $this->assertSame([0, 0, 1.0], $this->manipulator->setParams(['fit' => 'crop-top-left'])->getCrop()); $this->assertSame([0, 100, 1.0], $this->manipulator->setParams(['fit' => 'crop-bottom-left'])->getCrop()); @@ -110,7 +110,7 @@ public function testGetCrop() $this->assertSame([50, 50, 1.0], $this->manipulator->setParams(['fit' => 'invalid'])->getCrop()); } - public function testGetDpr() + public function testGetDpr(): void { $this->assertSame(1.0, $this->manipulator->setParams(['dpr' => 'invalid'])->getDpr()); $this->assertSame(1.0, $this->manipulator->setParams(['dpr' => '-1'])->getDpr()); @@ -118,7 +118,7 @@ public function testGetDpr() $this->assertSame(2.0, $this->manipulator->setParams(['dpr' => '2'])->getDpr()); } - public function testResolveMissingDimensions() + public function testResolveMissingDimensions(): void { $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('width')->andReturn(400); @@ -130,7 +130,7 @@ public function testResolveMissingDimensions() $this->assertSame([200, 100], $this->manipulator->resolveMissingDimensions($image, null, 100)); } - public function testResolveMissingDimensionsWithOddDimensions() + public function testResolveMissingDimensionsWithOddDimensions(): void { $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('width')->andReturn(1024); @@ -140,7 +140,7 @@ public function testResolveMissingDimensionsWithOddDimensions() $this->assertSame([411, 222], $this->manipulator->resolveMissingDimensions($image, 411, null)); } - public function testLimitImageSize() + public function testLimitImageSize(): void { $this->assertSame([1000, 1000], $this->manipulator->limitImageSize(1000, 1000)); $this->manipulator->setMaxImageSize(500 * 500); @@ -148,7 +148,7 @@ public function testLimitImageSize() $this->assertSame([500, 500], $this->manipulator->limitImageSize(1000, 1000)); } - public function testRunResize() + public function testRunResize(): void { $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('width')->andReturn(100)->times(4); @@ -202,7 +202,7 @@ public function testRunResize() ); } - public function testRunContainResize() + public function testRunContainResize(): void { $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('scale')->with(100, 100)->andReturn($mock)->once(); @@ -214,7 +214,7 @@ public function testRunContainResize() ); } - public function testRunFillResize() + public function testRunFillResize(): void { $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('pad')->with(100, 100)->andReturn($mock)->once(); @@ -226,7 +226,7 @@ public function testRunFillResize() ); } - public function testRunMaxResize() + public function testRunMaxResize(): void { $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('scaleDown')->with(100, 100)->andReturn($mock)->once(); @@ -238,7 +238,7 @@ public function testRunMaxResize() ); } - public function testRunStretchResize() + public function testRunStretchResize(): void { $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('resize')->with(100, 100)->andReturn($mock)->once(); @@ -250,7 +250,7 @@ public function testRunStretchResize() ); } - public function testRunCropResize() + public function testRunCropResize(): void { $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('width')->andReturn(100)->times(4); @@ -265,7 +265,7 @@ public function testRunCropResize() ); } - public function testRunCoverResize() + public function testRunCoverResize(): void { $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('width')->andReturn(100); @@ -281,7 +281,7 @@ public function testRunCoverResize() ); } - public function testRunCoverResizePosition() + public function testRunCoverResizePosition(): void { $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('width')->andReturn(100); @@ -307,7 +307,7 @@ public function testRunCoverResizePosition() ); } - public function testResizeDoesNotRunWhenNoParamsAreSet() + public function testResizeDoesNotRunWhenNoParamsAreSet(): void { $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('width')->andReturn(100)->twice(); @@ -321,7 +321,7 @@ public function testResizeDoesNotRunWhenNoParamsAreSet() ); } - public function testResizeDoesNotRunWhenSettingFitCropToCenterWithNoZoom() + public function testResizeDoesNotRunWhenSettingFitCropToCenterWithNoZoom(): void { $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('width')->andReturn(100)->twice(); @@ -337,7 +337,7 @@ public function testResizeDoesNotRunWhenSettingFitCropToCenterWithNoZoom() ); } - public function testResizeDoesRunWhenDimensionsAreTheSameAndTheCropZoomIsNotDefaultOne() + public function testResizeDoesRunWhenDimensionsAreTheSameAndTheCropZoomIsNotDefaultOne(): void { $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('width')->andReturn(100); From f1d1bad3063fc62cb2bee743d1a3feca6485bd8d Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 6 Jan 2025 12:53:01 -0600 Subject: [PATCH 7/8] fixed documentation for `fit=cover` option --- docs/3.0/api/crop.md | 16 ++++++++-------- docs/3.0/api/size.md | 7 ++++--- docs/3.0/api/watermarks.md | 5 +++-- docs/3.0/config/defaults-and-presets.md | 10 +++++----- docs/3.0/simple-example.md | 2 +- src/Manipulators/Size.php | 4 ++-- tests/Manipulators/SizeTest.php | 19 +++++++++++++------ 7 files changed, 36 insertions(+), 27 deletions(-) diff --git a/docs/3.0/api/crop.md b/docs/3.0/api/crop.md index 46abc1f..676b349 100644 --- a/docs/3.0/api/crop.md +++ b/docs/3.0/api/crop.md @@ -5,36 +5,36 @@ title: Crop # Crop -## Fit `fit=crop` +## Fit `fit=cover` - Crop to cover the dimensions Resizes the image to fill the width and height boundaries and crops any excess image data. The resulting image will match the width and height constraints without distorting the image. ~~~ html - + ~~~ [![© Photo Joel Reynolds](https://glide.herokuapp.com/1.0/kayaks.jpg?w=300&h=300&fit=crop)](https://glide.herokuapp.com/1.0/kayaks.jpg?w=300&h=300&fit=crop) ### Crop Position -You can also set where the image is cropped by adding a crop position. Accepts `crop-top-left`, `crop-top`, `crop-top-right`, `crop-left`, `crop-center`, `crop-right`, `crop-bottom-left`, `crop-bottom` or `crop-bottom-right`. Default is `crop-center`, and is the same as `crop`. +You can also set where the image is cropped by adding a crop position. Accepts `cover-top-left`, `cover-top`, `cover-top-right`, `cover-left`, `cover-center`, `cover-right`, `cover-bottom-left`, `cover-bottom` or `cover-bottom-right`. Default is `cover-center`, and is the same as `crop`. ~~~ html - + ~~~ -### Crop Focal Point +## Fit `fit=crop-x%-y%` - Crop based on Focal Point In addition to the crop position, you can be more specific about the exact crop position using a focal point. This is defined using two offset percentages: `crop-x%-y%`. ~~~ html - + ~~~ You may also choose to zoom into your focal point by providing a third value: a float between 1 and 100. Each full step is the equivalent of a 100% zoom. (eg. `x%-y%-2` is the equivalent of viewing the image at 200%). The suggested range is 1-10. ~~~ html - + ~~~ ## Crop `crop` @@ -45,4 +45,4 @@ Crops the image to specific dimensions prior to any other resize operations. Req ~~~ -[![© Photo Joel Reynolds](https://glide.herokuapp.com/1.0/kayaks.jpg?crop=100,100,915,155)](https://glide.herokuapp.com/1.0/kayaks.jpg?crop=100,100,915,155) \ No newline at end of file +[![© Photo Joel Reynolds](https://glide.herokuapp.com/1.0/kayaks.jpg?crop=100,100,915,155)](https://glide.herokuapp.com/1.0/kayaks.jpg?crop=100,100,915,155) diff --git a/docs/3.0/api/size.md b/docs/3.0/api/size.md index 462a4fc..4fca78d 100644 --- a/docs/3.0/api/size.md +++ b/docs/3.0/api/size.md @@ -29,14 +29,15 @@ Sets the height of the image, in pixels. Sets how the image is fitted to its target dimensions. -### Accepts: +### Accepts: - `contain`: Default. Resizes the image to fit within the width and height boundaries without cropping, distorting or altering the aspect ratio. -- `max`: Resizes the image to fit within the width and height boundaries without cropping, distorting or altering the aspect ratio, and will also not increase the size of the image if it is smaller than the output size. +- `max`: Resizes the image to fit within the width and height boundaries without cropping, distorting or altering the aspect ratio, and will also not increase the size of the image if it is smaller than the output size. - `fill`: Resizes the image to fit within the width and height boundaries without cropping or distorting the image, and the remaining space is filled with the background color. The resulting image will match the constraining dimensions. - `fill-max`: Resizes the image to fit within the width and height boundaries without cropping but upscaling the image if it's smaller. The finished image will have remaining space on either width or height (except if the aspect ratio of the new image is the same as the old image). The remaining space will be filled with the background color. The resulting image will match the constraining dimensions. - `stretch`: Stretches the image to fit the constraining dimensions exactly. The resulting image will fill the dimensions, and will not maintain the aspect ratio of the input image. -- `crop`: Resizes the image to fill the width and height boundaries and crops any excess image data. The resulting image will match the width and height constraints without distorting the image. See the [crop](api/crop/) page for more information. +- `cover`: Resizes the image to fill the width and height boundaries and crops any excess image data. The resulting image will match the width and height constraints without distorting the image. See the [crop](api/crop/) page for more information. +- `crop-x%-y%`: Resizes the image to fill the width and height boundaries and crops based on a focal point defined by `x%` (left offset) and `y%` (top offset). The resulting image will match the width and height constraints without distorting the image. See the [crop](api/crop/) page for more information. ~~~ html diff --git a/docs/3.0/api/watermarks.md b/docs/3.0/api/watermarks.md index 71e9364..99c9b60 100644 --- a/docs/3.0/api/watermarks.md +++ b/docs/3.0/api/watermarks.md @@ -54,10 +54,11 @@ Sets how the watermark is fitted to its target dimensions. - `max`: Resizes the image to fit within the width and height boundaries without cropping, distorting or altering the aspect ratio, and will also not increase the size of the image if it is smaller than the output size. - `fill`: Resizes the image to fit within the width and height boundaries without cropping or distorting the image, and the remaining space is filled with the background color. The resulting image will match the constraining dimensions. - `stretch`: Stretches the image to fit the constraining dimensions exactly. The resulting image will fill the dimensions, and will not maintain the aspect ratio of the input image. -- `crop`: Resizes the image to fill the width and height boundaries and crops any excess image data. The resulting image will match the width and height constraints without distorting the image. See the [crop](api/crop/) page for more information. +- `cover`: Resizes the image to fill the width and height boundaries and crops any excess image data. The resulting image will match the width and height constraints without distorting the image. See the [crop](api/crop/) page for more information. +- `crop-x%-y%`: Resizes the image to fill the width and height boundaries and crops based on a focal point defined by `x%` (left offset) and `y%` (top offset). The resulting image will match the width and height constraints without distorting the image. See the [crop](api/crop/) page for more information. ~~~ html - + ~~~ ## X-offset `markx` diff --git a/docs/3.0/config/defaults-and-presets.md b/docs/3.0/config/defaults-and-presets.md index 0826017..b889cbb 100644 --- a/docs/3.0/config/defaults-and-presets.md +++ b/docs/3.0/config/defaults-and-presets.md @@ -42,12 +42,12 @@ $server = League\Glide\ServerFactory::create([ 'small' => [ 'w' => 200, 'h' => 200, - 'fit' => 'crop', + 'fit' => 'cover', ], 'medium' => [ 'w' => 600, 'h' => 400, - 'fit' => 'crop', + 'fit' => 'cover', ] ] ]); @@ -57,12 +57,12 @@ $server->setPresets([ 'small' => [ 'w' => 200, 'h' => 200, - 'fit' => 'crop', + 'fit' => 'cover', ], 'medium' => [ 'w' => 600, 'h' => 400, - 'fit' => 'crop', + 'fit' => 'cover', ] ]); ~~~ @@ -89,4 +89,4 @@ It's even possible to use presets with additional parameters: ## Overriding defaults and presets -You can override the default and preset manipulations for a specific request by passing a new parameter (e.x. `mark=different.png`), or even disable it entirely by setting it to blank (e.x. `mark=`). \ No newline at end of file +You can override the default and preset manipulations for a specific request by passing a new parameter (e.x. `mark=different.png`), or even disable it entirely by setting it to blank (e.x. `mark=`). diff --git a/docs/3.0/simple-example.md b/docs/3.0/simple-example.md index 584ebc7..e15c302 100644 --- a/docs/3.0/simple-example.md +++ b/docs/3.0/simple-example.md @@ -16,7 +16,7 @@ In your templates simply define how the image will be manipulated. Using Glide's

name?>

- + ~~~

For simplicity this example has omitted HTTP signatures, however in a production environment it's very important to secure your images.

diff --git a/src/Manipulators/Size.php b/src/Manipulators/Size.php index 3613ed1..0d14bf9 100644 --- a/src/Manipulators/Size.php +++ b/src/Manipulators/Size.php @@ -111,7 +111,7 @@ public function getFit(): string return $fit; } - if (preg_match('/^(crop)(-top-left|-top|-top-right|-left|-center|-right|-bottom-left|-bottom|-bottom-right?)*$/', $fit)) { + if (preg_match('/^(crop|cover)(-top-left|-top|-top-right|-left|-center|-right|-bottom-left|-bottom|-bottom-right?)*$/', $fit)) { return 'cover'; } @@ -364,7 +364,7 @@ public function runCropResize(ImageInterface $image, int $width, int $height): I */ public function runCoverResize(ImageInterface $image, int $width, int $height, ?string $position = null): ImageInterface { - $position ??= str_replace('crop-', '', (string) $this->getParam('fit')); + $position ??= str_replace(['crop-', 'cover-'], '', (string) $this->getParam('fit')); $position = empty($position) || in_array($position, ['crop', 'cover']) ? 'center' : $position; diff --git a/tests/Manipulators/SizeTest.php b/tests/Manipulators/SizeTest.php index d7f51ff..4c640c0 100644 --- a/tests/Manipulators/SizeTest.php +++ b/tests/Manipulators/SizeTest.php @@ -77,6 +77,8 @@ public function testGetFit(): void $this->assertSame('max', $this->manipulator->setParams(['fit' => 'max'])->getFit()); $this->assertSame('stretch', $this->manipulator->setParams(['fit' => 'stretch'])->getFit()); $this->assertSame('cover', $this->manipulator->setParams(['fit' => 'cover'])->getFit()); + $this->assertSame('cover', $this->manipulator->setParams(['fit' => 'cover-top-left'])->getFit()); + $this->assertSame('cover', $this->manipulator->setParams(['fit' => 'cover-center'])->getFit()); $this->assertSame('cover', $this->manipulator->setParams(['fit' => 'crop'])->getFit()); $this->assertSame('cover', $this->manipulator->setParams(['fit' => 'crop-bottom'])->getFit()); $this->assertSame('cover', $this->manipulator->setParams(['fit' => 'crop-top-left'])->getFit()); @@ -270,14 +272,17 @@ public function testRunCoverResize(): void $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('width')->andReturn(100); $mock->shouldReceive('height')->andReturn(100); - $mock->shouldReceive('cover')->with(50, 50, 'center')->andReturn($mock)->once(); + $mock->shouldReceive('cover')->with(50, 50, 'center')->andReturn($mock)->twice(); }); - $this->manipulator->setParams(['w' => 50, 'h' => 50, 'fit' => 'crop']); + $this->assertInstanceOf( + ImageInterface::class, + $this->manipulator->setParams(['w' => 50, 'h' => 50, 'fit' => 'cover'])->run($image) + ); $this->assertInstanceOf( ImageInterface::class, - $this->manipulator->run($image) + $this->manipulator->setParams(['w' => 50, 'h' => 50, 'fit' => 'crop'])->run($image) ); } @@ -286,17 +291,19 @@ public function testRunCoverResizePosition(): void $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(); + $mock->shouldReceive('cover')->with(50, 50, 'top-left')->andReturn($mock)->twice(); $mock->shouldReceive('cover')->with(50, 50, 'bottom')->andReturn($mock)->once(); $mock->shouldReceive('cover')->with(50, 50, 'bottom-right')->andReturn($mock)->once(); }); - $this->manipulator->setParams(['w' => 50, 'h' => 50, 'fit' => 'crop-top-left']); - $this->assertInstanceOf( ImageInterface::class, $this->manipulator->setParams(['w' => 50, 'h' => 50, 'fit' => 'crop-top-left'])->run($image) ); + $this->assertInstanceOf( + ImageInterface::class, + $this->manipulator->setParams(['w' => 50, 'h' => 50, 'fit' => 'cover-top-left'])->run($image) + ); $this->assertInstanceOf( ImageInterface::class, $this->manipulator->setParams(['w' => 50, 'h' => 50, 'fit' => 'crop-bottom'])->run($image) From 57b2e31a2c3503dd20eec7017c9aa412245d5628 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 20 Jan 2025 11:23:04 -0600 Subject: [PATCH 8/8] fixed docs --- docs/3.0/api/crop.md | 4 ++-- docs/3.0/api/size.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/3.0/api/crop.md b/docs/3.0/api/crop.md index 676b349..537a36a 100644 --- a/docs/3.0/api/crop.md +++ b/docs/3.0/api/crop.md @@ -28,13 +28,13 @@ You can also set where the image is cropped by adding a crop position. Accepts ` In addition to the crop position, you can be more specific about the exact crop position using a focal point. This is defined using two offset percentages: `crop-x%-y%`. ~~~ html - + ~~~ You may also choose to zoom into your focal point by providing a third value: a float between 1 and 100. Each full step is the equivalent of a 100% zoom. (eg. `x%-y%-2` is the equivalent of viewing the image at 200%). The suggested range is 1-10. ~~~ html - + ~~~ ## Crop `crop` diff --git a/docs/3.0/api/size.md b/docs/3.0/api/size.md index 4fca78d..c40e7f3 100644 --- a/docs/3.0/api/size.md +++ b/docs/3.0/api/size.md @@ -37,6 +37,7 @@ Sets how the image is fitted to its target dimensions. - `fill-max`: Resizes the image to fit within the width and height boundaries without cropping but upscaling the image if it's smaller. The finished image will have remaining space on either width or height (except if the aspect ratio of the new image is the same as the old image). The remaining space will be filled with the background color. The resulting image will match the constraining dimensions. - `stretch`: Stretches the image to fit the constraining dimensions exactly. The resulting image will fill the dimensions, and will not maintain the aspect ratio of the input image. - `cover`: Resizes the image to fill the width and height boundaries and crops any excess image data. The resulting image will match the width and height constraints without distorting the image. See the [crop](api/crop/) page for more information. +- `crop`: Resizes the image to fill the width and height boundaries and crops any excess image data. (alias for `cover`). - `crop-x%-y%`: Resizes the image to fill the width and height boundaries and crops based on a focal point defined by `x%` (left offset) and `y%` (top offset). The resulting image will match the width and height constraints without distorting the image. See the [crop](api/crop/) page for more information. ~~~ html