BxDolImageResize.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup UnaCore UNA Core
  7. * @{
  8. */
  9. define('IMAGE_ERROR_SUCCESS', 0); ///< operation was successfull
  10. define('IMAGE_ERROR_WRONG_TYPE', 2); ///< operation failed, most probably because incorrect image format(or not image file) was provided
  11. class BxDolImageResize extends BxDolFactory implements iBxDolSingleton
  12. {
  13. protected $w = 64, $h = 64; ///< size of destination image
  14. protected $_isAutoCrop = false;
  15. protected $_iJpegQuality = 90; ///< jpeg quality
  16. protected $_isSquareResize = false; ///< use smart resize, destination image will be exact Width x Height size
  17. protected $_isUseGD; ///< use GD library or command line ImagMagic utilites
  18. protected $_oManager; ///< Intervention Image Manager
  19. protected $_sError; ///< Intervention Image Manager error string
  20. protected $_bRemoveTransparency = false; ///< remove transparency from images during resizing
  21. protected $_sRemoveTransparencyFillColor = '#ffffff'; ///< when removing transparency - fill with this color
  22. protected function __construct()
  23. {
  24. if (isset($GLOBALS['bxDolClasses'][get_class($this)]))
  25. trigger_error ('Multiple instances are not allowed for the class: ' . get_class($this), E_USER_ERROR);
  26. parent::__construct();
  27. $this->_isUseGD = getParam('enable_gd') == 'on' && extension_loaded('gd') ? true : false;
  28. $this->_oManager = new Intervention\Image\ImageManager(array('driver' => $this->_isUseGD ? 'gd' : 'imagick'));
  29. }
  30. /**
  31. * Prevent cloning the instance
  32. */
  33. public function __clone()
  34. {
  35. if (isset($GLOBALS['bxDolClasses'][get_class($this)]))
  36. trigger_error('Clone is not allowed for the class: ' . get_class($this), E_USER_ERROR);
  37. }
  38. /**
  39. * Get singleton instance of the class
  40. */
  41. public static function getInstance()
  42. {
  43. if(!isset($GLOBALS['bxDolClasses'][__CLASS__]))
  44. $GLOBALS['bxDolClasses'][__CLASS__] = new BxDolImageResize();
  45. return $GLOBALS['bxDolClasses'][__CLASS__];
  46. }
  47. function getManager ()
  48. {
  49. return $this->_oManager;
  50. }
  51. function getError ()
  52. {
  53. return $this->_sError;
  54. }
  55. function isAllowedImage ($sSrcImage)
  56. {
  57. try {
  58. $this->_oManager->make($sSrcImage);
  59. }
  60. catch (Exception $e) {
  61. return false;
  62. }
  63. return true;
  64. }
  65. function resize ($mixedImage, $sDstImage = '')
  66. {
  67. if (is_array($mixedImage)) {
  68. $aRet = array();
  69. foreach ($mixedImage as $s) {
  70. $aRet[] = $this->_resize ($s, $s);
  71. }
  72. return $aRet;
  73. } else {
  74. return $this->_resize ($mixedImage, $sDstImage);
  75. }
  76. }
  77. function applyWatermark ($mixedImage, $sDstImage, $sWtrImage, $iTransparency, $sPosition = 'bottom-right', $sPositionOffsetX = 0, $sPositionOffsetY = 0, $sScaleFactor = 0.2 )
  78. {
  79. if (is_array($mixedImage)) {
  80. $aRet = array();
  81. foreach ($mixedImage as $s)
  82. $aRet[] = $this->_applyWatermark ($s, $s, $sWtrImage, $iTransparency, $sPosition, $sPositionOffsetX, $sPositionOffsetY, $sScaleFactor);
  83. return $aRet;
  84. } else {
  85. return $this->_applyWatermark ($mixedImage, $sDstImage, $sWtrImage, $iTransparency, $sPosition, $sPositionOffsetX, $sPositionOffsetY, $sScaleFactor);
  86. }
  87. }
  88. function grayscale ($mixedImage, $sDstImage = '')
  89. {
  90. if (is_array($mixedImage)) {
  91. $aRet = array();
  92. foreach ($mixedImage as $s) {
  93. $aRet[] = $this->_grayscale ($s, $s);
  94. }
  95. return $aRet;
  96. } else {
  97. return $this->_grayscale ($mixedImage, $sDstImage);
  98. }
  99. }
  100. function setSize ($w, $h)
  101. {
  102. $this->w = $w;
  103. $this->h = $h;
  104. }
  105. function removeCropOptions ()
  106. {
  107. $this->_isAutoCrop = false;
  108. }
  109. /**
  110. * Crop image to destination size with filling whole area of destination size
  111. */
  112. function setAutoCrop ($b)
  113. {
  114. $this->_isAutoCrop = $b;
  115. }
  116. function setJpegQuality ($i)
  117. {
  118. $this->_iJpegQuality = $i;
  119. }
  120. public function getJpegQuality ()
  121. {
  122. return $this->_iJpegQuality;
  123. }
  124. function setSquareResize ($b)
  125. {
  126. $this->_isSquareResize = ($b ? true : false);
  127. }
  128. function isUsedGD ()
  129. {
  130. return $this->_isUseGD;
  131. }
  132. static function getImageSize($sPath)
  133. {
  134. $o = self::getInstance();
  135. return $o->_getImageSize($sPath);
  136. }
  137. function _getImageSize($sPath)
  138. {
  139. $this->_sError = '';
  140. try {
  141. $o = $this->_oManager->make($sPath);
  142. }
  143. catch (Exception $e) {
  144. $this->_sError = $e->getMessage();
  145. return false;
  146. }
  147. return array ('w' => $o->width(), 'h' => $o->height());
  148. }
  149. function getExifInfo($sSrcImage, $bCreateLocalFileIfUrl = true)
  150. {
  151. $this->_sError = '';
  152. $sTmpFileName = false;
  153. $mixedRet = false;
  154. if ($bCreateLocalFileIfUrl && preg_match('/^https?:\/\//', $sSrcImage)) {
  155. $sTmpFileName = tempnam(BX_DIRECTORY_PATH_TMP, '');
  156. file_put_contents($sTmpFileName, file_get_contents($sSrcImage));
  157. }
  158. try {
  159. $mixedRet = $this->_oManager
  160. ->make($sTmpFileName ? $sTmpFileName : $sSrcImage)
  161. ->exif();
  162. }
  163. catch (Exception $e) {
  164. $this->_sError = $e->getMessage();
  165. }
  166. if ($sTmpFileName)
  167. @unlink($sTmpFileName);
  168. return $mixedRet;
  169. }
  170. function getAverageColor($sSrcImage)
  171. {
  172. $this->_sError = '';
  173. try {
  174. $a = $this->_oManager
  175. ->make($sSrcImage)
  176. ->resize(1, 1)
  177. ->pickColor(0, 0, 'array');
  178. return array('r' => $a[0], 'g' => $a[1], 'b' => $a[2]);
  179. }
  180. catch (Exception $e) {
  181. $this->_sError = $e->getMessage();
  182. return false;
  183. }
  184. }
  185. // private functions are below -------------------------------
  186. function _grayscale ($sSrcImage, $sDstImage = '')
  187. {
  188. $this->_sError = '';
  189. try {
  190. $this->_oManager
  191. ->make($sSrcImage)
  192. ->greyscale()
  193. ->save($sDstImage ? $sDstImage : $sSrcImage, $this->_iJpegQuality);
  194. chmod($sDstImage ? $sDstImage : $sSrcImage, BX_DOL_FILE_RIGHTS);
  195. }
  196. catch (Exception $e) {
  197. $this->_sError = $e->getMessage();
  198. return IMAGE_ERROR_WRONG_TYPE;
  199. }
  200. return IMAGE_ERROR_SUCCESS;
  201. }
  202. function _removeTransparency ($oImg)
  203. {
  204. $oImgBack = $this->_oManager->canvas($oImg->width(), $oImg->height(), $this->_sRemoveTransparencyFillColor);
  205. return $oImgBack->insert($oImg);
  206. }
  207. function _resize ($sSrcImage, $sDstImage = '')
  208. {
  209. $this->_sError = '';
  210. try {
  211. if ($this->_isAutoCrop || $this->_isSquareResize) {
  212. $oImg = $this->_oManager
  213. ->make($sSrcImage)
  214. ->orientate();
  215. if ($this->_bRemoveTransparency)
  216. $oImg = $this->_removeTransparency($oImg);
  217. $oImg
  218. ->fit($this->w, $this->_isSquareResize ? $this->w : $this->h)
  219. ->save($sDstImage ? $sDstImage : $sSrcImage, $this->_iJpegQuality);
  220. }
  221. else {
  222. $oImg = $this->_oManager
  223. ->make($sSrcImage)
  224. ->orientate();
  225. if ($this->_bRemoveTransparency)
  226. $oImg = $this->_removeTransparency($oImg);
  227. $oImg
  228. ->resize($this->w, $this->h, function ($constraint) {
  229. $constraint->aspectRatio();
  230. $constraint->upsize();
  231. })
  232. ->save($sDstImage ? $sDstImage : $sSrcImage, $this->_iJpegQuality);
  233. }
  234. chmod($sDstImage ? $sDstImage : $sSrcImage, BX_DOL_FILE_RIGHTS);
  235. }
  236. catch (Exception $e) {
  237. $this->_sError = $e->getMessage();
  238. return IMAGE_ERROR_WRONG_TYPE;
  239. }
  240. return IMAGE_ERROR_SUCCESS;
  241. }
  242. function _applyWatermark( $sSrcImage, $sDstImage, $sWtrImage, $iTransparency, $sPosition = 'bottom-right', $sPositionOffsetX = 0, $sPositionOffsetY = 0, $sScaleFactor = 0.2)
  243. {
  244. $this->_sError = '';
  245. try {
  246. $oImageOrig = $this->_oManager->make($sSrcImage);
  247. $oImageOrig
  248. ->insert($this->_oManager
  249. ->make($sWtrImage)
  250. ->resize(round($oImageOrig->width() * $sScaleFactor), round($oImageOrig->height() * $sScaleFactor), function ($constraint) {
  251. $constraint->aspectRatio();
  252. $constraint->upsize();
  253. })
  254. ->opacity($iTransparency),
  255. $sPosition, $sPositionOffsetX, $sPositionOffsetY)
  256. ->save($sDstImage ? $sDstImage : $sSrcImage, $this->_iJpegQuality);
  257. chmod($sDstImage ? $sDstImage : $sSrcImage, BX_DOL_FILE_RIGHTS);
  258. }
  259. catch (Exception $e) {
  260. $this->_sError = $e->getMessage();
  261. return IMAGE_ERROR_WRONG_TYPE;
  262. }
  263. return IMAGE_ERROR_SUCCESS;
  264. }
  265. }
  266. /** @} */