source: trunk/include/derivative_params.inc.php @ 30586

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

Update headers to 2014. Happy new year!!

File size: 10.6 KB
RevLine 
[12796]1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
[26461]5// | Copyright(C) 2008-2014 Piwigo Team                  http://piwigo.org |
[12796]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
[25754]22/**
23 * @package Derivatives
24 */
25
26
27/**
28 * Formats a size name into a 2 chars identifier usable in filename.
29 *
30 * @param string $t one of IMG_*
31 * @return string
32 */
[12797]33function derivative_to_url($t)
34{
35  return substr($t, 0, 2);
36}
37
[25754]38/**
39 * Formats a size array into a identifier usable in filename.
40 *
41 * @param int[] $s
42 * @return string
43 */
[12796]44function size_to_url($s)
45{
46  if ($s[0]==$s[1])
47  {
48    return $s[0];
49  }
50  return $s[0].'x'.$s[1];
51}
52
[25754]53/**
54 * @param int[] $s1
55 * @param int[] $s2
56 * @return bool
57 */
[13021]58function size_equals($s1, $s2)
[12796]59{
[13021]60  return ($s1[0]==$s2[0] && $s1[1]==$s2[1]);
[12796]61}
62
[25754]63/**
64 * Converts a char a-z into a float.
65 *
66 * @param string
67 * @return float
68 */
[13021]69function char_to_fraction($c)
[12796]70{
[13021]71        return (ord($c) - ord('a'))/25;
[12796]72}
73
[25754]74/**
75 * Converts a float into a char a-z.
76 *
77 * @param float
78 * @return string
79 */
[13021]80function fraction_to_char($f)
81{
[13038]82        return chr(ord('a') + round($f*25));
[13021]83}
[12796]84
[25754]85
86/**
87 * Small utility to manipulate a 'rectangle'.
88 */
[12796]89final class ImageRect
90{
[25754]91  /**
92   * @var int $l
93   * @var int $t
94   * @var int $r
95   * @var int $b
96   */
[12796]97  public $l,$t,$r,$b;
98
[25754]99  /**
100   * @param int[] $l width and height
101   */
[12796]102  function __construct($l)
103  {
104    $this->l = $this->t = 0;
105    $this->r = $l[0];
106    $this->b = $l[1];
107  }
108
[25754]109  /**
110   * @return int
111   */
[12796]112  function width()
113  {
114    return $this->r - $this->l;
115  }
116
[25754]117  /**
118   * @return int
119   */
[12796]120  function height()
121  {
122    return $this->b - $this->t;
123  }
124
[25754]125  /**
126   * Crops horizontally this rectangle by increasing left side and/or reducing the right side.
127   *
128   * @param int $pixels - the amount to substract from the width
129   * @param stirng $coi - a 4 character string (or null) containing the center of interest
130   */
[13035]131  function crop_h($pixels, $coi)
[12796]132  {
133    if ($this->width() <= $pixels)
134      return;
135    $tlcrop = floor($pixels/2);
136
137    if (!empty($coi))
138    {
[13021]139      $coil = floor($this->r * char_to_fraction($coi[0]));
140      $coir = ceil($this->r * char_to_fraction($coi[2]));
[12796]141      $availableL = $coil > $this->l ? $coil - $this->l : 0;
142      $availableR = $coir < $this->r ? $this->r - $coir : 0;
[13035]143      if ($availableL + $availableR >= $pixels)
[12796]144      {
145        if ($availableL < $tlcrop)
146        {
147          $tlcrop = $availableL;
148        }
149        elseif ($availableR < $tlcrop)
150        {
151          $tlcrop = $pixels - $availableR;
152        }
153      }
154    }
155    $this->l += $tlcrop;
156    $this->r -= $pixels - $tlcrop;
157  }
158
[25754]159  /**
160   * Crops vertically this rectangle by increasing top side and/or reducing the bottom side.
161   *
162   * @param int $pixels - the amount to substract from the height
163   * @param string $coi - a 4 character string (or null) containing the center of interest
164   */
[13035]165  function crop_v($pixels, $coi)
[12796]166  {
167    if ($this->height() <= $pixels)
168      return;
169    $tlcrop = floor($pixels/2);
170
171    if (!empty($coi))
172    {
[13021]173      $coit = floor($this->b * char_to_fraction($coi[1]));
174      $coib = ceil($this->b * char_to_fraction($coi[3]));
[12796]175      $availableT = $coit > $this->t ? $coit - $this->t : 0;
176      $availableB = $coib < $this->b ? $this->b - $coib : 0;
[13035]177      if ($availableT + $availableB >= $pixels)
[12796]178      {
179        if ($availableT < $tlcrop)
180        {
181          $tlcrop = $availableT;
182        }
183        elseif ($availableB < $tlcrop)
184        {
185          $tlcrop = $pixels - $availableB;
186        }
187      }
188    }
189    $this->t += $tlcrop;
190    $this->b -= $pixels - $tlcrop;
191  }
192}
193
194
[25754]195/**
196 * Paramaters for derivative scaling and cropping.
197 * Instance of this class contained by DerivativeParams class.
198 */
[12796]199final class SizingParams
200{
[25754]201  /** @var int[] */
202  var $ideal_size;
203  /** @var float */
204  var $max_crop;
205  /** @var int[] */
206  var $min_size;
207
[20335]208  /**
[25754]209   * @param int[] $ideal_size - two element array of maximum output dimensions (width, height)
210   * @param float $max_crop - from 0=no cropping to 1= max cropping (100% of width/height);
211   *    expressed as a factor of the input width/height
212   * @param int[] $min_size - (used only if _$max_crop_ !=0) two element array of output dimensions (width, height)
213   */
214  function __construct($ideal_size, $max_crop=0, $min_size=null)
[12796]215  {
216    $this->ideal_size = $ideal_size;
[25754]217    $this->max_crop = $max_crop;
[12796]218    $this->min_size = $min_size;
219  }
220
[25754]221  /**
222   * Returns a simple SizingParams object.
223   *
224   * @param int $w
225   * @param int $h
226   * @return SizingParams
227   */
[12796]228  static function classic($w, $h)
229  {
230    return new SizingParams( array($w,$h) );
231  }
232
[25754]233  /**
234   * Returns a square SizingParams object.
235   *
236   * @param int $x
237   * @return SizingParams
238   */
[12796]239  static function square($w)
240  {
241    return new SizingParams( array($w,$w), 1, array($w,$w) );
242  }
243
[25754]244  /**
245   * Adds tokens depending on sizing configuration.
246   *
247   * @param array &$tokens
248   */
[12796]249  function add_url_tokens(&$tokens)
250  {
251      if ($this->max_crop == 0)
252      {
253        $tokens[] = 's'.size_to_url($this->ideal_size);
254      }
255      elseif ($this->max_crop == 1 && size_equals($this->ideal_size, $this->min_size) )
256      {
257        $tokens[] = 'e'.size_to_url($this->ideal_size);
258      }
259      else
260      {
261        $tokens[] = size_to_url($this->ideal_size);
[13021]262        $tokens[] = fraction_to_char($this->max_crop);
[12796]263        $tokens[] = size_to_url($this->min_size);
264      }
265  }
266
[25754]267  /**
268   * Calculates the cropping rectangle and the scaled size for an input image size.
269   *
270   * @param int[] $in_size - two element array of input dimensions (width, height)
271   * @param string $coi - four character encoded string containing the center of interest (unused if max_crop=0)
272   * @param ImageRect &$crop_rect - ImageRect containing the cropping rectangle or null if cropping is not required
273   * @param int[] &$scale_size - two element array containing width and height of the scaled image
274   */
[12796]275  function compute($in_size, $coi, &$crop_rect, &$scale_size)
276  {
277    $destCrop = new ImageRect($in_size);
278
279    if ($this->max_crop > 0)
280    {
281      $ratio_w = $destCrop->width() / $this->ideal_size[0];
282      $ratio_h = $destCrop->height() / $this->ideal_size[1];
283      if ($ratio_w>1 || $ratio_h>1)
284      {
285        if ($ratio_w > $ratio_h)
286        {
287          $h = $destCrop->height() / $ratio_w;
288          if ($h < $this->min_size[1])
289          {
[13035]290            $idealCropPx = $destCrop->width() - floor($destCrop->height() * $this->ideal_size[0] / $this->min_size[1]);
[12796]291            $maxCropPx = round($this->max_crop * $destCrop->width());
[13035]292            $destCrop->crop_h( min($idealCropPx, $maxCropPx), $coi);
[12796]293          }
294        }
295        else
296        {
297          $w = $destCrop->width() / $ratio_h;
298          if ($w < $this->min_size[0])
299          {
[13035]300            $idealCropPx = $destCrop->height() - floor($destCrop->width() * $this->ideal_size[1] / $this->min_size[0]);
[12796]301            $maxCropPx = round($this->max_crop * $destCrop->height());
[13035]302            $destCrop->crop_v( min($idealCropPx, $maxCropPx), $coi);
[12796]303          }
304        }
305      }
306    }
307
308    $scale_size = array($destCrop->width(), $destCrop->height());
309
310    $ratio_w = $destCrop->width() / $this->ideal_size[0];
311    $ratio_h = $destCrop->height() / $this->ideal_size[1];
312    if ($ratio_w>1 || $ratio_h>1)
313    {
314      if ($ratio_w > $ratio_h)
315      {
316        $scale_size[0] = $this->ideal_size[0];
[13426]317        $scale_size[1] = floor(1e-6 + $scale_size[1] / $ratio_w);
[12796]318      }
319      else
320      {
[13426]321        $scale_size[0] = floor(1e-6 + $scale_size[0] / $ratio_h);
[12796]322        $scale_size[1] = $this->ideal_size[1];
323      }
324    }
325    else
326    {
327      $scale_size = null;
328    }
329
330    $crop_rect = null;
331    if ($destCrop->width()!=$in_size[0] || $destCrop->height()!=$in_size[1] )
332    {
333      $crop_rect = $destCrop;
334    }
335  }
336}
337
338
[25754]339/**
340 * All needed parameters to generate a derivative image.
341 */
[12820]342final class DerivativeParams
[12796]343{
[25754]344  /** @var SizingParams */
345  public $sizing;
346  /** @var string among IMG_* */
347  public $type = IMG_CUSTOM;
348  /** @var int used for non-custom images to regenerate the cached files */
349  public $last_mod_time = 0;
350  /** @var bool */
[12851]351  public $use_watermark = false;
[25754]352  /** @var float from 0=no sharpening to 1=max sharpening */
353  public $sharpen = 0;
[12796]354
[25754]355  /**
356   * @param SizingParams $sizing
357   */
[12796]358  function __construct($sizing)
359  {
360    $this->sizing = $sizing;
361  }
362
[25754]363  /**
364   * @return array
365   */
[12820]366  public function __sleep()
367  {
[25754]368    return array('last_mod_time', 'sizing', 'sharpen');
[12820]369  }
[13035]370
[25754]371  /**
372   * Adds tokens depending on sizing configuration.
373   *
374   * @param array &$tokens
375   */
[12796]376  function add_url_tokens(&$tokens)
377  {
378    $this->sizing->add_url_tokens($tokens);
379  }
380
[25754]381  /**
382   * @return int[]
383   */
[13038]384  function compute_final_size($in_size)
[12796]385  {
[13038]386    $this->sizing->compute( $in_size, null, $crop_rect, $scale_size );
[12796]387    return $scale_size != null ? $scale_size : $in_size;
388  }
389
[25754]390  /**
391   * @return int
392   */
[12908]393  function max_width()
394  {
395    return $this->sizing->ideal_size[0];
396  }
397
[25754]398  /**
399   * @return int
400   */
[12908]401  function max_height()
402  {
403    return $this->sizing->ideal_size[1];
404  }
[13035]405
[25754]406  /**
407   * @todo : description of DerivativeParams::is_identity
408   *
409   * @return bool
410   */
[12796]411  function is_identity($in_size)
412  {
413    if ($in_size[0] > $this->sizing->ideal_size[0] or
414        $in_size[1] > $this->sizing->ideal_size[1] )
415    {
416      return false;
417    }
418    return true;
419  }
[20335]420
[25754]421  /**
422   * @return bool
423   */
[16989]424  function will_watermark($out_size)
425  {
426    if ($this->use_watermark)
427    {
428      $min_size = ImageStdParams::get_watermark()->min_size;
429      return $min_size[0]<=$out_size[0]
[16994]430        || $min_size[1]<=$out_size[1];
[16989]431    }
432    return false;
433  }
[12796]434}
[25754]435
[12796]436?>
Note: See TracBrowser for help on using the repository browser.