1
0
mirror of https://github.com/Intervention/image.git synced 2025-08-31 01:29:51 +02:00
This commit is contained in:
Oliver Vogel
2021-10-29 20:42:48 +02:00
parent da92a66926
commit 72f4e2e6ea
2 changed files with 564 additions and 0 deletions

194
src/Geometry/Resizer.php Normal file
View File

@@ -0,0 +1,194 @@
<?php
namespace Intervention\Image\Geometry;
use Intervention\Image\Interfaces\SizeInterface;
class Resizer
{
/**
* Size to be resized
*
* @var SizeInterface
*/
protected $size;
/**
* Target size
*
* @var SizeInterface
*/
protected $target;
public function __construct(SizeInterface $size)
{
$this->size = $size;
$this->target = new Size(0, 0);
}
public static function fromSize(SizeInterface $size): self
{
return new self($size);
}
public function getSize(): SizeInterface
{
return $this->size;
}
protected function hasTargetWidth(): bool
{
return $this->target->getWidth() > 0;
}
protected function hasTargetHeight(): bool
{
return $this->target->getHeight() > 0;
}
public function width(int $width): self
{
$this->target->setWidth($width);
return $this;
}
public function height(int $height): self
{
$this->target->setHeight($height);
return $this;
}
public function setTargetSizeByArray(array $arguments): self
{
if (isset($arguments[0]) && is_callable($arguments[0])) {
$arguments[0]($this);
return $this;
}
if (isset($arguments[0]) && is_numeric($arguments[0])) {
$this->width($arguments[0]);
}
if (isset($arguments[1]) && is_numeric($arguments[1])) {
$this->height($arguments[1]);
}
return $this;
}
public function setTargetSize(SizeInterface $size): self
{
$this->target = $size;
return $this;
}
public function resize(): SizeInterface
{
$resized = clone $this->size;
if ($this->hasTargetWidth()) {
$resized->setWidth($this->target->getWidth());
}
if ($this->hasTargetHeight()) {
$resized->setHeight($this->target->getHeight());
}
return $resized;
}
public function resizeDown(): SizeInterface
{
if ($this->hasTargetWidth()) {
$this->target->setWidth(
min($this->target->getWidth(), $this->size->getWidth())
);
}
if ($this->hasTargetHeight()) {
$this->target->setHeight(
min($this->target->getHeight(), $this->size->getHeight())
);
}
return $this->resize();
}
public function scale(): SizeInterface
{
if ($this->hasTargetWidth() && $this->hasTargetHeight()) {
$this->target->setWidth(min(
$this->getProportionalWidth(),
$this->target->getWidth()
));
$this->target->setHeight(min(
$this->getProportionalHeight(),
$this->target->getHeight()
));
} elseif ($this->hasTargetWidth()) {
$this->target->setHeight($this->getProportionalHeight());
} elseif ($this->hasTargetHeight()) {
$this->target->setWidth($this->getProportionalWidth());
}
return $this->resize();
}
public function scaleDown(): SizeInterface
{
if ($this->hasTargetWidth() && $this->hasTargetHeight()) {
$this->target->setWidth(min(
$this->getProportionalWidth(),
$this->target->getWidth(),
$this->size->getWidth()
));
$this->target->setHeight(min(
$this->getProportionalHeight(),
$this->target->getHeight(),
$this->size->getHeight()
));
} elseif ($this->hasTargetWidth()) {
$this->target->setWidth(min(
$this->target->getWidth(),
$this->size->getWidth()
));
$this->target->setHeight(min(
$this->getProportionalHeight(),
$this->size->getHeight()
));
} elseif ($this->hasTargetHeight()) {
$this->target->setWidth(min(
$this->getProportionalWidth(),
$this->size->getWidth()
));
$this->target->setHeight(min(
$this->target->getHeight(),
$this->size->getHeight()
));
}
return $this->resize();
}
protected function getProportionalWidth(): int
{
if (! $this->hasTargetHeight()) {
return $this->size->getWidth();
}
return (int) round($this->target->getHeight() * $this->size->getAspectRatio());
}
protected function getProportionalHeight(): int
{
if (! $this->hasTargetWidth()) {
return $this->size->getHeight();
}
return (int) round($this->target->getWidth() / $this->size->getAspectRatio());
}
}

View File

