1
0
mirror of https://github.com/Intervention/image.git synced 2025-08-13 17:34:04 +02:00
This commit is contained in:
Oliver Vogel
2021-11-08 16:04:14 +00:00
parent de343e1979
commit aaaf78c7dc
6 changed files with 203 additions and 25 deletions

View File

@@ -166,6 +166,13 @@ abstract class AbstractImage
); );
} }
public function fit(int $width, int $height, string $position = 'center'): ImageInterface
{
return $this->modify(
$this->resolveDriverClass('Modifiers\CropResizeModifier', $width, $height, $position)
);
}
public function place($element, string $position = 'top-left', int $offset_x = 0, int $offset_y = 0): ImageInterface public function place($element, string $position = 'top-left', int $offset_x = 0, int $offset_y = 0): ImageInterface
{ {
return $this->modify( return $this->modify(

View File

@@ -0,0 +1,126 @@
<?php
namespace Intervention\Image\Drivers\Gd\Modifiers;
use Intervention\Image\Geometry\Resizer;
use Intervention\Image\Interfaces\FrameInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\ModifierInterface;
use Intervention\Image\Interfaces\SizeInterface;
/*
# contain
1. Scale (keep aspect ratio) Original to fit Target
2. Scale (keep aspect ratio) Up/Down to fit Target (obsolete)
# cover
1. Scale (keep aspect ratio) Target to fit Original
2. Scale (keep aspect ratio) Up/Down to fit Target
*/
class CropResizeModifier implements ModifierInterface
{
protected $width;
protected $height;
protected $position;
public function __construct(int $width, int $height, string $position)
{
$this->width = $width;
$this->height = $height;
$this->position = $position;
}
public function apply(ImageInterface $image): ImageInterface
{
echo "<pre>";
var_dump($this->getCropSize($image));
var_dump($this->getResizeSize($image));
echo "</pre>";
exit;
// foreach ($image as $frame) {
// $this->modify($frame);
// }
return $image;
}
protected function getCropSize(ImageInterface $image): SizeInterface
{
$resizer = new Resizer(new Size($this->width, $this->height));
$resizer->width($image->width());
$resizer->height($image->height());
return $resizer->scale()->align($this->position);
}
protected function getResizeSize(ImageInterface $image): SizeInterface
{
$resizer = new Resizer($this->getCropSize($image));
$resizer->width($this->width);
$resizer->height($this->height);
return $resizer->scale()->align($this->position);
}
/**
* Wrapper function for 'imagecopyresampled'
*
* @param FrameInterface $frame
* @param int $dst_x
* @param int $dst_y
* @param int $src_x
* @param int $src_y
* @param int $dst_w
* @param int $dst_h
* @param int $src_w
* @param int $src_h
* @return void
*/
protected function modify(FrameInterface $frame): void
{
// create new image
$modified = imagecreatetruecolor(
$this->resizeTo->getWidth(),
$this->resizeTo->getHeight()
);
// get current image
$gd = $frame->getCore();
// preserve transparency
$transIndex = imagecolortransparent($gd);
if ($transIndex != -1) {
$rgba = imagecolorsforindex($modified, $transIndex);
$transColor = imagecolorallocatealpha($modified, $rgba['red'], $rgba['green'], $rgba['blue'], 127);
imagefill($modified, 0, 0, $transColor);
imagecolortransparent($modified, $transColor);
} else {
imagealphablending($modified, false);
imagesavealpha($modified, true);
}
// copy content from resource
$result = imagecopyresampled(
$modified,
$gd,
$this->resizeTo->getPivot()->getX(),
$this->resizeTo->getPivot()->getY(),
$this->cropTo->getPivot()->getX(),
$this->cropTo->getPivot()->getY(),
$this->resizeTo->getWidth(),
$this->resizeTo->getHeight(),
$this->cropTo->getWidth(),
$this->cropTo->getHeight()
);
imagedestroy($gd);
// set new content as recource
$frame->setCore($modified);
}
}

View File

@@ -58,8 +58,8 @@ class PlaceModifier implements ModifierInterface
protected function getPosition(Image $image, Image $watermark): Point protected function getPosition(Image $image, Image $watermark): Point
{ {
$image_size = $image->getSize()->align($this->position, $this->offset_x, $this->offset_y); $image_size = $image->getSize()->alignPivot($this->position, $this->offset_x, $this->offset_y);
$watermark_size = $watermark->getSize()->align($this->position); $watermark_size = $watermark->getSize()->alignPivot($this->position);
return $image_size->getRelativePositionTo($watermark_size); return $image_size->getRelativePositionTo($watermark_size);
} }

View File

@@ -50,8 +50,8 @@ class PlaceModifier implements ModifierInterface
protected function getPosition(Image $image, Image $watermark): Point protected function getPosition(Image $image, Image $watermark): Point
{ {
$image_size = $image->getSize()->align($this->position, $this->offset_x, $this->offset_y); $image_size = $image->getSize()->alignPivot($this->position, $this->offset_x, $this->offset_y);
$watermark_size = $watermark->getSize()->align($this->position); $watermark_size = $watermark->getSize()->alignPivot($this->position);
return $image_size->getRelativePositionTo($watermark_size); return $image_size->getRelativePositionTo($watermark_size);
} }

View File

@@ -106,7 +106,7 @@ class Size implements SizeInterface
* @param int $offset_y * @param int $offset_y
* @return Size * @return Size
*/ */
public function align(string $position, int $offset_x = 0, int $offset_y = 0): self public function alignPivot(string $position, int $offset_x = 0, int $offset_y = 0): self
{ {
switch (strtolower($position)) { switch (strtolower($position)) {
case 'top': case 'top':
@@ -184,6 +184,18 @@ class Size implements SizeInterface
return $this; return $this;
} }
public function alignPivotTo(Size $size, string $position): self
{
$reference = new Size($size->getWidth(), $size->getHeight());
$reference->alignPivot($position);
$this->alignPivot($position)->setPivot(
$reference->getRelativePositionTo($this)
);
return $this;
}
/** /**
* Calculate the relative position to another Size * Calculate the relative position to another Size
* based on the pivot point settings of both sizes. * based on the pivot point settings of both sizes.

View File

@@ -99,89 +99,122 @@ class SizeTest extends TestCase
$this->assertTrue($box->isPortrait()); $this->assertTrue($box->isPortrait());
} }
public function testAlign(): void public function testAlignPivot(): void
{ {
$box = new Size(640, 480); $box = new Size(640, 480);
$this->assertEquals(0, $box->getPivot()->getX()); $this->assertEquals(0, $box->getPivot()->getX());
$this->assertEquals(0, $box->getPivot()->getY()); $this->assertEquals(0, $box->getPivot()->getY());
$box->align('top-left', 3, 3); $box->alignPivot('top-left', 3, 3);
$this->assertEquals(3, $box->getPivot()->getX()); $this->assertEquals(3, $box->getPivot()->getX());
$this->assertEquals(3, $box->getPivot()->getY()); $this->assertEquals(3, $box->getPivot()->getY());
$box->align('top', 3, 3); $box->alignPivot('top', 3, 3);
$this->assertEquals(320, $box->getPivot()->getX()); $this->assertEquals(320, $box->getPivot()->getX());
$this->assertEquals(3, $box->getPivot()->getY()); $this->assertEquals(3, $box->getPivot()->getY());
$box->align('top-right', 3, 3); $box->alignPivot('top-right', 3, 3);
$this->assertEquals(637, $box->getPivot()->getX()); $this->assertEquals(637, $box->getPivot()->getX());
$this->assertEquals(3, $box->getPivot()->getY()); $this->assertEquals(3, $box->getPivot()->getY());
$box->align('left', 3, 3); $box->alignPivot('left', 3, 3);
$this->assertEquals(3, $box->getPivot()->getX()); $this->assertEquals(3, $box->getPivot()->getX());
$this->assertEquals(240, $box->getPivot()->getY()); $this->assertEquals(240, $box->getPivot()->getY());
$box->align('center', 3, 3); $box->alignPivot('center', 3, 3);
$this->assertEquals(323, $box->getPivot()->getX()); $this->assertEquals(323, $box->getPivot()->getX());
$this->assertEquals(243, $box->getPivot()->getY()); $this->assertEquals(243, $box->getPivot()->getY());
$box->align('right', 3, 3); $box->alignPivot('right', 3, 3);
$this->assertEquals(637, $box->getPivot()->getX()); $this->assertEquals(637, $box->getPivot()->getX());
$this->assertEquals(240, $box->getPivot()->getY()); $this->assertEquals(240, $box->getPivot()->getY());
$box->align('bottom-left', 3, 3); $box->alignPivot('bottom-left', 3, 3);
$this->assertEquals(3, $box->getPivot()->getX()); $this->assertEquals(3, $box->getPivot()->getX());
$this->assertEquals(477, $box->getPivot()->getY()); $this->assertEquals(477, $box->getPivot()->getY());
$box->align('bottom', 3, 3); $box->alignPivot('bottom', 3, 3);
$this->assertEquals(320, $box->getPivot()->getX()); $this->assertEquals(320, $box->getPivot()->getX());
$this->assertEquals(477, $box->getPivot()->getY()); $this->assertEquals(477, $box->getPivot()->getY());
$result = $box->align('bottom-right', 3, 3); $result = $box->alignPivot('bottom-right', 3, 3);
$this->assertEquals(637, $box->getPivot()->getX()); $this->assertEquals(637, $box->getPivot()->getX());
$this->assertEquals(477, $box->getPivot()->getY()); $this->assertEquals(477, $box->getPivot()->getY());
$this->assertInstanceOf(Size::class, $result); $this->assertInstanceOf(Size::class, $result);
} }
public function testAlignPivotTo(): void
{
$container = new Size(800, 600);
$size = new Size(200, 100);
$size->alignPivotTo($container, 'center');
$this->assertEquals(300, $size->getPivot()->getX());
$this->assertEquals(250, $size->getPivot()->getY());
$container = new Size(800, 600);
$size = new Size(100, 100);
$size->alignPivotTo($container, 'center');
$this->assertEquals(350, $size->getPivot()->getX());
$this->assertEquals(250, $size->getPivot()->getY());
$container = new Size(800, 600);
$size = new Size(800, 600);
$size->alignPivotTo($container, 'center');
$this->assertEquals(0, $size->getPivot()->getX());
$this->assertEquals(0, $size->getPivot()->getY());
$container = new Size(100, 100);
$size = new Size(800, 600);
$size->alignPivotTo($container, 'center');
$this->assertEquals(-350, $size->getPivot()->getX());
$this->assertEquals(-250, $size->getPivot()->getY());
$container = new Size(100, 100);
$size = new Size(800, 600);
$size->alignPivotTo($container, 'bottom-right');
$this->assertEquals(-700, $size->getPivot()->getX());
$this->assertEquals(-500, $size->getPivot()->getY());
}
public function testgetRelativePositionTo(): void public function testgetRelativePositionTo(): void
{ {
$container = new Size(800, 600); $container = new Size(800, 600);
$input = new Size(200, 100); $input = new Size(200, 100);
$container->align('top-left'); $container->alignPivot('top-left');
$input->align('top-left'); $input->alignPivot('top-left');
$pos = $container->getRelativePositionTo($input); $pos = $container->getRelativePositionTo($input);
$this->assertEquals(0, $pos->getX()); $this->assertEquals(0, $pos->getX());
$this->assertEquals(0, $pos->getY()); $this->assertEquals(0, $pos->getY());
$container = new Size(800, 600); $container = new Size(800, 600);
$input = new Size(200, 100); $input = new Size(200, 100);
$container->align('center'); $container->alignPivot('center');
$input->align('top-left'); $input->alignPivot('top-left');
$pos = $container->getRelativePositionTo($input); $pos = $container->getRelativePositionTo($input);
$this->assertEquals(400, $pos->getX()); $this->assertEquals(400, $pos->getX());
$this->assertEquals(300, $pos->getY()); $this->assertEquals(300, $pos->getY());
$container = new Size(800, 600); $container = new Size(800, 600);
$input = new Size(200, 100); $input = new Size(200, 100);
$container->align('bottom-right'); $container->alignPivot('bottom-right');
$input->align('top-right'); $input->alignPivot('top-right');
$pos = $container->getRelativePositionTo($input); $pos = $container->getRelativePositionTo($input);
$this->assertEquals(600, $pos->getX()); $this->assertEquals(600, $pos->getX());
$this->assertEquals(600, $pos->getY()); $this->assertEquals(600, $pos->getY());
$container = new Size(800, 600); $container = new Size(800, 600);
$input = new Size(200, 100); $input = new Size(200, 100);
$container->align('center'); $container->alignPivot('center');
$input->align('center'); $input->alignPivot('center');
$pos = $container->getRelativePositionTo($input); $pos = $container->getRelativePositionTo($input);
$this->assertEquals(300, $pos->getX()); $this->assertEquals(300, $pos->getX());
$this->assertEquals(250, $pos->getY()); $this->assertEquals(250, $pos->getY());
$container = new Size(100, 200); $container = new Size(100, 200);
$input = new Size(100, 100); $input = new Size(100, 100);
$container->align('center'); $container->alignPivot('center');
$input->align('center'); $input->alignPivot('center');
$pos = $container->getRelativePositionTo($input); $pos = $container->getRelativePositionTo($input);
$this->assertEquals(0, $pos->getX()); $this->assertEquals(0, $pos->getX());
$this->assertEquals(50, $pos->getY()); $this->assertEquals(50, $pos->getY());