-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Sibin Grasic <sibin.grasic@oblak.studio>
- Loading branch information
1 parent
dffb2bb
commit f035f7d
Showing
8 changed files
with
254 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Intervention\Image\Drivers\Gd\Modifiers; | ||
|
||
use Intervention\Image\Exceptions\AnimationException; | ||
use Intervention\Image\Exceptions\NotSupportedException; | ||
use Intervention\Image\Exceptions\RuntimeException; | ||
use Intervention\Image\Geometry\Point; | ||
use Intervention\Image\Interfaces\ImageInterface; | ||
use Intervention\Image\Interfaces\SpecializedInterface; | ||
use Intervention\Image\Modifiers\TrimModifier as GenericTrimModifier; | ||
|
||
class TrimModifier extends GenericTrimModifier implements SpecializedInterface | ||
{ | ||
public function apply(ImageInterface $image): ImageInterface | ||
{ | ||
if ($image->isAnimated()) { | ||
throw new NotSupportedException('Trim modifier cannot be applied to animated images.'); | ||
} | ||
|
||
// apply tolerance with a min. value of .5 because the default tolerance of '0' should | ||
// already trim away similar colors which is not the case with imagecropauto. | ||
$trimmed = imagecropauto( | ||
$image->core()->native(), | ||
IMG_CROP_THRESHOLD, | ||
max([.5, $this->tolerance / 10]), | ||
$this->trimColor($image) | ||
); | ||
|
||
// if the tolerance is very high, it is possible that no image is left. | ||
// imagick returns a 1x1 pixel image in this case. this does the same. | ||
if ($trimmed === false) { | ||
$trimmed = $this->driver()->createImage(1, 1)->core()->native(); | ||
} | ||
|
||
$image->core()->setNative($trimmed); | ||
|
||
return $image; | ||
} | ||
|
||
/** | ||
* Create an average color from the colors of the four corner points of the given image | ||
* | ||
* @param ImageInterface $image | ||
* @throws RuntimeException | ||
* @throws AnimationException | ||
* @return int | ||
*/ | ||
private function trimColor(ImageInterface $image): int | ||
{ | ||
// trim color base | ||
$red = 0; | ||
$green = 0; | ||
$blue = 0; | ||
|
||
// corner coordinates | ||
$size = $image->size(); | ||
$cornerPoints = [ | ||
new Point(0, 0), | ||
new Point($size->width() - 1, 0), | ||
new Point(0, $size->height() - 1), | ||
new Point($size->width() - 1, $size->height() - 1), | ||
]; | ||
|
||
// create an average color to be used in trim operation | ||
foreach ($cornerPoints as $pos) { | ||
$cornerColor = imagecolorat($image->core()->native(), $pos->x(), $pos->y()); | ||
$rgb = imagecolorsforindex($image->core()->native(), $cornerColor); | ||
$red += round(round(($rgb['red'] / 51)) * 51); | ||
$green += round(round(($rgb['green'] / 51)) * 51); | ||
$blue += round(round(($rgb['blue'] / 51)) * 51); | ||
} | ||
|
||
$red = (int) round($red / 4); | ||
$green = (int) round($green / 4); | ||
$blue = (int) round($blue / 4); | ||
|
||
return imagecolorallocate($image->core()->native(), $red, $green, $blue); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Intervention\Image\Drivers\Imagick\Modifiers; | ||
|
||
use Intervention\Image\Exceptions\NotSupportedException; | ||
use Intervention\Image\Interfaces\ImageInterface; | ||
use Intervention\Image\Interfaces\SpecializedInterface; | ||
use Intervention\Image\Modifiers\TrimModifier as GenericTrimModifier; | ||
|
||
class TrimModifier extends GenericTrimModifier implements SpecializedInterface | ||
{ | ||
public function apply(ImageInterface $image): ImageInterface | ||
{ | ||
if ($image->isAnimated()) { | ||
throw new NotSupportedException('Trim modifier cannot be applied to animated images.'); | ||
} | ||
|
||
$imagick = $image->core()->native(); | ||
$imagick->trimImage(($this->tolerance / 100 * $imagick->getQuantum()) / 1.5); | ||
$imagick->setImagePage(0, 0, 0, 0); | ||
|
||
return $image; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Intervention\Image\Modifiers; | ||
|
||
use Intervention\Image\Drivers\SpecializableModifier; | ||
|
||
class TrimModifier extends SpecializableModifier | ||
{ | ||
public function __construct(public int $tolerance = 0) | ||
{ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Intervention\Image\Tests\Unit\Drivers\Gd\Modifiers; | ||
|
||
use Intervention\Image\Exceptions\NotSupportedException; | ||
use PHPUnit\Framework\Attributes\CoversClass; | ||
use PHPUnit\Framework\Attributes\RequiresPhpExtension; | ||
use Intervention\Image\Modifiers\TrimModifier; | ||
use Intervention\Image\Tests\GdTestCase; | ||
|
||
#[RequiresPhpExtension('gd')] | ||
#[CoversClass(\Intervention\Image\Modifiers\TrimModifier::class)] | ||
#[CoversClass(\Intervention\Image\Drivers\Gd\Modifiers\TrimModifier::class)] | ||
final class TrimModifierTest extends GdTestCase | ||
{ | ||
public function testTrim(): void | ||
{ | ||
$image = $this->readTestImage('trim.png'); | ||
$this->assertEquals(50, $image->width()); | ||
$this->assertEquals(50, $image->height()); | ||
$image->modify(new TrimModifier()); | ||
$this->assertEquals(28, $image->width()); | ||
$this->assertEquals(28, $image->height()); | ||
} | ||
|
||
public function testTrimGradient(): void | ||
{ | ||
$image = $this->readTestImage('radial.png'); | ||
$this->assertEquals(50, $image->width()); | ||
$this->assertEquals(50, $image->height()); | ||
$image->modify(new TrimModifier(50)); | ||
$this->assertEquals(35, $image->width()); | ||
$this->assertEquals(35, $image->height()); | ||
} | ||
|
||
public function testTrimHighTolerance(): void | ||
{ | ||
$image = $this->readTestImage('trim.png'); | ||
$this->assertEquals(50, $image->width()); | ||
$this->assertEquals(50, $image->height()); | ||
$image->modify(new TrimModifier(1000000)); | ||
$this->assertEquals(1, $image->width()); | ||
$this->assertEquals(1, $image->height()); | ||
$this->assertColor(255, 255, 255, 0, $image->pickColor(0, 0)); | ||
} | ||
|
||
public function testTrimAnimated(): void | ||
{ | ||
$image = $this->readTestImage('animation.gif'); | ||
$this->expectException(NotSupportedException::class); | ||
$image->modify(new TrimModifier()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Modifiers; | ||
|
||
use Intervention\Image\Exceptions\NotSupportedException; | ||
use PHPUnit\Framework\Attributes\CoversClass; | ||
use PHPUnit\Framework\Attributes\RequiresPhpExtension; | ||
use Intervention\Image\Modifiers\TrimModifier; | ||
use Intervention\Image\Tests\ImagickTestCase; | ||
|
||
#[RequiresPhpExtension('imagick')] | ||
#[CoversClass(\Intervention\Image\Modifiers\TrimModifier::class)] | ||
#[CoversClass(\Intervention\Image\Drivers\Imagick\Modifiers\TrimModifier::class)] | ||
final class TrimModifierTest extends ImagickTestCase | ||
{ | ||
public function testTrim(): void | ||
{ | ||
$image = $this->readTestImage('trim.png'); | ||
$this->assertEquals(50, $image->width()); | ||
$this->assertEquals(50, $image->height()); | ||
$image->modify(new TrimModifier()); | ||
$this->assertEquals(28, $image->width()); | ||
$this->assertEquals(28, $image->height()); | ||
} | ||
|
||
public function testTrimGradient(): void | ||
{ | ||
$image = $this->readTestImage('radial.png'); | ||
$this->assertEquals(50, $image->width()); | ||
$this->assertEquals(50, $image->height()); | ||
$image->modify(new TrimModifier(50)); | ||
$this->assertEquals(29, $image->width()); | ||
$this->assertEquals(29, $image->height()); | ||
} | ||
|
||
public function testTrimHighTolerance(): void | ||
{ | ||
$image = $this->readTestImage('trim.png'); | ||
$this->assertEquals(50, $image->width()); | ||
$this->assertEquals(50, $image->height()); | ||
$image->modify(new TrimModifier(1000000)); | ||
$this->assertEquals(1, $image->width()); | ||
$this->assertEquals(1, $image->height()); | ||
$this->assertColor(255, 255, 255, 0, $image->pickColor(0, 0)); | ||
} | ||
|
||
public function testTrimAnimated(): void | ||
{ | ||
$image = $this->readTestImage('animation.gif'); | ||
$this->expectException(NotSupportedException::class); | ||
$image->modify(new TrimModifier()); | ||
} | ||
} |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.