From f00a59b4e2a3f78db78b72ceef984cacd3180259 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 16 Feb 2020 01:45:47 +0100 Subject: [PATCH] allow generating multiple preview sizes for a single file at once this saves having to do some of the overhead multiple times Signed-off-by: Robin Appelman --- lib/private/Preview/Generator.php | 98 +++++++++++++++++++------------ lib/private/PreviewManager.php | 44 ++++++++++---- lib/public/IPreview.php | 13 ++++ 3 files changed, 106 insertions(+), 49 deletions(-) diff --git a/lib/private/Preview/Generator.php b/lib/private/Preview/Generator.php index dcd4ccd130..b9f5674316 100644 --- a/lib/private/Preview/Generator.php +++ b/lib/private/Preview/Generator.php @@ -93,22 +93,37 @@ class Generator { * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid) */ public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null) { + $specification = [ + 'width' => $width, + 'height' => $height, + 'crop' => $crop, + 'mode' => $mode, + ]; + $this->eventDispatcher->dispatch( + IPreview::EVENT, + new GenericEvent($file, $specification) + ); + + // since we only ask for one preview, and the generate method return the last one it created, it returns the one we want + return $this->generatePreviews($file, [$specification], $mimeType); + } + + /** + * Generates previews of a file + * + * @param File $file + * @param array $specifications + * @param string $mimeType + * @return ISimpleFile the last preview that was generated + * @throws NotFoundException + * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid) + */ + public function generatePreviews(File $file, array $specifications, $mimeType = null) { //Make sure that we can read the file if (!$file->isReadable()) { throw new NotFoundException('Cannot read file'); } - - $this->eventDispatcher->dispatch( - IPreview::EVENT, - new GenericEvent($file, [ - 'width' => $width, - 'height' => $height, - 'crop' => $crop, - 'mode' => $mode - ]) - ); - if ($mimeType === null) { $mimeType = $file->getMimeType(); } @@ -130,36 +145,47 @@ class Generator { throw new NotFoundException('Max preview size 0, invalid!'); } - list($maxWidth, $maxHeight) = $this->getPreviewSize($maxPreview, $previewVersion); + [$maxWidth, $maxHeight] = $this->getPreviewSize($maxPreview, $previewVersion); - // If both width and heigth are -1 we just want the max preview - if ($width === -1 && $height === -1) { - $width = $maxWidth; - $height = $maxHeight; - } + $preview = null; - // Calculate the preview size - list($width, $height) = $this->calculateSize($width, $height, $crop, $mode, $maxWidth, $maxHeight); + foreach ($specifications as $specification) { + $width = $specification['width'] ?? -1; + $height = $specification['height'] ?? -1; + $crop = $specification['crop'] ?? false; + $mode = $specification['mode'] ?? IPreview::MODE_FILL; - // No need to generate a preview that is just the max preview - if ($width === $maxWidth && $height === $maxHeight) { - return $maxPreview; - } - - // Try to get a cached preview. Else generate (and store) one - try { - try { - $preview = $this->getCachedPreview($previewFolder, $width, $height, $crop, $maxPreview->getMimeType(), $previewVersion); - } catch (NotFoundException $e) { - $preview = $this->generatePreview($previewFolder, $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight, $previewVersion); + // If both width and heigth are -1 we just want the max preview + if ($width === -1 && $height === -1) { + $width = $maxWidth; + $height = $maxHeight; } - } catch (\InvalidArgumentException $e) { - throw new NotFoundException(); - } - if ($preview->getSize() === 0) { - $preview->delete(); - throw new NotFoundException('Cached preview size 0, invalid!'); + // Calculate the preview size + [$width, $height] = $this->calculateSize($width, $height, $crop, $mode, $maxWidth, $maxHeight); + + // No need to generate a preview that is just the max preview + if ($width === $maxWidth && $height === $maxHeight) { + // ensure correct return value if this was the last one + $preview = $maxPreview; + continue; + } + + // Try to get a cached preview. Else generate (and store) one + try { + try { + $preview = $this->getCachedPreview($previewFolder, $width, $height, $crop, $maxPreview->getMimeType(), $previewVersion); + } catch (NotFoundException $e) { + $preview = $this->generatePreview($previewFolder, $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight, $previewVersion); + } + } catch (\InvalidArgumentException $e) { + throw new NotFoundException(); + } + + if ($preview->getSize() === 0) { + $preview->delete(); + throw new NotFoundException('Cached preview size 0, invalid!'); + } } return $preview; diff --git a/lib/private/PreviewManager.php b/lib/private/PreviewManager.php index 652a442dee..e50b43a51d 100644 --- a/lib/private/PreviewManager.php +++ b/lib/private/PreviewManager.php @@ -151,6 +151,22 @@ class PreviewManager implements IPreview { return !empty($this->providers); } + private function getGenerator(): Generator { + if ($this->generator === null) { + $this->generator = new Generator( + $this->config, + $this, + $this->appData, + new GeneratorHelper( + $this->rootFolder, + $this->config + ), + $this->eventDispatcher + ); + } + return $this->generator; + } + /** * Returns a preview of a file * @@ -169,20 +185,22 @@ class PreviewManager implements IPreview { * @since 11.0.0 - \InvalidArgumentException was added in 12.0.0 */ public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null) { - if ($this->generator === null) { - $this->generator = new Generator( - $this->config, - $this, - $this->appData, - new GeneratorHelper( - $this->rootFolder, - $this->config - ), - $this->eventDispatcher - ); - } + return $this->getGenerator()->getPreview($file, $width, $height, $crop, $mode, $mimeType); + } - return $this->generator->getPreview($file, $width, $height, $crop, $mode, $mimeType); + /** + * Generates previews of a file + * + * @param File $file + * @param array $specifications + * @param string $mimeType + * @return ISimpleFile the last preview that was generated + * @throws NotFoundException + * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid) + * @since 19.0.0 + */ + public function generatePreviews(File $file, array $specifications, $mimeType = null) { + return $this->getGenerator()->generatePreviews($file, $specifications, $mimeType); } /** diff --git a/lib/public/IPreview.php b/lib/public/IPreview.php index b377d285ac..164cbbac2b 100644 --- a/lib/public/IPreview.php +++ b/lib/public/IPreview.php @@ -115,4 +115,17 @@ interface IPreview { * @since 8.0.0 */ public function isAvailable(\OCP\Files\FileInfo $file); + + /** + * Generates previews of a file + * + * @param File $file + * @param array $specifications + * @param string $mimeType + * @return ISimpleFile the last preview that was generated + * @throws NotFoundException + * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid) + * @since 19.0.0 + */ + public function generatePreviews(File $file, array $specifications, $mimeType = null); }