1
0
mirror of https://github.com/Intervention/image.git synced 2025-08-12 08:54:03 +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
{
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
{
$image_size = $image->getSize()->align($this->position, $this->offset_x, $this->offset_y);
$watermark_size = $watermark->getSize()->align($this->position);
$image_size = $image->getSize()->alignPivot($this->position, $this->offset_x, $this->offset_y);
$watermark_size = $watermark->getSize()->alignPivot($this->position);
return $image_size->getRelativePositionTo($watermark_size);
}

View File

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

View File

@@ -106,7 +106,7 @@ class Size implements SizeInterface
* @param int $offset_y
* @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)) {
case 'top':
@@ -184,6 +184,18 @@ class Size implements SizeInterface
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
* based on the pivot point settings of both sizes.

View File

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