From 20893cc3b335049a144a53be24eaacb2e33a1480 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20M=C3=BCller?= <thomas.mueller@tmit.eu>
Date: Tue, 29 Apr 2014 17:07:10 +0200
Subject: [PATCH] Images on public sharing get downscaled to increase use
 experience - this will speed up loading time

- adding keep aspect to core/ajax/preview.php
- remove duplicate method Preview::show()
- no more hard coded mimetype of preview
- remove .png from the preview urls
- keep old route preview.png for backwards compatibility
- aspect preserving previews are now cached
---
 apps/files_sharing/ajax/publicpreview.php |  8 ++-
 apps/files_sharing/appinfo/routes.php     |  8 +--
 apps/files_sharing/templates/public.php   |  5 +-
 apps/files_trashbin/appinfo/routes.php    |  5 +-
 apps/files_versions/appinfo/routes.php    |  3 +-
 core/ajax/preview.php                     |  8 ++-
 core/routes.php                           |  2 +
 lib/private/preview.php                   | 60 ++++++++++++++++-------
 lib/private/preview/image.php             |  3 +-
 lib/private/preview/mp3.php               |  2 +-
 lib/private/preview/pdf.php               |  1 +
 lib/private/preview/provider.php          |  1 +
 lib/private/preview/svg.php               |  3 +-
 13 files changed, 77 insertions(+), 32 deletions(-)

diff --git a/apps/files_sharing/ajax/publicpreview.php b/apps/files_sharing/ajax/publicpreview.php
index d12d212a2e..d8c892f1b7 100644
--- a/apps/files_sharing/ajax/publicpreview.php
+++ b/apps/files_sharing/ajax/publicpreview.php
@@ -16,6 +16,7 @@ $maxX = array_key_exists('x', $_GET) ? (int) $_GET['x'] : '36';
 $maxY = array_key_exists('y', $_GET) ? (int) $_GET['y'] : '36';
 $scalingUp = array_key_exists('scalingup', $_GET) ? (bool) $_GET['scalingup'] : true;
 $token = array_key_exists('t', $_GET) ? (string) $_GET['t'] : '';
