1<?php 2/** 3 * iReflect Plugin 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author i-net software <tools@inetsoftware.de> 7 * @author Gerry Weissbach <gweissbach@inetsoftware.de> 8 */ 9 10// must be run within Dokuwiki 11if(!defined('DOKU_INC')) die(); 12 13if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 14require_once(DOKU_PLUGIN.'action.php'); 15 16class action_plugin_reflect extends DokuWiki_Action_Plugin { 17 18 private $functions = null; 19 20 function register(Doku_Event_Handler $controller) { 21 22 if ( empty($_REQUEST['reflect']) ) { return; } 23 $controller->register_hook('MEDIA_SENDFILE', 'BEFORE', $this, 'reflect__reflect'); 24 } 25 26 function reflect__reflect(&$event, $args) { 27 28 if (extension_loaded('gd') == false && !@dl('gd.so')) { return; } 29 30 /* Filename for reflect Image */ 31 $data = $event->data; 32 $ext = empty( $_REQUEST['return_type'] ) ? $this->getConf('return_type') : (in_array( hsc($_REQUEST['return_type']), array('png', 'jpg') ) ? hsc($_REQUEST['return_type']) : $this->getConf('return_type')); 33 34 $data['height'] = $this->getConf('reflect_height'); 35 if ( empty($_REQUEST['bgc']) ) $_REQUEST['bgc'] = $this->getConf('bgc'); 36 if ( !empty($_REQUEST['reflect_height']) ) $data['height'] = $_REQUEST['reflect_height']; 37 $cacheFile = getCacheName($data['file'],".media.reflect.{$_REQUEST['bgc']}.$ext"); 38 39 $mtime = @filemtime($cacheFile); // 0 if not exists 40 $cache = $data['cache']; 41 42 if( ($mtime == 0) || // cache does not exist 43 ($mtime < time()-$cache) // 'recache' and cache has expired 44 ){ 45 if ( $this->create_reflect_image( $data, $cacheFile, $_REQUEST['bgc'] ) ) { 46 $data['orig'] = $data['file']; 47 $data['file'] = $cacheFile; 48 list($data['ext'],$data['mime'],$data['download']) = mimetype($cacheFile); 49 $event->data = $data; 50 } 51 } 52 } 53 54 function create_reflect_image( $data, $cache_path, $imagebgcolor=null ) { 55 global $conf; 56 57 $input = $data['file']; 58 $imagebgcolor = $this->calc_bgcolor($imagebgcolor); 59 60 // How big is the image? 61 if ( !($image_details = getimagesize($input)) ) { return false; } 62 63 $width = $image_details[0]; 64 $height = $image_details[1]; 65 $type = $image_details[2]; 66 $mime = $image_details['mime']; 67 68 // height (how tall should the reflection be?) 69 if (isset($data['height']) ) { 70 $output_height = $data['height']; 71 if ( $output_height == 0 ) $output_height = $this->getConf('reflect_height'); 72 } else { 73 // No height was given, so default to 50% of the source images height 74 $output_height = $this->getConf('reflect_height'); 75 } 76 77 // Calculate the height of the output image 78 if ($output_height < 1) { 79 // The output height is a percentage 80 $new_height = $height * $output_height; 81 } else { 82 // The output height is a fixed pixel value 83 $new_height = $output_height; 84 } 85 86 if (isset($_REQUEST['fade_start'])) 87 { 88 if (strpos($_REQUEST['fade_start'], '%') !== false) { 89 $alpha_start = str_replace('%', '', $_REQUEST['fade_start']); 90 $alpha_start = (int) (127 * $alpha_start / 100); 91 } else { 92 $alpha_start = (int) $_REQUEST['fade_start']; 93 94 if ($alpha_start < 1 || $alpha_start > 127) { 95 $alpha_start = $this->getConf('fade_start'); 96 } 97 } 98 } else { 99 $alpha_start = $this->getConf('fade_start'); 100 } 101 102 if (isset($_REQUEST['fade_end'])) 103 { 104 if (strpos($_REQUEST['fade_end'], '%') !== false) { 105 $alpha_end = str_replace('%', '', $_REQUEST['fade_end']); 106 $alpha_end = (int) (127 * $alpha_end / 100); 107 } else { 108 $alpha_end = (int) $_REQUEST['fade_end']; 109 110 if ($alpha_end < 1 || $alpha_end > 127) { 111 $alpha_end = $this->getConf('fade_end'); 112 } 113 } 114 } else { 115 $alpha_end = $this->getConf('fade_end'); 116 } 117 118 $alpha_start = 127 - $alpha_start; 119 $alpha_end = 127 - $alpha_end; 120 121 // Detect the source image format - only GIF, JPEG and PNG are supported. If you need more, extend this yourself. 122 switch ($type) 123 { 124 case 1:// GIF 125 $source = imagecreatefromgif($input); break; 126 case 2:// JPG 127 $source = imagecreatefromjpeg($input); break; 128 case 3:// PNG 129 $source = imagecreatefrompng($input); break; 130 default: return false; 131 } 132 133 /* ---------------------------------------------------------------- 134 Build the reflection image 135 ---------------------------------------------------------------- */ 136 $output = $this->imagereflection($source, $width, $height, $new_height, $alpha_start, $alpha_end); 137 138 /* ---------------------------------------------------------------- 139 Output our final Image 140 ---------------------------------------------------------------- */ 141 if ( headers_sent() ) { return false; } 142 143 // If you'd rather output a JPEG instead of a PNG then pass the parameter 'jpeg' (no value needed) on the querystring 144 if ( substr($cache_path, -3) == 'png' ) { 145 imagepng($output, $cache_path, intval($conf['jpg_quality'] / 11)); 146 } else if ( substr($cache_path, -3) == 'jpg' ) { 147 /* ----------------------------------------------------------------------- 148 HACK - Build the reflection image by combining the png output 149 image AND the color background in one new image! 150 ------------------------------------------------------------------------ */ 151 152 // Create transparent BG 153 $finaloutput = imagecreatetruecolor($width, $height+$new_height); 154 $white = imagecolorallocatealpha($finaloutput, $imagebgcolor['red'], $imagebgcolor['green'], $imagebgcolor['blue'], $imagebgcolor['alpha']); 155 imagecolortransparent($finaloutput, $white); 156 imagefill($finaloutput, 0, 0, $white); 157 158 imagecopy($finaloutput, $output, 0, 0, 0, 0, $width, $height+$new_height); 159 imagejpeg($finaloutput, $cache_path, intval($conf['jpg_quality'])); 160 } 161 imagedestroy($output); 162 return true; 163 164 } 165 166 function calc_bgcolor( $bgcolor ) { 167 168 if ( empty($bgcolor) ) { $bgcolor = $this->getConf('bgc'); } 169 170 // Does it start with a hash? If so then strip it 171 $bgcolor = str_replace('#', '', $bgcolor); 172 173 switch (strlen($bgcolor)) 174 { 175 case 8: 176 $red = hexdec(substr($bgcolor, 0, 2)); 177 $green = hexdec(substr($bgcolor, 2, 2)); 178 $blue = hexdec(substr($bgcolor, 4, 2)); 179 $alpha = hexdec(substr($bgcolor, 6, 2)); 180 break; 181 182 case 6: 183 $red = hexdec(substr($bgcolor, 0, 2)); 184 $green = hexdec(substr($bgcolor, 2, 2)); 185 $blue = hexdec(substr($bgcolor, 4, 2)); 186 $alpha = hexdec('00'); 187 break; 188 189 case 4: 190 $red = substr($bgcolor, 0, 1); 191 $green = substr($bgcolor, 1, 1); 192 $blue = substr($bgcolor, 2, 1); 193 $alpha = substr($bgcolor, 3, 1); 194 $red = hexdec($red . $red); 195 $green = hexdec($green . $green); 196 $blue = hexdec($blue . $blue); 197 $alpha = hexdec($alpha . $alpha); 198 break; 199 200 case 3: 201 $red = substr($bgcolor, 0, 1); 202 $green = substr($bgcolor, 1, 1); 203 $blue = substr($bgcolor, 2, 1); 204 $red = hexdec($red . $red); 205 $green = hexdec($green . $green); 206 $blue = hexdec($blue . $blue); 207 $alpha = hexdec('00'); 208 break; 209 210 default: 211 // Wrong values passed, default to black 212 $red = 0; 213 $green = 0; 214 $blue = 0; 215 $alpha = 0; 216 } 217 218 $alpha = floor($alpha / 2); 219 return array('red' => $red, 'green' => $green, 'blue' => $blue, 'alpha' => $alpha ); 220 } 221 222 function imagereflection($src_img, $src_width, $src_height, $reflection_height, $alpha_start, $alpha_end) { 223 $dest_height = $src_height + $reflection_height; 224 $dest_width = $src_width; 225 226 // Create Reflected Object 227 $reflected = imagecreatetruecolor($dest_width, $dest_height); 228 imagealphablending($reflected, false); 229 imagesavealpha($reflected, true); 230 231 // Copy Source 232 imagecopy($reflected, $src_img, 0, 0, 0, 0, $src_width, $src_height); 233 if ( empty($reflection_height) ) $reflection_height = $src_height / 2; 234 235 // Calc alpha width and step 236 $alpha_length = abs($alpha_start - $alpha_end); 237 238 // For each Pixel in the reflection area 239 for ($y = 1; $y <= $reflection_height; $y++) { 240 241 $pct = $y / $reflection_height; 242 for ($x = 0; $x < $dest_width; $x++) { 243 // copy pixel from x / $src_height - y to x / $src_height + y 244 $rgba = imagecolorat($src_img, $x, $src_height - $y); 245 $alpha = ($rgba & 0x7F000000) >> 24; 246 247 // Get % of alpha 248 if ($alpha_start > $alpha_end) { $alpha_calc = (int) ($alpha_start - ($pct * $alpha_length)); } 249 else { $alpha_calc = (int) ($alpha_start + ($pct * $alpha_length)); } 250 251 $alpha = max($alpha, $alpha_calc); 252 $rgba = imagecolorsforindex($src_img, $rgba); 253 $rgba = imagecolorallocatealpha($reflected, $rgba['red'], $rgba['green'], $rgba['blue'], $alpha); 254 imagesetpixel($reflected, $x, $src_height + $y - 1, $rgba); 255 } 256 } 257 258 return $reflected; 259 } 260}