Permalink
Browse files

Moved tile generator into plugin, added locking + nice support

Ignore-this: ab6e857c5a370af6cf8172b9040ef582

All functions are now inside the plugin class to avoid any future nameclashes.

The tile generator now locks itself so only one is run at a time. This slows
down the tiling process but lowers the memory and CPU impact a lot.

When using imagemagick, you now can also specify the path to the nice binary
to lower the priority of tiling process.

darcs-hash:20090609191538-7ad00-1ae8a94ea093ba34ae12a2e200a18dca99db3dcb.gz
  • Loading branch information...
1 parent c131b32 commit 1faa1ff036ef1d08d80723e22dca8ede944761c0 @splitbrain committed Jun 9, 2009
Showing with 144 additions and 82 deletions.
  1. +2 −0 conf/default.php
  2. +3 −0 conf/metadata.php
  3. +3 −0 lang/en/settings.php
  4. +125 −0 syntax.php
  5. +11 −82 tiles.php
View
@@ -0,0 +1,2 @@
+<?php
+$conf['nice'] = '/usr/bin/nice';
View
@@ -0,0 +1,3 @@
+<?php
+$meta['nice'] = array('string');
+
View
@@ -0,0 +1,3 @@
+<?php
+
+$lang['nice'] = 'Path to the "nice" binary. It will be used in conjunction with ImageMagick\'s "convert" tool to lower the CPU load during tile generation';
View
@@ -131,6 +131,131 @@ function render($mode, &$R, $data) {
return true;
}
+ // ----------- Tile Generator below ---------------
+
+ /**
+ * Create a tile using libGD
+ */
+ function tile_gd($d){
+ global $conf;
+
+ $img = null;
+ if(preg_match('/\.jpe?g$/',$d['file'])){
+ $img = @imagecreatefromjpeg($d['file']);
+ }elseif(preg_match('/\.png$/',$d['file'])){
+ $img = @imagecreatefrompng($d['file']);
+ }elseif(preg_match('/\.gif$/',$d['file'])){
+ $img = @imagecreatefromgif($d['file']);
+ }
+ if(!$img) $this->gfx_error('generic');
+
+ $crop = $this->image_crop($img,$d['width'],$d['height'],$d['tlx'],$d['tly'],$d['brx'],$d['bry']);
+ imagedestroy($img);
+
+ $scale = $this->image_scale($crop,abs($d['brx'] - $d['tlx']),abs($d['bry'] - $d['tly']),$d['ts'],$d['ts']);
+ imagedestroy($crop);
+
+ imagejpeg($scale,$d['cache'],$conf['jpg_quality']);
+ imagedestroy($scale);
+
+ if($conf['fperm']) chmod($d['cache'], $conf['fperm']);
+ }
+
+ /**
+ * Create a tile using Image Magick
+ */
+ function tile_im($d){
+ global $conf;
+
+ $cmd = $this->getConf('nice');
+ $cmd .= ' '.$conf['im_convert'];
+ $cmd .= ' '.escapeshellarg($d['file']);
+ $cmd .= ' -crop \''.abs($d['brx'] - $d['tlx']).'x'.abs($d['bry'] - $d['tly']).'!+'.$d['tlx'].'+'.$d['tly'].'\'';
+ $cmd .= ' -background black';
+ $cmd .= ' -extent \''.abs($d['brx'] - $d['tlx']).'x'.abs($d['bry'] - $d['tly']).'!\'';
+ $cmd .= ' -resize \''.$d['ts'].'x'.$d['ts'].'!\'';
+
+ $cmd .= ' -quality '.$conf['jpg_quality'];
+ $cmd .= ' '.escapeshellarg($d['cache']);
+
+ # dbg($cmd); exit;
+
+ @exec($cmd,$out,$retval);
+ if ($retval == 0) return true;
+ $this->gfx_error('generic');
+ }
+
+ /**
+ * Scale an image with libGD
+ */
+ function image_scale($image,$x,$y,$w,$h){
+ $scale=imagecreatetruecolor($w,$h);
+ imagecopyresampled($scale,$image,0,0,0,0,$w,$h,$x,$y);
+ return $scale;
+ }
+
+ /**
+ * Crop an image with libGD
+ */
+ function image_crop($image,$x,$y,$left,$upper,$right,$lower) {
+ $w=abs($right-$left);
+ $h=abs($lower-$upper);
+ $crop = imagecreatetruecolor($w,$h);
+ imagecopy($crop,$image,0,0,$left,$upper,$w,$h);
+ return $crop;
+ }
+
+ /**
+ * Send a graphical error message and stop script
+ */
+ function gfx_error($type){
+ $file = dirname(__FILE__).'/gfx/'.$type.'.gif';
+ $time = filemtime($file);
+ header('Content-type: image/gif');
+
+ http_conditionalRequest($time);
+ http_sendfile($file);
+ readfile($file);
+ exit;
+ }
+
+ /**
+ * Acquire a lock for the tile generator
+ */
+ function tile_lock($d){
+ global $conf;
+
+ $lockDir = $conf['lockdir'].'/'.md5($d['id']).'.panoview';
+ @ignore_user_abort(1);
+
+ $timeStart = time();
+ do {
+ //waited longer than 25 seconds? -> stale lock?
+ if ((time() - $timeStart) > 25){
+ if(time() - filemtime($lockDir) > 30) $this->tile_unlock($d);
+ send_redirect(DOKU_URL.'lib/plugins/panaoview/tiles.php?tile='.$d['zoom'].'-'.$d['col'].'-'.$d['row'].'&image='.rawurlencode($d['id']));
+ exit;
+ }
+ $locked = @mkdir($lockDir, $conf['dmode']);
+ if($locked){
+ if(!empty($conf['dperm'])) chmod($lockDir, $conf['dperm']);
+ break;
+ }
+ usleep(rand(500,3000));
+ } while ($locked === false);
+ }
+
+ /**
+ * Unlock the tile generator
+ */
+ function tile_unlock($d){
+ global $conf;
+
+ $lockDir = $conf['lockdir'].'/'.md5($d['id']).'.panoview';
+ @rmdir($lockDir);
+ @ignore_user_abort(0);
+ }
+
}
View
@@ -10,9 +10,13 @@
require_once(DOKU_INC.'inc/common.php');
require_once(DOKU_INC.'inc/pageutils.php');
require_once(DOKU_INC.'inc/httputils.php');
+require_once(DOKU_INC.'inc/pluginutils.php');
require_once(DOKU_INC.'inc/auth.php');
session_write_close();
+ // load plugin
+ $pl =& plugin_load('syntax','panoview');
+
$data = array();
// get parameters
list($data['zoom'],$data['col'],$data['row']) = explode('-',$_GET['tile']);
@@ -22,34 +26,36 @@
// check auth and existance
if(auth_quickaclcheck(getNS($data['id']).':X') < AUTH_READ) gfx_error('noauth');
- if(!$data['mtime']) gfx_error('notfound');
+ if(!$data['mtime']) $pl->gfx_error('notfound');
// calculate zoom level scaling
$data['ts'] = 256;
list($data['width'],$data['height']) = getimagesize($data['file']);
$data['scale'] = (int)pow(2,$data['zoom']);
$data['max'] = max($data['width'],$data['height']);
$data['inv'] = $data['max'] / ($data['ts'] * $data['scale']);
- if($data['inv'] < 1.0) gfx_error('maxzoom');
+ if($data['inv'] < 1.0) $pl->gfx_error('maxzoom');
// calculate tile boundaries
$data['tlx'] = (int) ($data['col'] * $data['ts'] * $data['inv']);
$data['tly'] = (int) ($data['row'] * $data['ts'] * $data['inv']);
$data['brx'] = (int) ($data['tlx'] + ($data['ts'] * $data['inv']));
$data['bry'] = (int) ($data['tly'] + ($data['ts'] * $data['inv']));
- if($data['tlx'] > $data['width'] || $data['tly'] > $data['height']) gfx_error('blank');
+ if($data['tlx'] > $data['width'] || $data['tly'] > $data['height']) $pl->gfx_error('blank');
// cache times
$data['cache'] = getCacheName($data['file'],'.pv.'.$data['zoom'].'-'.$data['col'].'-'.$data['row'].'.jpg');
$data['cachet'] = @filemtime($data['cache']);
// (re)generate
if($data['cachet'] < $data['mtime']){
+ $pl->tile_lock($data);
if($conf['im_convert']){
- tile_im($data);
+ $pl->tile_im($data);
}else{
- tile_gd($data);
+ $pl->tile_gd($data);
}
+ $pl->tile_unlock($data);
}
// send
@@ -59,81 +65,4 @@
readfile($data['cache']);
-
-
-/* --------------- functions -------------------- */
-
-
-function tile_gd($d){
- global $conf;
-
- $img = null;
- if(preg_match('/\.jpe?g$/',$d['file'])){
- $img = @imagecreatefromjpeg($d['file']);
- }elseif(preg_match('/\.png$/',$d['file'])){
- $img = @imagecreatefrompng($d['file']);
- }elseif(preg_match('/\.gif$/',$d['file'])){
- $img = @imagecreatefromgif($d['file']);
- }
- if(!$img) gfx_error('generic');
-
- $crop = image_crop($img,$d['width'],$d['height'],$d['tlx'],$d['tly'],$d['brx'],$d['bry']);
- imagedestroy($img);
-
- $scale = image_scale($crop,abs($d['brx'] - $d['tlx']),abs($d['bry'] - $d['tly']),$d['ts'],$d['ts']);
- imagedestroy($crop);
-
- imagejpeg($scale,$d['cache'],$conf['jpg_quality']);
- imagedestroy($scale);
-
- if($conf['fperm']) chmod($d['cache'], $conf['fperm']);
-}
-
-function tile_im($d){
- global $conf;
-
- $cmd = $conf['im_convert'];
- $cmd .= ' '.escapeshellarg($d['file']);
- $cmd .= ' -crop \''.abs($d['brx'] - $d['tlx']).'x'.abs($d['bry'] - $d['tly']).'!+'.$d['tlx'].'+'.$d['tly'].'\'';
- $cmd .= ' -background black';
- $cmd .= ' -extent \''.abs($d['brx'] - $d['tlx']).'x'.abs($d['bry'] - $d['tly']).'!\'';
- $cmd .= ' -resize \''.$d['ts'].'x'.$d['ts'].'!\'';
-
- $cmd .= ' -quality '.$conf['jpg_quality'];
- $cmd .= ' '.escapeshellarg($d['cache']);
-
-# dbg($cmd); exit;
-
- @exec($cmd,$out,$retval);
- if ($retval == 0) return true;
- gfx_error('generic');
-}
-
-
-
-function image_scale($image,$x,$y,$w,$h){
- $scale=imagecreatetruecolor($w,$h);
- imagecopyresampled($scale,$image,0,0,0,0,$w,$h,$x,$y);
- return $scale;
-}
-
-function image_crop($image,$x,$y,$left,$upper,$right,$lower) {
- $w=abs($right-$left);
- $h=abs($lower-$upper);
- $crop = imagecreatetruecolor($w,$h);
- imagecopy($crop,$image,0,0,$left,$upper,$w,$h);
- return $crop;
-}
-
-function gfx_error($type){
- $file = dirname(__FILE__).'/gfx/'.$type.'.gif';
- $time = filemtime($file);
- header('Content-type: image/gif');
-
- http_conditionalRequest($time);
- http_sendfile($file);
- readfile($file);
- exit;
-}
-
//Setup VIM: ex: et ts=4 enc=utf-8 :

0 comments on commit 1faa1ff

Please sign in to comment.