source: branches/2.4/include/derivative_params.inc.php @ 16990

Revision 16990, 7.5 KB checked in by rvelices, 7 years ago (diff)

bug 2682: Watermark sizing calculation is made on the requested size not on the final one (merge from trunk)

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 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  function crop_h($pixels, $coi)
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 ($availableL < $tlcrop)
88        {
89          $tlcrop = $availableL;
90        }
91        elseif ($availableR < $tlcrop)
92        {
93          $tlcrop = $pixels - $availableR;
94        }
95      }
96    }
97    $this->l += $tlcrop;
98    $this->r -= $pixels - $tlcrop;
99  }
100
101  function crop_v($pixels, $coi)
102  {
103    if ($this->height() <= $pixels)
104      return;
105    $tlcrop = floor($pixels/2);
106
107    if (!empty($coi))
108    {
109      $coit = floor($this->b * char_to_fraction($coi[1]));
110      $coib = ceil($this->b * char_to_fraction($coi[3]));
111      $availableT = $coit > $this->t ? $coit - $this->t : 0;
112      $availableB = $coib < $this->b ? $this->b - $coib : 0;
113      if ($availableT + $availableB >= $pixels)
114      {
115        if ($availableT < $tlcrop)
116        {
117          $tlcrop = $availableT;
118        }
119        elseif ($availableB < $tlcrop)
120        {
121          $tlcrop = $pixels - $availableB;
122        }
123      }
124    }
125    $this->t += $tlcrop;
126    $this->b -= $pixels - $tlcrop;
127  }
128
129}
130
131
132/*how we crop and/or resize an image*/
133final class SizingParams
134{
135  function __construct($ideal_size, $max_crop = 0, $min_size = null)
136  {
137    $this->ideal_size = $ideal_size;
138    $this->max_crop = $max_crop;
139    $this->min_size = $min_size;
140  }
141
142  static function classic($w, $h)
143  {
144    return new SizingParams( array($w,$h) );
145  }
146
147  static function square($w)
148  {
149    return new SizingParams( array($w,$w), 1, array($w,$w) );
150  }
151
152  function add_url_tokens(&$tokens)
153  {
154      if ($this->max_crop == 0)
155      {
156        $tokens[] = 's'.size_to_url($this->ideal_size);
157      }
158      elseif ($this->max_crop == 1 && size_equals($this->ideal_size, $this->min_size) )
159      {
160        $tokens[] = 'e'.size_to_url($this->ideal_size);
161      }
162      else
163      {
164        $tokens[] = size_to_url($this->ideal_size);
165        $tokens[] = fraction_to_char($this->max_crop);
166        $tokens[] = size_to_url($this->min_size);
167      }
168  }
169
170  function compute($in_size, $coi, &$crop_rect, &$scale_size)
171  {
172    $destCrop = new ImageRect($in_size);
173
174    if ($this->max_crop > 0)
175    {
176      $ratio_w = $destCrop->width() / $this->ideal_size[0];
177      $ratio_h = $destCrop->height() / $this->ideal_size[1];
178      if ($ratio_w>1 || $ratio_h>1)
179      {
180        if ($ratio_w > $ratio_h)
181        {
182          $h = $destCrop->height() / $ratio_w;
183          if ($h < $this->min_size[1])
184          {
185            $idealCropPx = $destCrop->width() - floor($destCrop->height() * $this->ideal_size[0] / $this->min_size[1]);
186            $maxCropPx = round($this->max_crop * $destCrop->width());
187            $destCrop->crop_h( min($idealCropPx, $maxCropPx), $coi);
188          }
189        }
190        else
191        {
192          $w = $destCrop->width() / $ratio_h;
193          if ($w < $this->min_size[0])
194          {
195            $idealCropPx = $destCrop->height() - floor($destCrop->width() * $this->ideal_size[1] / $this->min_size[0]);
196            $maxCropPx = round($this->max_crop * $destCrop->height());
197            $destCrop->crop_v( min($idealCropPx, $maxCropPx), $coi);
198          }
199        }
200      }
201    }
202
203    $scale_size = array($destCrop->width(), $destCrop->height());
204
205    $ratio_w = $destCrop->width() / $this->ideal_size[0];
206    $ratio_h = $destCrop->height() / $this->ideal_size[1];
207    if ($ratio_w>1 || $ratio_h>1)
208    {
209      if ($ratio_w > $ratio_h)
210      {
211        $scale_size[0] = $this->ideal_size[0];
212        $scale_size[1] = floor(1e-6 + $scale_size[1] / $ratio_w);
213      }
214      else
215      {
216        $scale_size[0] = floor(1e-6 + $scale_size[0] / $ratio_h);
217        $scale_size[1] = $this->ideal_size[1];
218      }
219    }
220    else
221    {
222      $scale_size = null;
223    }
224
225    $crop_rect = null;
226    if ($destCrop->width()!=$in_size[0] || $destCrop->height()!=$in_size[1] )
227    {
228      $crop_rect = $destCrop;
229    }
230  }
231
232}
233
234
235/*how we generate a derivative image*/
236final class DerivativeParams
237{
238  public $type = IMG_CUSTOM;
239  public $last_mod_time = 0; // used for non-custom images to regenerate the cached files
240  public $use_watermark = false;
241  public $sizing;
242  public $sharpen = 0;
243
244  function __construct($sizing)
245  {
246    $this->sizing = $sizing;
247  }
248
249  public function __sleep()
250  {
251      return array('last_mod_time', 'sizing', 'sharpen');
252  }
253
254  function add_url_tokens(&$tokens)
255  {
256    $this->sizing->add_url_tokens($tokens);
257  }
258
259  function compute_final_size($in_size)
260  {
261    $this->sizing->compute( $in_size, null, $crop_rect, $scale_size );
262    return $scale_size != null ? $scale_size : $in_size;
263  }
264
265  function max_width()
266  {
267    return $this->sizing->ideal_size[0];
268  }
269
270  function max_height()
271  {
272    return $this->sizing->ideal_size[1];
273  }
274
275  function is_identity($in_size)
276  {
277    if ($in_size[0] > $this->sizing->ideal_size[0] or
278        $in_size[1] > $this->sizing->ideal_size[1] )
279    {
280      return false;
281    }
282    return true;
283  }
284 
285  function will_watermark($out_size)
286  {
287    if ($this->use_watermark)
288    {
289      $min_size = ImageStdParams::get_watermark()->min_size;
290      return $min_size[0]<=$out_size[0]
291        && $min_size[1]<=$$out_size[1];
292    }
293    return false;
294  }
295}
296?>
Note: See TracBrowser for help on using the repository browser.