diff --git a/src/Gd/Imagine.php b/src/Gd/Imagine.php index 424c04570..5507085c7 100644 --- a/src/Gd/Imagine.php +++ b/src/Gd/Imagine.php @@ -30,11 +30,27 @@ final class Imagine extends AbstractImagine { /** - * @throws \Imagine\Exception\RuntimeException + * @var string + */ + private $tempdir; + + /** + * @param null $tempdir temporary directory for opening webp files */ - public function __construct() + public function __construct($tempdir = null) { $this->requireGdVersion('2.0.1'); + $this->tempdir = $tempdir ? $tempdir : sys_get_temp_dir(); + } + + /** + * Allows changing temporary directory for files. + * + * @param $tempdir + */ + public function setTempDir($tempdir) + { + $this->tempdir = $tempdir; } /** @@ -88,11 +104,16 @@ public function open($path) $path = $loader->getPath(); $data = $loader->getData(); - $resource = ErrorHandling::ignoring(-1, function () use (&$data) { - return @imagecreatefromstring($data); - }); - if (!is_resource($resource)) { + if (\function_exists('imagecreatefromwebp') && $this->isWebp($data)) { + $resource = $this->loadWebp($data); + } else { + $resource = ErrorHandling::ignoring(-1, function () use (&$data) { + return @imagecreatefromstring($data); + }); + } + + if (!\is_resource($resource)) { throw new RuntimeException(sprintf('Unable to open image %s', $path)); } @@ -116,7 +137,7 @@ public function load($string) */ public function read($resource) { - if (!is_resource($resource)) { + if (!\is_resource($resource)) { throw new InvalidArgumentException('Variable does not contain a stream resource'); } @@ -151,7 +172,7 @@ public function font($file, $size, ColorInterface $color) private function wrap($resource, PaletteInterface $palette, MetadataBag $metadata) { if (!imageistruecolor($resource)) { - if (function_exists('imagepalettetotruecolor')) { + if (\function_exists('imagepalettetotruecolor')) { if (false === imagepalettetotruecolor($resource)) { throw new RuntimeException('Could not convert a palette based image to true color'); } @@ -177,7 +198,7 @@ private function wrap($resource, PaletteInterface $palette, MetadataBag $metadat throw new RuntimeException('Could not set alphablending, savealpha and antialias values'); } - if (function_exists('imageantialias')) { + if (\function_exists('imageantialias')) { imageantialias($resource, true); } @@ -191,7 +212,7 @@ private function wrap($resource, PaletteInterface $palette, MetadataBag $metadat */ private function requireGdVersion($version) { - if (!function_exists('gd_info')) { + if (!\function_exists('gd_info')) { throw new RuntimeException('Gd not installed'); } if (version_compare(GD_VERSION, $version, '<')) { @@ -209,14 +230,46 @@ private function requireGdVersion($version) */ private function doLoad($string, MetadataBag $metadata) { - $resource = ErrorHandling::ignoring(-1, function () use (&$string) { - return @imagecreatefromstring($string); - }); + if (\function_exists('imagecreatefromwebp') && $this->isWebp($string)) { + $resource = $this->loadWebp($string); + } else { + $resource = ErrorHandling::ignoring(-1, function () use (&$string) { + return @imagecreatefromstring($string); + }); + } - if (!is_resource($resource)) { + if (!\is_resource($resource)) { throw new RuntimeException('An image could not be created from the given input'); } return $this->wrap($resource, new RGB(), $metadata); } + + + /** + * @param string $data + * + * @return bool + */ + private function isWebp($data) + { + return substr($data, 8, 7) === 'WEBPVP8'; + } + + /** + * @param string $data + * + * @return mixed + */ + private function loadWebp($data) + { + $tmpfile = tempnam($this->tempdir, 'imaginewebp_'); + file_put_contents($tmpfile, $data); + $resource = ErrorHandling::ignoring(-1, function () use ($tmpfile) { + return @imagecreatefromwebp($tmpfile); + }); + @unlink($tmpfile); + + return $resource; + } } diff --git a/tests/fixtures/google.webp b/tests/fixtures/google.webp new file mode 100644 index 000000000..122741b60 Binary files /dev/null and b/tests/fixtures/google.webp differ diff --git a/tests/tests/Gd/ImagineTest.php b/tests/tests/Gd/ImagineTest.php index 6e9c3df1d..822a8b93b 100644 --- a/tests/tests/Gd/ImagineTest.php +++ b/tests/tests/Gd/ImagineTest.php @@ -28,6 +28,26 @@ protected function setUp() } } + public function testShouldOpenAWebpImage() + { + // skip if not supported + if (function_exists('imagecreatefromwebp')) { + $source = IMAGINE_TEST_FIXTURESFOLDER . '/google.webp'; + $factory = $this->getImagine(); + $image = $factory->open($source); + $size = $image->getSize(); + + $this->assertInstanceOf('Imagine\Image\ImageInterface', $image); + $this->assertEquals(550, $size->getWidth()); + $this->assertEquals(368, $size->getHeight()); + + $metadata = $image->metadata(); + + $this->assertEquals($source, $metadata['uri']); + $this->assertEquals(realpath($source), $metadata['filepath']); + } + } + protected function getImagine() { return new Imagine();