PageRenderTime 246ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/fsn-site-central/mediatheque/include/derivative.inc.php

https://gitlab.com/team_fsn/fsn-php
PHP | 540 lines | 340 code | 47 blank | 153 comment | 52 complexity | a53ec7e729222f856637dd3970616f7c MD5 | raw file
  1. <?php
  2. // +-----------------------------------------------------------------------+
  3. // | Piwigo - a PHP based photo gallery |
  4. // +-----------------------------------------------------------------------+
  5. // | Copyright(C) 2008-2016 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. /**
  22. * @package Derivatives
  23. */
  24. /**
  25. * A source image is used to get a derivative image. It is either
  26. * the original file for a jpg/png/... or a 'representative' image
  27. * of a non image file or a standard icon for the non-image file.
  28. */
  29. final class SrcImage
  30. {
  31. const IS_ORIGINAL = 0x01;
  32. const IS_MIMETYPE = 0x02;
  33. const DIM_NOT_GIVEN = 0x04;
  34. /** @var int */
  35. public $id;
  36. /** @var string */
  37. public $rel_path;
  38. /** @var int */
  39. public $rotation = 0;
  40. /** @var int[] */
  41. private $size=null;
  42. /** @var int */
  43. private $flags=0;
  44. /**
  45. * @param array $infos assoc array of data from images table
  46. */
  47. function __construct($infos)
  48. {
  49. global $conf;
  50. $this->id = $infos['id'];
  51. $ext = get_extension($infos['path']);
  52. if (in_array($ext, $conf['picture_ext']))
  53. {
  54. $this->rel_path = $infos['path'];
  55. $this->flags |= self::IS_ORIGINAL;
  56. }
  57. elseif (!empty($infos['representative_ext']))
  58. {
  59. $this->rel_path = original_to_representative($infos['path'], $infos['representative_ext']);
  60. }
  61. else
  62. {
  63. $ext = strtolower($ext);
  64. $this->rel_path = trigger_change('get_mimetype_location', get_themeconf('mime_icon_dir').$ext.'.png', $ext );
  65. $this->flags |= self::IS_MIMETYPE;
  66. if ( ($size=@getimagesize(PHPWG_ROOT_PATH.$this->rel_path)) === false)
  67. {
  68. $this->rel_path = 'themes/default/icon/mimetypes/unknown.png';
  69. $size = getimagesize(PHPWG_ROOT_PATH.$this->rel_path);
  70. }
  71. $this->size = array($size[0],$size[1]);
  72. }
  73. if (!$this->size)
  74. {
  75. if (isset($infos['width']) && isset($infos['height']))
  76. {
  77. $width = $infos['width'];
  78. $height = $infos['height'];
  79. $this->rotation = intval($infos['rotation']) % 4;
  80. // 1 or 5 => 90 clockwise
  81. // 3 or 7 => 270 clockwise
  82. if ($this->rotation % 2)
  83. {
  84. $width = $infos['height'];
  85. $height = $infos['width'];
  86. }
  87. $this->size = array($width, $height);
  88. }
  89. elseif (!array_key_exists('width', $infos))
  90. {
  91. $this->flags |= self::DIM_NOT_GIVEN;
  92. }
  93. }
  94. }
  95. /**
  96. * @return bool
  97. */
  98. function is_original()
  99. {
  100. return $this->flags & self::IS_ORIGINAL;
  101. }
  102. /**
  103. * @return bool
  104. */
  105. function is_mimetype()
  106. {
  107. return $this->flags & self::IS_MIMETYPE;
  108. }
  109. /**
  110. * @return string
  111. */
  112. function get_path()
  113. {
  114. return PHPWG_ROOT_PATH.$this->rel_path;
  115. }
  116. /**
  117. * @return string
  118. */
  119. function get_url()
  120. {
  121. $url = get_root_url().$this->rel_path;
  122. if ( !($this->flags & self::IS_MIMETYPE) )
  123. {
  124. $url = trigger_change('get_src_image_url', $url, $this);
  125. }
  126. return embellish_url($url);
  127. }
  128. /**
  129. * @return bool
  130. */
  131. function has_size()
  132. {
  133. return $this->size != null;
  134. }
  135. /**
  136. * @return int[]|null 0=width, 1=height or null if fail to compute size
  137. */
  138. function get_size()
  139. {
  140. if ($this->size == null)
  141. {
  142. if ($this->flags & self::DIM_NOT_GIVEN)
  143. fatal_error('SrcImage dimensions required but not provided');
  144. // probably not metadata synced
  145. if ( ($size = getimagesize( $this->get_path() )) !== false)
  146. {
  147. $this->size = array($size[0],$size[1]);
  148. pwg_query('UPDATE '.IMAGES_TABLE.' SET width='.$size[0].', height='.$size[1].' WHERE id='.$this->id);
  149. }
  150. }
  151. return $this->size;
  152. }
  153. }
  154. /**
  155. * Holds information (path, url, dimensions) about a derivative image.
  156. * A derivative image is constructed from a source image (SrcImage class)
  157. * and derivative parameters (DerivativeParams class).
  158. */
  159. final class DerivativeImage
  160. {
  161. /** @var SrcImage */
  162. public $src_image;
  163. /** @var array */
  164. private $params;
  165. /** @var string */
  166. private $rel_path;
  167. /** @var string */
  168. private $rel_url;
  169. /** @var bool */
  170. private $is_cached=true;
  171. /**
  172. * @param string|DerivativeParams $type standard derivative param type (e.g. IMG_*)
  173. * or a DerivativeParams object
  174. * @param SrcImage $src_image the source image of this derivative
  175. */
  176. function __construct($type, SrcImage $src_image)
  177. {
  178. $this->src_image = $src_image;
  179. if (is_string($type))
  180. {
  181. $this->params = ImageStdParams::get_by_type($type);
  182. }
  183. else
  184. {
  185. $this->params = $type;
  186. }
  187. self::build($src_image, $this->params, $this->rel_path, $this->rel_url, $this->is_cached);
  188. }
  189. /**
  190. * Generates the url of a thumbnail.
  191. *
  192. * @param array|SrcImage $infos array of info from db or SrcImage
  193. * @return string
  194. */
  195. static function thumb_url($infos)
  196. {
  197. return self::url(IMG_THUMB, $infos);
  198. }
  199. /**
  200. * Generates the url for a particular photo size.
  201. *
  202. * @param string|DerivativeParams $type standard derivative param type (e.g. IMG_*)
  203. * or a DerivativeParams object
  204. * @param array|SrcImage $infos array of info from db or SrcImage
  205. * @return string
  206. */
  207. static function url($type, $infos)
  208. {
  209. $src_image = is_object($infos) ? $infos : new SrcImage($infos);
  210. $params = is_string($type) ? ImageStdParams::get_by_type($type) : $type;
  211. self::build($src_image, $params, $rel_path, $rel_url);
  212. if ($params == null)
  213. {
  214. return $src_image->get_url();
  215. }
  216. return embellish_url(
  217. trigger_change('get_derivative_url',
  218. get_root_url().$rel_url,
  219. $params, $src_image, $rel_url
  220. ) );
  221. }
  222. /**
  223. * Return associative an array of all DerivativeImage for a specific image.
  224. * Disabled derivative types can be still found in the return, mapped to an
  225. * enabled derivative (e.g. the values are not unique in the return array).
  226. * This is useful for any plugin/theme to just use $deriv[IMG_XLARGE] even if
  227. * the XLARGE is disabled.
  228. *
  229. * @param array|SrcImage $src_image array of info from db or SrcImage
  230. * @return DerivativeImage[]
  231. */
  232. static function get_all($src_image)
  233. {
  234. if (!is_object($src_image))
  235. {
  236. $src_image = new SrcImage($src_image);
  237. }
  238. $ret = array();
  239. // build enabled types
  240. foreach (ImageStdParams::get_defined_type_map() as $type => $params)
  241. {
  242. $derivative = new DerivativeImage($params, $src_image);
  243. $ret[$type] = $derivative;
  244. }
  245. // disabled types, fallback to enabled types
  246. foreach (ImageStdParams::get_undefined_type_map() as $type => $type2)
  247. {
  248. $ret[$type] = $ret[$type2];
  249. }
  250. return $ret;
  251. }
  252. /**
  253. * Returns an instance of DerivativeImage for a specific image and size.
  254. * Disabled derivatives fallback to an enabled derivative.
  255. *
  256. * @param string $type standard derivative param type (e.g. IMG_*)
  257. * @param array|SrcImage $src_image array of info from db or SrcImage
  258. * @return DerivativeImage|null null if $type not found
  259. */
  260. static function get_one($type, $src_image)
  261. {
  262. if (!is_object($src_image))
  263. {
  264. $src_image = new SrcImage($src_image);
  265. }
  266. $defined = ImageStdParams::get_defined_type_map();
  267. if (isset($defined[$type]))
  268. {
  269. return new DerivativeImage($defined[$type], $src_image);
  270. }
  271. $undefined = ImageStdParams::get_undefined_type_map();
  272. if (isset($undefined[$type]))
  273. {
  274. return new DerivativeImage($defined[ $undefined[$type] ], $src_image);
  275. }
  276. return null;
  277. }
  278. /**
  279. * @todo : documentation of DerivativeImage::build
  280. */
  281. private static function build($src, &$params, &$rel_path, &$rel_url, &$is_cached=null)
  282. {
  283. if ( $src->has_size() && $params->is_identity( $src->get_size() ) )
  284. {// the source image is smaller than what we should do - we do not upsample
  285. if (!$params->will_watermark($src->get_size()) && !$src->rotation)
  286. {// no watermark, no rotation required -> we will use the source image
  287. $params = null;
  288. $rel_path = $rel_url = $src->rel_path;
  289. return;
  290. }
  291. $defined_types = array_keys(ImageStdParams::get_defined_type_map());
  292. for ($i=0; $i<count($defined_types); $i++)
  293. {
  294. if ($defined_types[$i] == $params->type)
  295. {
  296. for ($i--; $i>=0; $i--)
  297. {
  298. $smaller = ImageStdParams::get_by_type($defined_types[$i]);
  299. if ($smaller->sizing->max_crop==$params->sizing->max_crop && $smaller->is_identity( $src->get_size() ))
  300. {
  301. $params = $smaller;
  302. self::build($src, $params, $rel_path, $rel_url, $is_cached);
  303. return;
  304. }
  305. }
  306. break;
  307. }
  308. }
  309. }
  310. $tokens=array();
  311. $tokens[] = substr($params->type,0,2);
  312. if ($params->type==IMG_CUSTOM)
  313. {
  314. $params->add_url_tokens($tokens);
  315. }
  316. $loc = $src->rel_path;
  317. if (substr_compare($loc, './', 0, 2)==0)
  318. {
  319. $loc = substr($loc, 2);
  320. }
  321. elseif (substr_compare($loc, '../', 0, 3)==0)
  322. {
  323. $loc = substr($loc, 3);
  324. }
  325. $loc = substr_replace($loc, '-'.implode('_', $tokens), strrpos($loc, '.'), 0 );
  326. $rel_path = PWG_DERIVATIVE_DIR.$loc;
  327. global $conf;
  328. $url_style=$conf['derivative_url_style'];
  329. if (!$url_style)
  330. {
  331. $mtime = @filemtime(PHPWG_ROOT_PATH.$rel_path);
  332. if ($mtime===false or $mtime < $params->last_mod_time)
  333. {
  334. $is_cached = false;
  335. $url_style = 2;
  336. }
  337. else
  338. {
  339. $url_style = 1;
  340. }
  341. }
  342. if ($url_style == 2)
  343. {
  344. $rel_url = 'i';
  345. if ($conf['php_extension_in_urls']) $rel_url .= '.php';
  346. if ($conf['question_mark_in_urls']) $rel_url .= '?';
  347. $rel_url .= '/'.$loc;
  348. }
  349. else
  350. {
  351. $rel_url = $rel_path;
  352. }
  353. }
  354. /**
  355. * @return string
  356. */
  357. function get_path()
  358. {
  359. return PHPWG_ROOT_PATH.$this->rel_path;
  360. }
  361. /**
  362. * @return string
  363. */
  364. function get_url()
  365. {
  366. if ($this->params == null)
  367. {
  368. return $this->src_image->get_url();
  369. }
  370. return embellish_url(
  371. trigger_change('get_derivative_url',
  372. get_root_url().$this->rel_url,
  373. $this->params, $this->src_image, $this->rel_url
  374. ) );
  375. }
  376. /**
  377. * @return bool
  378. */
  379. function same_as_source()
  380. {
  381. return $this->params == null;
  382. }
  383. /**
  384. * @return string one if IMG_* or 'Original'
  385. */
  386. function get_type()
  387. {
  388. if ($this->params == null)
  389. return 'Original';
  390. return $this->params->type;
  391. }
  392. /**
  393. * @return int[]
  394. */
  395. function get_size()
  396. {
  397. if ($this->params == null)
  398. {
  399. return $this->src_image->get_size();
  400. }
  401. return $this->params->compute_final_size($this->src_image->get_size());
  402. }
  403. /**
  404. * Returns the size as CSS rule.
  405. *
  406. * @return string
  407. */
  408. function get_size_css()
  409. {
  410. $size = $this->get_size();
  411. if ($size)
  412. {
  413. return 'width:'.$size[0].'px; height:'.$size[1].'px';
  414. }
  415. }
  416. /**
  417. * Returns the size as HTML attributes.
  418. *
  419. * @return string
  420. */
  421. function get_size_htm()
  422. {
  423. $size = $this->get_size();
  424. if ($size)
  425. {
  426. return 'width="'.$size[0].'" height="'.$size[1].'"';
  427. }
  428. }
  429. /**
  430. * Returns literal size: $widthx$height.
  431. *
  432. * @return string
  433. */
  434. function get_size_hr()
  435. {
  436. $size = $this->get_size();
  437. if ($size)
  438. {
  439. return $size[0].' x '.$size[1];
  440. }
  441. }
  442. /**
  443. * @param int $maxw
  444. * @param int $mawh
  445. * @return int[]
  446. */
  447. function get_scaled_size($maxw, $maxh)
  448. {
  449. $size = $this->get_size();
  450. if ($size)
  451. {
  452. $ratio_w = $size[0] / $maxw;
  453. $ratio_h = $size[1] / $maxh;
  454. if ($ratio_w>1 || $ratio_h>1)
  455. {
  456. if ($ratio_w > $ratio_h)
  457. {
  458. $size[0] = $maxw;
  459. $size[1] = floor($size[1] / $ratio_w);
  460. }
  461. else
  462. {
  463. $size[0] = floor($size[0] / $ratio_h);
  464. $size[1] = $maxh;
  465. }
  466. }
  467. }
  468. return $size;
  469. }
  470. /**
  471. * Returns the scaled size as HTML attributes.
  472. *
  473. * @param int $maxw
  474. * @param int $mawh
  475. * @return string
  476. */
  477. function get_scaled_size_htm($maxw=9999, $maxh=9999)
  478. {
  479. $size = $this->get_scaled_size($maxw, $maxh);
  480. if ($size)
  481. {
  482. return 'width="'.$size[0].'" height="'.$size[1].'"';
  483. }
  484. }
  485. /**
  486. * @return bool
  487. */
  488. function is_cached()
  489. {
  490. return $this->is_cached;
  491. }
  492. }
  493. ?>