vendor/contao/core-bundle/src/Resources/contao/library/Contao/Image.php line 754

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of Contao.
  4.  *
  5.  * (c) Leo Feyer
  6.  *
  7.  * @license LGPL-3.0-or-later
  8.  */
  9. namespace Contao;
  10. use Contao\Image\DeferredImageInterface;
  11. use Contao\Image\Image as NewImage;
  12. use Contao\Image\ImageDimensions;
  13. use Contao\Image\ImportantPart;
  14. use Contao\Image\ResizeConfiguration;
  15. use Contao\Image\ResizeOptions;
  16. use Imagine\Image\Box;
  17. /**
  18.  * Resizes images
  19.  *
  20.  * The class resizes images and stores them in the image target folder.
  21.  *
  22.  * Usage:
  23.  *
  24.  *     $imageObj = new Image(new File('example.jpg'));
  25.  *
  26.  *     $src = $imageObj->setTargetWidth(640)
  27.  *                     ->setTargetHeight(480)
  28.  *                     ->setResizeMode('center_center')
  29.  *                     ->executeResize()
  30.  *                     ->getResizedPath();
  31.  */
  32. class Image
  33. {
  34.     /**
  35.      * The File instance of the original image
  36.      *
  37.      * @var File
  38.      */
  39.     protected $fileObj;
  40.     /**
  41.      * The resized image path
  42.      *
  43.      * @var string
  44.      */
  45.     protected $resizedPath '';
  46.     /**
  47.      * The target width
  48.      *
  49.      * @var integer
  50.      */
  51.     protected $targetWidth 0;
  52.     /**
  53.      * The target height
  54.      *
  55.      * @var integer
  56.      */
  57.     protected $targetHeight 0;
  58.     /**
  59.      * The resize mode (defaults to crop for backwards compatibility)
  60.      *
  61.      * @var string
  62.      */
  63.     protected $resizeMode 'crop';
  64.     /**
  65.      * The target path
  66.      *
  67.      * @var string
  68.      */
  69.     protected $targetPath '';
  70.     /**
  71.      * Override an existing target
  72.      *
  73.      * @var boolean
  74.      */
  75.     protected $forceOverride false;
  76.     /**
  77.      * Zoom level (between 0 and 100)
  78.      *
  79.      * @var integer
  80.      */
  81.     protected $zoomLevel 0;
  82.     /**
  83.      * Root dir
  84.      * @var string
  85.      */
  86.     protected $strRootDir;
  87.     /**
  88.      * Important part settings
  89.      *
  90.      * @var array
  91.      */
  92.     protected $importantPart = array();
  93.     /**
  94.      * Create a new object to handle an image
  95.      *
  96.      * @param File $file A file instance of the original image
  97.      *
  98.      * @throws \InvalidArgumentException If the file does not exist or cannot be processed
  99.      *
  100.      * @deprecated Deprecated since Contao 4.3, to be removed in Contao 5.0.
  101.      *             Use the contao.image.factory service instead.
  102.      */
  103.     public function __construct(File $file)
  104.     {
  105.         trigger_deprecation('contao/core-bundle''4.3''Using the "Contao\Image" class has been deprecated and will no longer work in Contao 5.0. Use the "contao.image.factory" service instead.');
  106.         // Create deferred images (see #5873)
  107.         $file->createIfDeferred();
  108.         // Check whether the file exists
  109.         if (!$file->exists())
  110.         {
  111.             $webDir System::getContainer()->getParameter('contao.web_dir');
  112.             // Handle public bundle resources
  113.             if (file_exists($webDir '/' $file->path))
  114.             {
  115.                 $file = new File(StringUtil::stripRootDir($webDir) . '/' $file->path);
  116.             }
  117.             else
  118.             {
  119.                 throw new \InvalidArgumentException('Image "' $file->path '" could not be found');
  120.             }
  121.         }
  122.         $this->fileObj $file;
  123.         $arrAllowedTypes System::getContainer()->getParameter('contao.image.valid_extensions');
  124.         // Check the file type
  125.         if (!\in_array($this->fileObj->extension$arrAllowedTypes))
  126.         {
  127.             throw new \InvalidArgumentException('Image type "' $this->fileObj->extension '" was not allowed to be processed');
  128.         }
  129.         $this->strRootDir System::getContainer()->getParameter('kernel.project_dir');
  130.     }
  131.     /**
  132.      * Override the target image
  133.      *
  134.      * @param boolean $forceOverride True to override the target image
  135.      *
  136.      * @return $this The image object
  137.      */
  138.     public function setForceOverride($forceOverride)
  139.     {
  140.         $this->forceOverride = (bool) $forceOverride;
  141.         return $this;
  142.     }
  143.     /**
  144.      * Get force override setting
  145.      *
  146.      * @return boolean True if the target image will be overridden
  147.      */
  148.     public function getForceOverride()
  149.     {
  150.         return $this->forceOverride;
  151.     }
  152.     /**
  153.      * Set the important part settings
  154.      *
  155.      * @param array $importantPart The settings array
  156.      *
  157.      * @return $this The image object
  158.      *
  159.      * @throws \InvalidArgumentException If the settings array is malformed
  160.      */
  161.     public function setImportantPart(array $importantPart null)
  162.     {
  163.         if ($importantPart !== null)
  164.         {
  165.             if (!isset($importantPart['x'], $importantPart['y'], $importantPart['width'], $importantPart['height']))
  166.             {
  167.                 throw new \InvalidArgumentException('Malformed array for setting the important part!');
  168.             }
  169.             $this->importantPart = array
  170.             (
  171.                 'x' => max(0min($this->fileObj->viewWidth 1, (int) $importantPart['x'])),
  172.                 'y' => max(0min($this->fileObj->viewHeight 1, (int) $importantPart['y'])),
  173.             );
  174.             $this->importantPart['width'] = max(1min($this->fileObj->viewWidth $this->importantPart['x'], (int) $importantPart['width']));
  175.             $this->importantPart['height'] = max(1min($this->fileObj->viewHeight $this->importantPart['y'], (int) $importantPart['height']));
  176.         }
  177.         else
  178.         {
  179.             $this->importantPart null;
  180.         }
  181.         return $this;
  182.     }
  183.     /**
  184.      * Get the important part settings
  185.      *
  186.      * @return array The settings array
  187.      */
  188.     public function getImportantPart()
  189.     {
  190.         if ($this->importantPart)
  191.         {
  192.             return $this->importantPart;
  193.         }
  194.         return array('x'=>0'y'=>0'width'=>$this->fileObj->viewWidth'height'=>$this->fileObj->viewHeight);
  195.     }
  196.     /**
  197.      * Set the target height
  198.      *
  199.      * @param integer $targetHeight The target height
  200.      *
  201.      * @return $this The image object
  202.      */
  203.     public function setTargetHeight($targetHeight)
  204.     {
  205.         $this->targetHeight = (int) $targetHeight;
  206.         return $this;
  207.     }
  208.     /**
  209.      * Get the target height
  210.      *
  211.      * @return integer The target height
  212.      */
  213.     public function getTargetHeight()
  214.     {
  215.         return $this->targetHeight;
  216.     }
  217.     /**
  218.      * Set the target width
  219.      *
  220.      * @param integer $targetWidth The target width
  221.      *
  222.      * @return $this The image object
  223.      */
  224.     public function setTargetWidth($targetWidth)
  225.     {
  226.         $this->targetWidth = (int) $targetWidth;
  227.         return $this;
  228.     }
  229.     /**
  230.      * Get the target width
  231.      *
  232.      * @return integer The target width
  233.      */
  234.     public function getTargetWidth()
  235.     {
  236.         return $this->targetWidth;
  237.     }
  238.     /**
  239.      * Set the target path
  240.      *
  241.      * @param string $targetPath The target path
  242.      *
  243.      * @return $this The image object
  244.      */
  245.     public function setTargetPath($targetPath)
  246.     {
  247.         $this->targetPath = (string) $targetPath;
  248.         return $this;
  249.     }
  250.     /**
  251.      * Get the target path
  252.      *
  253.      * @return string The target path
  254.      */
  255.     public function getTargetPath()
  256.     {
  257.         return $this->targetPath;
  258.     }
  259.     /**
  260.      * Set the zoom level
  261.      *
  262.      * @param integer $zoomLevel The zoom level
  263.      *
  264.      * @return $this The object instance
  265.      *
  266.      * @throws \InvalidArgumentException If the zoom level is out of bounds
  267.      */
  268.     public function setZoomLevel($zoomLevel)
  269.     {
  270.         $zoomLevel = (int) $zoomLevel;
  271.         if ($zoomLevel || $zoomLevel 100)
  272.         {
  273.             throw new \InvalidArgumentException('Zoom level must be between 0 and 100!');
  274.         }
  275.         $this->zoomLevel $zoomLevel;
  276.         return $this;
  277.     }
  278.     /**
  279.      * Get the zoom level
  280.      *
  281.      * @return integer The zoom level
  282.      */
  283.     public function getZoomLevel()
  284.     {
  285.         return $this->zoomLevel;
  286.     }
  287.     /**
  288.      * Set the resize mode
  289.      *
  290.      * @param string $resizeMode The resize mode
  291.      *
  292.      * @return $this The image object
  293.      */
  294.     public function setResizeMode($resizeMode)
  295.     {
  296.         $this->resizeMode $resizeMode;
  297.         return $this;
  298.     }
  299.     /**
  300.      * Get the resize mode
  301.      *
  302.      * @return string The resize mode
  303.      */
  304.     public function getResizeMode()
  305.     {
  306.         return $this->resizeMode;
  307.     }
  308.     /**
  309.      * Get the path of the original image
  310.      *
  311.      * @return string The path of the original image
  312.      */
  313.     public function getOriginalPath()
  314.     {
  315.         return $this->fileObj->path;
  316.     }
  317.     /**
  318.      * Get the path of the resized image
  319.      *
  320.      * @return string The path of the resized image
  321.      */
  322.     public function getResizedPath()
  323.     {
  324.         $path $this->resizedPath;
  325.         $webDir StringUtil::stripRootDir(System::getContainer()->getParameter('contao.web_dir'));
  326.         // Strip the contao.web_dir directory prefix (see #337)
  327.         if (strncmp($path$webDir '/'\strlen($webDir) + 1) === 0)
  328.         {
  329.             $path substr($path\strlen($webDir) + 1);
  330.         }
  331.         return $path;
  332.     }
  333.     /**
  334.      * Get the cache name
  335.      *
  336.      * @return string The cache name
  337.      */
  338.     public function getCacheName()
  339.     {
  340.         $importantPart $this->getImportantPart();
  341.         $strCacheKey substr(md5
  342.         (
  343.             '-w' $this->getTargetWidth()
  344.             . '-h' $this->getTargetHeight()
  345.             . '-o' $this->getOriginalPath()
  346.             . '-m' $this->getResizeMode()
  347.             . '-z' $this->getZoomLevel()
  348.             . '-x' $importantPart['x']
  349.             . '-y' $importantPart['y']
  350.             . '-i' $importantPart['width']
  351.             . '-e' $importantPart['height']
  352.             . '-t' $this->fileObj->mtime
  353.         ), 08);
  354.         return StringUtil::stripRootDir(System::getContainer()->getParameter('contao.image.target_dir')) . '/' substr($strCacheKey, -1) . '/' $this->fileObj->filename '-' $strCacheKey '.' $this->fileObj->extension;
  355.     }
  356.     /**
  357.      * Resize the image
  358.      *
  359.      * @return $this The image object
  360.      */
  361.     public function executeResize()
  362.     {
  363.         $image $this->prepareImage();
  364.         $resizeConfig $this->prepareResizeConfig();
  365.         if (
  366.             $this->getTargetPath()
  367.             && !$this->getForceOverride()
  368.             && !System::getContainer()->getParameter('contao.image.bypass_cache')
  369.             && file_exists($this->strRootDir '/' $this->getTargetPath())
  370.             && $this->fileObj->mtime <= filemtime($this->strRootDir '/' $this->getTargetPath())
  371.         ) {
  372.             // HOOK: add custom logic
  373.             if (isset($GLOBALS['TL_HOOKS']['executeResize']) && \is_array($GLOBALS['TL_HOOKS']['executeResize']))
  374.             {
  375.                 foreach ($GLOBALS['TL_HOOKS']['executeResize'] as $callback)
  376.                 {
  377.                     $return System::importStatic($callback[0])->{$callback[1]}($this);
  378.                     if (\is_string($return))
  379.                     {
  380.                         $this->resizedPath System::urlEncode($return);
  381.                         return $this;
  382.                     }
  383.                 }
  384.             }
  385.             $this->resizedPath System::urlEncode($this->getTargetPath());
  386.             return $this;
  387.         }
  388.         $image System::getContainer()
  389.             ->get('contao.image.legacy_resizer')
  390.             ->resize(
  391.                 $image,
  392.                 $resizeConfig,
  393.                 (new ResizeOptions())
  394.                     ->setImagineOptions(System::getContainer()->getParameter('contao.image.imagine_options'))
  395.                     ->setTargetPath($this->targetPath $this->strRootDir '/' $this->targetPath null)
  396.                     ->setBypassCache(System::getContainer()->getParameter('contao.image.bypass_cache'))
  397.                     ->setSkipIfDimensionsMatch(true)
  398.             )
  399.         ;
  400.         $this->resizedPath $image->getUrl($this->strRootDir);
  401.         return $this;
  402.     }
  403.     /**
  404.      * Prepare image object.
  405.      *
  406.      * @return NewImage
  407.      */
  408.     protected function prepareImage()
  409.     {
  410.         if ($this->fileObj->isSvgImage)
  411.         {
  412.             $imagine System::getContainer()->get('contao.image.imagine_svg');
  413.         }
  414.         else
  415.         {
  416.             $imagine System::getContainer()->get('contao.image.imagine');
  417.         }
  418.         $image = new NewImage($this->strRootDir '/' $this->fileObj->path$imagineSystem::getContainer()->get('filesystem'));
  419.         $image->setImportantPart($this->prepareImportantPart());
  420.         return $image;
  421.     }
  422.     /**
  423.      * Prepare important part object.
  424.      *
  425.      * @return ImportantPart
  426.      */
  427.     protected function prepareImportantPart()
  428.     {
  429.         $importantPart $this->getImportantPart();
  430.         if (substr_count($this->resizeMode'_') === 1)
  431.         {
  432.             $importantPart = array
  433.             (
  434.                 'x' => 0,
  435.                 'y' => 0,
  436.                 'width' => $this->fileObj->viewWidth,
  437.                 'height' => $this->fileObj->viewHeight,
  438.             );
  439.             $mode explode('_'$this->resizeMode);
  440.             if ($mode[0] === 'left')
  441.             {
  442.                 $importantPart['width'] = 1;
  443.             }
  444.             elseif ($mode[0] === 'right')
  445.             {
  446.                 $importantPart['x'] = $importantPart['width'] - 1;
  447.                 $importantPart['width'] = 1;
  448.             }
  449.             if ($mode[1] === 'top')
  450.             {
  451.                 $importantPart['height'] = 1;
  452.             }
  453.             elseif ($mode[1] === 'bottom')
  454.             {
  455.                 $importantPart['y'] = $importantPart['height'] - 1;
  456.                 $importantPart['height'] = 1;
  457.             }
  458.         }
  459.         if (!$importantPart['width'] || !$importantPart['height'])
  460.         {
  461.             return null;
  462.         }
  463.         return new ImportantPart(
  464.             $importantPart['x'] / $this->fileObj->viewWidth,
  465.             $importantPart['y'] / $this->fileObj->viewHeight,
  466.             $importantPart['width'] / $this->fileObj->viewWidth,
  467.             $importantPart['height'] / $this->fileObj->viewHeight
  468.         );
  469.     }
  470.     /**
  471.      * Prepare resize configuration object.
  472.      *
  473.      * @return ResizeConfiguration
  474.      */
  475.     protected function prepareResizeConfig()
  476.     {
  477.         $resizeConfig = new ResizeConfiguration();
  478.         $resizeConfig->setWidth($this->targetWidth);
  479.         $resizeConfig->setHeight($this->targetHeight);
  480.         $resizeConfig->setZoomLevel($this->zoomLevel);
  481.         if (substr_count($this->resizeMode'_') === 1)
  482.         {
  483.             $resizeConfig->setMode(ResizeConfiguration::MODE_CROP);
  484.             $resizeConfig->setZoomLevel(0);
  485.         }
  486.         else
  487.         {
  488.             try
  489.             {
  490.                 $resizeConfig->setMode($this->resizeMode);
  491.             }
  492.             catch (\Throwable $exception)
  493.             {
  494.                 $resizeConfig->setMode(ResizeConfiguration::MODE_CROP);
  495.             }
  496.         }
  497.         return $resizeConfig;
  498.     }
  499.     /**
  500.      * Calculate the resize coordinates
  501.      *
  502.      * @return array The resize coordinates (width, height, target_x, target_y, target_width, target_height)
  503.      */
  504.     public function computeResize()
  505.     {
  506.         $resizeCoordinates System::getContainer()
  507.             ->get('contao.image.resize_calculator')
  508.             ->calculate(
  509.                 $this->prepareResizeConfig(),
  510.                 new ImageDimensions(
  511.                     new Box($this->fileObj->viewWidth$this->fileObj->viewHeight),
  512.                     $this->fileObj->viewWidth !== $this->fileObj->width
  513.                 ),
  514.                 $this->prepareImportantPart()
  515.             )
  516.         ;
  517.         return array
  518.         (
  519.             'width' => $resizeCoordinates->getCropSize()->getWidth(),
  520.             'height' => $resizeCoordinates->getCropSize()->getHeight(),
  521.             'target_x' => -$resizeCoordinates->getCropStart()->getX(),
  522.             'target_y' => -$resizeCoordinates->getCropStart()->getY(),
  523.             'target_width' => $resizeCoordinates->getSize()->getWidth(),
  524.             'target_height' => $resizeCoordinates->getSize()->getHeight(),
  525.         );
  526.     }
  527.     /**
  528.      * Get the relative path to an image
  529.      *
  530.      * @param string $src The image name or path
  531.      *
  532.      * @return string The relative path
  533.      */
  534.     public static function getPath($src)
  535.     {
  536.         if (!$src)
  537.         {
  538.             return '';
  539.         }
  540.         $src rawurldecode($src);
  541.         if (strpos($src'/') !== false)
  542.         {
  543.             return $src;
  544.         }
  545.         $projectDir System::getContainer()->getParameter('kernel.project_dir');
  546.         if (strncmp($src'icon'4) === 0)
  547.         {
  548.             if (pathinfo($srcPATHINFO_EXTENSION) == 'svg')
  549.             {
  550.                 return 'assets/contao/images/' $src;
  551.             }
  552.             $filename pathinfo($srcPATHINFO_FILENAME);
  553.             // Prefer SVG icons
  554.             if (file_exists($projectDir '/assets/contao/images/' $filename '.svg'))
  555.             {
  556.                 return 'assets/contao/images/' $filename '.svg';
  557.             }
  558.             return 'assets/contao/images/' $src;
  559.         }
  560.         $theme Backend::getTheme();
  561.         if (pathinfo($srcPATHINFO_EXTENSION) == 'svg')
  562.         {
  563.             return 'system/themes/' $theme '/icons/' $src;
  564.         }
  565.         $filename pathinfo($srcPATHINFO_FILENAME);
  566.         // Prefer SVG icons
  567.         if (file_exists($projectDir '/system/themes/' $theme '/icons/' $filename '.svg'))
  568.         {
  569.             return 'system/themes/' $theme '/icons/' $filename '.svg';
  570.         }
  571.         return 'system/themes/' $theme '/images/' $src;
  572.     }
  573.     /**
  574.      * Generate an image tag and return it as string
  575.      *
  576.      * @param string $src        The image path
  577.      * @param string $alt        An optional alt attribute
  578.      * @param string $attributes A string of other attributes
  579.      *
  580.      * @return string The image HTML tag
  581.      */
  582.     public static function getHtml($src$alt=''$attributes='')
  583.     {
  584.         $src = static::getPath($src);
  585.         if (!$src)
  586.         {
  587.             return '';
  588.         }
  589.         $container System::getContainer();
  590.         $projectDir $container->getParameter('kernel.project_dir');
  591.         $webDir StringUtil::stripRootDir($container->getParameter('contao.web_dir'));
  592.         if (!is_file($projectDir '/' $src))
  593.         {
  594.             try
  595.             {
  596.                 $deferredImage $container->get('contao.image.factory')->create($projectDir '/' $src);
  597.             }
  598.             catch (\Exception $e)
  599.             {
  600.                 $deferredImage null;
  601.             }
  602.             // Handle public bundle resources
  603.             if (file_exists($projectDir '/' $webDir '/' $src))
  604.             {
  605.                 $src $webDir '/' $src;
  606.             }
  607.             elseif (!$deferredImage instanceof DeferredImageInterface)
  608.             {
  609.                 return '';
  610.             }
  611.         }
  612.         $objFile = new File($src);
  613.         // Strip the contao.web_dir directory prefix (see #337)
  614.         if (strncmp($src$webDir '/'\strlen($webDir) + 1) === 0)
  615.         {
  616.             $src substr($src\strlen($webDir) + 1);
  617.         }
  618.         $context = (strncmp($src'assets/'7) === 0) ? 'assets_context' 'files_context';
  619.         return '<img src="' Controller::addStaticUrlTo(System::urlEncode($src), $container->get('contao.assets.' $context)) . '" width="' $objFile->width '" height="' $objFile->height '" alt="' StringUtil::specialchars($alt) . '"' . ($attributes ' ' $attributes '') . '>';
  620.     }
  621.     /**
  622.      * Resize or crop an image and replace the original with the resized version
  623.      *
  624.      * @param string  $image  The image path
  625.      * @param integer $width  The target width
  626.      * @param integer $height The target height
  627.      * @param string  $mode   The resize mode
  628.      *
  629.      * @return boolean True if the image could be resized successfully
  630.      *
  631.      * @deprecated Deprecated since Contao 4.3, to be removed in Contao 5.0.
  632.      *             Use the contao.image.factory service instead.
  633.      */
  634.     public static function resize($image$width$height$mode='')
  635.     {
  636.         trigger_deprecation('contao/core-bundle''4.3''Using "Contao\Image::resize()" has been deprecated and will no longer work in Contao 5.0. Use the "contao.image.factory" service instead.');
  637.         return static::get($image$width$height$mode$imagetrue) ? true false;
  638.     }
  639.     /**
  640.      * Create an image instance from the given image path and size
  641.      *
  642.      * @param string|File          $image The image path or File instance
  643.      * @param array|integer|string $size  The image size as array (width, height, resize mode) or a tl_image_size ID or a predefined image size key
  644.      *
  645.      * @return static The created image instance
  646.      *
  647.      * @deprecated Deprecated since Contao 4.3, to be removed in Contao 5.0.
  648.      *             Use the contao.image.factory service instead.
  649.      */
  650.     public static function create($image$size=null)
  651.     {
  652.         trigger_deprecation('contao/core-bundle''4.3''Using "Contao\Image::create()" has been deprecated and will no longer work in Contao 5.0. Use the "contao.image.factory" service instead.');
  653.         if (\is_string($image))
  654.         {
  655.             $image = new File(rawurldecode($image));
  656.         }
  657.         $imageObj = new static($image);
  658.         if (\is_array($size) && !empty($size[2]))
  659.         {
  660.             // tl_image_size ID as resize mode
  661.             if (is_numeric($size[2]))
  662.             {
  663.                 $size = (int) $size[2];
  664.             }
  665.             // Predefined image size as resize mode
  666.             elseif (\is_string($size[2]) && $size[2][0] === '_')
  667.             {
  668.                 $size $size[2];
  669.             }
  670.         }
  671.         if (\is_array($size))
  672.         {
  673.             $size += array(00'crop');
  674.             $imageObj
  675.                 ->setTargetWidth($size[0])
  676.                 ->setTargetHeight($size[1])
  677.                 ->setResizeMode($size[2])
  678.             ;
  679.         }
  680.         // Load the image size from the database if $size is an ID or a predefined size
  681.         elseif (($imageSize self::getImageSizeConfig($size)) !== null)
  682.         {
  683.             $imageObj
  684.                 ->setTargetWidth($imageSize->width)
  685.                 ->setTargetHeight($imageSize->height)
  686.                 ->setResizeMode($imageSize->resizeMode)
  687.                 ->setZoomLevel($imageSize->zoom)
  688.             ;
  689.         }
  690.         $fileRecord FilesModel::findByPath($image->path);
  691.         $currentSize $image->imageViewSize;
  692.         // Set the important part
  693.         if ($fileRecord !== null && $fileRecord->importantPartWidth && $fileRecord->importantPartHeight)
  694.         {
  695.             $imageObj->setImportantPart(array
  696.             (
  697.                 'x' => (int) ($fileRecord->importantPartX $currentSize[0]),
  698.                 'y' => (int) ($fileRecord->importantPartY $currentSize[1]),
  699.                 'width' => (int) ($fileRecord->importantPartWidth $currentSize[0]),
  700.                 'height' => (int) ($fileRecord->importantPartHeight $currentSize[1]),
  701.             ));
  702.         }
  703.         return $imageObj;
  704.     }
  705.     private static function getImageSizeConfig($size)
  706.     {
  707.         if (is_numeric($size))
  708.         {
  709.             return ImageSizeModel::findByPk($size);
  710.         }
  711.         if (!\is_string($size) || $size[0] !== '_')
  712.         {
  713.             return null;
  714.         }
  715.         static $predefinedSizes null;
  716.         if ($predefinedSizes === null)
  717.         {
  718.             $factory System::getContainer()->get('contao.image.factory');
  719.             $predefinedSizes = (new \ReflectionObject($factory))->getProperty('predefinedSizes');
  720.             $predefinedSizes->setAccessible(true);
  721.             $predefinedSizes $predefinedSizes->getValue($factory) ?? array();
  722.         }
  723.         if (!isset($predefinedSizes[$size]))
  724.         {
  725.             return null;
  726.         }
  727.         $imageSize = new \stdClass();
  728.         $imageSize->width $predefinedSizes[$size]['width'];
  729.         $imageSize->height $predefinedSizes[$size]['height'];
  730.         $imageSize->resizeMode $predefinedSizes[$size]['resizeMode'];
  731.         $imageSize->zoom $predefinedSizes[$size]['zoom'];
  732.         return $imageSize;
  733.     }
  734.     /**
  735.      * Resize an image and store the resized version in the image target folder
  736.      *
  737.      * @param string  $image  The image path
  738.      * @param integer $width  The target width
  739.      * @param integer $height The target height
  740.      * @param string  $mode   The resize mode
  741.      * @param string  $target An optional target path
  742.      * @param boolean $force  Override existing target images
  743.      *
  744.      * @return string|null The path of the resized image or null
  745.      *
  746.      * @deprecated Deprecated since Contao 4.3, to be removed in Contao 5.0.
  747.      *             Use the contao.image.factory service instead.
  748.      */
  749.     public static function get($image$width$height$mode=''$target=null$force=false)
  750.     {
  751.         trigger_deprecation('contao/core-bundle''4.3''Using "Contao\Image::get()" has been deprecated and will no longer work in Contao 5.0. Use the "contao.image.factory" service instead.');
  752.         if (!$image)
  753.         {
  754.             return null;
  755.         }
  756.         try
  757.         {
  758.             $imageObj = static::create($image, array($width$height$mode));
  759.             $imageObj->setTargetPath($target);
  760.             $imageObj->setForceOverride($force);
  761.             if ($path $imageObj->executeResize()->getResizedPath())
  762.             {
  763.                 return $path;
  764.             }
  765.         }
  766.         catch (\Exception $e)
  767.         {
  768.             System::getContainer()->get('monolog.logger.contao.error')->error('Image "' $image '" could not be processed: ' $e->getMessage());
  769.         }
  770.         return null;
  771.     }
  772.     /**
  773.      * Convert sizes like 2em, 10cm or 12pt to pixels
  774.      *
  775.      * @param string $size The size string
  776.      *
  777.      * @return integer The pixel value
  778.      *
  779.      * @deprecated Deprecated since Contao 4.3, to be removed in Contao 5.0.
  780.      *             Use the contao.image.factory service instead.
  781.      */
  782.     public static function getPixelValue($size)
  783.     {
  784.         trigger_deprecation('contao/core-bundle''4.3''Using "Contao\Image::getPixelValue()" has been deprecated and will no longer work in Contao 5.0. Use the "contao.image.factory" service instead.');
  785.         $value preg_replace('/[^0-9.-]+/'''$size);
  786.         $unit preg_replace('/[^acehimnprtvwx%]/'''$size);
  787.         // Convert 16px = 1em = 2ex = 12pt = 1pc = 1/6in = 2.54/6cm = 25.4/6mm = 100%
  788.         switch ($unit)
  789.         {
  790.             case '':
  791.             case 'px':
  792.                 return (int) round($value);
  793.             case 'pc':
  794.             case 'em':
  795.                 return (int) round($value 16);
  796.             case 'ex':
  797.                 return (int) round($value 16 2);
  798.             case 'pt':
  799.                 return (int) round($value 16 12);
  800.             case 'in':
  801.                 return (int) round($value 16 6);
  802.             case 'cm':
  803.                 return (int) round($value 16 / (2.54 6));
  804.             case 'mm':
  805.                 return (int) round($value 16 / (25.4 6));
  806.             case '%':
  807.                 return (int) round($value 16 100);
  808.         }
  809.         return 0;
  810.     }
  811. }
  812. class_alias(Image::class, 'Image');