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

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

derivatives - can display several sizes on picture page

File size: 6.7 KB
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->max_crop == 0)
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
191  function compute($in_size, $coi, &$crop_rect, &$scale_size)
192  {
193    $destCrop = new ImageRect($in_size);
194
195    if ($this->max_crop > 0)
196    {
197      $ratio_w = $destCrop->width() / $this->ideal_size[0];
198      $ratio_h = $destCrop->height() / $this->ideal_size[1];
199      if ($ratio_w>1 || $ratio_h>1)
200      {
201        if ($ratio_w > $ratio_h)
202        {
203          $h = $destCrop->height() / $ratio_w;
204          if ($h < $this->min_size[1])
205          {
206            $idealCropPx = $destCrop->width() - round($destCrop->height() * $this->ideal_size[0] / $this->min_size[1], 0);
207            $maxCropPx = round($this->max_crop * $destCrop->width());
208            $destCrop->crop_h( min($idealCropPx, $maxCropPx), $coi, false);
209          }
210        }
211        else
212        {
213          $w = $destCrop->width() / $ratio_h;
214          if ($w < $this->min_size[0])
215          {
216            $idealCropPx = $destCrop->height() - round($destCrop->width() * $this->ideal_size[1] / $this->min_size[0], 0);
217            $maxCropPx = round($this->max_crop * $destCrop->height());
218            $destCrop->crop_v( min($idealCropPx, $maxCropPx), $coi, false);
219          }
220        }
221      }
222    }
223
224    $scale_size = array($destCrop->width(), $destCrop->height());
225
226    $ratio_w = $destCrop->width() / $this->ideal_size[0];
227    $ratio_h = $destCrop->height() / $this->ideal_size[1];
228    if ($ratio_w>1 || $ratio_h>1)
229    {
230      if ($ratio_w > $ratio_h)
231      {
232        $scale_size[0] = $this->ideal_size[0];
233        $scale_size[1] = floor($scale_size[1] / $ratio_w);
234      }
235      else
236      {
237        $scale_size[0] = floor($scale_size[0] / $ratio_h);
238        $scale_size[1] = $this->ideal_size[1];
239      }
240    }
241    else
242    {
243      $scale_size = null;
244    }
245
246    $crop_rect = null;
247    if ($destCrop->width()!=$in_size[0] || $destCrop->height()!=$in_size[1] )
248    {
249      $crop_rect = $destCrop;
250    }
251  }
252
253}
254
255
256/*how we generate a derivative image*/
257final class ImageParams
258{
259  public $type = IMG_CUSTOM;
260  public $sizing;
261
262  function __construct($sizing)
263  {
264    $this->sizing = $sizing;
265  }
266
267  function add_url_tokens(&$tokens)
268  {
269    $this->sizing->add_url_tokens($tokens);
270  }
271
272  static function from_url_tokens($tokens)
273  {
274    $sizing = SizingParams::from_url_tokens($tokens);
275    $ret = new ImageParams($sizing);
276    return $ret;
277  }
278
279  function compute_final_size($in_size, $coi)
280  {
281    $this->sizing->compute( $in_size, $coi, $crop_rect, $scale_size );
282    return $scale_size != null ? $scale_size : $in_size;
283  }
284
285  function is_identity($in_size)
286  {
287    if ($in_size[0] > $this->sizing->ideal_size[0] or
288        $in_size[1] > $this->sizing->ideal_size[1] )
289    {
290      return false;
291    }
292    return true;
293  }
294}
295?>
Note: See TracBrowser for help on using the repository browser.