+$keepAspect = array_key_exists('a', $_GET) ? true : false;
 
 if($token === ''){
 	\OC_Response::setStatus(400); //400 Bad Request
@@ -70,6 +71,10 @@ if(substr($path, 0, 1) === '/') {
 	$path = substr($path, 1);
 }
 
+if ($keepAspect === true) {
+	$maxY = $maxX;
+}
+
 if($maxX === 0 || $maxY === 0) {
 	\OC_Response::setStatus(400); //400 Bad Request
 	\OC_Log::write('core-preview', 'x and/or y set to 0', \OC_Log::DEBUG);
@@ -84,8 +89,9 @@ try{
 	$preview->setMaxX($maxX);
 	$preview->setMaxY($maxY);
 	$preview->setScalingUp($scalingUp);
+	$preview->setKeepAspect($keepAspect);
 
-	$preview->show();
+	$preview->showPreview();
 } catch (\Exception $e) {
 	\OC_Response::setStatus(500);
 	\OC_Log::write('core', $e->getmessage(), \OC_Log::DEBUG);
diff --git a/apps/files_sharing/appinfo/routes.php b/apps/files_sharing/appinfo/routes.php
index 06e454b7d7..7c2834dc9c 100644
--- a/apps/files_sharing/appinfo/routes.php
+++ b/apps/files_sharing/appinfo/routes.php
@@ -1,9 +1,9 @@
 <?php
 /** @var $this \OCP\Route\IRouter */
-$this->create('core_ajax_public_preview', '/publicpreview.png')->action(
-function() {
-	require_once __DIR__ . '/../ajax/publicpreview.php';
-});
+$this->create('core_ajax_public_preview', '/publicpreview')->action(
+	function() {
+		require_once __DIR__ . '/../ajax/publicpreview.php';
+	});
 
 // OCS API
 
diff --git a/apps/files_sharing/templates/public.php b/apps/files_sharing/templates/public.php
index f3c75134a5..7614e122e8 100644
--- a/apps/files_sharing/templates/public.php
+++ b/apps/files_sharing/templates/public.php
@@ -30,7 +30,10 @@
 		<?php else: ?>
 			<?php if (substr($_['mimetype'], 0, strpos($_['mimetype'], '/')) == 'image'): ?>
 				<div id="imgframe">
-					<img src="<?php p($_['downloadURL']); ?>" alt="" />
+					<img
+						src="<?php p(OCP\Util::linkToRoute( 'core_ajax_public_preview', array('x' => 1000, 'y' => 1000, 'a' => 'true', 'file' => $_['directory_path'], 't' => $_['dirToken']))); ?>"
+						class="publicpreview"
+						alt=""/>
 				</div>
 			<?php elseif (substr($_['mimetype'], 0, strpos($_['mimetype'], '/')) == 'video'): ?>
 				<div id="imgframe">
diff --git a/apps/files_trashbin/appinfo/routes.php b/apps/files_trashbin/appinfo/routes.php
index b1c3f02741..42398a06c8 100644
--- a/apps/files_trashbin/appinfo/routes.php
+++ b/apps/files_trashbin/appinfo/routes.php
@@ -1,5 +1,6 @@
 <?php
-$this->create('core_ajax_trashbin_preview', '/preview.png')->action(
+/** @var $this \OCP\Route\IRouter */
+$this->create('core_ajax_trashbin_preview', '/preview')->action(
 function() {
 	require_once __DIR__ . '/../ajax/preview.php';
-});
\ No newline at end of file
+});
diff --git a/apps/files_versions/appinfo/routes.php b/apps/files_versions/appinfo/routes.php
index 8d2abaa89e..80fe0e5d61 100644
--- a/apps/files_versions/appinfo/routes.php
+++ b/apps/files_versions/appinfo/routes.php
@@ -8,7 +8,8 @@
 // Register with the capabilities API
 OC_API::register('get', '/cloud/capabilities', array('OCA\Files_Versions\Capabilities', 'getCapabilities'), 'files_versions', OC_API::USER_AUTH);
 
-$this->create('core_ajax_versions_preview', '/preview.png')->action(
+/** @var $this \OCP\Route\IRouter */
+$this->create('core_ajax_versions_preview', '/preview')->action(
 function() {
 	require_once __DIR__ . '/../ajax/preview.php';
 });
diff --git a/core/ajax/preview.php b/core/ajax/preview.php
index 526719e8a1..d38043707a 100644
--- a/core/ajax/preview.php
+++ b/core/ajax/preview.php
@@ -11,6 +11,7 @@ $file = array_key_exists('file', $_GET) ? (string)$_GET['file'] : '';
 $maxX = array_key_exists('x', $_GET) ? (int)$_GET['x'] : '36';
 $maxY = array_key_exists('y', $_GET) ? (int)$_GET['y'] : '36';
 $scalingUp = array_key_exists('scalingup', $_GET) ? (bool)$_GET['scalingup'] : true;
+$keepAspect = array_key_exists('a', $_GET) ? true : false;
 $always = array_key_exists('forceIcon', $_GET) ? (bool)$_GET['forceIcon'] : true;
 
 if ($file === '') {
@@ -20,6 +21,10 @@ if ($file === '') {
 	exit;
 }
 
+if ($keepAspect === true) {
+	$maxY = $maxX;
+}
+
 if ($maxX === 0 || $maxY === 0) {
 	//400 Bad Request
 	\OC_Response::setStatus(400);
@@ -36,9 +41,10 @@ try {
 		$preview->setMaxX($maxX);
 		$preview->setMaxY($maxY);
 		$preview->setScalingUp($scalingUp);
+		$preview->setKeepAspect($keepAspect);
 	}
 
-	$preview->show();
+	$preview->showPreview();
 } catch (\Exception $e) {
 	\OC_Response::setStatus(500);
 	\OC_Log::write('core', $e->getmessage(), \OC_Log::DEBUG);
diff --git a/core/routes.php b/core/routes.php
index 74be880612..5368fd4564 100644
--- a/core/routes.php
+++ b/core/routes.php
@@ -66,6 +66,8 @@ $this->create('core_tags_delete', '/tags/{type}/delete')
 $this->create('js_config', '/core/js/oc.js')
 	->actionInclude('core/js/config.php');
 // Routing
+$this->create('core_ajax_preview', '/core/preview')
+	->actionInclude('core/ajax/preview.php');
 $this->create('core_ajax_preview', '/core/preview.png')
 	->actionInclude('core/ajax/preview.php');
 $this->create('core_lostpassword_index', '/lostpassword/')
diff --git a/lib/private/preview.php b/lib/private/preview.php
index cdf2224038..361073a091 100755
--- a/lib/private/preview.php
+++ b/lib/private/preview.php
@@ -43,6 +43,7 @@ class Preview {
 	private $maxY;
 	private $scalingUp;
 	private $mimeType;
+	private $keepAspect = false;
 
 	//filemapper used for deleting previews
 	// index is path, value is fileinfo
@@ -267,6 +268,11 @@ class Preview {
 		return $this;
 	}
 
+	public function setKeepAspect($keepAspect) {
+		$this->keepAspect = $keepAspect;
+		return $this;
+	}
+
 	/**
 	 * @brief check if all parameters are valid
 	 * @return bool
@@ -297,7 +303,7 @@ class Preview {
 		if($fileInfo !== null && $fileInfo !== false) {
 			$fileId = $fileInfo->getId();
 
-			$previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/' . $this->getMaxX() . '-' . $this->getMaxY() . '.png';
+			$previewPath = $this->buildCachePath($fileId);
 			return $this->userView->unlink($previewPath);
 		}
 		return false;
@@ -330,15 +336,12 @@ class Preview {
 		if (is_null($fileId)) {
 			return false;
 		}
-		
-		$maxX = $this->getMaxX();
-		$maxY = $this->getMaxY();
 
-		$previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/';
+		$preview = $this->buildCachePath($fileId);
 
 		//does a preview with the wanted height and width already exist?
-		if ($this->userView->file_exists($previewPath . $maxX . '-' . $maxY . '.png')) {
-			return $previewPath . $maxX . '-' . $maxY . '.png';
+		if ($this->userView->file_exists($preview)) {
+			return $preview;
 		}
 
 		return $this->isCachedBigger($fileId);
@@ -355,6 +358,11 @@ class Preview {
 			return false;
 		}
 
+		// in order to not loose quality we better generate aspect preserving previews from the original file
+		if ($this->keepAspect) {
+			return false;
+		}
+
 		$maxX = $this->getMaxX();
 
 		//array for usable cached thumbnails
@@ -466,12 +474,12 @@ class Preview {
 		$fileId = $fileInfo->getId();
 
 		$cached = $this->isCached($fileId);
-
 		if ($cached) {
 			$stream = $this->userView->fopen($cached, 'r');
 			$image = new \OC_Image();
 			$image->loadFromFileHandle($stream);
 			$this->preview = $image->valid() ? $image : null;
+
 			$this->resizeAndCrop();
 			fclose($stream);
 		}
@@ -497,7 +505,7 @@ class Preview {
 				$this->resizeAndCrop();
 
 				$previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/';
-				$cachePath = $previewPath . $maxX . '-' . $maxY . '.png';
+				$cachePath = $this->buildCachePath($fileId);
 
 				if ($this->userView->is_dir($this->getThumbnailsFolder() . '/') === false) {
 					$this->userView->mkdir($this->getThumbnailsFolder() . '/');
@@ -524,20 +532,12 @@ class Preview {
 	 * @brief show preview
 	 * @return void
 	 */
-	public function showPreview() {
+	public function showPreview($mimeType = null) {
 		\OCP\Response::enableCaching(3600 * 24); // 24 hours
 		if (is_null($this->preview)) {
 			$this->getPreview();
 		}
-		$this->preview->show('image/png');
-	}
-
-	/**
-	 * @brief show preview
-	 * @return void
-	 */
-	public function show() {
-		$this->showPreview();
+		$this->preview->show($mimeType);
 	}
 
 	/**
@@ -561,6 +561,11 @@ class Preview {
 		$realX = (int)$image->width();
 		$realY = (int)$image->height();
 
+		// compute $maxY using the aspect of the generated preview
+		if ($this->keepAspect) {
+			$y = $x / ($realX / $realY);
+		}
+
 		if ($x === $realX && $y === $realY) {
 			$this->preview = $image;
 			return;
@@ -743,4 +748,21 @@ class Preview {
 		}
 		return false;
 	}
+
+	/**
+	 * @param $fileId
+	 * @return string
+	 */
+	private function buildCachePath($fileId) {
+		$maxX = $this->getMaxX();
+		$maxY = $this->getMaxY();
+
+		$previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/';
+		$preview = $previewPath . $maxX . '-' . $maxY . '.png';
+		if ($this->keepAspect) {
+			$preview = $previewPath . $maxX . '-with-aspect.png';
+			return $preview;
+		}
+		return $preview;
+	}
 }
diff --git a/lib/private/preview/image.php b/lib/private/preview/image.php
index 84343df260..59aaa27ef3 100644
--- a/lib/private/preview/image.php
+++ b/lib/private/preview/image.php
@@ -31,6 +31,7 @@ class Image extends Provider {
 
 		return $image->valid() ? $image : false;
 	}
+
 }
 
-\OC\Preview::registerProvider('OC\Preview\Image');
\ No newline at end of file
+\OC\Preview::registerProvider('OC\Preview\Image');
diff --git a/lib/private/preview/mp3.php b/lib/private/preview/mp3.php
index 3fc0ab0490..21f160fd50 100644
--- a/lib/private/preview/mp3.php
+++ b/lib/private/preview/mp3.php
@@ -47,4 +47,4 @@ class MP3 extends Provider {
 
 }
 
-\OC\Preview::registerProvider('OC\Preview\MP3');
\ No newline at end of file
+\OC\Preview::registerProvider('OC\Preview\MP3');
diff --git a/lib/private/preview/pdf.php b/lib/private/preview/pdf.php
index 064a5a3b3d..4b88b1a31e 100644
--- a/lib/private/preview/pdf.php
+++ b/lib/private/preview/pdf.php
@@ -40,6 +40,7 @@ if (extension_loaded('imagick')) {
 				//check if image object is valid
 				return $image->valid() ? $image : false;
 			}
+
 		}
 
 		\OC\Preview::registerProvider('OC\Preview\PDF');
diff --git a/lib/private/preview/provider.php b/lib/private/preview/provider.php
index 88337d64e4..f769823f6e 100644
--- a/lib/private/preview/provider.php
+++ b/lib/private/preview/provider.php
@@ -22,4 +22,5 @@ abstract class Provider {
 	 *		OC_Image object of the preview
 	 */
 	abstract public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview);
+
 }
diff --git a/lib/private/preview/svg.php b/lib/private/preview/svg.php
index 505122fddb..82ef3cdebf 100644
--- a/lib/private/preview/svg.php
+++ b/lib/private/preview/svg.php
@@ -45,8 +45,9 @@ if (extension_loaded('imagick')) {
 				//check if image object is valid
 				return $image->valid() ? $image : false;
 			}
+
 		}
 
 		\OC\Preview::registerProvider('OC\Preview\SVG');
 	}
-}
\ No newline at end of file
+}
-- 
GitLab