mirror of
https://github.com/Intervention/image.git
synced 2025-08-12 08:54:03 +02:00
Resizing
This commit is contained in:
@@ -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(
|
||||
|
126
src/Drivers/Gd/Modifiers/CropResizeModifier.php
Normal file
126
src/Drivers/Gd/Modifiers/CropResizeModifier.php
Normal 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);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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.
|
||||
|
@@ -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());
|
||||
|
Reference in New Issue
Block a user