PageRenderTime 25ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/tine20/Tinebase/Model/Image.php

https://gitlab.com/rsilveira1987/Expresso
PHP | 272 lines | 157 code | 25 blank | 90 comment | 17 complexity | 3e2c2e0ff881cec42bba7bd31f5f400f MD5 | raw file
  1. <?php
  2. /**
  3. * Tine 2.0
  4. *
  5. * @package Tinebase
  6. * @subpackage Record
  7. * @license http://www.gnu.org/licenses/agpl.html AGPL Version 3
  8. * @copyright Copyright (c) 2007-2008 Metaways Infosystems GmbH (http://www.metaways.de)
  9. * @author Cornelius Weiss <c.weiss@metaways.de>
  10. */
  11. /**
  12. * class Tinebase_Model_Image
  13. *
  14. * @package Tinebase
  15. * @subpackage Record
  16. */
  17. class Tinebase_Model_Image extends Tinebase_Record_Abstract
  18. {
  19. /**
  20. * preserves ratio and cropes image on the oversize side
  21. */
  22. const RATIOMODE_PRESERVANDCROP = 0;
  23. /**
  24. * preserves ratio and does not crop image. Resuling image dimension is less
  25. * than requested on one dimension as this dim is not filled
  26. */
  27. const RATIOMODE_PRESERVNOFILL = 1;
  28. protected $_identifier = 'id';
  29. /**
  30. * application the record belongs to
  31. *
  32. * @var string
  33. */
  34. protected $_application = 'Tinebase';
  35. protected $_validators = array(
  36. // image identifiers
  37. 'id' => array('presence' => 'required', 'allowEmpty' => false, /*'Alnum'*/ ),
  38. 'application' => array('presence' => 'required', 'allowEmpty' => false, 'Alnum' ),
  39. 'location' => array('default' => '', 'allowEmpty' => true, 'Alnum', ),
  40. // image properties
  41. 'width' => array('allowEmpty' => true, 'Int' ),
  42. 'height' => array('allowEmpty' => true, 'Int' ),
  43. 'bits' => array('allowEmpty' => true, 'Int' ),
  44. 'channels' => array('allowEmpty' => true, 'Int' ),
  45. 'mime' => array('allowEmpty' => true, array('InArray', array('image/png', 'image/jpeg', 'image/gif'))),
  46. // binary data
  47. 'blob' => array('allowEmpty' => true)
  48. );
  49. /**
  50. * returns image from given path
  51. *
  52. * @param string $_path
  53. * @return Tinebase_Model_Image
  54. * @throws Tinebase_Exception_NotFound
  55. */
  56. public static function getImageFromPath($_path)
  57. {
  58. if (!file_exists($_path)) {
  59. throw new Tinebase_Exception_NotFound('Image file not found.');
  60. }
  61. $imgBlob = file_get_contents($_path);
  62. return self::getImageFromBlob($imgBlob);
  63. }
  64. /**
  65. * returns image from given blob
  66. *
  67. * @param string $_blob
  68. * @return Tinebase_Model_Image
  69. */
  70. public static function getImageFromBlob($_blob)
  71. {
  72. return new Tinebase_Model_Image(Tinebase_ImageHelper::getImageInfoFromBlob($_blob), true);
  73. }
  74. /**
  75. * returns image from imageURL
  76. *
  77. * @param string imageURL
  78. * @return Tinebase_Model_Image
  79. */
  80. public static function getImageFromImageURL($_imageURL)
  81. {
  82. $params = self::parseImageURL($_imageURL);
  83. $image = Tinebase_Controller::getInstance()->getImage($params['application'], $params['id'], $params['location']);
  84. return $image;
  85. }
  86. /**
  87. * parses an imageURL
  88. *
  89. * @param string imageURL
  90. * @return array array of image params
  91. * @throws Tinebase_Exception_InvalidArgument
  92. */
  93. public static function parseImageURL($_imageURL)
  94. {
  95. $params = array();
  96. parse_str(parse_url($_imageURL, PHP_URL_QUERY), $params);
  97. if (!empty($params['application']) && !empty($params['id'])) {
  98. return $params;
  99. } else {
  100. throw new Tinebase_Exception_InvalidArgument("$_imageURL is not a valid imageURL");
  101. }
  102. }
  103. /**
  104. * returns an image url
  105. * @param string $appName the name of the application
  106. * @param string $id the identifier
  107. * @param string $location location
  108. * @param integer $width width
  109. * @param integer $height height
  110. * @param integer $ratiomode ratiomode
  111. */
  112. public static function getImageUrl($appName, $id, $location = '', $width = 90, $height = 90, $ratiomode = 0) {
  113. return 'index.php?method=Tinebase.getImage&application=' . $appName . '&location=' . $location . '&id=' . $id . '&width=' . $width . '&height=' . $height . '&ratiomode='.$ratiomode;
  114. }
  115. /**
  116. * scales given image to given size
  117. *
  118. * @param int $_width desitination width
  119. * @param int $_height destination height
  120. * @param int $_ratiomode
  121. * @throws Tinebase_Exception_InvalidArgument
  122. */
  123. public function resize($_width, $_height, $_ratiomode)
  124. {
  125. $tmpPath = tempnam(Tinebase_Core::getTempDir(), 'tine20_tmp_gd');
  126. file_put_contents($tmpPath, $this->blob);
  127. switch ($this->mime) {
  128. case ('image/png'):
  129. $src_image = imagecreatefrompng($tmpPath);
  130. $imgDumpFunction = 'imagepng';
  131. break;
  132. case ('image/jpeg'):
  133. $src_image = imagecreatefromjpeg($tmpPath);
  134. $imgDumpFunction = 'imagejpeg';
  135. break;
  136. case ('image/gif'):
  137. $src_image = imagecreatefromgif($tmpPath);
  138. $imgDumpFunction = 'imagegif';
  139. break;
  140. default:
  141. throw new Tinebase_Exception_InvalidArgument("Unsupported image type: " . $this->mime);
  142. break;
  143. }
  144. $src_ratio = $this->width/$this->height;
  145. $dst_ratio = $_width/$_height;
  146. switch ($_ratiomode) {
  147. case self::RATIOMODE_PRESERVANDCROP:
  148. $dst_width = $_width;
  149. $dst_height = $_height;
  150. if($src_ratio - $dst_ratio >= 0) {
  151. // crop width
  152. $dst_image = imagecreatetruecolor($dst_width, $dst_height);
  153. imagecopyresampled($dst_image, $src_image, 0, 0, 0, 0, $dst_width, $dst_height, $this->height * $dst_ratio, $this->height);
  154. } else {
  155. // crop heights
  156. $dst_image = imagecreatetruecolor($dst_width, $dst_height);
  157. imagecopyresampled($dst_image, $src_image, 0, 0, 0, 0, $dst_width, $dst_height, $this->width, $this->width / $dst_ratio);
  158. }
  159. break;
  160. case self::RATIOMODE_PRESERVNOFILL:
  161. if($src_ratio - $dst_ratio >= 0) {
  162. // fit width
  163. $dst_height = floor($_width / $src_ratio);
  164. $dst_width = $_width;
  165. } else {
  166. // fit height
  167. $dst_height = $_height;
  168. $dst_width = floor($_height * $src_ratio);
  169. }
  170. // recalculate dst_ratio
  171. $dst_ratio = $dst_width/$dst_height;
  172. $dst_image = imagecreatetruecolor($dst_width, $dst_height);
  173. imagecopyresampled($dst_image, $src_image, 0, 0, 0, 0, $dst_width, $dst_height, $this->width, $this->height);
  174. break;
  175. default:
  176. throw new Tinebase_Exception_InvalidArgument('Ratiomode not supported.');
  177. break;
  178. }
  179. $imgDumpFunction($dst_image, $tmpPath);
  180. $this->width = $dst_width;
  181. $this->height = $dst_height;
  182. $this->blob = file_get_contents($tmpPath);
  183. unlink($tmpPath);
  184. return;
  185. }
  186. /**
  187. * returns binary string in given format
  188. *
  189. * @param string $_mime
  190. * @param int $_maxSize in bytes
  191. * @return string
  192. */
  193. public function getBlob($_mime='image/jpeg', $_maxSize=0)
  194. {
  195. if ($this->mime != $_mime) {
  196. $img = @imagecreatefromstring($this->blob);
  197. $tmpPath = tempnam(Tinebase_Core::getTempDir(), 'tine20_tmp_gd');
  198. switch ($_mime) {
  199. case ('image/png'):
  200. imagepng($img, $tmpPath, 0);
  201. break;
  202. case ('image/jpeg'):
  203. imagejpeg($img, $tmpPath, 100);
  204. break;
  205. case ('image/gif'):
  206. imagegif($img, $tmpPath);
  207. break;
  208. default:
  209. throw new Tinebase_Exception_InvalidArgument("Unsupported image type: " . $_mime);
  210. break;
  211. }
  212. $blob = file_get_contents($tmpPath);
  213. unlink($tmpPath);
  214. } else {
  215. $blob = $this->blob;
  216. }
  217. if ($_maxSize && strlen($blob) > $_maxSize) {
  218. $q = $_maxSize/strlen($blob);
  219. $width = floor(sqrt(pow($this->width, 2) * $q));
  220. $height = floor(sqrt(pow($this->height, 2) * $q));
  221. $this->resize($width, $height, self::RATIOMODE_PRESERVANDCROP);
  222. return $this->getBlob($_mime, $_maxSize);
  223. }
  224. return $blob;
  225. }
  226. /**
  227. * returns image extension from mime type
  228. *
  229. * @return string extension
  230. */
  231. public function getImageExtension()
  232. {
  233. $extension = '';
  234. switch ( $this->mime ) {
  235. case 'image/png':
  236. $extension = '.png';
  237. break;
  238. case 'image/jpeg':
  239. $extension = '.jpg';
  240. break;
  241. case 'image/gif':
  242. $extension = '.gif';
  243. break;
  244. }
  245. return $extension;
  246. }
  247. } // end of Tinebase_Model_Image