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

Last change on this file since 25504 was 25504, checked in by mistic100, 10 years ago

add DerivativeImage::get_one method working like DerivateImage::get_all but returning only one size

File size: 11.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 associative an array of all DerivativeImage for a specific image.
196   * Disabled derivative types can be still found in the return mapped to an
197   * enabled derivative (e.g. the values are not unique in the return array).
198   * This is useful for any plugin/theme to just use $deriv[IMG_XLARGE] even if
199   * the XLARGE is disabled.
200   *
201   * @param array|SrcImage $src_image array of info from db or SrcImage
202   * @return DerivativeImage[]
203   */
204  static function get_all($src_image)
205  {
206    if (!is_object($src_image))
207    {
208      $src_image = new SrcImage($src_image);
209    }
210
211    $ret = array();
212    // build enabled types
213    foreach (ImageStdParams::get_defined_type_map() as $type => $params)
214    {
215      $derivative = new DerivativeImage($params, $src_image);
216      $ret[$type] = $derivative;
217    }
218    // disabled types, fallback to enabled types
219    foreach (ImageStdParams::get_undefined_type_map() as $type => $type2)
220    {
221      $ret[$type] = $ret[$type2];
222    }
223
224    return $ret;
225  }
226
227  /**
228   * Returns an instance of DerivativeImage for a specific image and size.
229   * Disabled derivatives fallback to an enabled derivative.
230   *
231   * @param string $type
232   * @param array|SrcImage $src_image array of info from db or SrcImage
233   * @return DerivativeImage|null null if $type not found
234   */
235  static function get_one($type, $src_image)
236  {
237    if (!is_object($src_image))
238    {
239      $src_image = new SrcImage($src_image);
240    }
241
242    $defined = ImageStdParams::get_defined_type_map();
243    if (isset($defined[$type]))
244    {
245      return new DerivativeImage($defined[$type], $src_image);
246    }
247
248    $undefined = ImageStdParams::get_undefined_type_map();
249    if (isset($undefined[$type]))
250    {
251      return new DerivativeImage($defined[ $undefined[$type] ], $src_image);
252    }
253
254    return null;
255  }
256
257  private static function build($src, &$params, &$rel_path, &$rel_url, &$is_cached=null)
258  {
259    if ( $src->has_size() && $params->is_identity( $src->get_size() ) )
260    {// the source image is smaller than what we should do - we do not upsample
261      if (!$params->will_watermark($src->get_size()) && !$src->rotation)
262      {// no watermark, no rotation required -> we will use the source image
263        $params = null;
264        $rel_path = $rel_url = $src->rel_path;
265        return;
266      }
267      $defined_types = array_keys(ImageStdParams::get_defined_type_map());
268      for ($i=0; $i<count($defined_types); $i++)
269      {
270        if ($defined_types[$i] == $params->type)
271        {
272          for ($i--; $i>=0; $i--)
273          {
274            $smaller = ImageStdParams::get_by_type($defined_types[$i]);
275            if ($smaller->sizing->max_crop==$params->sizing->max_crop && $smaller->is_identity( $src->get_size() ))
276            {
277              $params = $smaller;
278              self::build($src, $params, $rel_path, $rel_url, $is_cached);
279              return;
280            }
281          }
282          break;
283        }
284      }
285    }
286
287    $tokens=array();
288    $tokens[] = substr($params->type,0,2);
289
290    if ($params->type==IMG_CUSTOM)
291    {
292      $params->add_url_tokens($tokens);
293    }
294
295    $loc = $src->rel_path;
296    if (substr_compare($loc, './', 0, 2)==0)
297    {
298      $loc = substr($loc, 2);
299    }
300    elseif (substr_compare($loc, '../', 0, 3)==0)
301    {
302      $loc = substr($loc, 3);
303    }
304    $loc = substr_replace($loc, '-'.implode('_', $tokens), strrpos($loc, '.'), 0 );
305
306    $rel_path = PWG_DERIVATIVE_DIR.$loc;
307
308    global $conf;
309    $url_style=$conf['derivative_url_style'];
310    if (!$url_style)
311    {
312      $mtime = @filemtime(PHPWG_ROOT_PATH.$rel_path);
313      if ($mtime===false or $mtime < $params->last_mod_time)
314      {
315        $is_cached = false;
316        $url_style = 2;
317      }
318      else
319      {
320        $url_style = 1;
321      }
322    }
323
324    if ($url_style == 2)
325    {
326      $rel_url = 'i';
327      if ($conf['php_extension_in_urls']) $rel_url .= '.php';
328      if ($conf['question_mark_in_urls']) $rel_url .= '?';
329      $rel_url .= '/'.$loc;
330    }
331    else
332    {
333      $rel_url = $rel_path;
334    }
335  }
336
337  function get_path()
338  {
339    return PHPWG_ROOT_PATH.$this->rel_path;
340  }
341
342  function get_url()
343  {
344    if ($this->params == null)
345    {
346      return $this->src_image->get_url();
347    }
348    return embellish_url(
349        trigger_event('get_derivative_url',
350          get_root_url().$this->rel_url,
351          $this->params, $this->src_image, $this->rel_url
352          ) );
353  }
354
355  function same_as_source()
356  {
357    return $this->params == null;
358  }
359
360
361  function get_type()
362  {
363    if ($this->params == null)
364      return 'Original';
365    return $this->params->type;
366  }
367
368  /* returns the size of the derivative image*/
369  function get_size()
370  {
371    if ($this->params == null)
372    {
373      return $this->src_image->get_size();
374    }
375    return $this->params->compute_final_size($this->src_image->get_size());
376  }
377
378  function get_size_css()
379  {
380    $size = $this->get_size();
381    if ($size)
382    {
383      return 'width:'.$size[0].'px; height:'.$size[1].'px';
384    }
385  }
386
387  function get_size_htm()
388  {
389    $size = $this->get_size();
390    if ($size)
391    {
392      return 'width="'.$size[0].'" height="'.$size[1].'"';
393    }
394  }
395
396  function get_size_hr()
397  {
398    $size = $this->get_size();
399    if ($size)
400    {
401      return $size[0].' x '.$size[1];
402    }
403  }
404
405  function get_scaled_size($maxw, $maxh)
406  {
407    $size = $this->get_size();
408    if ($size)
409    {
410      $ratio_w = $size[0] / $maxw;
411      $ratio_h = $size[1] / $maxh;
412      if ($ratio_w>1 || $ratio_h>1)
413      {
414        if ($ratio_w > $ratio_h)
415        {
416          $size[0] = $maxw;
417          $size[1] = floor($size[1] / $ratio_w);
418        }
419        else
420        {
421          $size[0] = floor($size[0] / $ratio_h);
422          $size[1] = $maxh;
423        }
424      }
425    }
426    return $size;
427  }
428
429  function get_scaled_size_htm($maxw=9999, $maxh=9999)
430  {
431    $size = $this->get_scaled_size($maxw, $maxh);
432    if ($size)
433    {
434      return 'width="'.$size[0].'" height="'.$size[1].'"';
435    }
436  }
437
438  function is_cached()
439  {
440    return $this->is_cached;
441  }
442}
443
444?>
Note: See TracBrowser for help on using the repository browser.