mirror of
https://github.com/Intervention/image.git
synced 2025-08-24 22:35:46 +02:00
Merge branch 'master' of github.com:olivervogel/image into olivervogel-master
This commit is contained in:
BIN
public/gradient.png
Normal file
BIN
public/gradient.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 206 B |
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Exception;
|
||||
|
||||
class TrimToleranceOutOfBoundsException extends \OutOfBoundsException
|
||||
{
|
||||
# nothing to override
|
||||
}
|
@@ -726,9 +726,10 @@ class Image
|
||||
*
|
||||
* @param string $base Position of the color to trim away
|
||||
* @param array $away Borders to trim away
|
||||
* @param int $tolerance Tolerance of color comparison
|
||||
* @return Image
|
||||
*/
|
||||
public function trim($base = null, $away = null)
|
||||
public function trim($base = null, $away = null, $tolerance = null)
|
||||
{
|
||||
// default values
|
||||
$checkTransparency = false;
|
||||
@@ -768,19 +769,54 @@ class Image
|
||||
break;
|
||||
}
|
||||
|
||||
// define tolerance
|
||||
$tolerance = is_numeric($tolerance) ? intval($tolerance) : 0;
|
||||
|
||||
if ($tolerance < 0 || $tolerance > 100) {
|
||||
throw new Exception\TrimToleranceOutOfBoundsException(
|
||||
'Tolerance level must be between 0 and 100'
|
||||
);
|
||||
} else {
|
||||
$color_tolerance = round($tolerance * 2.55);
|
||||
$alpha_tolerance = round($tolerance * 1.27);
|
||||
}
|
||||
|
||||
// pick base color
|
||||
$color = imagecolorsforindex($this->resource, imagecolorat($this->resource, $base_x, $base_y));
|
||||
|
||||
// compare colors
|
||||
$matches = function($c1, $c2) use ($checkTransparency, $color_tolerance, $alpha_tolerance) {
|
||||
|
||||
if ($checkTransparency == true) {
|
||||
|
||||
$alpha_delta = abs($c1['alpha'] - $c2['alpha']);
|
||||
return($alpha_delta <= $alpha_tolerance);
|
||||
|
||||
} else {
|
||||
|
||||
$color_delta = round((
|
||||
abs($c1['red'] - $c2['red']) +
|
||||
abs($c1['green'] - $c2['green']) +
|
||||
abs($c1['blue'] - $c2['blue'])) / 3
|
||||
);
|
||||
|
||||
$alpha_delta = abs($c1['alpha'] - $c2['alpha']);
|
||||
return($color_delta <= $color_tolerance && $alpha_delta <= $alpha_tolerance);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
$top_x = 0;
|
||||
$top_y = 0;
|
||||
$bottom_x = $this->width;
|
||||
$bottom_y = $this->height;
|
||||
|
||||
// search upper part of image for colors to trim away
|
||||
if (in_array('top', $away)) {
|
||||
for ($y=0; $y < $this->height; $y++) {
|
||||
for ($y=0; $y < ceil($this->height/2); $y++) {
|
||||
for ($x=0; $x < $this->width; $x++) {
|
||||
$checkColor = imagecolorsforindex($this->resource, imagecolorat($this->resource, $x, $y));
|
||||
if (($checkTransparency == false && $checkColor != $color) or ($checkTransparency == true && $checkColor['alpha'] != 127)) {
|
||||
if ( ! $matches($color, $checkColor)) {
|
||||
$top_y = $y;
|
||||
break 2;
|
||||
}
|
||||
@@ -788,11 +824,12 @@ class Image
|
||||
}
|
||||
}
|
||||
|
||||
// search left part of image for colors to trim away
|
||||
if (in_array('left', $away)) {
|
||||
for ($x=0; $x < $this->width; $x++) {
|
||||
for ($x=0; $x < ceil($this->width/2); $x++) {
|
||||
for ($y=$top_y; $y < $this->height; $y++) {
|
||||
$checkColor = imagecolorsforindex($this->resource, imagecolorat($this->resource, $x, $y));
|
||||
if (($checkTransparency == false && $checkColor != $color) or ($checkTransparency == true && $checkColor['alpha'] != 127)) {
|
||||
if ( ! $matches($color, $checkColor)) {
|
||||
$top_x = $x;
|
||||
break 2;
|
||||
}
|
||||
@@ -800,11 +837,12 @@ class Image
|
||||
}
|
||||
}
|
||||
|
||||
// search lower part of image for colors to trim away
|
||||
if (in_array('bottom', $away)) {
|
||||
for ($y=($this->height-1); $y >= 0; $y--) {
|
||||
for ($y=($this->height-1); $y >= floor($this->height/2); $y--) {
|
||||
for ($x=$top_x; $x < $this->width; $x++) {
|
||||
$checkColor = imagecolorsforindex($this->resource, imagecolorat($this->resource, $x, $y));
|
||||
if (($checkTransparency == false && $checkColor != $color) or ($checkTransparency == true && $checkColor['alpha'] != 127)) {
|
||||
if ( ! $matches($color, $checkColor)) {
|
||||
$bottom_y = $y+1;
|
||||
break 2;
|
||||
}
|
||||
@@ -812,11 +850,12 @@ class Image
|
||||
}
|
||||
}
|
||||
|
||||
// search right part of image for colors to trim away
|
||||
if (in_array('right', $away)) {
|
||||
for ($x=($this->width-1); $x >= 0; $x--) {
|
||||
for ($x=($this->width-1); $x >= floor($this->width/2); $x--) {
|
||||
for ($y=$top_y; $y < $bottom_y; $y++) {
|
||||
$checkColor = imagecolorsforindex($this->resource, imagecolorat($this->resource, $x, $y));
|
||||
if (($checkTransparency == false && $checkColor != $color) or ($checkTransparency == true && $checkColor['alpha'] != 127)) {
|
||||
if ( ! $matches($color, $checkColor)) {
|
||||
$bottom_x = $x+1;
|
||||
break 2;
|
||||
}
|
||||
@@ -824,6 +863,7 @@ class Image
|
||||
}
|
||||
}
|
||||
|
||||
// trim parts of image
|
||||
$this->modify(0, 0, $top_x, $top_y, ($bottom_x-$top_x), ($bottom_y-$top_y), ($bottom_x-$top_x), ($bottom_y-$top_y));
|
||||
|
||||
return $this;
|
||||
@@ -1579,6 +1619,7 @@ class Image
|
||||
case 'integer':
|
||||
# in gd2 library color already is int...
|
||||
break;
|
||||
|
||||
default:
|
||||
case 'array':
|
||||
$color = imagecolorsforindex($this->resource, $color);
|
||||
|
@@ -1937,6 +1937,198 @@ class ImageTest extends PHPUnit_Framework_Testcase
|
||||
$this->assertEquals($img->width, 1);
|
||||
$this->assertEquals($img->height, 1);
|
||||
$this->assertEquals('#000000', $img->pickColor(0, 0, 'hex'));
|
||||
|
||||
// try to trim non-transparent image with transparency
|
||||
$img = Image::make('public/gradient.png');
|
||||
$img->trim('transparent', null);
|
||||
$this->assertEquals($img->width, 50);
|
||||
$this->assertEquals($img->height, 50);
|
||||
}
|
||||
|
||||
public function testTrimWithTolerance()
|
||||
{
|
||||
// prepare test image
|
||||
$canvas = Image::canvas(1, 1, '000000');
|
||||
$canvas->resizeCanvas(5, 5, 'center', false, '808080');
|
||||
$canvas->resizeCanvas(11, 11, 'center', false, 'ffffff');
|
||||
$this->assertEquals($canvas->width, 11);
|
||||
$this->assertEquals($canvas->height, 11);
|
||||
$this->assertEquals('#000000', $canvas->pickColor(5, 5, 'hex'));
|
||||
$this->assertEquals('#808080', $canvas->pickColor(3, 3, 'hex'));
|
||||
$this->assertEquals('#ffffff', $canvas->pickColor(0, 0, 'hex'));
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(); // trim without tolerance (should trim away ffffff)
|
||||
$this->assertEquals($img->width, 5);
|
||||
$this->assertEquals($img->height, 5);
|
||||
$this->assertEquals('#000000', $img->pickColor(2, 2, 'hex'));
|
||||
$this->assertEquals('#808080', $img->pickColor(0, 0, 'hex'));
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 30); // trim with 40 tolerance (should not touch 808080)
|
||||
$this->assertEquals($img->width, 5);
|
||||
$this->assertEquals($img->height, 5);
|
||||
$this->assertEquals('#000000', $img->pickColor(2, 2, 'hex'));
|
||||
$this->assertEquals('#808080', $img->pickColor(0, 0, 'hex'));
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 50); // trim with 50 tolerance (should only leave 000000)
|
||||
$this->assertEquals($img->width, 1);
|
||||
$this->assertEquals($img->height, 1);
|
||||
$this->assertEquals('#000000', $img->pickColor(0, 0, 'hex'));
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 100); // trim with 100 tolerance (should leave image as is)
|
||||
$this->assertEquals($img->width, 11);
|
||||
$this->assertEquals($img->height, 11);
|
||||
$this->assertEquals('#000000', $canvas->pickColor(5, 5, 'hex'));
|
||||
$this->assertEquals('#808080', $canvas->pickColor(3, 3, 'hex'));
|
||||
$this->assertEquals('#ffffff', $canvas->pickColor(0, 0, 'hex'));
|
||||
|
||||
// prepare test image
|
||||
$canvas = Image::canvas(1, 1, '000000');
|
||||
$canvas->resizeCanvas(5, 5, 'center', false, '804040');
|
||||
$canvas->resizeCanvas(11, 11, 'center', false, 'ffffff');
|
||||
$this->assertEquals($canvas->width, 11);
|
||||
$this->assertEquals($canvas->height, 11);
|
||||
$this->assertEquals('#000000', $canvas->pickColor(5, 5, 'hex'));
|
||||
$this->assertEquals('#804040', $canvas->pickColor(3, 3, 'hex'));
|
||||
$this->assertEquals('#ffffff', $canvas->pickColor(0, 0, 'hex'));
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(); // trim without tolerance (should trim away ffffff)
|
||||
$this->assertEquals($img->width, 5);
|
||||
$this->assertEquals($img->height, 5);
|
||||
$this->assertEquals('#000000', $img->pickColor(2, 2, 'hex'));
|
||||
$this->assertEquals('#804040', $img->pickColor(0, 0, 'hex'));
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 30); // trim with 40 tolerance (should not touch 804040)
|
||||
$this->assertEquals($img->width, 5);
|
||||
$this->assertEquals($img->height, 5);
|
||||
$this->assertEquals('#000000', $img->pickColor(2, 2, 'hex'));
|
||||
$this->assertEquals('#804040', $img->pickColor(0, 0, 'hex'));
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 50); // trim with 50 tolerance (should not touch 804040)
|
||||
$this->assertEquals($img->width, 5);
|
||||
$this->assertEquals($img->height, 5);
|
||||
$this->assertEquals('#000000', $img->pickColor(2, 2, 'hex'));
|
||||
$this->assertEquals('#804040', $img->pickColor(0, 0, 'hex'));
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 70); // trim with 70 tolerance (should only leave 000000)
|
||||
$this->assertEquals($img->width, 1);
|
||||
$this->assertEquals($img->height, 1);
|
||||
$this->assertEquals('#000000', $img->pickColor(0, 0, 'hex'));
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 100); // trim with 100 tolerance (should leave image as is)
|
||||
$this->assertEquals($img->width, 11);
|
||||
$this->assertEquals($img->height, 11);
|
||||
$this->assertEquals('#000000', $canvas->pickColor(5, 5, 'hex'));
|
||||
$this->assertEquals('#804040', $canvas->pickColor(3, 3, 'hex'));
|
||||
$this->assertEquals('#ffffff', $canvas->pickColor(0, 0, 'hex'));
|
||||
|
||||
// prepare test image
|
||||
$canvas = Image::canvas(1, 1, '000000');
|
||||
$canvas->resizeCanvas(5, 5, 'center', false, array(255, 255, 255, 0.5));
|
||||
$canvas->resizeCanvas(11, 11, 'center', false, array(0, 0, 0, 0));
|
||||
$this->assertEquals($canvas->width, 11);
|
||||
$this->assertEquals($canvas->height, 11);
|
||||
$this->assertEquals('rgba(0, 0, 0, 0.00)', $canvas->pickColor(0, 0, 'rgba'));
|
||||
$this->assertEquals('rgba(255, 255, 255, 0.50)', $canvas->pickColor(3, 3, 'rgba'));
|
||||
$this->assertEquals('rgba(0, 0, 0, 1.00)', $canvas->pickColor(5, 5, 'rgba'));
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim('transparent', null);
|
||||
$this->assertEquals($img->width, 5);
|
||||
$this->assertEquals($img->height, 5);
|
||||
$this->assertEquals('rgba(255, 255, 255, 0.50)', $img->pickColor(0, 0, 'rgba'));
|
||||
$this->assertEquals('rgba(0, 0, 0, 1.00)', $img->pickColor(2, 2, 'rgba'));
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim('transparent', null, 40);
|
||||
$this->assertEquals($img->width, 5);
|
||||
$this->assertEquals($img->height, 5);
|
||||
$this->assertEquals('rgba(255, 255, 255, 0.50)', $img->pickColor(0, 0, 'rgba'));
|
||||
$this->assertEquals('rgba(0, 0, 0, 1.00)', $img->pickColor(2, 2, 'rgba'));
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim('transparent', null, 50);
|
||||
$this->assertEquals($img->width, 1);
|
||||
$this->assertEquals($img->height, 1);
|
||||
$this->assertEquals('rgba(0, 0, 0, 1.00)', $img->pickColor(0, 0, 'rgba'));
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim('transparent', null, 100);
|
||||
$this->assertEquals($canvas->width, 11);
|
||||
$this->assertEquals($canvas->height, 11);
|
||||
$this->assertEquals('rgba(0, 0, 0, 0.00)', $canvas->pickColor(0, 0, 'rgba'));
|
||||
$this->assertEquals('rgba(255, 255, 255, 0.50)', $canvas->pickColor(3, 3, 'rgba'));
|
||||
$this->assertEquals('rgba(0, 0, 0, 1.00)', $canvas->pickColor(5, 5, 'rgba'));
|
||||
|
||||
// trim gradient
|
||||
$canvas = Image::make('public/gradient.png');
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim();
|
||||
$this->assertEquals($img->width, 46);
|
||||
$this->assertEquals($img->height, 46);
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 10);
|
||||
$this->assertEquals($img->width, 38);
|
||||
$this->assertEquals($img->height, 38);
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 20);
|
||||
$this->assertEquals($img->width, 34);
|
||||
$this->assertEquals($img->height, 34);
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 30);
|
||||
$this->assertEquals($img->width, 30);
|
||||
$this->assertEquals($img->height, 30);
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 40);
|
||||
$this->assertEquals($img->width, 26);
|
||||
$this->assertEquals($img->height, 26);
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 50);
|
||||
$this->assertEquals($img->width, 22);
|
||||
$this->assertEquals($img->height, 22);
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 60);
|
||||
$this->assertEquals($img->width, 20);
|
||||
$this->assertEquals($img->height, 20);
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 70);
|
||||
$this->assertEquals($img->width, 16);
|
||||
$this->assertEquals($img->height, 16);
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 80);
|
||||
$this->assertEquals($img->width, 12);
|
||||
$this->assertEquals($img->height, 12);
|
||||
|
||||
$img = clone $canvas;
|
||||
$img->trim(null, null, 90);
|
||||
$this->assertEquals($img->width, 8);
|
||||
$this->assertEquals($img->height, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Intervention\Image\Exception\TrimToleranceOutOfBoundsException
|
||||
*/
|
||||
public function testTrimToleranceOutOfBounds()
|
||||
{
|
||||
$img = new Image;
|
||||
$img->trim(null, null, 200);
|
||||
}
|
||||
|
||||
public function testEncoded()
|
||||
|
Reference in New Issue
Block a user