root/trunk/include/derivative_params.inc.php @ 13021

Revision 13021, 7.6 KB (checked in by rvelices, 17 months ago)

feature 2548 multisize - custom sizes restricted to those requested by theme/plugin
code refacto

Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2012 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 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  function crop_h($pixels, $coi, $force)
74  {
75    if ($this->width() <= $pixels)
76      return;
77    $tlcrop = floor($pixels/2);
78
79    if (!empty($coi))
80    {
81      $coil = floor($this->r * char_to_fraction($coi[0]));
82      $coir = ceil($this->r * char_to_fraction($coi[2]));
83      $availableL = $coil > $this->l ? $coil - $this->l : 0;
84      $availableR = $coir < $this->r ? $this->r - $coir : 0;
85      if ($availableL + $availableR <= $pixels)
86      {
87        if (!$force)
88        {
89          $pixels = $availableL + $availableR;
90          $tlcrop = $availableL;
91        }
92      }
93      else
94      {
95        if ($availableL < $tlcrop)
96        {
97          $tlcrop = $availableL;
98        }
99        elseif ($availableR < $tlcrop)
100        {
101          $tlcrop = $pixels - $availableR;
102        }
103      }
104    }
105    $this->l += $tlcrop;
106    $this->r -= $pixels - $tlcrop;
107  }
108
109  function crop_v($pixels, $coi, $force)
110  {
111    if ($this->height() <= $pixels)
112      return;
113    $tlcrop = floor($pixels/2);
114
115    if (!empty($coi))
116    {
117      $coit = floor($this->b * char_to_fraction($coi[1]));
118      $coib = ceil($this->b * char_to_fraction($coi[3]));
119      $availableT = $coit > $this->t ? $coit - $this->t : 0;
120      $availableB = $coib < $this->b ? $this->b - $coib : 0;
121      if ($availableT + $availableB <= $pixels)
122      {
123        if (!$force)
124        {
125          $pixels = $availableT + $availableB;
126          $tlcrop = $availableT;
127        }
128      }
129      else
130      {
131        if ($availableT < $tlcrop)
132        {
133          $tlcrop = $availableT;
134        }
135        elseif ($availableB < $tlcrop)
136        {
137          $tlcrop = $pixels - $availableB;
138        }
139      }
140    }
141    $this->t += $tlcrop;
142    $this->b -= $pixels - $tlcrop;
143  }
144
145}
146
147
148/*how we crop and/or resize an image*/
149final class SizingParams
150{
151  function __construct($ideal_size, $max_crop = 0, $min_size = null)
152  {
153    $this->ideal_size = $ideal_size;
154    $this->max_crop = $max_crop;
155    $this->min_size = $min_size;
156  }
157
158  static function classic($w, $h)
159  {
160    return new SizingParams( array($w,$h) );
161  }
162
163  static function square($w)
164  {
165    return new SizingParams( array($w,$w), 1, array($w,$w) );
166  }
167
168  function add_url_tokens(&$tokens)
169  {
170      if ($this->max_crop == 0)
171      {
172        $tokens[] = 's'.size_to_url($this->ideal_size);
173      }
174      elseif ($this->max_crop == 1 && size_equals($this->ideal_size, $this->min_size) )
175      {
176        $tokens[] = 'e'.size_to_url($this->ideal_size);
177      }
178      else
179      {
180        $tokens[] = size_to_url($this->ideal_size);
181        $tokens[] = fraction_to_char($this->max_crop);
182        $tokens[] = size_to_url($this->min_size);
183      }
184  }
185
186  function compute($in_size, $coi, &$crop_rect, &$scale_size)
187  {
188    $destCrop = new ImageRect($in_size);
189
190    if ($this->max_crop > 0)
191    {
192      $ratio_w = $destCrop->width() / $this->ideal_size[0];
193      $ratio_h = $destCrop->height() / $this->ideal_size[1];
194      if ($ratio_w>1 || $ratio_h>1)
195      {
196        if ($ratio_w > $ratio_h)
197        {
198          $h = $destCrop->height() / $ratio_w;
199          if ($h < $this->min_size[1])
200          {
201            $idealCropPx = $destCrop->width() - round($destCrop->height() * $this->ideal_size[0] / $this->min_size[1], 0);
202            $maxCropPx = round($this->max_crop * $destCrop->width());
203            $destCrop->crop_h( min($idealCropPx, $maxCropPx), $coi, false);
204          }
205        }
206        else
207        {
208          $w = $destCrop->width() / $ratio_h;
209          if ($w < $this->min_size[0])
210          {
211            $idealCropPx = $destCrop->height() - round($destCrop->width() * $this->ideal_size[1] / $this->min_size[0], 0);
212            $maxCropPx = round($this->max_crop * $destCrop->height());
213            $destCrop->crop_v( min($idealCropPx, $maxCropPx), $coi, false);
214          }
215        }
216      }
217    }
218
219    $scale_size = array($destCrop->width(), $destCrop->height());
220
221    $ratio_w = $destCrop->width() / $this->ideal_size[0];
222    $ratio_h = $destCrop->height() / $this->ideal_size[1];
223    if ($ratio_w>1 || $ratio_h>1)
224    {
225      if ($ratio_w > $ratio_h)
226      {
227        $scale_size[0] = $this->ideal_size[0];
228        $scale_size[1] = floor($scale_size[1] / $ratio_w);
229      }
230      else
231      {
232        $scale_size[0] = floor($scale_size[0] / $ratio_h);
233        $scale_size[1] = $this->ideal_size[1];
234      }
235    }
236    else
237    {
238      $scale_size = null;
239    }
240
241    $crop_rect = null;
242    if ($destCrop->width()!=$in_size[0] || $destCrop->height()!=$in_size[1] )
243    {
244      $crop_rect = $destCrop;
245    }
246  }
247
248}
249
250
251/*how we generate a derivative image*/
252final class DerivativeParams
253{
254  public $type = IMG_CUSTOM;
255  public $last_mod_time = 0; // used for non-custom images to regenerate the cached files
256  public $use_watermark = false;
257  public $sizing;
258  public $sharpen = 0;
259  public $quality = 85;
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', 'quality');
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, $coi)
277  {
278    $this->sizing->compute( $in_size, $coi, $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?>
Note: See TracBrowser for help on using the browser.