vendor/imagine/imagine/src/Gd/Imagine.php line 85

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Imagine package.
  4.  *
  5.  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Imagine\Gd;
  11. use Imagine\Exception\InvalidArgumentException;
  12. use Imagine\Exception\RuntimeException;
  13. use Imagine\Factory\ClassFactoryInterface;
  14. use Imagine\File\LoaderInterface;
  15. use Imagine\Image\AbstractImagine;
  16. use Imagine\Image\BoxInterface;
  17. use Imagine\Image\Metadata\MetadataBag;
  18. use Imagine\Image\Palette\Color\ColorInterface;
  19. use Imagine\Image\Palette\Color\RGB as RGBColor;
  20. use Imagine\Image\Palette\PaletteInterface;
  21. use Imagine\Image\Palette\RGB;
  22. use Imagine\Utils\ErrorHandling;
  23. /**
  24.  * Imagine implementation using the GD library.
  25.  */
  26. final class Imagine extends AbstractImagine
  27. {
  28.     /**
  29.      * Initialize the class.
  30.      */
  31.     public function __construct()
  32.     {
  33.         $this->requireGdVersion('2.0.1');
  34.     }
  35.     /**
  36.      * {@inheritdoc}
  37.      *
  38.      * @see \Imagine\Image\ImagineInterface::create()
  39.      */
  40.     public function create(BoxInterface $sizeColorInterface $color null)
  41.     {
  42.         $width $size->getWidth();
  43.         $height $size->getHeight();
  44.         $resource imagecreatetruecolor($width$height);
  45.         if (false === $resource) {
  46.             throw new RuntimeException('Create operation failed');
  47.         }
  48.         $palette null !== $color $color->getPalette() : new RGB();
  49.         $color $color $color $palette->color('fff');
  50.         if (!$color instanceof RGBColor) {
  51.             throw new InvalidArgumentException('GD driver only supports RGB colors');
  52.         }
  53.         $index imagecolorallocatealpha($resource$color->getRed(), $color->getGreen(), $color->getBlue(), round(127 * (100 $color->getAlpha()) / 100));
  54.         if (false === $index) {
  55.             throw new RuntimeException('Unable to allocate color');
  56.         }
  57.         if (false === imagefill($resource00$index)) {
  58.             throw new RuntimeException('Could not set background color fill');
  59.         }
  60.         if ($color->getAlpha() <= 5) {
  61.             imagecolortransparent($resource$index);
  62.         }
  63.         return $this->wrap($resource$palette, new MetadataBag());
  64.     }
  65.     /**
  66.      * {@inheritdoc}
  67.      *
  68.      * @see \Imagine\Image\ImagineInterface::open()
  69.      */
  70.     public function open($path)
  71.     {
  72.         $loader $path instanceof LoaderInterface $path $this->getClassFactory()->createFileLoader($path);
  73.         $path $loader->getPath();
  74.         $data $loader->getData();
  75.         $resource $this->createImageFromString($data);
  76.         if (!$resource instanceof \GdImage && !\is_resource($resource)) {
  77.             throw new RuntimeException(sprintf('Unable to open image %s'$path));
  78.         }
  79.         return $this->wrap($resource, new RGB(), $this->getMetadataReader()->readFile($loader));
  80.     }
  81.     /**
  82.      * {@inheritdoc}
  83.      *
  84.      * @see \Imagine\Image\ImagineInterface::load()
  85.      */
  86.     public function load($string)
  87.     {
  88.         return $this->doLoad($string$this->getMetadataReader()->readData($string));
  89.     }
  90.     /**
  91.      * {@inheritdoc}
  92.      *
  93.      * @see \Imagine\Image\ImagineInterface::read()
  94.      */
  95.     public function read($resource)
  96.     {
  97.         if (!\is_resource($resource)) {
  98.             throw new InvalidArgumentException('Variable does not contain a stream resource');
  99.         }
  100.         $content stream_get_contents($resource);
  101.         if (false === $content) {
  102.             throw new InvalidArgumentException('Cannot read resource content');
  103.         }
  104.         return $this->doLoad($content$this->getMetadataReader()->readData($content$resource));
  105.     }
  106.     /**
  107.      * {@inheritdoc}
  108.      *
  109.      * @see \Imagine\Image\ImagineInterface::font()
  110.      */
  111.     public function font($file$sizeColorInterface $color)
  112.     {
  113.         return $this->getClassFactory()->createFont(ClassFactoryInterface::HANDLE_GD$file$size$color);
  114.     }
  115.     /**
  116.      * @param resource|\GdImage $resource
  117.      * @param \Imagine\Image\Palette\PaletteInterface $palette
  118.      * @param \Imagine\Image\Metadata\MetadataBag $metadata
  119.      *
  120.      * @throws \Imagine\Exception\RuntimeException
  121.      *
  122.      * @return \Imagine\Image\ImageInterface
  123.      */
  124.     private function wrap($resourcePaletteInterface $paletteMetadataBag $metadata)
  125.     {
  126.         if (!imageistruecolor($resource)) {
  127.             if (\function_exists('imagepalettetotruecolor')) {
  128.                 if (false === imagepalettetotruecolor($resource)) {
  129.                     throw new RuntimeException('Could not convert a palette based image to true color');
  130.                 }
  131.             } else {
  132.                 list($width$height) = array(imagesx($resource), imagesy($resource));
  133.                 // create transparent truecolor canvas
  134.                 $truecolor imagecreatetruecolor($width$height);
  135.                 $transparent imagecolorallocatealpha($truecolor255255255127);
  136.                 imagealphablending($truecolorfalse);
  137.                 imagefilledrectangle($truecolor00$width$height$transparent);
  138.                 imagealphablending($truecolorfalse);
  139.                 imagecopy($truecolor$resource0000$width$height);
  140.                 imagedestroy($resource);
  141.                 $resource $truecolor;
  142.             }
  143.         }
  144.         if (false === imagealphablending($resourcefalse) || false === imagesavealpha($resourcetrue)) {
  145.             throw new RuntimeException('Could not set alphablending, savealpha and antialias values');
  146.         }
  147.         if (\function_exists('imageantialias')) {
  148.             imageantialias($resourcetrue);
  149.         }
  150.         return $this->getClassFactory()->createImage(ClassFactoryInterface::HANDLE_GD$resource$palette$metadata);
  151.     }
  152.     /**
  153.      * @param string $version
  154.      *
  155.      * @throws \Imagine\Exception\RuntimeException
  156.      */
  157.     private function requireGdVersion($version)
  158.     {
  159.         if (!\function_exists('gd_info')) {
  160.             throw new RuntimeException('Gd not installed');
  161.         }
  162.         if (version_compare(GD_VERSION$version'<')) {
  163.             throw new RuntimeException(sprintf('GD2 version %s or higher is required, %s provided'$versionGD_VERSION));
  164.         }
  165.     }
  166.     /**
  167.      * @param string $string
  168.      * @param \Imagine\Image\Metadata\MetadataBag $metadata
  169.      *
  170.      * @throws \Imagine\Exception\RuntimeException
  171.      *
  172.      * @return \Imagine\Image\ImageInterface
  173.      */
  174.     private function doLoad($stringMetadataBag $metadata)
  175.     {
  176.         $resource $this->createImageFromString($string);
  177.         if (!$resource instanceof \GdImage && !\is_resource($resource)) {
  178.             throw new RuntimeException('An image could not be created from the given input');
  179.         }
  180.         return $this->wrap($resource, new RGB(), $metadata);
  181.     }
  182.     /**
  183.      * Check if the raw image data represents an image in WebP format.
  184.      *
  185.      * @param string $data
  186.      *
  187.      * @return bool
  188.      */
  189.     private function isWebP(&$data)
  190.     {
  191.         return substr($data87) === 'WEBPVP8';
  192.     }
  193.     /**
  194.      * Create an image resource starting from its raw daa.
  195.      *
  196.      * @param string $string
  197.      *
  198.      * @return resource|\GdImage|false
  199.      */
  200.     private function createImageFromString(&$string)
  201.     {
  202.         return ErrorHandling::ignoring(-1, function () use (&$string) {
  203.             //  imagecreatefromstring() does not support webp images before PHP 7.3.0
  204.             if (PHP_VERSION_ID 70300 && function_exists('imagecreatefromwebp') && $this->isWebP($string)) {
  205.                 return @imagecreatefromwebp('data:image/webp;base64,' base64_encode($string));
  206.             }
  207.             return @imagecreatefromstring($string);
  208.         });
  209.     }
  210. }