diff --git a/apps/files_sharing/ajax/publicpreview.php b/apps/files_sharing/ajax/publicpreview.php
index d12d212a2e64f089f68bccb13ee3da426bc93839..d8c892f1b7f952d2fae55e8e029475e8b4c50e7a 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 06e454b7d779d65c3045c495ace73a0350a7ec38..7c2834dc9c2b008f02fef4ea6c2e4876699fbac7 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/js/public.js b/apps/files_sharing/js/public.js
index ae2412f6a3b6fd027cfdc840efa8405705a5a717..0b4dec817643ae7f5d03732ba9365f4ad64c5047 100644
--- a/apps/files_sharing/js/public.js
+++ b/apps/files_sharing/js/public.js
@@ -12,10 +12,11 @@
 
 $(document).ready(function() {
 
+	var mimetype = $('#mimetype').val();
+
 	if (typeof FileActions !== 'undefined') {
-		var mimetype = $('#mimetype').val();
 		// Show file preview if previewer is available, images are already handled by the template
-		if (mimetype.substr(0, mimetype.indexOf('/')) != 'image' && $('.publicpreview').length === 0) {
+		if (mimetype.substr(0, mimetype.indexOf('/')) !== 'image' && $('.publicpreview').length === 0) {
 			// Trigger default action if not download TODO
 			var action = FileActions.getDefault(mimetype, 'file', OC.PERMISSION_READ);
 			if (typeof action !== 'undefined') {
@@ -24,57 +25,74 @@ $(document).ready(function() {
 		}
 	}
 
-	// override since the format is different
-	Files.getDownloadUrl = function(filename, dir) {
-		if ($.isArray(filename)) {
-			filename = JSON.stringify(filename);
-		}
-		var path = dir || FileList.getCurrentDirectory();
+	// dynamically load image previews
+	if (mimetype.substr(0, mimetype.indexOf('/')) === 'image' ) {
+
 		var params = {
-			service: 'files',
-			t: $('#sharingToken').val(),
-			path: path,
-			files: filename,
-			download: null
+			x: $(document).width() * window.devicePixelRatio,
+			a: 'true',
+			file: encodeURIComponent($('#dir').val() + $('#filename').val()),
+			t: $('#sharingToken').val()
 		};
-		return OC.filePath('', '', 'public.php') + '?' + OC.buildQueryString(params);
-	};
 
-	Files.getAjaxUrl = function(action, params) {
-		params = params || {};
-		params.t = $('#sharingToken').val();
-		return OC.filePath('files_sharing', 'ajax', action + '.php') + '?' + OC.buildQueryString(params);
-	};
+		var img = $('<img class="publicpreview">');
+		img.attr('src', OC.filePath('files_sharing', 'ajax', 'publicpreview.php') + '?' + OC.buildQueryString(params));
+		img.appendTo('#imgframe');
+	}
 
-	FileList.linkTo = function(dir) {
-		var params = {
-			service: 'files',
-			t: $('#sharingToken').val(),
-			dir: dir
+	// override since the format is different
+	if (typeof Files !== 'undefined') {
+		Files.getDownloadUrl = function(filename, dir) {
+			if ($.isArray(filename)) {
+				filename = JSON.stringify(filename);
+			}
+			var path = dir || FileList.getCurrentDirectory();
+			var params = {
+				service: 'files',
+				t: $('#sharingToken').val(),
+				path: path,
+				files: filename,
+				download: null
+			};
+			return OC.filePath('', '', 'public.php') + '?' + OC.buildQueryString(params);
 		};
-		return OC.filePath('', '', 'public.php') + '?' + OC.buildQueryString(params);
-	};
 
-	Files.generatePreviewUrl = function(urlSpec) {
-		urlSpec.t = $('#dirToken').val();
-		return OC.generateUrl('/apps/files_sharing/ajax/publicpreview.php?') + $.param(urlSpec);
-	};
+		Files.getAjaxUrl = function(action, params) {
+			params = params || {};
+			params.t = $('#sharingToken').val();
+			return OC.filePath('files_sharing', 'ajax', action + '.php') + '?' + OC.buildQueryString(params);
+		};
 
-	var file_upload_start = $('#file_upload_start');
-	file_upload_start.on('fileuploadadd', function(e, data) {
-		var fileDirectory = '';
-		if(typeof data.files[0].relativePath !== 'undefined') {
-			fileDirectory = data.files[0].relativePath;
-		}
+		FileList.linkTo = function(dir) {
+			var params = {
+				service: 'files',
+				t: $('#sharingToken').val(),
+				dir: dir
+			};
+			return OC.filePath('', '', 'public.php') + '?' + OC.buildQueryString(params);
+		};
 
-		// Add custom data to the upload handler
-		data.formData = {
-			requesttoken: $('#publicUploadRequestToken').val(),
-			dirToken: $('#dirToken').val(),
-			subdir: $('input#dir').val(),
-			file_directory: fileDirectory
+		Files.generatePreviewUrl = function(urlSpec) {
+			urlSpec.t = $('#dirToken').val();
+			return OC.generateUrl('/apps/files_sharing/ajax/publicpreview.php?') + $.param(urlSpec);
 		};
-	});
+
+		var file_upload_start = $('#file_upload_start');
+		file_upload_start.on('fileuploadadd', function(e, data) {
+			var fileDirectory = '';
+			if(typeof data.files[0].relativePath !== 'undefined') {
+				fileDirectory = data.files[0].relativePath;
+			}
+
+			// Add custom data to the upload handler
+			data.formData = {
+				requesttoken: $('#publicUploadRequestToken').val(),
+				dirToken: $('#dirToken').val(),
+				subdir: $('input#dir').val(),
+				file_directory: fileDirectory
+			};
+		});
+	}
 
 	$(document).on('click', '#directLink', function() {
 		$(this).focus();
diff --git a/apps/files_sharing/templates/public.php b/apps/files_sharing/templates/public.php
index f3c75134a5fa77f25d4ba07286003487b958a7ce..9471752b6b5d493bc9d2e58c0978a5d68353ee2b 100644
--- a/apps/files_sharing/templates/public.php
+++ b/apps/files_sharing/templates/public.php
@@ -30,7 +30,6 @@
 		<?php else: ?>
 			<?php if (substr($_['mimetype'], 0, strpos($_['mimetype'], '/')) == 'image'): ?>
 				<div id="imgframe">
-					<img src="<?php p($_['downloadURL']); ?>" 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 b1c3f02741edde288e37139dad7a59d9dba63969..42398a06c8b38c7c48f01b01a4c4c2cc98ab9aaa 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 8d2abaa89e5ed80cc8a5585e41394a6774d62f9b..80fe0e5d617e5921a970f9b66768f2c0c616d945 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 526719e8a1b067e0f15cf50b1b75f06c063d200a..d38043707ac7086c4673946223f58300c1aa5705 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 74be88061200befdd596a7d71e2ad1ae201197c1..5368fd45645dcc56e93b965c836b1437fd24efc9 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 cdf22240382363cff57443d3d5a3851e0a8599be..361073a09165ea3863c0ebbf88e160ebd9493634 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 84343df2608b1ad3129fceacaba84f081a0470ee..59aaa27ef3456f8006343b6806ab6aaca8c1a83f 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 3fc0ab0490cadfff428346b11fdaa58669cdb3f9..21f160fd50fe087971907d0252736b35d790a5b1 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 064a5a3b3d14b304184b46e1085ecb0aa114ff5d..4b88b1a31e29b78087ffc38c118d381765983332 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 88337d64e4bbdff1951cd88660b68f5d20fe6913..f769823f6e6359bdd57107ee4e46597adffa7cf4 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 505122fddbfb2eb837df110e83f47756fc8cfd6f..82ef3cdebf649c5b35cf95c741e1855f42949c00 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
+}