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

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(0, min($this->fileObj->viewWidth - 1, (int) $importantPart['x'])),
  172. 'y' => max(0, min($this->fileObj->viewHeight - 1, (int) $importantPart['y'])),
  173. );
  174. $this->importantPart['width'] = max(1, min($this->fileObj->viewWidth - $this->importantPart['x'], (int) $importantPart['width']));
  175. $this->importantPart['height'] = max(1, min($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 < 0 || $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. ), 0, 8);
  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, $imagine, System::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($src, PATHINFO_EXTENSION) == 'svg')
  549. {
  550. return 'assets/contao/images/' . $src;
  551. }
  552. $filename = pathinfo($src, PATHINFO_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($src, PATHINFO_EXTENSION) == 'svg')
  562. {
  563. return 'system/themes/' . $theme . '/icons/' . $src;
  564. }
  565. $filename = pathinfo($src, PATHINFO_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, $image, true) ? 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(0, 0, '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'] ?? 0;
  729. $imageSize->height = $predefinedSizes[$size]['height'] ?? 0;
  730. $imageSize->resizeMode = $predefinedSizes[$size]['resizeMode'] ?? 'crop';
  731. $imageSize->zoom = $predefinedSizes[$size]['zoom'] ?? 0;
  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');