View Issue Details

IDProjectCategoryView StatusLast Update
369RackTablesdefaultpublic2019-01-08 11:55
Reporterf0urtyfiveAssigned Toinfrastation 
PrioritynormalSeverityfeatureReproducibilityN/A
Status closedResolutionfixed 
Product Version0.18.4 
Target Version0.19.0Fixed in Version0.19.0 
Summary369: Caching of thumbnails to reduce load time of large pictures
DescriptionI've implemented caching of thumbnails to decrease the load time for large pictures. I've also switched the thumbnail output format to img/jpeg as it was 1/5th the space with no noticable loss in quality for a thumbnail. Diff and SQL required to make it work will be attached.
TagsNo tags attached.

Activities

2010-09-18 23:40

 

FileCache.diff (5,238 bytes)
diff -rupN RackTables-0.18.4/inc/database.php RackTables-0.18.4-orig/inc/database.php
--- RackTables-0.18.4/inc/database.php	2010-09-18 19:35:58.000000000 -0400
+++ RackTables-0.18.4-orig/inc/database.php	2010-07-09 11:01:54.000000000 -0400
@@ -3071,49 +3071,6 @@ function getFile ($file_id = 0)
 	return $ret;
 }
 
-function getFileCache($file_id = 0)
-{
-        $query = usePreparedSelectBlade
-        (
-                'SELECT FileCache.contents FROM FileCache ' .
-		'JOIN File on (FileCache.id = File.id) ' . 
-                'WHERE FileCache.mtime = File.mtime and FileCache.id = ?',
-                array ($file_id)
-        );
-	if (($row = $query->fetch (PDO::FETCH_ASSOC)) == NULL)
-        {
-		$ret = false;
-	}
-	else
-	{
-		$ret = $row['contents'];
-		$query->CloseCursor();
-
-		usePreparedExecuteBlade ('UPDATE File SET atime = ? WHERE id = ?', array (date ('YmdHis'), $file_id));
-	}
-	return $ret;
-}
-
-function commitAddFileCache ($file_id, $file_mtime, $contents)
-{               
-        usePreparedExecuteBlade ('DELETE from FileCache where id = ?', array($file_id));
-       
-        global $dbxlink;
-        $query  = $dbxlink->prepare('INSERT INTO FileCache (id, mtime, contents) VALUES (?, ?, ?)');
-        $query->bindParam(1, $file_id);
-	$query->bindParam(2, $file_mtime);
-        $query->bindParam(3, $contents, PDO::PARAM_LOB);
-        try     
-        {
-                return $query->execute();
-        }
-        catch (PDOException $e)
-        {
-                throw convertPDOException ($e);
-        }
-}               
-	
-
 function getFileLinks ($file_id = 0)
 {
 	$query = usePreparedSelectBlade
@@ -3286,13 +3243,6 @@ function commitDeleteFile ($file_id)
 	return '';
 }
 
-function commitDeleteFileCache ($file_id)
-{
-        if (usePreparedDeleteBlade ('FileCache', array ('id' => $file_id)) === FALSE)
-                return __FUNCTION__ . '(): query failed';
-        return '';
-}
-
 function getChapterList ()
 {
 	$ret = array();
diff -rupN RackTables-0.18.4/inc/ophandlers.php RackTables-0.18.4-orig/inc/ophandlers.php
--- RackTables-0.18.4/inc/ophandlers.php	2010-09-18 19:35:26.000000000 -0400
+++ RackTables-0.18.4-orig/inc/ophandlers.php	2010-07-05 13:07:09.000000000 -0400
@@ -1926,11 +1926,6 @@ function deleteFile ()
 	if ($error != '')
 		return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
 
-	$error = commitDeleteFileCache ($_REQUEST['file_id']);
-
-        if ($error != '')
-                return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
-
 	return buildRedirectURL (__FUNCTION__, 'OK', array (htmlspecialchars ($shortInfo['name'])));
 }
 
diff -rupN RackTables-0.18.4/render_image.php RackTables-0.18.4-orig/render_image.php
--- RackTables-0.18.4/render_image.php	2010-09-18 19:22:42.000000000 -0400
+++ RackTables-0.18.4-orig/render_image.php	2010-06-24 09:42:17.000000000 -0400
@@ -1,5 +1,6 @@
 <?php
 
