| | 1 | <?php |
|---|
| | 2 | /** |
|---|
| | 3 | * @package jelix |
|---|
| | 4 | * @subpackage utils |
|---|
| | 5 | * @author Bastien Jaillot |
|---|
| | 6 | * @contributor Dominique Papin, Lepeltier kévin (the author of the original plugin) |
|---|
| | 7 | * @copyright 2007-2008 Lepeltier kévin, 2008 Dominique Papin, 2008 Bastien Jaillot |
|---|
| | 8 | * @link http://www.jelix.org |
|---|
| | 9 | * @licence GNU Lesser General Public Licence see LICENCE file or http://www.gnu.org/licenses/lgpl.html |
|---|
| | 10 | */ |
|---|
| | 11 | |
|---|
| | 12 | /** |
|---|
| | 13 | * Utility class to create cache image |
|---|
| | 14 | * @package jelix |
|---|
| | 15 | * @subpackage utils |
|---|
| | 16 | * @static |
|---|
| | 17 | */ |
|---|
| | 18 | class jImage { |
|---|
| | 19 | |
|---|
| | 20 | |
|---|
| | 21 | /** |
|---|
| | 22 | * image plugin : write the url corresponding to the image |
|---|
| | 23 | * |
|---|
| | 24 | * Add a link to the image, |
|---|
| | 25 | * The image is resized, and cached |
|---|
| | 26 | * |
|---|
| | 27 | * class :string |
|---|
| | 28 | * id :string |
|---|
| | 29 | * alt :string |
|---|
| | 30 | * width :uint |
|---|
| | 31 | * height :uint |
|---|
| | 32 | * maxwidth :uint only with maxheight |
|---|
| | 33 | * maxheight :uint only with maxwidth |
|---|
| | 34 | * zoom 1-100 |
|---|
| | 35 | * omo :boolean |
|---|
| | 36 | * alignh [left|center|right|:int] |
|---|
| | 37 | * alignv [top|center|bottom|:int] |
|---|
| | 38 | * ext [png|jpg|gif] |
|---|
| | 39 | * quality 0-100 if ext = jpg |
|---|
| | 40 | * shadow :boolean |
|---|
| | 41 | * soffset :uint |
|---|
| | 42 | * sangle :uint |
|---|
| | 43 | * sblur :uint |
|---|
| | 44 | * sopacity :uint |
|---|
| | 45 | * scolor #000000 :string |
|---|
| | 46 | * background #000000 :string |
|---|
| | 47 | * |
|---|
| | 48 | * gif -> image/gif |
|---|
| | 49 | * jpeg -> image/jpeg |
|---|
| | 50 | * jpg -> image/jpeg |
|---|
| | 51 | * jpe -> image/jpeg |
|---|
| | 52 | * xpm -> image/x-xpixmap |
|---|
| | 53 | * xbm -> image/x-xbitmap |
|---|
| | 54 | * wbmp -> image/vnd.wap.wbmp |
|---|
| | 55 | * png -> image/png |
|---|
| | 56 | * other -> image/png |
|---|
| | 57 | * |
|---|
| | 58 | * @param string $src the url of image (myapp/www/):string.[gif|jpeg|jpg|jpe|xpm|xbm|wbmp|png] |
|---|
| | 59 | * @param array $params parameters for the url |
|---|
| | 60 | * @return array of attribut |
|---|
| | 61 | **/ |
|---|
| | 62 | static function generateCachedImage ($src, $params = array(), $send_cache_path = true) { |
|---|
| | 63 | |
|---|
| | 64 | // Extension |
|---|
| | 65 | if( empty($params['ext']) ) { |
|---|
| | 66 | $path_parts = pathinfo($src); |
|---|
| | 67 | $ext = strtolower($path_parts['extension']); |
|---|
| | 68 | } else $ext = strtolower($params['ext']); |
|---|
| | 69 | |
|---|
| | 70 | // White background for IE |
|---|
| | 71 | if ( empty($params['background']) |
|---|
| | 72 | && strpos($_SERVER["HTTP_USER_AGENT"], 'MSIE') !== false |
|---|
| | 73 | && strpos($_SERVER["HTTP_USER_AGENT"], 'MSIE 7') === false) { |
|---|
| | 74 | $params['background'] = '#ffffff'; |
|---|
| | 75 | } |
|---|
| | 76 | |
|---|
| | 77 | // Name of the file cache |
|---|
| | 78 | $chaine = $src; |
|---|
| | 79 | foreach($params as $key => $value) |
|---|
| | 80 | if( !in_array($key, array('alt', 'class', 'id', 'style', 'longdesc', 'name', 'ismap', 'usemap', 'title', 'dir', 'lang', 'onclick', 'ondblclick', 'onmousedown', 'onmouseup', 'onmouseover', 'onmousemove', 'onmouseout', 'onkeypress', 'onkeydown', 'onkeyup'))) |
|---|
| | 81 | $chaine .= $key.$value; |
|---|
| | 82 | $cachename = md5($chaine).'.'.$ext; |
|---|
| | 83 | |
|---|
| | 84 | // Path |
|---|
| | 85 | $cache_path = JELIX_APP_WWW_PATH.'cache/images/'.$cachename; |
|---|
| | 86 | $origine_path = JELIX_APP_WWW_PATH.$src; |
|---|
| | 87 | |
|---|
| | 88 | global $gJConfig; |
|---|
| | 89 | $www = 'http'.(empty($_SERVER['HTTPS'])?'':'s').'://'.$_SERVER['HTTP_HOST'].$gJConfig->urlengine['basePath']; |
|---|
| | 90 | $cache_www = $www.'cache/images/'.$cachename; |
|---|
| | 91 | $origine_www = $www.$src; |
|---|
| | 92 | |
|---|
| | 93 | // Cache and make changes if necessary |
|---|
| | 94 | if( is_file($origine_path) && !is_file($cache_path) ) { |
|---|
| | 95 | $att = array('width'=>'', 'height'=>'', 'maxwidth'=>'', 'maxheight'=>'', 'zoom'=>'', 'alignh'=>'', 'alignv'=>'', 'ext'=>'', 'quality'=>'', 'shadow'=>''); |
|---|
| | 96 | if( count(array_intersect_key($params, $att)) ) |
|---|
| | 97 | self::image_inCache($src, $cachename, $params); |
|---|
| | 98 | } |
|---|
| | 99 | |
|---|
| | 100 | // Attributes |
|---|
| | 101 | $att = array('alt'=>'', 'id'=>'', 'class'=>'', 'style'=>'', 'longdesc'=>'', 'name'=>'', 'ismap'=>'', 'usemap'=>'', 'title'=>'', 'dir'=>'', 'lang'=>'', 'onclick'=>'', 'ondblclick'=>'', 'onmousedown'=>'', 'onmouseup'=>'', 'onmouseover'=>'', 'onmousemove'=>'', 'onmouseout'=>'', 'onkeypress'=>'', 'onkeydown'=>'', 'onkeyup'=>''); |
|---|
| | 102 | $att = array_intersect_key($params, $att); |
|---|
| | 103 | |
|---|
| | 104 | // If the image does not undergo transformation |
|---|
| | 105 | if( !is_file($cache_path) ) { |
|---|
| | 106 | $att['src'] = $origine_www; |
|---|
| | 107 | $att['style'] = empty($att['style'])?'':$att['style']; |
|---|
| | 108 | if( !empty($params['width']) ) $att['style'] .= 'width: '.$params['width'].'px;'; |
|---|
| | 109 | else if( !empty($params['maxwidth']) ) $att['style'] .= 'width: '.$params['maxwidth'].'px;'; |
|---|
| | 110 | if( !empty($params['height']) ) $att['style'] .= 'height: '.$params['height'].'px;'; |
|---|
| | 111 | else if( !empty($params['maxheight']) ) $att['style'] .= 'height: '.$params['maxheight'].'px;'; |
|---|
| | 112 | } else |
|---|
| | 113 | $att['src'] = $cache_www; |
|---|
| | 114 | |
|---|
| | 115 | if ($send_cache_path) |
|---|
| | 116 | $att['cache_path'] = $cache_path; |
|---|
| | 117 | |
|---|
| | 118 | return $att; |
|---|
| | 119 | } |
|---|
| | 120 | |
|---|
| | 121 | |
|---|
| | 122 | /** |
|---|
| | 123 | * generate cache image |
|---|
| | 124 | * @param string $src the url of image (myapp/www/):string.[gif|jpeg|jpg|jpe|xpm|xbm|wbmp|png] |
|---|
| | 125 | * @param string image's hashname |
|---|
| | 126 | * @param array $params parameters for the url |
|---|
| | 127 | **/ |
|---|
| | 128 | static protected function image_inCache($src, $cachename, $array) { |
|---|
| | 129 | |
|---|
| | 130 | $mimes = array('gif'=>'image/gif', 'png'=>'image/png', |
|---|
| | 131 | 'jpeg'=>'image/jpeg', 'jpg'=>'image/jpeg', 'jpe'=>'image/jpeg', |
|---|
| | 132 | 'xpm'=>'image/x-xpixmap', 'xbm'=>'image/x-xbitmap', 'wbmp'=>'image/vnd.wap.wbmp'); |
|---|
| | 133 | |
|---|
| | 134 | global $gJConfig; |
|---|
| | 135 | $origine_www = 'http'.(empty($_SERVER['HTTPS'])?'':'s').'://'.$_SERVER['HTTP_HOST'].$gJConfig->urlengine['basePath'].$src; |
|---|
| | 136 | |
|---|
| | 137 | $path_parts = pathinfo($origine_www); |
|---|
| | 138 | $ext = $mimes[strtolower($path_parts['extension'])]; |
|---|
| | 139 | $quality = (!empty($array['quality']))? $array['quality'] : 100; |
|---|
| | 140 | |
|---|
| | 141 | // Creating an image |
|---|
| | 142 | switch ( $ext ) { |
|---|
| | 143 | case 'image/gif' : $image = imagecreatefromgif($origine_www); break; |
|---|
| | 144 | case 'image/jpeg' : $image = imagecreatefromjpeg($origine_www); break; |
|---|
| | 145 | case 'image/png' : $image = imagecreatefrompng($origine_www); break; |
|---|
| | 146 | case 'image/vnd.wap.wbmp' : $image = imagecreatefromwbmp($origine_www); break; |
|---|
| | 147 | case 'image/image/x-xbitmap' : $image = imagecreatefromxbm($origine_www); break; |
|---|
| | 148 | case 'image/x-xpixmap' : $image = imagecreatefromxpm($origine_www); break; |
|---|
| | 149 | default : return ; |
|---|
| | 150 | } |
|---|
| | 151 | |
|---|
| | 152 | if(!empty($array['maxwidth']) && !empty($array['maxheight'])) { |
|---|
| | 153 | |
|---|
| | 154 | $origWidth = imagesx($image); |
|---|
| | 155 | $origHeight = imagesy($image); |
|---|
| | 156 | $constWidth = $array['maxwidth']; |
|---|
| | 157 | $constHeight = $array['maxheight']; |
|---|
| | 158 | $ratio = imagesx($image)/imagesy($image); |
|---|
| | 159 | |
|---|
| | 160 | if ( $origWidth < $constWidth && $origHeight < $constHeight ) { |
|---|
| | 161 | $array['width'] = $origWidth; |
|---|
| | 162 | $array['height'] = $origHeight; |
|---|
| | 163 | } else { |
|---|
| | 164 | $ratioHeight = $constWidth/$ratio; |
|---|
| | 165 | $ratioWidth = $constHeight*$ratio; |
|---|
| | 166 | if ( $ratioWidth > $constWidth ) { |
|---|
| | 167 | $constHeight = $ratioHeight; |
|---|
| | 168 | } |
|---|
| | 169 | else if ( $ratioHeight > $constHeight ) { |
|---|
| | 170 | $constWidth = $ratioWidth; |
|---|
| | 171 | } |
|---|
| | 172 | $array['width'] = $constWidth; |
|---|
| | 173 | $array['height'] = $constHeight; |
|---|
| | 174 | } |
|---|
| | 175 | } |
|---|
| | 176 | |
|---|
| | 177 | if (!empty($array['width']) || !empty($array['height'])) { |
|---|
| | 178 | |
|---|
| | 179 | $ancienimage = $image; |
|---|
| | 180 | $resampleheight = imagesy($ancienimage); |
|---|
| | 181 | $resamplewidth = imagesx($ancienimage); |
|---|
| | 182 | $posx = 0; |
|---|
| | 183 | $posy = 0; |
|---|
| | 184 | |
|---|
| | 185 | if(empty($array['width'])) { |
|---|
| | 186 | $finalheight = $array['height']; |
|---|
| | 187 | $finalwidth = $finalheight*imagesx($ancienimage)/imagesy($ancienimage); |
|---|
| | 188 | } else if (empty($array['height'])) { |
|---|
| | 189 | $finalwidth = $array['width']; |
|---|
| | 190 | $finalheight = $finalwidth*imagesy($ancienimage)/imagesx($ancienimage); |
|---|
| | 191 | } else { |
|---|
| | 192 | $finalwidth = $array['width']; |
|---|
| | 193 | $finalheight = $array['height']; |
|---|
| | 194 | if(!empty($array['omo']) && $array['omo'] == 'true') { |
|---|
| | 195 | if($array['width'] >= $array['height']) { |
|---|
| | 196 | $resampleheight = ( $resamplewidth*$array['height'] )/$array['width']; |
|---|
| | 197 | } else { |
|---|
| | 198 | $resamplewidth = ( $resampleheight*$array['width'] )/$array['height']; |
|---|
| | 199 | } |
|---|
| | 200 | } |
|---|
| | 201 | } |
|---|
| | 202 | |
|---|
| | 203 | if(!empty($array['zoom'])) { |
|---|
| | 204 | $resampleheight /= 100/$array['zoom']; |
|---|
| | 205 | $resamplewidth /= 100/$array['zoom']; |
|---|
| | 206 | } |
|---|
| | 207 | |
|---|
| | 208 | $posx = imagesx($ancienimage)/2 -$resamplewidth/2; |
|---|
| | 209 | $posy = imagesy($ancienimage)/2 -$resampleheight/2; |
|---|
| | 210 | |
|---|
| | 211 | if(!empty($array['alignh'])) { |
|---|
| | 212 | if($array['alignh'] == 'left') $posx = 0; |
|---|
| | 213 | else if($array['alignh'] == 'right') $posx = -($resamplewidth - imagesx($ancienimage)); |
|---|
| | 214 | else if($array['alignh'] != 'center') $posx = -$array['alignh']; |
|---|
| | 215 | } |
|---|
| | 216 | |
|---|
| | 217 | if(!empty($array['alignv'])) { |
|---|
| | 218 | if($array['alignv'] == 'top') $posy = 0; |
|---|
| | 219 | else if($array['alignv'] == 'bottom') $posy = -($resampleheight - imagesy($ancienimage)); |
|---|
| | 220 | else if($array['alignv'] != 'center') $posy = -$array['alignv']; |
|---|
| | 221 | } |
|---|
| | 222 | |
|---|
| | 223 | $image = imagecreatetruecolor($finalwidth, $finalheight); |
|---|
| | 224 | imagesavealpha($image, true); |
|---|
| | 225 | $tp = imagecolorallocatealpha($image,0,0,0,127); |
|---|
| | 226 | imagefill($image,0,0,$tp); |
|---|
| | 227 | |
|---|
| | 228 | imagecopyresampled($image, $ancienimage, 0, 0, $posx, $posy, imagesx($image), imagesy($image), $resamplewidth, $resampleheight); |
|---|
| | 229 | } |
|---|
| | 230 | |
|---|
| | 231 | // The shadow cast adds to the dimension of the image chooses |
|---|
| | 232 | if( !empty($array['shadow']) ) |
|---|
| | 233 | $image = self::image_shadow ($image, $array); |
|---|
| | 234 | |
|---|
| | 235 | // Background |
|---|
| | 236 | if( !empty($array['background']) ) { |
|---|
| | 237 | $array['background'] = str_replace('#', '', $array['background']); |
|---|
| | 238 | $rgb = array(0,0,0); |
|---|
| | 239 | for ($x=0;$x<3;$x++) $rgb[$x] = hexdec(substr($array['background'],(2*$x),2)); |
|---|
| | 240 | $fond = imagecreatetruecolor(imagesx($image), imagesy($image)); |
|---|
| | 241 | imagefill( $fond, 0, 0, imagecolorallocate( $fond, $rgb[0], $rgb[1], $rgb[2]) ); |
|---|
| | 242 | imagecopy( $fond, $image, 0, 0, 0, 0, imagesx($image), imagesy($image)); |
|---|
| | 243 | $image = $fond; |
|---|
| | 244 | } |
|---|
| | 245 | |
|---|
| | 246 | |
|---|
| | 247 | $ext = empty($array['ext'])?$ext:$mimes[$array['ext']]; |
|---|
| | 248 | $cache_path = JELIX_APP_WWW_PATH.'cache/images/'; |
|---|
| | 249 | jFile::createDir($cache_path); |
|---|
| | 250 | |
|---|
| | 251 | |
|---|
| | 252 | // Register |
|---|
| | 253 | switch ( $ext ) { |
|---|
| | 254 | case 'image/gif' : imagegif($image, $cache_path.$cachename); break; |
|---|
| | 255 | case 'image/jpeg' : imagejpeg($image, $cache_path.$cachename, $quality); break; |
|---|
| | 256 | default : imagepng($image, $cache_path.$cachename); |
|---|
| | 257 | } |
|---|
| | 258 | |
|---|
| | 259 | // Destruction |
|---|
| | 260 | @imagedestroy($image); |
|---|
| | 261 | } |
|---|
| | 262 | |
|---|
| | 263 | |
|---|
| | 264 | /** |
|---|
| | 265 | * create a shadow |
|---|
| | 266 | * @param string $src the url of image (myapp/www/):string.[gif|jpeg|jpg|jpe|xpm|xbm|wbmp|png] |
|---|
| | 267 | * @param array $params parameters for the url |
|---|
| | 268 | * @return the image with shadow |
|---|
| | 269 | **/ |
|---|
| | 270 | static protected function image_shadow ($image, $array) { |
|---|
| | 271 | |
|---|
| | 272 | // Default |
|---|
| | 273 | $leng = isset($array['soffset'])?$array['soffset']:10; |
|---|
| | 274 | $angle = isset($array['sangle'])?$array['sangle']:135; |
|---|
| | 275 | $flou = isset($array['sblur'])?$array['sblur']:10; |
|---|
| | 276 | $opac = isset($array['sopacity'])?$array['sopacity']:20; |
|---|
| | 277 | $color = isset($array['scolor'])?$array['scolor']:'#000000'; |
|---|
| | 278 | |
|---|
| | 279 | // Color of the shadow |
|---|
| | 280 | $color = str_replace('#', '', $color); |
|---|
| | 281 | $rgb = array(0,0,0); |
|---|
| | 282 | if (strlen($color) == 6) |
|---|
| | 283 | for ($x=0;$x<3;$x++) |
|---|
| | 284 | $rgb[$x] = hexdec(substr($color,(2*$x),2)); |
|---|
| | 285 | else if (strlen($color) == 3) |
|---|
| | 286 | for ($x=0;$x<3;$x++) |
|---|
| | 287 | $rgb[$x] = hexdec(substr($color,(2*$x),1)); |
|---|
| | 288 | |
|---|
| | 289 | // Gaussian blur parameter |
|---|
| | 290 | $coeffs = array (array ( 1), |
|---|
| | 291 | array ( 1, 1), |
|---|
| | 292 | array ( 1, 2, 1), |
|---|
| | 293 | array ( 1, 3, 3, 1), |
|---|
| | 294 | array ( 1, 4, 6, 4, 1), |
|---|
| | 295 | array ( 1, 5, 10, 10, 5, 1), |
|---|
| | 296 | array ( 1, 6, 15, 20, 15, 6, 1), |
|---|
| | 297 | array ( 1, 7, 21, 35, 35, 21, 7, 1), |
|---|
| | 298 | array ( 1, 8, 28, 56, 70, 56, 28, 8, 1), |
|---|
| | 299 | array ( 1, 9, 36, 84, 126, 126, 84, 36, 9, 1), |
|---|
| | 300 | array ( 1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1), |
|---|
| | 301 | array ( 1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1)); |
|---|
| | 302 | $sum = pow (2, $flou); |
|---|
| | 303 | $demi = $flou/2; |
|---|
| | 304 | |
|---|
| | 305 | |
|---|
| | 306 | // Horizontal blur and blur margin |
|---|
| | 307 | $temp1 = imagecreatetruecolor(imagesx($image)+$flou, imagesy($image)+$flou); |
|---|
| | 308 | imagesavealpha($temp1, true); |
|---|
| | 309 | $tp = imagecolorallocatealpha($temp1,0,0,0,127); |
|---|
| | 310 | imagefill($temp1,0,0,$tp); |
|---|
| | 311 | |
|---|
| | 312 | for ( $i=0 ; $i < imagesx($temp1) ; $i++ ) |
|---|
| | 313 | for ( $j=0 ; $j < imagesy($temp1) ; $j++ ) { |
|---|
| | 314 | $ig = $i-$demi; $jg = $j-$demi; $suma = 0; |
|---|
| | 315 | for ( $k=0 ; $k <= $flou ; $k++ ) { |
|---|
| | 316 | $ik = $ig-$demi+$k; |
|---|
| | 317 | if( $jg<0 || $jg>imagesy($temp1)-$flou-1 ) $alpha = 127; |
|---|
| | 318 | else if( $ik<0 || $ik>imagesx($temp1)-$flou-1 ) $alpha = 127; |
|---|
| | 319 | else $alpha = (imagecolorat($image, $ik, $jg) & 0x7F000000) >> 24; |
|---|
| | 320 | $suma += $alpha*$coeffs[$flou][$k]; |
|---|
| | 321 | } |
|---|
| | 322 | $c = imagecolorallocatealpha($temp1, 0, 0, 0, $suma/$sum ); |
|---|
| | 323 | imagesetpixel($temp1,$i,$j,$c); |
|---|
| | 324 | } |
|---|
| | 325 | |
|---|
| | 326 | // Vertical blur, a shift of the angle, opacity and color |
|---|
| | 327 | |
|---|
| | 328 | $x = cos(deg2rad($angle))*$leng; |
|---|
| | 329 | $y = sin(deg2rad($angle))*$leng; |
|---|
| | 330 | |
|---|
| | 331 | $temp2 = imagecreatetruecolor(imagesx($temp1)+abs($x), imagesy($temp1)+abs($y)); |
|---|
| | 332 | imagesavealpha($temp2, true); |
|---|
| | 333 | $tp = imagecolorallocatealpha($temp2,0,0,0,127); |
|---|
| | 334 | imagefill($temp2,0,0,$tp); |
|---|
| | 335 | |
|---|
| | 336 | $x1 = $x<0?0:$x; |
|---|
| | 337 | $y1 = $y<0?0:$y; |
|---|
| | 338 | |
|---|
| | 339 | for ( $i=0 ; $i < imagesx($temp1) ; $i++ ) |
|---|
| | 340 | for ( $j=0 ; $j < imagesy($temp1) ; $j++ ) { |
|---|
| | 341 | $suma = 0; |
|---|
| | 342 | for ( $k=0 ; $k <= $flou ; $k++ ) { |
|---|
| | 343 | $jk = $j-$demi+$k; |
|---|
| | 344 | if( $jk<0 || $jk>imagesy($temp1)-1 ) $alpha = 127; |
|---|
| | 345 | else $alpha = (imagecolorat($temp1, $i, $jk) & 0x7F000000) >> 24; |
|---|
| | 346 | $suma += $alpha*$coeffs[$flou][$k]; |
|---|
| | 347 | } |
|---|
| | 348 | $alpha = 127-((127-($suma/$sum))/(100/$opac)); |
|---|
| | 349 | $c = imagecolorallocatealpha($temp2, $rgb[0], $rgb[1], $rgb[2], $alpha < 0 ? 0 : $alpha > 127 ? 127 : $alpha ); |
|---|
| | 350 | imagesetpixel($temp2,$i+$x1,$j+$y1,$c); |
|---|
| | 351 | } |
|---|
| | 352 | imagedestroy($temp1); |
|---|
| | 353 | |
|---|
| | 354 | // Merge of the image and are shade |
|---|
| | 355 | $x = $x>0?0:$x; |
|---|
| | 356 | $y = $y>0?0:$y; |
|---|
| | 357 | imagecopy( $temp2, $image, $demi-$x, $demi-$y, 0, 0, imagesx($image), imagesy($image)); |
|---|
| | 358 | |
|---|
| | 359 | return $temp2; |
|---|
| | 360 | |
|---|
| | 361 | } |
|---|
| | 362 | |
|---|
| | 363 | } |