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

Last change on this file since 21182 was 20335, checked in by rvelices, 12 years ago

some code comments

File size: 9.0 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
22function derivative_to_url($t)
23{
24  return substr($t, 0, 2);
25}
26
27function size_to_url($s)
28{
29  if ($s[0]==$s[1])
30  {
31    return $s[0];
32  }
33  return $s[0].'x'.$s[1];
34}
35
36function size_equals($s1, $s2)
37{
38  return ($s1[0]==$s2[0] && $s1[1]==$s2[1]);
39}
40
41function char_to_fraction($c)
42{
43        return (ord($c) - ord('a'))/25;
44}
45
46function fraction_to_char($f)
47{
48        return chr(ord('a') + round($f*25));
49}
50
51/** small utility to manipulate a 'rectangle'*/
52final class ImageRect
53{
54  public $l,$t,$r,$b;
55
56  function __construct($l)
57  {
58    $this->l = $this->t = 0;
59    $this->r = $l[0];
60    $this->b = $l[1];
61  }
62
63  function width()
64  {
65    return $this->r - $this->l;
66  }
67
68  function height()
69  {
70    return $this->b - $this->t;
71  }
72
73  /** crops horizontally this rectangle by increasing left side and/or reducing the right side.
74  @param pixels the amount to substract from the width
75  @param coi a 4 character string (or null) containing the center of interest*/
76  function crop_h($pixels, $coi)
77  {
78    if ($this->width() <= $pixels)
79      return;
80    $tlcrop = floor($pixels/2);
81
82    if (!empty($coi))
83    {
84      $coil = floor($this->r * char_to_fraction($coi[0]));
85      $coir = ceil($this->r * char_to_fraction($coi[2]));
86      $availableL = $coil > $this->l ? $coil - $this->l : 0;
87      $availableR = $coir < $this->r ? $this->r - $coir : 0;
88      if ($availableL + $availableR >= $pixels)
89      {
90        if ($availableL < $tlcrop)
91        {
92          $tlcrop = $availableL;
93        }
94        elseif ($availableR < $tlcrop)
95        {
96          $tlcrop = $pixels - $availableR;
97        }
98      }
99    }
100    $this->l += $tlcrop;
101    $this->r -= $pixels - $tlcrop;
102  }
103
104  /** crops vertically this rectangle by increasing top side and/or reducing the bottom side.
105  @param pixels the amount to substract from the height
106  @param coi a 4 character string (or null) containing the center of interest*/
107  function crop_v($pixels, $coi)
108  {
109    if ($this->height() <= $pixels)
110      return;
111    $tlcrop = floor($pixels/2);
112
113    if (!empty($coi))
114    {
115      $coit = floor($this->b * char_to_fraction($coi[1]));
116      $coib = ceil($this->b * char_to_fraction($coi[3]));
117      $availableT = $coit > $this->t ? $coit - $this->t : 0;
118      $availableB = $coib < $this->b ? $this->b - $coib : 0;
119      if ($availableT + $availableB >= $pixels)
120      {
121        if ($availableT < $tlcrop)
122        {
123          $tlcrop = $availableT;
124        }
125        elseif ($availableB < $tlcrop)
126        {
127          $tlcrop = $pixels - $availableB;
128        }
129      }
130    }
131    $this->t += $tlcrop;
132    $this->b -= $pixels - $tlcrop;
133  }
134
135}
136
137
138/** Paramaters for derivative scaling and cropping. Instance of this class contained by DerivativeParams class.*/
139final class SizingParams
140{
141  /**
142  @param ideal_size two element array of maximum output dimensions (width, height)
143  @param max_crop range 0=no cropping ... 1= max cropping (100% of width/height); expressed as a factor of the input width/height
144  @param min_size used only if max_crop != 0 - two element array of output dimensions (width, height)
145  */
146  function __construct($ideal_size, $max_crop = 0, $min_size = null)
147  {
148    $this->ideal_size = $ideal_size;
149    $this->max_crop = $max_crop; // range 0=no cropping ... 1= max cropping (100% of width/height)
150    $this->min_size = $min_size;
151  }
152
153  static function classic($w, $h)
154  {
155    return new SizingParams( array($w,$h) );
156  }
157
158  static function square($w)
159  {
160    return new SizingParams( array($w,$w), 1, array($w,$w) );
161  }
162
163  function add_url_tokens(&$tokens)
164  {
165      if ($this->max_crop == 0)
166      {
167        $tokens[] = 's'.size_to_url($this->ideal_size);
168      }
169      elseif ($this->max_crop == 1 && size_equals($this->ideal_size, $this->min_size) )
170      {
171        $tokens[] = 'e'.size_to_url($this->ideal_size);
172      }
173      else
174      {
175        $tokens[] = size_to_url($this->ideal_size);
176        $tokens[] = fraction_to_char($this->max_crop);
177        $tokens[] = size_to_url($this->min_size);
178      }
179  }
180
181  /* calculate the cropping rectangle and the scaled size for an input image size
182  @param in_size two element array of input dimensions (width, height)
183  @param coi empty or a four character encoded string containing the center of interest (unused if max_crop=0)
184  @param crop_rect output ImageRect containing the cropping rectangle or null if cropping is not required
185  @param scale_size output two element array containing width and height of the scaled image
186  */
187  function compute($in_size, $coi, &$crop_rect, &$scale_size)
188  {
189    $destCrop = new ImageRect($in_size);
190
191    if ($this->max_crop > 0)
192    {
193      $ratio_w = $destCrop->width() / $this->ideal_size[0];
194      $ratio_h = $destCrop->height() / $this->ideal_size[1];
195      if ($ratio_w>1 || $ratio_h>1)
196      {
197        if ($ratio_w > $ratio_h)
198        {
199          $h = $destCrop->height() / $ratio_w;
200          if ($h < $this->min_size[1])
201          {
202            $idealCropPx = $destCrop->width() - floor($destCrop->height() * $this->ideal_size[0] / $this->min_size[1]);
203            $maxCropPx = round($this->max_crop * $destCrop->width());
204            $destCrop->crop_h( min($idealCropPx, $maxCropPx), $coi);
205          }
206        }
207        else
208        {
209          $w = $destCrop->width() / $ratio_h;
210          if ($w < $this->min_size[0])
211          {
212            $idealCropPx = $destCrop->height() - floor($destCrop->width() * $this->ideal_size[1] / $this->min_size[0]);
213            $maxCropPx = round($this->max_crop * $destCrop->height());
214            $destCrop->crop_v( min($idealCropPx, $maxCropPx), $coi);
215          }
216        }
217      }
218    }
219
220    $scale_size = array($destCrop->width(), $destCrop->height());
221
222    $ratio_w = $destCrop->width() / $this->ideal_size[0];
223    $ratio_h = $destCrop->height() / $this->ideal_size[1];
224    if ($ratio_w>1 || $ratio_h>1)
225    {
226      if ($ratio_w > $ratio_h)
227      {
228        $scale_size[0] = $this->ideal_size[0];
229        $scale_size[1] = floor(1e-6 + $scale_size[1] / $ratio_w);
230      }
231      else
232      {
233        $scale_size[0] = floor(1e-6 + $scale_size[0] / $ratio_h);
234        $scale_size[1] = $this->ideal_size[1];
235      }
236    }
237    else
238    {
239      $scale_size = null;
240    }
241
242    $crop_rect = null;
243    if ($destCrop->width()!=$in_size[0] || $destCrop->height()!=$in_size[1] )
244    {
245      $crop_rect = $destCrop;
246    }
247  }
248
249}
250
251
252/** All needed parameters to generate a derivative image.*/
253final class DerivativeParams
254{
255  public $type = IMG_CUSTOM; // string IMG_xxx
256  public $last_mod_time = 0; // used for non-custom images to regenerate the cached files
257  public $use_watermark = false;
258  public $sizing; // of type SizingParams
259  public $sharpen = 0; // range 0= no sharpening ... 1= max sharpening
260
261  function __construct($sizing)
262  {
263    $this->sizing = $sizing;
264  }
265
266  public function __sleep()
267  {
268      return array('last_mod_time', 'sizing', 'sharpen');
269  }
270
271  function add_url_tokens(&$tokens)
272  {
273    $this->sizing->add_url_tokens($tokens);
274  }
275
276  function compute_final_size($in_size)
277  {
278    $this->sizing->compute( $in_size, null, $crop_rect, $scale_size );
279    return $scale_size != null ? $scale_size : $in_size;
280  }
281
282  function max_width()
283  {
284    return $this->sizing->ideal_size[0];
285  }
286
287  function max_height()
288  {
289    return $this->sizing->ideal_size[1];
290  }
291
292  function is_identity($in_size)
293  {
294    if ($in_size[0] > $this->sizing->ideal_size[0] or
295        $in_size[1] > $this->sizing->ideal_size[1] )
296    {
297      return false;
298    }
299    return true;
300  }
301
302  function will_watermark($out_size)
303  {
304    if ($this->use_watermark)
305    {
306      $min_size = ImageStdParams::get_watermark()->min_size;
307      return $min_size[0]<=$out_size[0]
308        || $min_size[1]<=$out_size[1];
309    }
310    return false;
311  }
312}
313?>
Note: See TracBrowser for help on using the repository browser.