diff options
author | Roeland Jago Douma <rullzer@users.noreply.github.com> | 2020-04-10 15:57:06 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-10 15:57:06 +0200 |
commit | eba3726e1e1b7ce0a98df4552cfdecfe05e0d63a (patch) | |
tree | 7d50a939305460fbb34078c1da49f992552747e7 /lib/private/Preview/Generator.php | |
parent | edf8ce32cffdb920e8171207b342abbd7f1fbe73 (diff) | |
parent | 8f9bac26f874e105c017de2b1791b23c2a135b28 (diff) | |
download | nextcloud-server-eba3726e1e1b7ce0a98df4552cfdecfe05e0d63a.tar.gz nextcloud-server-eba3726e1e1b7ce0a98df4552cfdecfe05e0d63a.zip |
Merge pull request #19495 from nextcloud/preview-generate-batch
optimize batch generation of previews
Diffstat (limited to 'lib/private/Preview/Generator.php')
-rw-r--r-- | lib/private/Preview/Generator.php | 112 |
1 files changed, 71 insertions, 41 deletions
diff --git a/lib/private/Preview/Generator.php b/lib/private/Preview/Generator.php index f945849c276..650c3a6ba9f 100644 --- a/lib/private/Preview/Generator.php +++ b/lib/private/Preview/Generator.php @@ -91,22 +91,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(); } @@ -123,41 +138,57 @@ class Generator { // Get the max preview and infer the max preview sizes from that $maxPreview = $this->getMaxPreview($previewFolder, $file, $mimeType, $previewVersion); + $maxPreviewImage = null; // only load the image when we need it if ($maxPreview->getSize() === 0) { $maxPreview->delete(); 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; - } + // If both width and heigth are -1 we just want the max preview + if ($width === -1 && $height === -1) { + $width = $maxWidth; + $height = $maxHeight; + } - // Try to get a cached preview. Else generate (and store) one - try { + // 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 { - $preview = $this->getCachedPreview($previewFolder, $width, $height, $crop, $maxPreview->getMimeType(), $previewVersion); - } catch (NotFoundException $e) { - $preview = $this->generatePreview($previewFolder, $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight, $previewVersion); + try { + $preview = $this->getCachedPreview($previewFolder, $width, $height, $crop, $maxPreview->getMimeType(), $previewVersion); + } catch (NotFoundException $e) { + if ($maxPreviewImage === null) { + $maxPreviewImage = $this->helper->getImage($maxPreview); + } + + $preview = $this->generatePreview($previewFolder, $maxPreviewImage, $width, $height, $crop, $maxWidth, $maxHeight, $previewVersion); + } + } catch (\InvalidArgumentException $e) { + throw new NotFoundException("", 0, $e); } - } catch (\InvalidArgumentException $e) { - throw new NotFoundException(); - } - if ($preview->getSize() === 0) { - $preview->delete(); - throw new NotFoundException('Cached preview size 0, invalid!'); + if ($preview->getSize() === 0) { + $preview->delete(); + throw new NotFoundException('Cached preview size 0, invalid!'); + } } return $preview; @@ -360,9 +391,8 @@ class Generator { * @throws NotFoundException * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid) */ - private function generatePreview(ISimpleFolder $previewFolder, ISimpleFile $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight, $prefix) { - $preview = $this->helper->getImage($maxPreview); - + private function generatePreview(ISimpleFolder $previewFolder, IImage $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight, $prefix) { + $preview = $maxPreview; if (!$preview->valid()) { throw new \InvalidArgumentException('Failed to generate preview, failed to load image'); } @@ -380,13 +410,13 @@ class Generator { $scaleH = $maxHeight / $widthR; $scaleW = $width; } - $preview->preciseResize((int)round($scaleW), (int)round($scaleH)); + $preview = $preview->preciseResizeCopy((int)round($scaleW), (int)round($scaleH)); } $cropX = (int)floor(abs($width - $preview->width()) * 0.5); $cropY = (int)floor(abs($height - $preview->height()) * 0.5); - $preview->crop($cropX, $cropY, $width, $height); + $preview = $preview->cropCopy($cropX, $cropY, $width, $height); } else { - $preview->resize(max($width, $height)); + $preview = $maxPreview->resizeCopy(max($width, $height)); } @@ -448,7 +478,7 @@ class Generator { case 'image/gif': return 'gif'; default: - throw new \InvalidArgumentException('Not a valid mimetype'); + throw new \InvalidArgumentException('Not a valid mimetype: "' . $mimeType . '"'); } } } |