1
0
mirror of https://github.com/Intervention/image.git synced 2025-08-31 09:31:53 +02:00
This commit is contained in:
Oliver Vogel
2021-11-10 18:47:12 +00:00
parent 4520580511
commit 372f84ef4c
6 changed files with 226 additions and 31 deletions

View File

@@ -65,11 +65,6 @@ abstract class AbstractImage
return new Size($this->width(), $this->height());
}
public function getResizer(): Resizer
{
return new Resizer($this->getSize());
}
public function isAnimated(): bool
{
return $this->getFrames()->count() > 1;
@@ -132,46 +127,66 @@ abstract class AbstractImage
public function resize(...$arguments): ImageInterface
{
$size = $this->getResizer()->setTargetSizeByArray($arguments)->resize();
$crop = $this->getSize();
$resize = Resizer::make()
->setTargetSizeByArray($arguments)
->resize($crop);
return $this->modify(
$this->resolveDriverClass('Modifiers\ResizeModifier', $size)
$this->resolveDriverClass('Modifiers\CropResizeModifier', $crop, $resize)
);
}
public function resizeDown(...$arguments): ImageInterface
{
$size = $this->getResizer()->setTargetSizeByArray($arguments)->resizeDown();
$crop = $this->getSize();
$resize = Resizer::make()
->setTargetSizeByArray($arguments)
->resizeDown($crop);
return $this->modify(
$this->resolveDriverClass('Modifiers\ResizeModifier', $size)
$this->resolveDriverClass('Modifiers\CropResizeModifier', $crop, $resize)
);
}
public function scale(...$arguments): ImageInterface
{
$size = $this->getResizer()->setTargetSizeByArray($arguments)->scale();
$crop = $this->getSize();
$resize = Resizer::make()
->setTargetSizeByArray($arguments)
->scale($crop);
return $this->modify(
$this->resolveDriverClass('Modifiers\ResizeModifier', $size)
$this->resolveDriverClass('Modifiers\CropResizeModifier', $crop, $resize)
);
}
public function scaleDown(...$arguments): ImageInterface
{
$size = $this->getResizer()->setTargetSizeByArray($arguments)->scaleDown();
$crop = $this->getSize();
$resize = Resizer::make()
->setTargetSizeByArray($arguments)
->scaleDown($crop);
return $this->modify(
$this->resolveDriverClass('Modifiers\ResizeModifier', $size)
$this->resolveDriverClass('Modifiers\CropResizeModifier', $size)
);
}
public function fit(int $width, int $height, string $position = 'center'): ImageInterface
{
$size = new Size($width, $height);
// crop
$crop = Resizer::make()
->toSize($this->getSize())
->contain(new Size($width, $height));
$crop = Resizer::make()
->toSize($crop)
->crop($this->getSize(), $position);
$resize = new Size($width, $height);
return $this->modify(
$this->resolveDriverClass('Modifiers\FitModifier', $size, $position)
$this->resolveDriverClass('Modifiers\CropResizeModifier', $crop, $resize, $position)
);
}
@@ -180,7 +195,7 @@ abstract class AbstractImage
$size = new Size($width, $height);
return $this->modify(
$this->resolveDriverClass('Modifiers\FitDownModifier', $size, $position)
$this->resolveDriverClass('Modifiers\CropResizeModifier', $crop, $resize, $position)
);
}

View File