@@ -0,0 +1,370 @@
<?php
namespace Intervention\Image\Tests\Geometry;
use Intervention\Image\Geometry\Resizer;
use Intervention\Image\Geometry\Size;
use PHPUnit\Framework\TestCase;
class ResizerTest extends TestCase
{
public function testSetTargetSizeByArray()
{
$resizer = new Resizer(new Size(300, 200));
$result = $resizer->setTargetSizeByArray([800, 600]);
$this->assertInstanceOf(Resizer::class, $result);
$this->assertEquals(800, $result->resize()->getWidth());
$this->assertEquals(600, $result->resize()->getHeight());
$resizer = new Resizer(new Size(300, 200));
$result = $resizer->setTargetSizeByArray([800]);
$this->assertInstanceOf(Resizer::class, $result);
$this->assertEquals(800, $result->resize()->getWidth());
$this->assertEquals(200, $result->resize()->getHeight());
$resizer = new Resizer(new Size(300, 200));
$result = $resizer->setTargetSizeByArray([function ($size) {
$size->width(80);
$size->height(40);
}]);
$this->assertInstanceOf(Resizer::class, $result);
$this->assertEquals(80, $result->resize()->getWidth());
$this->assertEquals(40, $result->resize()->getHeight());
$resizer = new Resizer(new Size(300, 200));
$result = $resizer->setTargetSizeByArray([function ($size) {
$size->width(80);
}]);
$this->assertInstanceOf(Resizer::class, $result);
$this->assertEquals(80, $result->resize()->getWidth());
$this->assertEquals(200, $result->resize()->getHeight());
$resizer = new Resizer(new Size(300, 200));
$result = $resizer->setTargetSizeByArray([function ($size) {
$size->height(10);
}]);
$this->assertInstanceOf(Resizer::class, $result);
$this->assertEquals(300, $result->resize()->getWidth());
$this->assertEquals(10, $result->resize()->getHeight());
}
public function testSetTargetSize(): void
{
$resizer = new Resizer(new Size(300, 200));
$result = $resizer->setTargetSize(new Size(200, 100));
$this->assertInstanceOf(Resizer::class, $result);
$this->assertEquals(200, $result->resize()->getWidth());
$this->assertEquals(100, $result->resize()->getHeight());
}
public function testResize()
{
$size = new Size(300, 200);
$resizer = new Resizer($size);
$resizer->width(150);
$result = $resizer->resize();
$original = $resizer->getSize();
$this->assertEquals(150, $result->getWidth());
$this->assertEquals(200, $result->getHeight());
$this->assertEquals(300, $original->getWidth());
$this->assertEquals(200, $original->getHeight());
$size = new Size(300, 200);
$resizer = new Resizer($size);
$resizer->width(20);
$resizer->height(10);
$result = $resizer->resize();
$original = $resizer->getSize();
$this->assertEquals(20, $result->getWidth());
$this->assertEquals(10, $result->getHeight());
$this->assertEquals(300, $original->getWidth());
$this->assertEquals(200, $original->getHeight());
}
public function testResizeDown()
{
// 800x600 > 1000x2000 = 800x600
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(1000);
$resizer->height(2000);
$result = $resizer->resizeDown();
$this->assertEquals(800, $result->getWidth());
$this->assertEquals(600, $result->getHeight());
// 800x600 > 400x1000 = 400x600
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(400);
$resizer->height(1000);
$result = $resizer->resizeDown();
$this->assertEquals(400, $result->getWidth());
$this->assertEquals(600, $result->getHeight());
// 800x600 > 1000x400 = 800x400
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(1000);
$resizer->height(400);
$result = $resizer->resizeDown();
$this->assertEquals(800, $result->getWidth());
$this->assertEquals(400, $result->getHeight());
// 800x600 > 400x300 = 400x300
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(400);
$resizer->height(300);
$result = $resizer->resizeDown();
$this->assertEquals(400, $result->getWidth());
$this->assertEquals(300, $result->getHeight());
// 800x600 > 1000xnull = 800x600
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(1000);
$result = $resizer->resizeDown();
$this->assertEquals(800, $result->getWidth());
$this->assertEquals(600, $result->getHeight());
// 800x600 > nullx1000 = 800x600
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->height(1000);
$result = $resizer->resizeDown();
$this->assertEquals(800, $result->getWidth());
$this->assertEquals(600, $result->getHeight());
}
public function testScale()
{
// 800x600 > 1000x2000 = 1000x750
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(1000);
$resizer->height(2000);
$result = $resizer->scale();
$this->assertEquals(1000, $result->getWidth());
$this->assertEquals(750, $result->getHeight());
// 800x600 > 2000x1000 = 1333x1000
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(2000);
$resizer->height(1000);
$result = $resizer->scale();
$this->assertEquals(1333, $result->getWidth());
$this->assertEquals(1000, $result->getHeight());
// // 800x600 > nullx3000 = 4000x3000
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->height(3000);
$result = $resizer->scale();
$this->assertEquals(4000, $result->getWidth());
$this->assertEquals(3000, $result->getHeight());
// // 800x600 > 8000xnull = 8000x6000
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(8000);
$result = $resizer->scale();
$this->assertEquals(8000, $result->getWidth());
$this->assertEquals(6000, $result->getHeight());
// // 800x600 > 100x400 = 100x75
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(100);
$resizer->height(400);
$result = $resizer->scale();
$this->assertEquals(100, $result->getWidth());
$this->assertEquals(75, $result->getHeight());
// // 800x600 > 400x100 = 133x100
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(400);
$resizer->height(100);
$result = $resizer->scale();
$this->assertEquals(133, $result->getWidth());
$this->assertEquals(100, $result->getHeight());
// // 800x600 > nullx300 = 400x300
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->height(300);
$result = $resizer->scale();
$this->assertEquals(400, $result->getWidth());
$this->assertEquals(300, $result->getHeight());
// // 800x600 > 80xnull = 80x60
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(80);
$result = $resizer->scale();
$this->assertEquals(80, $result->getWidth());
$this->assertEquals(60, $result->getHeight());
// // 640x480 > 225xnull = 225x169
$size = new Size(640, 480);
$resizer = new Resizer($size);
$resizer->width(225);
$result = $resizer->scale();
$this->assertEquals(225, $result->getWidth());
$this->assertEquals(169, $result->getHeight());
// // 640x480 > 223xnull = 223x167
$size = new Size(640, 480);
$resizer = new Resizer($size);
$resizer->width(223);
$result = $resizer->scale();
$this->assertEquals(223, $result->getWidth());
$this->assertEquals(167, $result->getHeight());
// // 600x800 > 300x300 = 225x300
$size = new Size(600, 800);
$resizer = new Resizer($size);
$resizer->width(300);
$resizer->height(300);
$result = $resizer->scale();
$this->assertEquals(225, $result->getWidth());
$this->assertEquals(300, $result->getHeight());
// // 800x600 > 400x10 = 13x10
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(400);
$resizer->height(10);
$result = $resizer->scale();
$this->assertEquals(13, $result->getWidth());
$this->assertEquals(10, $result->getHeight());
// // 800x600 > 1000x1200 = 1000x750
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(1000);
$resizer->height(1200);
$result = $resizer->scale();
$this->assertEquals(1000, $result->getWidth());
$this->assertEquals(750, $result->getHeight());
$size = new Size(12000, 12);
$resizer = new Resizer($size);
$resizer->width(4000);
$resizer->height(3000);
$result = $resizer->scale();
$this->assertEquals(4000, $result->getWidth());
$this->assertEquals(4, $result->getHeight());
$size = new Size(12, 12000);
$resizer = new Resizer($size);
$resizer->width(4000);
$resizer->height(3000);
$result = $resizer->scale();
$this->assertEquals(3, $result->getWidth());
$this->assertEquals(3000, $result->getHeight());
$size = new Size(12000, 6000);
$resizer = new Resizer($size);
$resizer->width(4000);
$resizer->height(3000);
$result = $resizer->scale();
$this->assertEquals(4000, $result->getWidth());
$this->assertEquals(2000, $result->getHeight());
}
public function testScaleDown()
{
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(1000);
$resizer->height(2000);
$result = $resizer->scaleDown();
$this->assertEquals(800, $result->getWidth());
$this->assertEquals(600, $result->getHeight());
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(1000);
$resizer->height(600);
$result = $resizer->scaleDown();
$this->assertEquals(800, $result->getWidth());
$this->assertEquals(600, $result->getHeight());
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(1000);
$resizer->height(300);
$result = $resizer->scaleDown();
$this->assertEquals(400, $result->getWidth());
$this->assertEquals(300, $result->getHeight());
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(400);
$resizer->height(1000);
$result = $resizer->scaleDown();
$this->assertEquals(400, $result->getWidth());
$this->assertEquals(300, $result->getHeight());
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(400);
$result = $resizer->scaleDown();
$this->assertEquals(400, $result->getWidth());
$this->assertEquals(300, $result->getHeight());
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->height(300);
$result = $resizer->scaleDown();
$this->assertEquals(400, $result->getWidth());
$this->assertEquals(300, $result->getHeight());
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(1000);
$result = $resizer->scaleDown();
$this->assertEquals(800, $result->getWidth());
$this->assertEquals(600, $result->getHeight());
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->height(1000);
$result = $resizer->scaleDown();
$this->assertEquals(800, $result->getWidth());
$this->assertEquals(600, $result->getHeight());
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(100);
$result = $resizer->scaleDown();
$this->assertEquals(100, $result->getWidth());
$this->assertEquals(75, $result->getHeight());
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(300);
$resizer->height(200);
$result = $resizer->scaleDown();
$this->assertEquals(267, $result->getWidth());
$this->assertEquals(200, $result->getHeight());
$size = new Size(600, 800);
$resizer = new Resizer($size);
$resizer->width(300);
$resizer->height(300);
$result = $resizer->scaleDown();
$this->assertEquals(225, $result->getWidth());
$this->assertEquals(300, $result->getHeight());
$size = new Size(800, 600);
$resizer = new Resizer($size);
$resizer->width(400);
$resizer->height(10);
$result = $resizer->scaleDown();
$this->assertEquals(13, $result->getWidth());
$this->assertEquals(10, $result->getHeight());
}
}