source: extensions/derivatives/include/derivative_params.inc.php @ 12770

Revision 12770, 6.6 KB checked in by rvelices, 8 years ago (diff)
Line 
1<?php
2
3function size_to_url($s)
4{
5  if ($s[0]==$s[1])
6  {
7    return $s[0];
8  }
9  return $s[0].'x'.$s[1];
10}
11
12function url_to_size($s)
13{
14  $pos = strpos($s, 'x');
15  if ($pos===false)
16  {
17    return array((int)$s, (int)$s);
18  }
19  return array((int)substr($s,0,$pos), (int)substr($s,$pos+1));
20}
21
22function size_equals($s1, $s2)
23{
24  return ($s1[0]==$s2[0] && $s1[1]==$s2[1]);
25}
26
27
28/** small utility to manipulate a 'rectangle'*/
29final class ImageRect
30{
31  public $l,$t,$r,$b;
32 
33  function __construct($l)
34  {
35    $this->l = $this->t = 0;
36    $this->r = $l[0];
37    $this->b = $l[1];
38  }
39 
40  function width()
41  {
42    return $this->r - $this->l;
43  }
44 
45  function height()
46  {
47    return $this->b - $this->t;
48  }
49
50  function crop_h($pixels, $coi, $force)
51  {
52    if ($this->width() <= $pixels)
53      return;
54    $tlcrop = floor($pixels/2);
55   
56    if (!empty($coi))
57    {
58      $coil = floor($this->r * (ord($coi[0]) - ord('a'))/25);
59      $coir = ceil($this->r * (ord($coi[2]) - ord('a'))/25);
60      $availableL = $coil > $this->l ? $coil - $this->l : 0;
61      $availableR = $coir < $this->r ? $this->r - $coir : 0;
62      if ($availableL + $availableR <= $pixels)
63      {
64        if (!$force)
65        {
66          $pixels = $availableL + $availableR;
67          $tlcrop = $availableL;
68        }
69      }
70      else
71      {
72        if ($availableL < $tlcrop)
73        {
74          $tlcrop = $availableL;
75        }
76        elseif ($availableR < $tlcrop)
77        {
78          $tlcrop = $pixels - $availableR;
79        }
80      }
81    }
82    $this->l += $tlcrop;
83    $this->r -= $pixels - $tlcrop;
84  }
85 
86  function crop_v($pixels, $coi, $force)
87  {
88    if ($this->height() <= $pixels)
89      return;
90    $tlcrop = floor($pixels/2);
91   
92    if (!empty($coi))
93    {
94      $coit = floor($this->b * (ord($coi[1]) - ord('a'))/25);
95      $coib = ceil($this->b * (ord($coi[3]) - ord('a'))/25);
96      $availableT = $coit > $this->t ? $coit - $this->t : 0;
97      $availableB = $coib < $this->b ? $this->b - $coib : 0;
98      if ($availableT + $availableB <= $pixels)
99      {
100        if (!$force)
101        {
102          $pixels = $availableT + $availableB;
103          $tlcrop = $availableT;
104        }
105      }
106      else
107      {
108        if ($availableT < $tlcrop)
109        {
110          $tlcrop = $availableT;
111        }
112        elseif ($availableB < $tlcrop)
113        {
114          $tlcrop = $pixels - $availableB;
115        }
116      }
117    }
118    $this->t += $tlcrop;
119    $this->b -= $pixels - $tlcrop;
120  }
121
122}
123
124
125/*how we crop and/or resize an image*/
126final class SizingParams
127{
128  function __construct($ideal_size, $max_crop = 0, $min_size = null)
129  {
130    $this->ideal_size = $ideal_size;
131    $this->max_crop = $max_crop;
132    $this->min_size = $min_size;
133  }
134 
135  static function classic($w, $h)
136  {
137    return new SizingParams( array($w,$h) );
138  }
139
140  static function square($w)
141  {
142    return new SizingParams( array($w,$w), 1, array($w,$w) );
143  }
144 
145  function add_url_tokens(&$tokens)
146  {
147      if (!$this->could_crop())
148      {
149        $tokens[] = 's'.size_to_url($this->ideal_size);
150      }
151      elseif ($this->max_crop == 1 && size_equals($this->ideal_size, $this->min_size) )
152      {
153        $tokens[] = 'e'.size_to_url($this->ideal_size);
154      }
155      else
156      {
157        $tokens[] = size_to_url($this->ideal_size);
158        $tokens[] = sprintf('%02x', round(100*$this->max_crop) );
159        $tokens[] = size_to_url($this->min_size);
160      }
161  }
162 
163  static function from_url_tokens($tokens)
164  {
165    if (count($tokens)<1)
166      throw new Exception('Empty array while parsing Sizing');
167    $token = array_shift($tokens);
168    if ($token[0]=='s')
169    {
170      return new SizingParams( url_to_size( substr($token,1) ) );
171    }
172    if ($token[0]=='e')
173    {
174      $s = url_to_size( substr($token,1) );
175      return new SizingParams($s, 1, $s);
176    }
177   
178    $ideal_size = url_to_size( $token );
179    if (count($tokens)<2)
180      throw new Exception('Sizing arr');
181     
182    $token = array_shift($tokens);
183    $crop = sscanf('%02x' , $token) / 100;
184   
185    $token = array_shift($tokens);
186    $min_size = url_to_size( $token );
187    return new SizingParams($ideal_size, $crop, $min_size);
188  }
189 
190  function could_crop()
191  {
192    return $this->max_crop > 0;
193  }
194
195  function compute($in_size, $coi, &$crop_rect, &$scale_size)
196  {
197    $destCrop = new ImageRect($in_size);
198   
199    if ($this->max_crop > 0)
200    {
201      $ratio_w = $destCrop->width() / $this->ideal_size[0];
202      $ratio_h = $destCrop->height() / $this->ideal_size[1];
203      if ($ratio_w>1 || $ratio_h>1)
204      {
205        if ($ratio_w > $ratio_h)
206        {
207          $h = $destCrop->height() / $ratio_w;
208          if ($h < $this->min_size[1])
209          {
210            $idealCropPx = $destCrop->width() - round($destCrop->height() * $this->ideal_size[0] / $this->min_size[1], 0);
211            $maxCropPx = round($this->max_crop * $destCrop->width());
212            $destCrop->crop_h( min($idealCropPx, $maxCropPx), $coi, false);
213          }
214        }
215        else
216        {
217          $w = $destCrop->width() / $ratio_h;
218          if ($w < $this->min_size[0])
219          {
220            $idealCropPx = $destCrop->height() - round($destCrop->width() * $this->ideal_size[1] / $this->min_size[0], 0);
221            $maxCropPx = round($this->max_crop * $destCrop->height());
222            $destCrop->crop_v( min($idealCropPx, $maxCropPx), $coi, false);
223          }
224        }
225      }
226    }
227   
228    $scale_size = array($destCrop->width(), $destCrop->height());
229   
230    $ratio_w = $destCrop->width() / $this->ideal_size[0];
231    $ratio_h = $destCrop->height() / $this->ideal_size[1];
232    if ($ratio_w>1 || $ratio_h>1)
233    {
234      if ($ratio_w > $ratio_h)
235      {
236        $scale_size[0] = $this->ideal_size[0];
237        $scale_size[1] = floor($scale_size[1] / $ratio_w);
238      }
239      else
240      {
241        $scale_size[0] = floor($scale_size[0] / $ratio_h);
242        $scale_size[1] = $this->ideal_size[1];
243      }
244    }
245    else
246    {
247      $scale_size = null;
248    }
249   
250    $crop_rect = null;
251    if ($destCrop->width()!=$in_size[0] || $destCrop->height()!=$in_size[1] )
252    {
253      $crop_rect = $destCrop;
254    }
255  }
256
257}
258
259
260/*how we generate a derivative image*/
261final class ImageParams
262{
263  public $sizing;
264 
265  function __construct($sizing)
266  {
267    $this->sizing = $sizing;
268  }
269 
270  function add_url_tokens(&$tokens)
271  {
272    $this->sizing->add_url_tokens($tokens);
273  }
274 
275  static function from_url_tokens($tokens)
276  {
277    $sizing = SizingParams::from_url_tokens($tokens);
278    $ret = new ImageParams($sizing);
279    return $ret;
280  }
281 
282  function compute_final_size($in_size, $coi)
283  {
284    $this->sizing->compute( $in_size, $coi, $crop_rect, $scale_size );
285    return $scale_size != null ? $scale_size : $in_size;
286  }
287}
288?>
Note: See TracBrowser for help on using the repository browser.