BxDolTranscoderImage.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
  4. * CC-BY License - http://creativecommons.org/licenses/by/3.0/
  5. *
  6. * @defgroup TridentCore Trident Core
  7. * @{
  8. */
  9. bx_import('BxDolTranscoder');
  10. bx_import('BxDolTranscoderImageQuery');
  11. /**
  12. * @page objects
  13. * @section transcoder_images Images Transcoder
  14. * @ref BxDolTranscoderImage
  15. */
  16. /**
  17. * This class transcodes images on the fly.
  18. * Transcoded image is saved in the specified storage engine and next time ready image is served.
  19. *
  20. *
  21. * To add image transcoder object add record to 'sys_objects_transcoder' table:
  22. * - object - name of the transcoder object, in the format: vendor prefix, underscore, module prefix, underscore, image size name; for example: bx_images_thumb.
  23. * - storage_object - name of the storage object to store transcoded data, the specified storage object need to be created too, @see BxDolStorage.
  24. * - source_type - type of the source, where is source image is taken from, available options 'Storage' and 'Folder' for now.
  25. * - source_params - source_type params, each source_type can have own set of params, please read futher for more info about particular source_types, serialized array of params is stored here.
  26. * - private - how to store transcoded data:
  27. * - no - store transcoded data publicly.
  28. * - yes - store transcoded data privately.
  29. * - auto - detect automatically, not supported for 'Folder' source type.
  30. * - atime_tracking - track last access time to the transcoded data, allowed values 0 - disables or 1 - enabled.
  31. * - atime_pruning - prune transcoded images by last access time, if last access time of the image is older than atime_pruning seconds - it is deleted, it works when atime_tracking is enabled
  32. * - ts - unix timestamp of the last change of transcoder parameters, if transcoded image is older than this value - image is deleted and transcoded again.
  33. *
  34. *
  35. * Then you need to add image filters to 'sys_transcoder_filters' table:
  36. * - transcoder_object - name of the transcoded object to apply filter to.
  37. * - filter - filter name, please read futher for available filters.
  38. * - filter_params - serialized array of filter params, please read futher for particular filters params.
  39. * - order - if there are several filters for one object, they will be applied in this order.
  40. *
  41. *
  42. * 'Folder' source types:
  43. * This source type is some folder with original images for the transcoding, the identifier of the image (handler) is file name.
  44. * The params are the following:
  45. * - path - path to the folder with original images
  46. * This source type has some limitation:
  47. * - automatic detection of private files is not supported
  48. * - transcoded file is not automaticlaly deleted/renewed if original file is changed
  49. *
  50. *
  51. * 'Storage' source type:
  52. * The source of original files is Storage engine, the identifier of the image (handler) is file id.
  53. * The params are the following:
  54. * - object - name of the Storage object
  55. *
  56. *
  57. * Available filters:
  58. * - Resize - this filter resizes original image, the parameters are the following:
  59. * - w - width of resulted image.
  60. * - h - height of resulted image.
  61. * - square_resize - make resulted image square, even of original image is not square, 'w' and 'h' parameters must be the same.
  62. * - crop_resize - crop image to destination size with filling whole area of destination size.
  63. * - force_type - always change type of the image to the specified type: jpg, png, gif.
  64. * - Grayscale - make image grayscale, there is no parameters for this filter
  65. *
  66. *
  67. * Automatic deletetion of associated data is supported - in the case if original or transcoded file is deleted,
  68. * but you need to register alert handlers, just call registerHandlers () function to register handler (for example, during module installation)
  69. * and call unregisterHandlers () function to unregister handlers (for example, during module uninstallation)
  70. *
  71. *
  72. * Example of usage:
  73. * @code
  74. * bx_import('BxDolTranscoderImage');
  75. * $oTranscoder = BxDolTranscoderImage::getObjectInstance('bx_images_thumb'); // change images transcode object name to your own
  76. * $oTranscoder->registerHandlers(); // make sure to call it only once! before the first usage, no need to call it every time
  77. * $sTranscodedImageUrl = $oTranscoder->getFileUrl('my_dog.jpg'); // the name of file, in the case of 'Folder' storage type this is file name
  78. * echo 'My dog : <img src="' . $sUrl . '" />'; // transcoded(resized and/or grayscaled) image will be shown, according to the specified filters
  79. * @endcode
  80. *
  81. */
  82. class BxDolTranscoderImage extends BxDolTranscoder implements iBxDolFactoryObject
  83. {
  84. protected function __construct($aObject, $oStorage)
  85. {
  86. parent::__construct($aObject, $oStorage);
  87. $this->_oDb = new BxDolTranscoderImageQuery($aObject, false);
  88. $this->_sQueueTable = $this->_oDb->getQueueTable();
  89. }
  90. /**
  91. * Get file url when file isn't transcoded yet
  92. */
  93. public function getFileUrlNotReady($mixedHandler)
  94. {
  95. return BX_DOL_URL_ROOT . 'image_transcoder.php?o=' . $this->_aObject['object'] . '&h=' . $mixedHandler . '&dpx=' . $this->getDevicePixelRatio() . '&t=' . time();
  96. }
  97. public function isFileReady ($mixedHandler, $isCheckOutdated = true)
  98. {
  99. if (isAdmin() && false !== $this->getFilterParams('ResizeVar')) { // only operators can apply new image size
  100. $aTranscodedFileData = $this->_oDb->getTranscodedFileData ($mixedHandler);
  101. $x = $this->getCustomResizeDimension ('x');
  102. $y = $this->getCustomResizeDimension ('y');
  103. // if new sizes are provided - delete old image, so new one will be created
  104. if (($x && (!isset($aTranscodedFileData['x']) || $x != $aTranscodedFileData['x'])) || ($y && (!isset($aTranscodedFileData['y']) || $y != $aTranscodedFileData['y']))) {
  105. if (!($iFileId = $this->_oDb->getFileIdByHandler($mixedHandler)))
  106. return false;
  107. if (!($aFile = $this->_oStorage->getFile($iFileId)))
  108. return false;
  109. if (!$this->_oStorage->deleteFile($aFile['id']))
  110. return false;
  111. }
  112. }
  113. return parent::isFileReady ($mixedHandler, $isCheckOutdated);
  114. }
  115. protected function getCustomResizeDimension ($sName)
  116. {
  117. $i = (int)bx_get($sName);
  118. if ($i > 2048) $i = 2048;
  119. if ($i && $i < 16) $i = 16;
  120. return $i;
  121. }
  122. public function transcode ($mixedHandler, $iProfileId = 0)
  123. {
  124. if (!($bRet = parent::transcode ($mixedHandler, $iProfileId)))
  125. return $bRet;
  126. $x = $this->getCustomResizeDimension ('x');
  127. $y = $this->getCustomResizeDimension ('y');
  128. if ($x || $y)
  129. $this->_oDb->updateTranscodedFileData($mixedHandler, array('x' => $x, 'y' => $y));
  130. return $bRet;
  131. }
  132. protected function applyFilter_Grayscale ($sFile, $aParams)
  133. {
  134. bx_import ('BxDolImageResize');
  135. $o = BxDolImageResize::getInstance();
  136. $o->removeCropOptions ();
  137. $this->_checkForceType ($o, $aParams);
  138. if (IMAGE_ERROR_SUCCESS == $o->grayscale($sFile))
  139. return true;
  140. return false;
  141. }
  142. protected function applyFilter_ResizeVar ($sFile, $aParams)
  143. {
  144. $aParams['w'] = $this->getCustomResizeDimension ('x');
  145. $aParams['h'] = $this->getCustomResizeDimension ('y');
  146. if (!$aParams['w'] && !$aParams['h'])
  147. return true;
  148. return $this->applyFilter_Resize ($sFile, $aParams);
  149. }
  150. protected function applyFilter_Resize ($sFile, $aParams)
  151. {
  152. bx_import ('BxDolImageResize');
  153. $o = BxDolImageResize::getInstance();
  154. $o->removeCropOptions ();
  155. // if only one dimension specified - automatically calculate another dimension
  156. if ((isset($aParams['w']) && !isset($aParams['h'])) || (isset($aParams['h']) && !isset($aParams['w']))) {
  157. $a = $o->getImageSize ($sFile);
  158. $fRatio = $a['w'] / $a['h'];
  159. if (isset($aParams['w']))
  160. $aParams['h'] = round($aParams['w'] / $fRatio);
  161. else
  162. $aParams['w'] = round($aParams['h'] * $fRatio);
  163. }
  164. if (isset($aParams['w']) && isset($aParams['h']))
  165. $o->setSize ($aParams['w'] * $this->getDevicePixelRatio(), $aParams['h'] * $this->getDevicePixelRatio());
  166. if (isset($aParams['crop_resize']) && $aParams['crop_resize'])
  167. $o->setAutoCrop (true);
  168. elseif (isset($aParams['square_resize']) && $aParams['square_resize'])
  169. $o->setSquareResize (true);
  170. else
  171. $o->setSquareResize (false);
  172. $this->_checkForceType ($o, $aParams);
  173. if (IMAGE_ERROR_SUCCESS == $o->resize($sFile))
  174. return true;
  175. return false;
  176. }
  177. protected function _checkForceType ($oImageProcessor, $aParams)
  178. {
  179. if (empty($aParams['force_type']))
  180. $aParams['force_type'] = false;
  181. switch ($aParams['force_type']) {
  182. case 'jpeg':
  183. case 'jpg':
  184. $oImageProcessor->setOutputType(IMAGE_TYPE_JPG);
  185. break;
  186. case 'png':
  187. $oImageProcessor->setOutputType(IMAGE_TYPE_PNG);
  188. break;
  189. case 'gif':
  190. $oImageProcessor->setOutputType(IMAGE_TYPE_GIF);
  191. break;
  192. default:
  193. $oImageProcessor->setOutputType(false);
  194. break;
  195. }
  196. }
  197. }
  198. /** @} */