BxDolImageResize.php 9.7 KB

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