diff --git a/src/Intervention/Image/AbstractDecoder.php b/src/Intervention/Image/AbstractDecoder.php index 8caebcd9..e010d1c8 100644 --- a/src/Intervention/Image/AbstractDecoder.php +++ b/src/Intervention/Image/AbstractDecoder.php @@ -136,6 +136,18 @@ abstract class AbstractDecoder return false; } + /** + * Determines if current source data is data-url + * + * @return boolean + */ + public function isDataUrl() + { + $data = $this->decodeDataUrl($this->data); + + return is_null($data) ? false : true; + } + /** * Initiates new Image from Intervention\Image\Image * @@ -147,6 +159,24 @@ abstract class AbstractDecoder return $object; } + /** + * Parses and decodes binary image data from data-url + * + * @param string $data_url + * @return string + */ + private function decodeDataUrl($data_url) + { + $pattern = "/^data:(?:image\/.+)(?:charset=\".+\")?;base64,(?P.+)$/"; + preg_match($pattern, $data_url, $matches); + + if (is_array($matches) && array_key_exists('data', $matches)) { + return base64_decode($matches['data']); + } + + return null; + } + /** * Initiates new image from mixed data * @@ -180,6 +210,9 @@ abstract class AbstractDecoder case $this->isFilePath(): return $this->initFromPath($this->data); + case $this->isDataUrl(): + return $this->initFromBinary($this->decodeDataUrl($this->data)); + default: throw new Exception\NotReadableException("Image source not readable"); } diff --git a/tests/AbstractDecoderTest.php b/tests/AbstractDecoderTest.php index d3679318..b237dbc2 100644 --- a/tests/AbstractDecoderTest.php +++ b/tests/AbstractDecoderTest.php @@ -99,6 +99,15 @@ class AbstractDecoderTest extends PHPUnit_Framework_TestCase $this->assertTrue($source->isSymfonyUpload()); } + public function testIsDataUrl() + { + $source = $this->getTestDecoder('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGElEQVQYlWM8c+bMfwYiABMxikYVUk8hAHWzA3cRvs4UAAAAAElFTkSuQmCC'); + $this->assertTrue($source->isDataUrl()); + + $source = $this->getTestDecoder(null); + $this->assertFalse($source->isDataUrl()); + } + public function getTestDecoder($data) { return $this->getMockForAbstractClass('\Intervention\Image\AbstractDecoder', array($data)); diff --git a/tests/GdSystemTest.php b/tests/GdSystemTest.php index 64932284..7663e80b 100644 --- a/tests/GdSystemTest.php +++ b/tests/GdSystemTest.php @@ -45,6 +45,17 @@ class GdSystemTest extends PHPUnit_Framework_TestCase $this->assertEquals(50, $img->getHeight()); } + public function testMakeFromDataUrl() + { + $img = $this->manager()->make('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGElEQVQYlWM8c+bMfwYiABMxikYVUk8hAHWzA3cRvs4UAAAAAElFTkSuQmCC'); + $this->assertInstanceOf('Intervention\Image\Image', $img); + $this->assertInternalType('resource', $img->getCore()); + $this->assertInternalType('int', $img->getWidth()); + $this->assertInternalType('int', $img->getHeight()); + $this->assertEquals(10, $img->getWidth()); + $this->assertEquals(10, $img->getHeight()); + } + public function testCanvas() { $img = $this->manager()->canvas(30, 20); diff --git a/tests/ImagickSystemTest.php b/tests/ImagickSystemTest.php index 25b28db6..aaa4dbfa 100644 --- a/tests/ImagickSystemTest.php +++ b/tests/ImagickSystemTest.php @@ -45,6 +45,19 @@ class ImagickSystemTest extends PHPUnit_Framework_TestCase $this->assertEquals(50, $img->getHeight()); } + public function testMakeFromDataUrl() + { + $str = file_get_contents('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGElEQVQYlWM8c+bMfwYiABMxikYVUk8hAHWzA3cRvs4UAAAAAElFTkSuQmCC'); + $img = $this->manager()->make($str); + $this->assertInstanceOf('Intervention\Image\Image', $img); + $this->assertInstanceOf('Imagick', $img->getCore()); + $this->assertInternalType('int', $img->getWidth()); + $this->assertInternalType('int', $img->getHeight()); + $this->assertEquals(10, $img->getWidth()); + $this->assertEquals(10, $img->getHeight()); + $this->assertEquals('image/png', $img->mime); + } + public function testCanvas() { $img = $this->manager()->canvas(30, 20);