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

Last change on this file since 12851 was 12851, checked in by rvelices, 9 years ago

feature 2548 multisize - sharpen + watermarks (partially implemented / no test with imagick extension)

File size: 8.4 KB
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 url_to_size($s)
37{
38  $pos = strpos($s, 'x');
39  if ($pos===false)
40  {
41    return array((int)$s, (int)$s);
42  }
43  return array((int)substr($s,0,$pos), (int)substr($s,$pos+1));
44}
45
46function size_equals($s1, $s2)
47{
48  return ($s1[0]==$s2[0] && $s1[1]==$s2[1]);
49}
50
51
52/** small utility to manipulate a 'rectangle'*/
53final class ImageRect
54{
55  public $l,$t,$r,$b;
56
57  function __construct($l)
58  {
59    $this->l = $this->t = 0;
60    $this->r = $l[0];
61    $this->b = $l[1];
62  }
63
64  function width()
65  {
66    return $this->r - $this->l;
67  }
68
69  function height()
70  {
71    return $this->b - $this->t;
72  }
73
74  function crop_h($pixels, $coi, $force)
75  {
76    if ($this->width() <= $pixels)
77      return;
78    $tlcrop = floor($pixels/2);
79
80    if (!empty($coi))
81    {
82      $coil = floor($this->r * (ord($coi[0]) - ord('a'))/25);
83      $coir = ceil($this->r * (ord($coi[2]) - ord('a'))/25);
84      $availableL = $coil > $this->l ? $coil - $this->l : 0;
85      $availableR = $coir < $this->r ? $this->r - $coir : 0;
86      if ($availableL + $availableR <= $pixels)
87      {
88        if (!$force)
89        {
90          $pixels = $availableL + $availableR;
91          $tlcrop = $availableL;
92        }
93      }
94      else
95      {
96        if ($availableL < $tlcrop)
97        {
98          $tlcrop = $availableL;
99        }
100        elseif ($availableR < $tlcrop)
101        {
102          $tlcrop = $pixels - $availableR;
103        }
104      }
105    }
106    $this->l += $tlcrop;
107    $this->r -= $pixels - $tlcrop;
108  }
109
110  function crop_v($pixels, $coi, $force)
111  {
112    if ($this->height() <= $pixels)
113      return;
114    $tlcrop = floor($pixels/2);
115
116    if (!empty($coi))
117    {
118      $coit = floor($this->b * (ord($coi[1]) - ord('a'))/25);
119      $coib = ceil($this->b * (ord($coi[3]) - ord('a'))/25);
120      $availableT = $coit > $this->t ? $coit - $this->t : 0;
121      $availableB = $coib < $this->b ? $this->b - $coib : 0;
122      if ($availableT + $availableB <= $pixels)
123      {
124        if (!$force)
125        {
126          $pixels = $availableT + $availableB;
127          $tlcrop = $availableT;
128        }
129      }
130      else
131      {
132        if ($availableT < $tlcrop)
133        {
134          $tlcrop = $availableT;
135        }
136        elseif ($availableB < $tlcrop)
137        {
138          $tlcrop = $pixels - $availableB;
139        }
140      }
141    }
142    $this->t += $tlcrop;
143    $this->b -= $pixels - $tlcrop;
144  }
145
146}
147
148
149/*how we crop and/or resize an image*/
150final class SizingParams
151{
152  function __construct($ideal_size, $max_crop = 0, $min_size = null)
153  {
154    $this->ideal_size = $ideal_size;
155    $this->max_crop = $max_crop;
156    $this->min_size = $min_size;
157  }
158
159  static function classic($w, $h)
160  {
161    return new SizingParams( array($w,$h) );
162  }
163
164  static function square($w)
165  {
166    return new SizingParams( array($w,$w), 1, array($w,$w) );
167  }
168
169  function add_url_tokens(&$tokens)
170  {
171      if ($this->max_crop == 0)
172      {
173        $tokens[] = 's'.size_to_url($this->ideal_size);
174      }
175      elseif ($this->max_crop == 1 && size_equals($this->ideal_size, $this->min_size) )
176      {
177        $tokens[] = 'e'.size_to_url($this->ideal_size);
178      }
179      else
180      {
181        $tokens[] = size_to_url($this->ideal_size);
182        $tokens[] = sprintf('%02x', round(100*$this->max_crop) );
183        $tokens[] = size_to_url($this->min_size);
184      }
185  }
186
187  static function from_url_tokens($tokens)
188  {
189    if (count($tokens)<1)
190      throw new Exception('Empty array while parsing Sizing');
191    $token = array_shift($tokens);
192    if ($token[0]=='s')
193    {
194      return new SizingParams( url_to_size( substr($token,1) ) );
195    }
196    if ($token[0]=='e')
197    {
198      $s = url_to_size( substr($token,1) );
199      return new SizingParams($s, 1, $s);
200    }
201
202    $ideal_size = url_to_size( $token );
203    if (count($tokens)<2)
204      throw new Exception('Sizing arr');
205
206    $token = array_shift($tokens);
207    $crop = sscanf('%02x' , $token) / 100;
208
209    $token = array_shift($tokens);
210    $min_size = url_to_size( $token );
211    return new SizingParams($ideal_size, $crop, $min_size);
212  }
213
214
215  function compute($in_size, $coi, &$crop_rect, &$scale_size)
216  {
217    $destCrop = new ImageRect($in_size);
218
219    if ($this->max_crop > 0)
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          $h = $destCrop->height() / $ratio_w;
228          if ($h < $this->min_size[1])
229          {
230            $idealCropPx = $destCrop->width() - round($destCrop->height() * $this->ideal_size[0] / $this->min_size[1], 0);
231            $maxCropPx = round($this->max_crop * $destCrop->width());
232            $destCrop->crop_h( min($idealCropPx, $maxCropPx), $coi, false);
233          }
234        }
235        else
236        {
237          $w = $destCrop->width() / $ratio_h;
238          if ($w < $this->min_size[0])
239          {
240            $idealCropPx = $destCrop->height() - round($destCrop->width() * $this->ideal_size[1] / $this->min_size[0], 0);
241            $maxCropPx = round($this->max_crop * $destCrop->height());
242            $destCrop->crop_v( min($idealCropPx, $maxCropPx), $coi, false);
243          }
244        }
245      }
246    }
247
248    $scale_size = array($destCrop->width(), $destCrop->height());
249
250    $ratio_w = $destCrop->width() / $this->ideal_size[0];
251    $ratio_h = $destCrop->height() / $this->ideal_size[1];
252    if ($ratio_w>1 || $ratio_h>1)
253    {
254      if ($ratio_w > $ratio_h)
255      {
256        $scale_size[0] = $this->ideal_size[0];
257        $scale_size[1] = floor($scale_size[1] / $ratio_w);
258      }
259      else
260      {
261        $scale_size[0] = floor($scale_size[0] / $ratio_h);
262        $scale_size[1] = $this->ideal_size[1];
263      }
264    }
265    else
266    {
267      $scale_size = null;
268    }
269
270    $crop_rect = null;
271    if ($destCrop->width()!=$in_size[0] || $destCrop->height()!=$in_size[1] )
272    {
273      $crop_rect = $destCrop;
274    }
275  }
276
277}
278
279
280/*how we generate a derivative image*/
281final class DerivativeParams
282{
283  public $type = IMG_CUSTOM;
284  public $last_mod_time = 0; // used for non-custom images to regenerate the cached files
285  public $use_watermark = false;
286  public $sizing;
287  public $sharpen = 0;
288  public $quality = 85;
289
290  function __construct($sizing)
291  {
292    $this->sizing = $sizing;
293  }
294
295  public function __sleep()
296  {
297      return array('last_mod_time', 'sizing', 'sharpen', 'quality');
298  }
299   
300  function add_url_tokens(&$tokens)
301  {
302    $this->sizing->add_url_tokens($tokens);
303  }
304
305  static function from_url_tokens($tokens)
306  {
307    $sizing = SizingParams::from_url_tokens($tokens);
308    $ret = new DerivativeParams($sizing);
309    return $ret;
310  }
311
312  function compute_final_size($in_size, $coi)
313  {
314    $this->sizing->compute( $in_size, $coi, $crop_rect, $scale_size );
315    return $scale_size != null ? $scale_size : $in_size;
316  }
317
318  function is_identity($in_size)
319  {
320    if ($in_size[0] > $this->sizing->ideal_size[0] or
321        $in_size[1] > $this->sizing->ideal_size[1] )
322    {
323      return false;
324    }
325    return true;
326  }
327}
328?>
Note: See TracBrowser for help on using the repository browser.