diff --git a/src/Drivers/Abstract/AbstractImage.php b/src/Drivers/Abstract/AbstractImage.php index b315f0b1..ab789ce3 100644 --- a/src/Drivers/Abstract/AbstractImage.php +++ b/src/Drivers/Abstract/AbstractImage.php @@ -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( diff --git a/src/Drivers/Gd/Modifiers/CropResizeModifier.php b/src/Drivers/Gd/Modifiers/CropResizeModifier.php new file mode 100644 index 00000000..a1b6539c --- /dev/null +++ b/src/Drivers/Gd/Modifiers/CropResizeModifier.php @@ -0,0 +1,126 @@ +width = $width; + $this->height = $height; + $this->position = $position; + } + + public function apply(ImageInterface $image): ImageInterface + { + echo "
"; + var_dump($this->getCropSize($image)); + var_dump($this->getResizeSize($image)); + echo ""; + 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); + } +} diff --git a/src/Drivers/Gd/Modifiers/PlaceModifier.php b/src/Drivers/Gd/Modifiers/PlaceModifier.php index 92f8aff1..596ee79f 100644 --- a/src/Drivers/Gd/Modifiers/PlaceModifier.php +++ b/src/Drivers/Gd/Modifiers/PlaceModifier.php @@ -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); } diff --git a/src/Drivers/Imagick/Modifiers/PlaceModifier.php b/src/Drivers/Imagick/Modifiers/PlaceModifier.php index efc8a166..c043adf0 100644 --- a/src/Drivers/Imagick/Modifiers/PlaceModifier.php +++ b/src/Drivers/Imagick/Modifiers/PlaceModifier.php @@ -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); } diff --git a/src/Geometry/Size.php b/src/Geometry/Size.php index 735439f2..18f6a8e3 100644 --- a/src/Geometry/Size.php +++ b/src/Geometry/Size.php @@ -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. diff --git a/tests/Geometry/SizeTest.php b/tests/Geometry/SizeTest.php index 0dc55166..40eb5ecb 100644 --- a/tests/Geometry/SizeTest.php +++ b/tests/Geometry/SizeTest.php @@ -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());