aboutsummaryrefslogtreecommitdiffstats
path: root/include/derivative_params.inc.php
diff options
context:
space:
mode:
authorrvelices <rv-github@modusoptimus.com>2011-12-27 05:26:44 +0000
committerrvelices <rv-github@modusoptimus.com>2011-12-27 05:26:44 +0000
commit753f58d6a966a1051dcd62a3eeab8fc18798bcac (patch)
tree2ebbfec86d511aa980e0d23c170bfa5006a8793e /include/derivative_params.inc.php
parente77e68b7db17c28c1ca44f4865758f2afb871d07 (diff)
feature 2541 multisize
- core implementation + usage on most public/admin pages - still to do: sync process, upload, gui/persistence for size parameters, migration script, center of interest ... git-svn-id: http://piwigo.org/svn/trunk@12796 68402e56-0260-453c-a942-63ccdbb3a9ee
Diffstat (limited to '')
-rw-r--r--include/derivative_params.inc.php315
1 files changed, 315 insertions, 0 deletions
diff --git a/include/derivative_params.inc.php b/include/derivative_params.inc.php
new file mode 100644
index 000000000..9fe76cd43
--- /dev/null
+++ b/include/derivative_params.inc.php
@@ -0,0 +1,315 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based photo gallery |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2012 Piwigo Team http://piwigo.org |
+// +-----------------------------------------------------------------------+
+// | This program is free software; you can redistribute it and/or modify |
+// | it under the terms of the GNU General Public License as published by |
+// | the Free Software Foundation |
+// | |
+// | This program is distributed in the hope that it will be useful, but |
+// | WITHOUT ANY WARRANTY; without even the implied warranty of |
+// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
+// | General Public License for more details. |
+// | |
+// | You should have received a copy of the GNU General Public License |
+// | along with this program; if not, write to the Free Software |
+// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
+// | USA. |
+// +-----------------------------------------------------------------------+
+
+function size_to_url($s)
+{
+ if ($s[0]==$s[1])
+ {
+ return $s[0];
+ }
+ return $s[0].'x'.$s[1];
+}
+
+function url_to_size($s)
+{
+ $pos = strpos($s, 'x');
+ if ($pos===false)
+ {
+ return array((int)$s, (int)$s);
+ }
+ return array((int)substr($s,0,$pos), (int)substr($s,$pos+1));
+}
+
+function size_equals($s1, $s2)
+{
+ return ($s1[0]==$s2[0] && $s1[1]==$s2[1]);
+}
+
+
+/** small utility to manipulate a 'rectangle'*/
+final class ImageRect
+{
+ public $l,$t,$r,$b;
+
+ function __construct($l)
+ {
+ $this->l = $this->t = 0;
+ $this->r = $l[0];
+ $this->b = $l[1];
+ }
+
+ function width()
+ {
+ return $this->r - $this->l;
+ }
+
+ function height()
+ {
+ return $this->b - $this->t;
+ }
+
+ function crop_h($pixels, $coi, $force)
+ {
+ if ($this->width() <= $pixels)
+ return;
+ $tlcrop = floor($pixels/2);
+
+ if (!empty($coi))
+ {
+ $coil = floor($this->r * (ord($coi[0]) - ord('a'))/25);
+ $coir = ceil($this->r * (ord($coi[2]) - ord('a'))/25);
+ $availableL = $coil > $this->l ? $coil - $this->l : 0;
+ $availableR = $coir < $this->r ? $this->r - $coir : 0;
+ if ($availableL + $availableR <= $pixels)
+ {
+ if (!$force)
+ {
+ $pixels = $availableL + $availableR;
+ $tlcrop = $availableL;
+ }
+ }
+ else
+ {
+ if ($availableL < $tlcrop)
+ {
+ $tlcrop = $availableL;
+ }
+ elseif ($availableR < $tlcrop)
+ {
+ $tlcrop = $pixels - $availableR;
+ }
+ }
+ }
+ $this->l += $tlcrop;
+ $this->r -= $pixels - $tlcrop;
+ }
+
+ function crop_v($pixels, $coi, $force)
+ {
+ if ($this->height() <= $pixels)
+ return;
+ $tlcrop = floor($pixels/2);
+
+ if (!empty($coi))
+ {
+ $coit = floor($this->b * (ord($coi[1]) - ord('a'))/25);
+ $coib = ceil($this->b * (ord($coi[3]) - ord('a'))/25);
+ $availableT = $coit > $this->t ? $coit - $this->t : 0;
+ $availableB = $coib < $this->b ? $this->b - $coib : 0;
+ if ($availableT + $availableB <= $pixels)
+ {
+ if (!$force)
+ {
+ $pixels = $availableT + $availableB;
+ $tlcrop = $availableT;
+ }
+ }
+ else
+ {
+ if ($availableT < $tlcrop)
+ {
+ $tlcrop = $availableT;
+ }
+ elseif ($availableB < $tlcrop)
+ {
+ $tlcrop = $pixels - $availableB;
+ }
+ }
+ }
+ $this->t += $tlcrop;
+ $this->b -= $pixels - $tlcrop;
+ }
+
+}
+
+
+/*how we crop and/or resize an image*/
+final class SizingParams
+{
+ function __construct($ideal_size, $max_crop = 0, $min_size = null)
+ {
+ $this->ideal_size = $ideal_size;
+ $this->max_crop = $max_crop;
+ $this->min_size = $min_size;
+ }
+
+ static function classic($w, $h)
+ {
+ return new SizingParams( array($w,$h) );
+ }
+
+ static function square($w)
+ {
+ return new SizingParams( array($w,$w), 1, array($w,$w) );
+ }
+
+ function add_url_tokens(&$tokens)
+ {
+ if ($this->max_crop == 0)
+ {
+ $tokens[] = 's'.size_to_url($this->ideal_size);
+ }
+ elseif ($this->max_crop == 1 && size_equals($this->ideal_size, $this->min_size) )
+ {
+ $tokens[] = 'e'.size_to_url($this->ideal_size);
+ }
+ else
+ {
+ $tokens[] = size_to_url($this->ideal_size);
+ $tokens[] = sprintf('%02x', round(100*$this->max_crop) );
+ $tokens[] = size_to_url($this->min_size);
+ }
+ }
+
+ static function from_url_tokens($tokens)
+ {
+ if (count($tokens)<1)
+ throw new Exception('Empty array while parsing Sizing');
+ $token = array_shift($tokens);
+ if ($token[0]=='s')
+ {
+ return new SizingParams( url_to_size( substr($token,1) ) );
+ }
+ if ($token[0]=='e')
+ {
+ $s = url_to_size( substr($token,1) );
+ return new SizingParams($s, 1, $s);
+ }
+
+ $ideal_size = url_to_size( $token );
+ if (count($tokens)<2)
+ throw new Exception('Sizing arr');
+
+ $token = array_shift($tokens);
+ $crop = sscanf('%02x' , $token) / 100;
+
+ $token = array_shift($tokens);
+ $min_size = url_to_size( $token );
+ return new SizingParams($ideal_size, $crop, $min_size);
+ }
+
+
+ function compute($in_size, $coi, &$crop_rect, &$scale_size)
+ {
+ $destCrop = new ImageRect($in_size);
+
+ if ($this->max_crop > 0)
+ {
+ $ratio_w = $destCrop->width() / $this->ideal_size[0];
+ $ratio_h = $destCrop->height() / $this->ideal_size[1];
+ if ($ratio_w>1 || $ratio_h>1)
+ {
+ if ($ratio_w > $ratio_h)
+ {
+ $h = $destCrop->height() / $ratio_w;
+ if ($h < $this->min_size[1])
+ {
+ $idealCropPx = $destCrop->width() - round($destCrop->height() * $this->ideal_size[0] / $this->min_size[1], 0);
+ $maxCropPx = round($this->max_crop * $destCrop->width());
+ $destCrop->crop_h( min($idealCropPx, $maxCropPx), $coi, false);
+ }
+ }
+ else
+ {
+ $w = $destCrop->width() / $ratio_h;
+ if ($w < $this->min_size[0])
+ {
+ $idealCropPx = $destCrop->height() - round($destCrop->width() * $this->ideal_size[1] / $this->min_size[0], 0);
+ $maxCropPx = round($this->max_crop * $destCrop->height());
+ $destCrop->crop_v( min($idealCropPx, $maxCropPx), $coi, false);
+ }
+ }
+ }
+ }
+
+ $scale_size = array($destCrop->width(), $destCrop->height());
+
+ $ratio_w = $destCrop->width() / $this->ideal_size[0];
+ $ratio_h = $destCrop->height() / $this->ideal_size[1];
+ if ($ratio_w>1 || $ratio_h>1)
+ {
+ if ($ratio_w > $ratio_h)
+ {
+ $scale_size[0] = $this->ideal_size[0];
+ $scale_size[1] = floor($scale_size[1] / $ratio_w);
+ }
+ else
+ {
+ $scale_size[0] = floor($scale_size[0] / $ratio_h);
+ $scale_size[1] = $this->ideal_size[1];
+ }
+ }
+ else
+ {
+ $scale_size = null;
+ }
+
+ $crop_rect = null;
+ if ($destCrop->width()!=$in_size[0] || $destCrop->height()!=$in_size[1] )
+ {
+ $crop_rect = $destCrop;
+ }
+ }
+
+}
+
+
+/*how we generate a derivative image*/
+final class ImageParams
+{
+ public $type = IMG_CUSTOM;
+ public $last_mod_time = 0; // used for non-custom images to regenerate the cached files
+ public $sizing;
+
+ function __construct($sizing)
+ {
+ $this->sizing = $sizing;
+ }
+
+ function add_url_tokens(&$tokens)
+ {
+ $this->sizing->add_url_tokens($tokens);
+ }
+
+ static function from_url_tokens($tokens)
+ {
+ $sizing = SizingParams::from_url_tokens($tokens);
+ $ret = new ImageParams($sizing);
+ return $ret;
+ }
+
+ function compute_final_size($in_size, $coi)
+ {
+ $this->sizing->compute( $in_size, $coi, $crop_rect, $scale_size );
+ return $scale_size != null ? $scale_size : $in_size;
+ }
+
+ function is_identity($in_size)
+ {
+ if ($in_size[0] > $this->sizing->ideal_size[0] or
+ $in_size[1] > $this->sizing->ideal_size[1] )
+ {
+ return false;
+ }
+ return true;
+ }
+}
+?> \ No newline at end of file