You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
4.2 KiB

3 years ago
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @copyright Copyright (c) 2018, ownCloud GmbH
  5. * @copyright Copyright (c) 2018, Sebastian Steinmetz (me@sebastiansteinmetz.ch)
  6. *
  7. * @author Robin Appelman <robin@icewind.nl>
  8. * @author Roeland Jago Douma <roeland@famdouma.nl>
  9. * @author Sebastian Steinmetz <462714+steiny2k@users.noreply.github.com>
  10. * @author Sebastian Steinmetz <me@sebastiansteinmetz.ch>
  11. *
  12. * @license AGPL-3.0
  13. *
  14. * This code is free software: you can redistribute it and/or modify
  15. * it under the terms of the GNU Affero General Public License, version 3,
  16. * as published by the Free Software Foundation.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU Affero General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU Affero General Public License, version 3,
  24. * along with this program. If not, see <http://www.gnu.org/licenses/>
  25. *
  26. */
  27. namespace OC\Preview;
  28. use OCP\Files\File;
  29. use OCP\IImage;
  30. use OCP\ILogger;
  31. /**
  32. * Creates a JPG preview using ImageMagick via the PECL extension
  33. *
  34. * @package OC\Preview
  35. */
  36. class HEIC extends ProviderV2 {
  37. /**
  38. * {@inheritDoc}
  39. */
  40. public function getMimeType(): string {
  41. return '/image\/hei(f|c)/';
  42. }
  43. /**
  44. * {@inheritDoc}
  45. */
  46. public function isAvailable(\OCP\Files\FileInfo $file): bool {
  47. return in_array('HEIC', \Imagick::queryFormats("HEI*"));
  48. }
  49. /**
  50. * {@inheritDoc}
  51. */
  52. public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage {
  53. $tmpPath = $this->getLocalFile($file);
  54. // Creates \Imagick object from the heic file
  55. try {
  56. $bp = $this->getResizedPreview($tmpPath, $maxX, $maxY);
  57. $bp->setFormat('jpg');
  58. } catch (\Exception $e) {
  59. \OC::$server->getLogger()->logException($e, [
  60. 'message' => 'File: ' . $file->getPath() . ' Imagick says:',
  61. 'level' => ILogger::ERROR,
  62. 'app' => 'core',
  63. ]);
  64. return null;
  65. }
  66. $this->cleanTmpFiles();
  67. //new bitmap image object
  68. $image = new \OC_Image();
  69. $image->loadFromData($bp);
  70. //check if image object is valid
  71. return $image->valid() ? $image : null;
  72. }
  73. /**
  74. * Returns a preview of maxX times maxY dimensions in JPG format
  75. *
  76. * * The default resolution is already 72dpi, no need to change it for a bitmap output
  77. * * It's possible to have proper colour conversion using profileimage().
  78. * ICC profiles are here: http://www.color.org/srgbprofiles.xalter
  79. * * It's possible to Gamma-correct an image via gammaImage()
  80. *
  81. * @param string $tmpPath the location of the file to convert
  82. * @param int $maxX
  83. * @param int $maxY
  84. *
  85. * @return \Imagick
  86. */
  87. private function getResizedPreview($tmpPath, $maxX, $maxY) {
  88. $bp = new \Imagick();
  89. // Layer 0 contains either the bitmap or a flat representation of all vector layers
  90. $bp->readImage($tmpPath . '[0]');
  91. $bp->setImageFormat('jpg');
  92. $bp = $this->resize($bp, $maxX, $maxY);
  93. return $bp;
  94. }
  95. /**
  96. * Returns a resized \Imagick object
  97. *
  98. * If you want to know more on the various methods available to resize an
  99. * image, check out this link : @link https://stackoverflow.com/questions/8517304/what-the-difference-of-sample-resample-scale-resize-adaptive-resize-thumbnail-im
  100. *
  101. * @param \Imagick $bp
  102. * @param int $maxX
  103. * @param int $maxY
  104. *
  105. * @return \Imagick
  106. */
  107. private function resize($bp, $maxX, $maxY) {
  108. list($previewWidth, $previewHeight) = array_values($bp->getImageGeometry());
  109. // We only need to resize a preview which doesn't fit in the maximum dimensions
  110. if ($previewWidth > $maxX || $previewHeight > $maxY) {
  111. // If we want a small image (thumbnail) let's be most space- and time-efficient
  112. if ($maxX <= 500 && $maxY <= 500) {
  113. $bp->thumbnailImage($maxY, $maxX, true);
  114. $bp->stripImage();
  115. } else {
  116. // A bigger image calls for some better resizing algorithm
  117. // According to http://www.imagemagick.org/Usage/filter/#lanczos
  118. // the catrom filter is almost identical to Lanczos2, but according
  119. // to http://php.net/manual/en/imagick.resizeimage.php it is
  120. // significantly faster
  121. $bp->resizeImage($maxX, $maxY, \Imagick::FILTER_CATROM, 1, true);
  122. }
  123. }
  124. return $bp;
  125. }
  126. }