@@ -2,22 +2,29 @@
namespace Intervention\Image\Drivers\Gd\Modifiers;
use Intervention\Image\Drivers\Abstract\Modifiers\AbstractResizeModifier;
use Intervention\Image\Interfaces\FrameInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\ModifierInterface;
use Intervention\Image\Interfaces\SizeInterface;
use Intervention\Image\Traits\CanResizeGeometrically;
class ResizeModifier extends AbstractResizeModifier implements ModifierInterface
class CropResizeModifier implements ModifierInterface
{
protected $crop;
protected $resize;
protected $position;
public function __construct(SizeInterface $crop, SizeInterface $resize, string $position = 'top-left')
{
$this->crop = $crop;
$this->resize = $resize;
$this->position = $position;
}
public function apply(ImageInterface $image): ImageInterface
{
$crop = $this->getCropSize($image);
$resize = $this->getResizeSize($image);
foreach ($image as $frame) {
$this->modify($frame, $crop, $resize);
$this->modify($frame, $this->crop, $this->resize);
}
return $image;

View File

@@ -6,16 +6,8 @@ use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\ModifierInterface;
use Intervention\Image\Interfaces\SizeInterface;
class FitModifier extends ResizeModifier implements ModifierInterface
class FitModifier extends CropResizeModifier implements ModifierInterface
{
protected $position;
public function __construct(SizeInterface $target, string $position = 'top-left')
{
$this->target = $target;
$this->position = $position;
}
protected function getCropSize(ImageInterface $image): SizeInterface
{
$imagesize = $image->getSize();

View File

@@ -67,6 +67,17 @@ class Resizer
$this->target = new Size(0, 0);
}
public static function make(callable $callback = null): self
{
$resizer = new self();
if (is_callable($callback)) {
$callback($resizer);
}
return $resizer;
}
protected function hasTargetWidth(): bool
{
return $this->target->getWidth() > 0;
@@ -245,4 +256,65 @@ class Resizer
return $resized;
}
/**
* Scale given size to cover target size
*
* @param SizeInterface $size Size to be resized
* @return SizeInterface
*/
public function cover(SizeInterface $size): SizeInterface
{
$resized = clone $size;
// auto height
$resized->setWidth($this->target->getWidth());
$resized->setHeight($this->getProportionalHeight($size));
if ($resized->fitsInto($this->target)) {
// auto width
$resized->setWidth($this->getProportionalWidth($size));
$resized->setHeight($this->target->getHeight());
}
return $resized;
}
/**
* Scale given size to contain target size
*
* @param SizeInterface $size Size to be resized
* @return SizeInterface
*/
public function contain(SizeInterface $size): SizeInterface
{
$resized = clone $size;
// auto height
$resized->setWidth($this->target->getWidth());
$resized->setHeight($this->getProportionalHeight($size));
if (!$resized->fitsInto($this->target)) {
// auto width
$resized->setWidth($this->getProportionalWidth($size));
$resized->setHeight($this->target->getHeight());
}
return $resized;
}
/**
* Crop target size out of given size at given position (i.e. move the pivot point)
*
* @param SizeInterface $size
* @param string $position
* @return SizeInterface
*/
public function crop(SizeInterface $size, string $position = 'top-left'): SizeInterface
{
return $this->resize($size)->alignPivotTo(
$size->alignPivot($position),
$position
);
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Intervention\Image\Tests\Drivers\Gd\Modifiers;
use Intervention\Image\Drivers\Gd\Image;
use Intervention\Image\Drivers\Gd\Modifiers\FitModifier;
use Intervention\Image\Geometry\Size;
use Intervention\Image\Tests\TestCase;
use Intervention\Image\Tests\Traits\CanCreateGdTestImage;
class FitModifierTest extends TestCase
{
use CanCreateGdTestImage;
public function testColorChange(): void
{
$image = $this->createTestImage('test.jpg');
$image->resize(800, 600);
$this->assertEquals(800, $image->width());
$this->assertEquals(600, $image->height());
$image->fit(100, 100);
// $image->modify(new FitModifier(new Size(100, 100)));
// $this->assertEquals(30, $image->width());
// $this->assertEquals(20, $image->height());
}
}

View File

@@ -2,6 +2,7 @@
namespace Intervention\Image\Tests\Geometry;
use Intervention\Image\Geometry\Point;
use Intervention\Image\Geometry\Resizer;
use Intervention\Image\Geometry\Size;
use PHPUnit\Framework\TestCase;
@@ -367,4 +368,84 @@ class ResizerTest extends TestCase
$this->assertEquals(13, $result->getWidth());
$this->assertEquals(10, $result->getHeight());
}
/**
* @dataProvider coverDataProvider
*/
public function testCover($origin, $target, $result): void
{
$resizer = new Resizer();
$resizer->toSize($target);
$resized = $resizer->cover($origin);
$this->assertEquals($result->getWidth(), $resized->getWidth());
$this->assertEquals($result->getHeight(), $resized->getHeight());
}
public function coverDataProvider(): array
{
return [
[new Size(800, 600), new Size(100, 100), new Size(133, 100)],
[new Size(800, 600), new Size(200, 100), new Size(200, 150)],
[new Size(800, 600), new Size(100, 200), new Size(267, 200)],
[new Size(800, 600), new Size(2000, 10), new Size(2000, 1500)],
[new Size(800, 600), new Size(10, 2000), new Size(2667, 2000)],
[new Size(800, 600), new Size(800, 600), new Size(800, 600)],
[new Size(400, 300), new Size(120, 120), new Size(160, 120)],
[new Size(600, 800), new Size(100, 100), new Size(100, 133)],
];
}
/**
* @dataProvider containDataProvider
*/
public function testContain($origin, $target, $result): void
{
$resizer = new Resizer();
$resizer->toSize($target);
$resized = $resizer->contain($origin);
$this->assertEquals($result->getWidth(), $resized->getWidth());
$this->assertEquals($result->getHeight(), $resized->getHeight());
}
public function containDataProvider(): array
{
return [
[new Size(800, 600), new Size(100, 100), new Size(100, 75)],
[new Size(800, 600), new Size(200, 100), new Size(133, 100)],
[new Size(800, 600), new Size(100, 200), new Size(100, 75)],
[new Size(800, 600), new Size(2000, 10), new Size(13, 10)],
[new Size(800, 600), new Size(10, 2000), new Size(10, 8)],
[new Size(800, 600), new Size(800, 600), new Size(800, 600)],
[new Size(400, 300), new Size(120, 120), new Size(120, 90)],
[new Size(600, 800), new Size(100, 100), new Size(75, 100)],
];
}
/**
* @dataProvider cropDataProvider
*/
public function testCrop($origin, $target, $position, $result): void
{
$resizer = new Resizer();
$resizer->toSize($target);
$resized = $resizer->crop($origin, $position);
$this->assertEquals($result->getWidth(), $resized->getWidth());
$this->assertEquals($result->getHeight(), $resized->getHeight());
$this->assertEquals($result->getPivot()->getX(), $resized->getPivot()->getX());
$this->assertEquals($result->getPivot()->getY(), $resized->getPivot()->getY());
}
public function cropDataProvider(): array
{
return [
[new Size(800, 600), new Size(100, 100), 'center', new Size(100, 100, new Point(350, 250))],
[new Size(800, 600), new Size(200, 100), 'center', new Size(200, 100, new Point(300, 250))],
[new Size(800, 600), new Size(100, 200), 'center', new Size(100, 200, new Point(350, 200))],
[new Size(800, 600), new Size(2000, 10), 'center', new Size(2000, 10, new Point(-600, 295))],
[new Size(800, 600), new Size(10, 2000), 'center', new Size(10, 2000, new Point(395, -700))],
[new Size(800, 600), new Size(800, 600), 'center', new Size(800, 600, new Point(0, 0))],
[new Size(400, 300), new Size(120, 120), 'center', new Size(120, 120, new Point(140, 90))],
[new Size(600, 800), new Size(100, 100), 'center', new Size(100, 100, new Point(250, 350))],
];
}
}