source: trunk/include/derivative.inc.php @ 21088

Last change on this file since 21088 was 20516, checked in by rvelices, 12 years ago

feature 2831: simple way to protect urls of originals

File size: 10.9 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2013 Piwigo Team                  http://piwigo.org |
6// +-----------------------------------------------------------------------+
7// | This program is free software; you can redistribute it and/or modify  |
8// | it under the terms of the GNU General Public License as published by  |
9// | the Free Software Foundation                                          |
10// |                                                                       |
11// | This program is distributed in the hope that it will be useful, but   |
12// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
13// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
14// | General Public License for more details.                              |
15// |                                                                       |
16// | You should have received a copy of the GNU General Public License     |
17// | along with this program; if not, write to the Free Software           |
18// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
19// | USA.                                                                  |
20// +-----------------------------------------------------------------------+
21
22/*A source image is used to get a derivative image. A source image is either the original file for a jpg or a
23'representative' image of a non image file or a standard icon for the non-image file.*/
24final class SrcImage
25{
26  const IS_ORIGINAL = 0x01;
27  const IS_MIMETYPE = 0x02;
28  const DIM_NOT_GIVEN = 0x04;
29
30  public $id;
31  public $rel_path;
32  public $rotation = 0;
33
34  private $size=null;
35  private $flags=0;
36
37  /*@param infos assoc array of data from images table*/
38  function __construct($infos)
39  {
40    global $conf;
41
42    $this->id = $infos['id'];
43    $ext = get_extension($infos['path']);
44    if (in_array($ext, $conf['picture_ext']))
45    {
46      $this->rel_path = $infos['path'];
47      $this->flags |= self::IS_ORIGINAL;
48    }
49    elseif (!empty($infos['representative_ext']))
50    {
51      $this->rel_path = original_to_representative($infos['path'], $infos['representative_ext']);
52    }
53    else
54    {
55      $ext = strtolower($ext);
56      $this->rel_path = trigger_event('get_mimetype_location', get_themeconf('mime_icon_dir').$ext.'.png', $ext );
57      $this->flags |= self::IS_MIMETYPE;
58      if ( ($size=@getimagesize(PHPWG_ROOT_PATH.$this->rel_path)) === false)
59      {
60        $this->rel_path = 'themes/default/icon/mimetypes/unknown.png';
61        $size = getimagesize(PHPWG_ROOT_PATH.$this->rel_path);
62      }
63      $this->size = array($size[0],$size[1]);
64    }
65
66    if (!$this->size)
67    {
68      if (isset($infos['width']) && isset($infos['height']))
69      {
70        $width = $infos['width'];
71        $height = $infos['height'];
72
73        $this->rotation = intval($infos['rotation']) % 4;
74        // 1 or 5 =>  90 clockwise
75        // 3 or 7 => 270 clockwise
76        if ($this->rotation % 2)
77        {
78          $width = $infos['height'];
79          $height = $infos['width'];
80        }
81
82        $this->size = array($width, $height);
83      }
84      elseif (!array_key_exists('width', $infos))
85      {
86        $this->flags |= self::DIM_NOT_GIVEN;
87      }
88    }
89  }
90
91  function is_original()
92  {
93    return $this->flags & self::IS_ORIGINAL;
94  }
95
96  function is_mimetype()
97  {
98    return $this->flags & self::IS_MIMETYPE;
99  }
100
101  function get_path()
102  {
103    return PHPWG_ROOT_PATH.$this->rel_path;
104  }
105
106  function get_url()
107  {
108    $url = get_root_url().$this->rel_path;
109    if ( !($this->flags & self::IS_MIMETYPE) )
110    {
111      $url = trigger_event('get_src_image_url', $url, $this);
112    }
113    return embellish_url($url);
114  }
115
116  function has_size()
117  {
118    return $this->size != null;
119  }
120
121  /* @return a 2-element array containing width/height or null if dimensions are not available*/
122  function get_size()
123  {
124    if ($this->size == null)
125    {
126      if ($this->flags & self::DIM_NOT_GIVEN)
127        fatal_error('SrcImage dimensions required but not provided');
128      // probably not metadata synced
129      if ( ($size = getimagesize( $this->get_path() )) !== false)
130      {
131        $this->size = array($size[0],$size[1]);
132        pwg_query('UPDATE '.IMAGES_TABLE.' SET width='.$size[0].', height='.$size[1].' WHERE id='.$this->id);
133      }
134    }
135    return $this->size;
136  }
137}
138
139
140/*Holds information (path, url, dimensions) about a derivative image. A derivative image is constructed from a source
141image (SrcImage class) and derivative parameters (DerivativeParams class).
142*/
143final class DerivativeImage
144{
145  public $src_image;
146
147  private $params;
148  private $rel_path, $rel_url, $is_cached=true;
149
150  /*
151  @param type string of standard derivative param type (e.g. IMG_???) or a DerivativeParams object
152  @param src_image the source image of this derivative*/
153  function __construct($type, SrcImage $src_image)
154  {
155    $this->src_image = $src_image;
156    if (is_string($type))
157    {
158      $this->params = ImageStdParams::get_by_type($type);
159    }
160    else
161    {
162      $this->params = $type;
163    }
164
165    self::build($src_image, $this->params, $this->rel_path, $this->rel_url, $this->is_cached);
166  }
167
168  static function thumb_url($infos)
169  {
170    return self::url(IMG_THUMB, $infos);
171  }
172
173  /**
174  @return derivative image url
175  @param type string of standard derivative param type (e.g. IMG_???) or a DerivativeParams object
176  @param infos assoc array of data from images table or a SrcImage object
177  */
178  static function url($type, $infos)
179  {
180    $src_image = is_object($infos) ? $infos : new SrcImage($infos);
181    $params = is_string($type) ? ImageStdParams::get_by_type($type) : $type;
182    self::build($src_image, $params, $rel_path, $rel_url);
183    if ($params == null)
184    {
185      return $src_image->get_url();
186    }
187    return embellish_url(
188        trigger_event('get_derivative_url',
189          get_root_url().$rel_url,
190          $params, $src_image, $rel_url
191          ) );
192  }
193
194  /**
195  @return an associative array of derivative images with keys all standard derivative image types:
196  Disabled derivative types can be still found in the return mapped to an enabled derivative (e.g. the values are not
197  unique in the return array). This is useful for any plugin/theme to just use $deriv[IMG_XLARGE] even if the XLARGE is
198  disabled.
199  */
200  static function get_all($src_image)
201  {
202    $ret = array();
203    // build enabled types
204    foreach (ImageStdParams::get_defined_type_map() as $type => $params)
205    {
206      $derivative = new DerivativeImage($params, $src_image);
207      $ret[$type] = $derivative;
208    }
209    // disabled types fqllbqck to enqbled types
210    foreach (ImageStdParams::get_undefined_type_map() as $type => $type2)
211    {
212      $ret[$type] = $ret[$type2];
213    }
214
215    return $ret;
216  }
217
218  private static function build($src, &$params, &$rel_path, &$rel_url, &$is_cached=null)
219  {
220    if ( $src->has_size() && $params->is_identity( $src->get_size() ) )
221    {// the source image is smaller than what we should do - we do not upsample
222      if (!$params->will_watermark($src->get_size()) && !$src->rotation)
223      {// no watermark, no rotation required -> we will use the source image
224        $params = null;
225        $rel_path = $rel_url = $src->rel_path;
226        return;
227      }
228      $defined_types = array_keys(ImageStdParams::get_defined_type_map());
229      for ($i=0; $i<count($defined_types); $i++)
230      {
231        if ($defined_types[$i] == $params->type)
232        {
233          for ($i--; $i>=0; $i--)
234          {
235            $smaller = ImageStdParams::get_by_type($defined_types[$i]);
236            if ($smaller->sizing->max_crop==$params->sizing->max_crop && $smaller->is_identity( $src->get_size() ))
237            {
238              $params = $smaller;
239              self::build($src, $params, $rel_path, $rel_url, $is_cached);
240              return;
241            }
242          }
243          break;
244        }
245      }
246    }
247
248    $tokens=array();
249    $tokens[] = substr($params->type,0,2);
250
251    if ($params->type==IMG_CUSTOM)
252    {
253      $params->add_url_tokens($tokens);
254    }
255
256    $loc = $src->rel_path;
257    if (substr_compare($loc, './', 0, 2)==0)
258    {
259      $loc = substr($loc, 2);
260    }
261    elseif (substr_compare($loc, '../', 0, 3)==0)
262    {
263      $loc = substr($loc, 3);
264    }
265    $loc = substr_replace($loc, '-'.implode('_', $tokens), strrpos($loc, '.'), 0 );
266
267    $rel_path = PWG_DERIVATIVE_DIR.$loc;
268
269    global $conf;
270    $url_style=$conf['derivative_url_style'];
271    if (!$url_style)
272    {
273      $mtime = @filemtime(PHPWG_ROOT_PATH.$rel_path);
274      if ($mtime===false or $mtime < $params->last_mod_time)
275      {
276        $is_cached = false;
277        $url_style = 2;
278      }
279      else
280      {
281        $url_style = 1;
282      }
283    }
284
285    if ($url_style == 2)
286    {
287      $rel_url = 'i';
288      if ($conf['php_extension_in_urls']) $rel_url .= '.php';
289      if ($conf['question_mark_in_urls']) $rel_url .= '?';
290      $rel_url .= '/'.$loc;
291    }
292    else
293    {
294      $rel_url = $rel_path;
295    }
296  }
297
298  function get_path()
299  {
300    return PHPWG_ROOT_PATH.$this->rel_path;
301  }
302
303  function get_url()
304  {
305    if ($this->params == null)
306    {
307      return $this->src_image->get_url();
308    }
309    return embellish_url(
310        trigger_event('get_derivative_url',
311          get_root_url().$this->rel_url,
312          $this->params, $this->src_image, $this->rel_url
313          ) );
314  }
315
316  function same_as_source()
317  {
318    return $this->params == null;
319  }
320
321
322  function get_type()
323  {
324    if ($this->params == null)
325      return 'Original';
326    return $this->params->type;
327  }
328
329  /* returns the size of the derivative image*/
330  function get_size()
331  {
332    if ($this->params == null)
333    {
334      return $this->src_image->get_size();
335    }
336    return $this->params->compute_final_size($this->src_image->get_size());
337  }
338
339  function get_size_css()
340  {
341    $size = $this->get_size();
342    if ($size)
343    {
344      return 'width:'.$size[0].'px; height:'.$size[1].'px';
345    }
346  }
347
348  function get_size_htm()
349  {
350    $size = $this->get_size();
351    if ($size)
352    {
353      return 'width="'.$size[0].'" height="'.$size[1].'"';
354    }
355  }
356
357  function get_size_hr()
358  {
359    $size = $this->get_size();
360    if ($size)
361    {
362      return $size[0].' x '.$size[1];
363    }
364  }
365
366  function get_scaled_size($maxw, $maxh)
367  {
368    $size = $this->get_size();
369    if ($size)
370    {
371      $ratio_w = $size[0] / $maxw;
372      $ratio_h = $size[1] / $maxh;
373      if ($ratio_w>1 || $ratio_h>1)
374      {
375        if ($ratio_w > $ratio_h)
376        {
377          $size[0] = $maxw;
378          $size[1] = floor($size[1] / $ratio_w);
379        }
380        else
381        {
382          $size[0] = floor($size[0] / $ratio_h);
383          $size[1] = $maxh;
384        }
385      }
386    }
387    return $size;
388  }
389
390  function get_scaled_size_htm($maxw=9999, $maxh=9999)
391  {
392    $size = $this->get_scaled_size($maxw, $maxh);
393    if ($size)
394    {
395      return 'width="'.$size[0].'" height="'.$size[1].'"';
396    }
397  }
398
399  function is_cached()
400  {
401    return $this->is_cached;
402  }
403}
404
405?>
Note: See TracBrowser for help on using the repository browser.