+
 ob_start();
 try {
 require 'inc/init.php';
@@ -197,37 +198,26 @@ function renderFilePreview ($file_id = 0
 		echo $file['contents'];
 		break;
 	case 'preview':
-		if(!($image = getFileCache($file_id))){
-			$file = getFile ($file_id);
-			$image = imagecreatefromstring ($file['contents']);
-			unset ($file['contents']);
-			$width = imagesx ($image);
-			$height = imagesy ($image);
-			if ($width > getConfigVar ('PREVIEW_IMAGE_MAXPXS') or $height > getConfigVar ('PREVIEW_IMAGE_MAXPXS'))
-			{
-				// TODO: cache thumbs for faster page generation
-				$ratio = getConfigVar ('PREVIEW_IMAGE_MAXPXS') / max ($width, $height);
-				$newwidth = $width * $ratio;
-				$newheight = $height * $ratio;
-				$resampled = imagecreatetruecolor ($newwidth, $newheight);
-				imagecopyresampled ($resampled, $image, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
-				imagedestroy ($image);
-				$image = $resampled;
-				
-				//TODO: Find a better way to save the stream of the image... Output buffer seems silly.
-				ob_start();
-				imagejpeg($image);
-				commitAddFileCache($file_id, $file['mtime'], ob_get_contents());
-				ob_flush();
-
-				imagedestroy ($image);
-				unset ($file);
-				unset ($resampled);
-			}
-			
+		$file = getFile ($file_id);
+		$image = imagecreatefromstring ($file['contents']);
+		unset ($file);
+		$width = imagesx ($image);
+		$height = imagesy ($image);
+		if ($width > getConfigVar ('PREVIEW_IMAGE_MAXPXS') or $height > getConfigVar ('PREVIEW_IMAGE_MAXPXS'))
+		{
+			// TODO: cache thumbs for faster page generation
+			$ratio = getConfigVar ('PREVIEW_IMAGE_MAXPXS') / max ($width, $height);
+			$newwidth = $width * $ratio;
+			$newheight = $height * $ratio;
+			$resampled = imagecreatetruecolor ($newwidth, $newheight);
+			imagecopyresampled ($resampled, $image, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
+			imagedestroy ($image);
+			$image = $resampled;
+			unset ($resampled);
 		}
-		header("Content-type: image/jpeg"); // don't announce content-length, it may have changed after resampling
-		if($image !== false) echo $image;
+		header("Content-type: image/png"); // don't announce content-length, it may have changed after resampling
+		imagepng ($image);
+		imagedestroy ($image);
 		break;
 	default:
 		showError ('Invalid argument', __FUNCTION__);
FileCache.diff (5,238 bytes)

2010-09-18 23:40

 

FileCache.sql (363 bytes)

2010-09-22 01:06

 

FileCache-v2.diff (4,949 bytes)
diff -ru RackTables-0.18.4-orig/inc/database.php rt-filecache-branch/inc/database.php
--- RackTables-0.18.4-orig/inc/database.php	2010-07-09 11:01:54.000000000 -0400
+++ rt-filecache-branch/inc/database.php	2010-09-21 20:42:38.000000000 -0400
@@ -3071,6 +3071,45 @@
 	return $ret;
 }
 
+function getFileCache($file_id = 0)
+{
+        $query = usePreparedSelectBlade
+        (
+                'SELECT File.thumbnail FROM File ' .
+                'WHERE File.id = ? and File.thumbnail IS NOT NULL',
+                array ($file_id)
+        );
+	if (($row = $query->fetch (PDO::FETCH_ASSOC)) == NULL)
+        {
+		$ret = false;
+	}
+	else
+	{
+		$ret = $row['contents'];
+		$query->CloseCursor();
+
+		usePreparedExecuteBlade ('UPDATE File SET atime = ? WHERE id = ?', array (date ('YmdHis'), $file_id));
+	}
+	return $ret;
+}
+
+function commitAddFileCache ($file_id, $file_mtime, $contents)
+{               
+        global $dbxlink;
+        $query  = $dbxlink->prepare('UPDATE File SET thumbnail = ? WHERE id = ?');
+        $query->bindParam(1, $contents, PDO::PARAM_LOB);
+	$query->bindParam(2, $file_id);
+        try     
+        {
+                return $query->execute();
+        }
+        catch (PDOException $e)
+        {
+                throw convertPDOException ($e);
+        }
+}               
+	
+
 function getFileLinks ($file_id = 0)
 {
 	$query = usePreparedSelectBlade
@@ -3243,6 +3282,21 @@
 	return '';
 }
 
+function commitDeleteFileCache ($file_id)
+{
+	global $dbxlink;
+        $query  = $dbxlink->prepare('UPDATE File SET thumbnail = NULL WHERE id = ?');
+        $query->bindParam(1, $file_id);
+        try
+        {
+                return $query->execute();
+        }
+        catch (PDOException $e)
+        {
+                throw convertPDOException ($e);
+        }
+}
+
 function getChapterList ()
 {
 	$ret = array();
diff -ru RackTables-0.18.4-orig/inc/ophandlers.php rt-filecache-branch/inc/ophandlers.php
--- RackTables-0.18.4-orig/inc/ophandlers.php	2010-07-05 13:07:09.000000000 -0400
+++ rt-filecache-branch/inc/ophandlers.php	2010-09-21 20:43:14.000000000 -0400
@@ -1885,6 +1885,8 @@
 	if (FALSE === commitReplaceFile ($sic['file_id'], $fp))
 		return buildRedirectURL (__FUNCTION__, 'ERR3');
 
+	commitDeleteFileCache ($sic['file_id']);
+
 	return buildRedirectURL (__FUNCTION__, 'OK', array (htmlspecialchars ($shortInfo['name'])));
 }
 
diff -ru RackTables-0.18.4-orig/render_image.php rt-filecache-branch/render_image.php
--- RackTables-0.18.4-orig/render_image.php	2010-06-24 09:42:17.000000000 -0400
+++ rt-filecache-branch/render_image.php	2010-09-18 19:22:42.000000000 -0400
@@ -1,6 +1,5 @@
 <?php
 
-
 ob_start();
 try {
 require 'inc/init.php';
@@ -198,26 +197,37 @@
 		echo $file['contents'];
 		break;
 	case 'preview':
-		$file = getFile ($file_id);
-		$image = imagecreatefromstring ($file['contents']);
-		unset ($file);
-		$width = imagesx ($image);
-		$height = imagesy ($image);
-		if ($width > getConfigVar ('PREVIEW_IMAGE_MAXPXS') or $height > getConfigVar ('PREVIEW_IMAGE_MAXPXS'))
-		{
-			// TODO: cache thumbs for faster page generation
-			$ratio = getConfigVar ('PREVIEW_IMAGE_MAXPXS') / max ($width, $height);
-			$newwidth = $width * $ratio;
-			$newheight = $height * $ratio;
-			$resampled = imagecreatetruecolor ($newwidth, $newheight);
-			imagecopyresampled ($resampled, $image, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
-			imagedestroy ($image);
-			$image = $resampled;
-			unset ($resampled);
+		if(!($image = getFileCache($file_id))){
+			$file = getFile ($file_id);
+			$image = imagecreatefromstring ($file['contents']);
+			unset ($file['contents']);
+			$width = imagesx ($image);
+			$height = imagesy ($image);
+			if ($width > getConfigVar ('PREVIEW_IMAGE_MAXPXS') or $height > getConfigVar ('PREVIEW_IMAGE_MAXPXS'))
+			{
+				// TODO: cache thumbs for faster page generation
+				$ratio = getConfigVar ('PREVIEW_IMAGE_MAXPXS') / max ($width, $height);
+				$newwidth = $width * $ratio;
+				$newheight = $height * $ratio;
+				$resampled = imagecreatetruecolor ($newwidth, $newheight);
+				imagecopyresampled ($resampled, $image, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
+				imagedestroy ($image);
+				$image = $resampled;
+				
+				//TODO: Find a better way to save the stream of the image... Output buffer seems silly.
+				ob_start();
+				imagejpeg($image);
+				commitAddFileCache($file_id, $file['mtime'], ob_get_contents());
+				ob_flush();
+
+				imagedestroy ($image);
+				unset ($file);
+				unset ($resampled);
+			}
+			
 		}
-		header("Content-type: image/png"); // don't announce content-length, it may have changed after resampling
-		imagepng ($image);
-		imagedestroy ($image);
+		header("Content-type: image/jpeg"); // don't announce content-length, it may have changed after resampling
+		if($image !== false) echo $image;
 		break;
 	default:
 		showError ('Invalid argument', __FUNCTION__);
FileCache-v2.diff (4,949 bytes)

2010-09-22 01:06

 

FileCache-v2.sql (68 bytes)
f0urtyfive

f0urtyfive

2010-09-22 01:07

reporter   ~0000134

Per Denis Ovsienko's suggestion I've added an alternate version (marked v2) that inserts the thumbnails into a column of the file table.
infrastation

infrastation

2010-10-28 20:55

administrator   ~0000167

Committed to trunk with some minor justifications. Having reviewed this, I see, that the old (rack) thumbnail management also needs a cleanup. This code will be seen in 0.19 series (because it involves a schema change). Thank you.
infrastation

infrastation

2010-11-21 13:39

administrator   ~0000189

Could you review this?

[Sun Nov 21 15:14:05 2010] [error] [client 127.0.0.1] PHP Warning: strtotime(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Europe/Moscow' for 'MSK/3.0/no DST' instead in /var/www/html/racktables/render_image.php on line 9, referer: http://localhost/racktables/index.php?page=rack&tab=default&rack_id=48

[Sun Nov 21 15:14:14 2010] [error] [client 127.0.0.1] PHP Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Europe/Moscow' for 'MSK/3.0/no DST' instead in /var/www/html/racktables/render_image.php on line 43, referer: http://localhost/racktables/index.php?page=object&object_id=906
f0urtyfive

f0urtyfive

2011-01-07 19:40

reporter   ~0000214

According to php.net it looks like this is a new feature in PHP 5.1.0 to deal with invalid local timezones (or invalid in PHP's eyes at least), try adding this code somewhere in the init of the script:

if(date_default_timezone_set(ini_get('date.timezone') === FALSE)
    date_default_timezone_set('UTC');
f0urtyfive

f0urtyfive

2011-01-08 17:30

reporter   ~0000217

I was able to reproduce in a test environment and it looks like the issue is caused by PHP's use of non-standard timezone naming (see http://nl3.php.net/manual/en/timezones.php)

Setting this line in php.ini on the host got rid of the errors.
date.timezone = Europe/Moscow

I'd say there are three options; tell the user to set the timezone in php.ini if they see these errors, stick the silence operator (@) in front of all the functions that are generating it as it still seems to get the right TZ (however I imagine there are cases where this could cause problems, like if the user has a totally nonsensical timezone configured), or prompt for a timezone at Install and store it as a config variable (would not be very difficult, just a select box with DateTimeZone::listIdentifiers which is built into PHP).
infrastation

infrastation

2011-01-11 11:21

administrator   ~0000219

A fix is committed.

Related Changesets

RackTables: master b6993903

2011-01-11 11:20:12

infrastation

Details Diff
r4093 Finalise the work on issue 369 by means of new function HTTPDateToUnixTime(),
which is supposed to do a better job, than strtotime() did (by Matt Mills).
Affected Issues
369
mod - render_image.php Diff File

Issue History

Date Modified Username Field Change
2010-09-18 23:40 f0urtyfive New Issue
2010-09-18 23:40 f0urtyfive File Added: FileCache.diff
2010-09-18 23:40 f0urtyfive File Added: FileCache.sql
2010-09-22 01:06 f0urtyfive File Added: FileCache-v2.diff
2010-09-22 01:06 f0urtyfive File Added: FileCache-v2.sql
2010-09-22 01:07 f0urtyfive Note Added: 0000134
2010-10-09 11:09 infrastation Status new => assigned
2010-10-09 11:09 infrastation Assigned To => infrastation
2010-10-28 20:55 infrastation Note Added: 0000167
2010-10-28 20:55 infrastation Status assigned => resolved
2010-10-28 20:55 infrastation Resolution open => fixed
2010-10-28 20:55 infrastation Fixed in Version => 0.19.0
2010-10-28 20:55 infrastation Target Version => 0.19.0
2010-11-21 13:39 infrastation Note Added: 0000189
2010-11-21 13:39 infrastation Status resolved => feedback
2010-11-21 13:39 infrastation Resolution fixed => reopened
2011-01-07 19:40 f0urtyfive Note Added: 0000214
2011-01-08 17:30 f0urtyfive Note Added: 0000217
2011-01-11 11:21 infrastation Note Added: 0000219
2011-01-11 11:21 infrastation Status feedback => closed
2011-01-11 11:21 infrastation Resolution reopened => fixed
2019-01-08 11:55 infrastation Changeset attached => RackTables master b6993903