127bbde00SAndreas Gohr<?php 227bbde00SAndreas Gohr/** 327bbde00SAndreas Gohr * Embed an image gallery 427bbde00SAndreas Gohr * 527bbde00SAndreas Gohr * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 627bbde00SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 727bbde00SAndreas Gohr */ 827bbde00SAndreas Gohr 927bbde00SAndreas Gohrif(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); 1027bbde00SAndreas Gohrif(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 1127bbde00SAndreas Gohrrequire_once(DOKU_PLUGIN.'syntax.php'); 1227bbde00SAndreas Gohrrequire_once(DOKU_INC.'inc/search.php'); 1327bbde00SAndreas Gohrrequire_once(DOKU_INC.'inc/JpegMeta.php'); 1427bbde00SAndreas Gohr 1527bbde00SAndreas Gohrclass syntax_plugin_panoview extends DokuWiki_Syntax_Plugin { 1627bbde00SAndreas Gohr /** 1727bbde00SAndreas Gohr * return some info 1827bbde00SAndreas Gohr */ 1927bbde00SAndreas Gohr function getInfo(){ 2027bbde00SAndreas Gohr return confToHash(dirname(__FILE__).'/info.txt'); 2127bbde00SAndreas Gohr } 2227bbde00SAndreas Gohr 2327bbde00SAndreas Gohr /** 2427bbde00SAndreas Gohr * What kind of syntax are we? 2527bbde00SAndreas Gohr */ 2627bbde00SAndreas Gohr function getType(){ 2727bbde00SAndreas Gohr return 'substition'; 2827bbde00SAndreas Gohr } 2927bbde00SAndreas Gohr 3027bbde00SAndreas Gohr /** 3127bbde00SAndreas Gohr * What about paragraphs? 3227bbde00SAndreas Gohr */ 3327bbde00SAndreas Gohr function getPType(){ 3427bbde00SAndreas Gohr return 'block'; 3527bbde00SAndreas Gohr } 3627bbde00SAndreas Gohr 3727bbde00SAndreas Gohr /** 3827bbde00SAndreas Gohr * Where to sort in? 3927bbde00SAndreas Gohr */ 4027bbde00SAndreas Gohr function getSort(){ 4127bbde00SAndreas Gohr return 301; 4227bbde00SAndreas Gohr } 4327bbde00SAndreas Gohr 4427bbde00SAndreas Gohr 4527bbde00SAndreas Gohr /** 4627bbde00SAndreas Gohr * Connect pattern to lexer 4727bbde00SAndreas Gohr */ 4827bbde00SAndreas Gohr function connectTo($mode) { 4927bbde00SAndreas Gohr $this->Lexer->addSpecialPattern('\{\{panoview>[^}]*\}\}',$mode,'plugin_panoview'); 5027bbde00SAndreas Gohr } 5127bbde00SAndreas Gohr 5227bbde00SAndreas Gohr /** 5327bbde00SAndreas Gohr * Handle the match 5427bbde00SAndreas Gohr */ 5527bbde00SAndreas Gohr function handle($match, $state, $pos, &$handler){ 5627bbde00SAndreas Gohr global $ID; 5727bbde00SAndreas Gohr 581a675665SAndreas Gohr $data = array( 5927bbde00SAndreas Gohr 'width' => 500, 6027bbde00SAndreas Gohr 'height' => 250, 611a675665SAndreas Gohr 'align' => 0, 6227bbde00SAndreas Gohr 'initialZoom' => 2, 6327bbde00SAndreas Gohr 'tileBaseUri' => DOKU_BASE.'lib/plugins/panoview/tiles.php', 6427bbde00SAndreas Gohr 'tileSize' => 256, 6527bbde00SAndreas Gohr 'maxZoom' => 10, 6627bbde00SAndreas Gohr 'blankTile' => DOKU_BASE.'lib/plugins/panoview/gfx/blank.gif', 6727bbde00SAndreas Gohr 'loadingTile' => DOKU_BASE.'lib/plugins/panoview/gfx/progress.gif', 6827bbde00SAndreas Gohr ); 6927bbde00SAndreas Gohr 701a675665SAndreas Gohr $match = substr($match,11,-2); //strip markup from start and end 7127bbde00SAndreas Gohr 721a675665SAndreas Gohr // alignment 731a675665SAndreas Gohr $data['align'] = 0; 741a675665SAndreas Gohr if(substr($match,0,1) == ' ') $data['align'] += 1; 751a675665SAndreas Gohr if(substr($match,-1,1) == ' ') $data['align'] += 2; 761a675665SAndreas Gohr 771a675665SAndreas Gohr // extract params 781a675665SAndreas Gohr list($img,$params) = explode('?',$match,2); 791a675665SAndreas Gohr $img = trim($img); 801a675665SAndreas Gohr 811a675665SAndreas Gohr // resolving relatives 821a675665SAndreas Gohr $data['image'] = resolve_id(getNS($ID),$img); 831a675665SAndreas Gohr 841a675665SAndreas Gohr $file = mediaFN($data['image']); 851a675665SAndreas Gohr list($data['imageWidth'],$data['imageHeight']) = @getimagesize($file); 861a675665SAndreas Gohr 871a675665SAndreas Gohr // size 881a675665SAndreas Gohr if(preg_match('/^(\d+)[xX](\d+)$/',$params,$match)){ 891a675665SAndreas Gohr $data['width'] = $match[1]; 901a675665SAndreas Gohr $data['height'] = $match[2]; 911a675665SAndreas Gohr } 921a675665SAndreas Gohr 931a675665SAndreas Gohr return $data; 9427bbde00SAndreas Gohr } 9527bbde00SAndreas Gohr 9627bbde00SAndreas Gohr /** 9727bbde00SAndreas Gohr * Create output 9827bbde00SAndreas Gohr */ 9927bbde00SAndreas Gohr function render($mode, &$R, $data) { 10027bbde00SAndreas Gohr if($mode != 'xhtml') return false; 10127bbde00SAndreas Gohr 10227bbde00SAndreas Gohr require_once(DOKU_INC.'inc/JSON.php'); 10327bbde00SAndreas Gohr $json = new JSON(); 10427bbde00SAndreas Gohr 1051a675665SAndreas Gohr $img = '<a href="'.ml($data['image']).'"><img src="'. 1061a675665SAndreas Gohr ml($data['image'], array('w'=>$data['width'],'h'=>$data['height'])).'" width="'. 1071a675665SAndreas Gohr $data['width'].'" height="'.$data['height'].'" alt="" /></a>'; 10827bbde00SAndreas Gohr 1091613315fSAndreas Gohr if($data['align'] == 1){ 1101613315fSAndreas Gohr $align = 'medialeft'; 1111613315fSAndreas Gohr }elseif($data['align'] == 2){ 1121613315fSAndreas Gohr $align = 'mediaright'; 1131613315fSAndreas Gohr }else{ 1141613315fSAndreas Gohr $align = 'mediacenter'; 1151613315fSAndreas Gohr } 1161613315fSAndreas Gohr 11727bbde00SAndreas Gohr 11827bbde00SAndreas Gohr $R->doc .= ' 1191613315fSAndreas Gohr <div class="panoview_plugin '.$align.'" style="width: '.$data['width'].'px; height: '.$data['height'].'px;"> 1209d7db126SAndreas Gohr <div class="well"><!-- --></div> 1219d7db126SAndreas Gohr <div class="surface">'.$img.'</div> 12227bbde00SAndreas Gohr <p class="controls" style="display: none"> 12327bbde00SAndreas Gohr <span class="zoomIn" title="Zoom In">+</span> 12427bbde00SAndreas Gohr <span class="zoomOut" title="Zoom Out">-</span> 12527bbde00SAndreas Gohr </p> 12627bbde00SAndreas Gohr <div class="options" style="display:none">'.hsc($json->encode($data)).'</div> 12727bbde00SAndreas Gohr </div> 12827bbde00SAndreas Gohr '; 12927bbde00SAndreas Gohr 13027bbde00SAndreas Gohr 13127bbde00SAndreas Gohr return true; 13227bbde00SAndreas Gohr } 13327bbde00SAndreas Gohr 134*1faa1ff0SAndreas Gohr // ----------- Tile Generator below --------------- 135*1faa1ff0SAndreas Gohr 136*1faa1ff0SAndreas Gohr /** 137*1faa1ff0SAndreas Gohr * Create a tile using libGD 138*1faa1ff0SAndreas Gohr */ 139*1faa1ff0SAndreas Gohr function tile_gd($d){ 140*1faa1ff0SAndreas Gohr global $conf; 141*1faa1ff0SAndreas Gohr 142*1faa1ff0SAndreas Gohr $img = null; 143*1faa1ff0SAndreas Gohr if(preg_match('/\.jpe?g$/',$d['file'])){ 144*1faa1ff0SAndreas Gohr $img = @imagecreatefromjpeg($d['file']); 145*1faa1ff0SAndreas Gohr }elseif(preg_match('/\.png$/',$d['file'])){ 146*1faa1ff0SAndreas Gohr $img = @imagecreatefrompng($d['file']); 147*1faa1ff0SAndreas Gohr }elseif(preg_match('/\.gif$/',$d['file'])){ 148*1faa1ff0SAndreas Gohr $img = @imagecreatefromgif($d['file']); 149*1faa1ff0SAndreas Gohr } 150*1faa1ff0SAndreas Gohr if(!$img) $this->gfx_error('generic'); 151*1faa1ff0SAndreas Gohr 152*1faa1ff0SAndreas Gohr $crop = $this->image_crop($img,$d['width'],$d['height'],$d['tlx'],$d['tly'],$d['brx'],$d['bry']); 153*1faa1ff0SAndreas Gohr imagedestroy($img); 154*1faa1ff0SAndreas Gohr 155*1faa1ff0SAndreas Gohr $scale = $this->image_scale($crop,abs($d['brx'] - $d['tlx']),abs($d['bry'] - $d['tly']),$d['ts'],$d['ts']); 156*1faa1ff0SAndreas Gohr imagedestroy($crop); 157*1faa1ff0SAndreas Gohr 158*1faa1ff0SAndreas Gohr imagejpeg($scale,$d['cache'],$conf['jpg_quality']); 159*1faa1ff0SAndreas Gohr imagedestroy($scale); 160*1faa1ff0SAndreas Gohr 161*1faa1ff0SAndreas Gohr if($conf['fperm']) chmod($d['cache'], $conf['fperm']); 162*1faa1ff0SAndreas Gohr } 163*1faa1ff0SAndreas Gohr 164*1faa1ff0SAndreas Gohr /** 165*1faa1ff0SAndreas Gohr * Create a tile using Image Magick 166*1faa1ff0SAndreas Gohr */ 167*1faa1ff0SAndreas Gohr function tile_im($d){ 168*1faa1ff0SAndreas Gohr global $conf; 169*1faa1ff0SAndreas Gohr 170*1faa1ff0SAndreas Gohr $cmd = $this->getConf('nice'); 171*1faa1ff0SAndreas Gohr $cmd .= ' '.$conf['im_convert']; 172*1faa1ff0SAndreas Gohr $cmd .= ' '.escapeshellarg($d['file']); 173*1faa1ff0SAndreas Gohr $cmd .= ' -crop \''.abs($d['brx'] - $d['tlx']).'x'.abs($d['bry'] - $d['tly']).'!+'.$d['tlx'].'+'.$d['tly'].'\''; 174*1faa1ff0SAndreas Gohr $cmd .= ' -background black'; 175*1faa1ff0SAndreas Gohr $cmd .= ' -extent \''.abs($d['brx'] - $d['tlx']).'x'.abs($d['bry'] - $d['tly']).'!\''; 176*1faa1ff0SAndreas Gohr $cmd .= ' -resize \''.$d['ts'].'x'.$d['ts'].'!\''; 177*1faa1ff0SAndreas Gohr 178*1faa1ff0SAndreas Gohr $cmd .= ' -quality '.$conf['jpg_quality']; 179*1faa1ff0SAndreas Gohr $cmd .= ' '.escapeshellarg($d['cache']); 180*1faa1ff0SAndreas Gohr 181*1faa1ff0SAndreas Gohr # dbg($cmd); exit; 182*1faa1ff0SAndreas Gohr 183*1faa1ff0SAndreas Gohr @exec($cmd,$out,$retval); 184*1faa1ff0SAndreas Gohr if ($retval == 0) return true; 185*1faa1ff0SAndreas Gohr $this->gfx_error('generic'); 186*1faa1ff0SAndreas Gohr } 187*1faa1ff0SAndreas Gohr 188*1faa1ff0SAndreas Gohr /** 189*1faa1ff0SAndreas Gohr * Scale an image with libGD 190*1faa1ff0SAndreas Gohr */ 191*1faa1ff0SAndreas Gohr function image_scale($image,$x,$y,$w,$h){ 192*1faa1ff0SAndreas Gohr $scale=imagecreatetruecolor($w,$h); 193*1faa1ff0SAndreas Gohr imagecopyresampled($scale,$image,0,0,0,0,$w,$h,$x,$y); 194*1faa1ff0SAndreas Gohr return $scale; 195*1faa1ff0SAndreas Gohr } 196*1faa1ff0SAndreas Gohr 197*1faa1ff0SAndreas Gohr /** 198*1faa1ff0SAndreas Gohr * Crop an image with libGD 199*1faa1ff0SAndreas Gohr */ 200*1faa1ff0SAndreas Gohr function image_crop($image,$x,$y,$left,$upper,$right,$lower) { 201*1faa1ff0SAndreas Gohr $w=abs($right-$left); 202*1faa1ff0SAndreas Gohr $h=abs($lower-$upper); 203*1faa1ff0SAndreas Gohr $crop = imagecreatetruecolor($w,$h); 204*1faa1ff0SAndreas Gohr imagecopy($crop,$image,0,0,$left,$upper,$w,$h); 205*1faa1ff0SAndreas Gohr return $crop; 206*1faa1ff0SAndreas Gohr } 207*1faa1ff0SAndreas Gohr 208*1faa1ff0SAndreas Gohr /** 209*1faa1ff0SAndreas Gohr * Send a graphical error message and stop script 210*1faa1ff0SAndreas Gohr */ 211*1faa1ff0SAndreas Gohr function gfx_error($type){ 212*1faa1ff0SAndreas Gohr $file = dirname(__FILE__).'/gfx/'.$type.'.gif'; 213*1faa1ff0SAndreas Gohr $time = filemtime($file); 214*1faa1ff0SAndreas Gohr header('Content-type: image/gif'); 215*1faa1ff0SAndreas Gohr 216*1faa1ff0SAndreas Gohr http_conditionalRequest($time); 217*1faa1ff0SAndreas Gohr http_sendfile($file); 218*1faa1ff0SAndreas Gohr readfile($file); 219*1faa1ff0SAndreas Gohr exit; 220*1faa1ff0SAndreas Gohr } 221*1faa1ff0SAndreas Gohr 222*1faa1ff0SAndreas Gohr /** 223*1faa1ff0SAndreas Gohr * Acquire a lock for the tile generator 224*1faa1ff0SAndreas Gohr */ 225*1faa1ff0SAndreas Gohr function tile_lock($d){ 226*1faa1ff0SAndreas Gohr global $conf; 227*1faa1ff0SAndreas Gohr 228*1faa1ff0SAndreas Gohr $lockDir = $conf['lockdir'].'/'.md5($d['id']).'.panoview'; 229*1faa1ff0SAndreas Gohr @ignore_user_abort(1); 230*1faa1ff0SAndreas Gohr 231*1faa1ff0SAndreas Gohr $timeStart = time(); 232*1faa1ff0SAndreas Gohr do { 233*1faa1ff0SAndreas Gohr //waited longer than 25 seconds? -> stale lock? 234*1faa1ff0SAndreas Gohr if ((time() - $timeStart) > 25){ 235*1faa1ff0SAndreas Gohr if(time() - filemtime($lockDir) > 30) $this->tile_unlock($d); 236*1faa1ff0SAndreas Gohr send_redirect(DOKU_URL.'lib/plugins/panaoview/tiles.php?tile='.$d['zoom'].'-'.$d['col'].'-'.$d['row'].'&image='.rawurlencode($d['id'])); 237*1faa1ff0SAndreas Gohr exit; 238*1faa1ff0SAndreas Gohr } 239*1faa1ff0SAndreas Gohr $locked = @mkdir($lockDir, $conf['dmode']); 240*1faa1ff0SAndreas Gohr if($locked){ 241*1faa1ff0SAndreas Gohr if(!empty($conf['dperm'])) chmod($lockDir, $conf['dperm']); 242*1faa1ff0SAndreas Gohr break; 243*1faa1ff0SAndreas Gohr } 244*1faa1ff0SAndreas Gohr usleep(rand(500,3000)); 245*1faa1ff0SAndreas Gohr } while ($locked === false); 246*1faa1ff0SAndreas Gohr } 247*1faa1ff0SAndreas Gohr 248*1faa1ff0SAndreas Gohr /** 249*1faa1ff0SAndreas Gohr * Unlock the tile generator 250*1faa1ff0SAndreas Gohr */ 251*1faa1ff0SAndreas Gohr function tile_unlock($d){ 252*1faa1ff0SAndreas Gohr global $conf; 253*1faa1ff0SAndreas Gohr 254*1faa1ff0SAndreas Gohr $lockDir = $conf['lockdir'].'/'.md5($d['id']).'.panoview'; 255*1faa1ff0SAndreas Gohr @rmdir($lockDir); 256*1faa1ff0SAndreas Gohr @ignore_user_abort(0); 257*1faa1ff0SAndreas Gohr } 258*1faa1ff0SAndreas Gohr 25927bbde00SAndreas Gohr 26027bbde00SAndreas Gohr} 26127bbde00SAndreas Gohr 26227bbde00SAndreas Gohr//Setup VIM: ex: et ts=4 enc=utf-8 : 263