PageRenderTime 64ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/includes/class.ImageConverter.php

https://github.com/reshadf/Library
PHP | 526 lines | 357 code | 29 blank | 140 comment | 42 complexity | 50da90182394ada499cb32e075e09255 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * class ImageConverter
  4. *
  5. * Convert images: resize or merge an image
  6. *
  7. * @author Teye Heimans
  8. * @package FormHandler
  9. */
  10. class ImageConverter
  11. {
  12. // private vars!
  13. var $_sImage;
  14. var $_sError;
  15. var $_aSize;
  16. var $_aNewSize;
  17. var $_iQuality;
  18. var $_bConstrainProportions;
  19. /**
  20. * ImageConverter::ImageConverter()
  21. *
  22. * constructor: Create a new ImageConverter object
  23. *
  24. * @param string $sImage: The image to work with
  25. * @return ImageConverter
  26. * @author Teye Heimans
  27. * @access public
  28. */
  29. function ImageConverter( $sImage )
  30. {
  31. $this->_bConstrainProportions = true;
  32. $this->_sError = '';
  33. $this->_sImage = $sImage;
  34. $this->_iQuality = 80;
  35. // does the file exists ?
  36. if( file_exists($sImage) )
  37. {
  38. $this->_aSize = getimagesize( $sImage );
  39. $this->_aNewSize = $this->_aSize;
  40. // is the type of the image right to convert it ?
  41. if(!in_array(
  42. $this->_getExtension( $sImage ) ,
  43. array('jpg', 'png', 'jpeg', 'gif')))
  44. {
  45. $this->_sError = 'Only gif, jpg, jpeg and png files can be converted!';
  46. return;
  47. }
  48. }
  49. // file does not exitst
  50. else
  51. {
  52. $this->_sError = 'File not found: '.$sImage;
  53. return;
  54. }
  55. }
  56. /**
  57. * ImageConverter::setQuality()
  58. *
  59. * Set the quality of the new resized image
  60. *
  61. * @param int $iQuality: the quality
  62. * @return void
  63. * @author Teye Heimans
  64. * @access public
  65. */
  66. function setQuality( $iQuality )
  67. {
  68. if( !empty( $iQuality ) && is_numeric( $iQuality ) )
  69. {
  70. $this->_iQuality = (int) $iQuality;
  71. }
  72. }
  73. /**
  74. * ImageConverter::getError()
  75. *
  76. * Return the last error occoured
  77. *
  78. * @return string: the last occoured error
  79. * @author Teye Heimans
  80. * @access public
  81. */
  82. function getError()
  83. {
  84. return isset($this->_sError) ? $this->_sError : '';
  85. }
  86. /**
  87. * ImageConverter::doResize()
  88. *
  89. * Resize the image
  90. *
  91. * @param string $sDestination: The file how we have to save it
  92. * @param int $iNewWidth: The new width of the image
  93. * @param int $iNewHeight: The new height of the image
  94. * @return void
  95. * @author Teye Heimans
  96. * @access public
  97. */
  98. function doResize( $sDestination , $iNewWidth, $iNewHeight )
  99. {
  100. // if no errors occourd
  101. if($this->_sError == '')
  102. {
  103. // set the new size
  104. $this->_setSize( $iNewWidth, $iNewHeight );
  105. // check if the destination dir exists
  106. if(!is_dir( dirname( $sDestination ) ))
  107. {
  108. $this->_sError = 'Destination dir does not exists: '.dirname( $sDestination );
  109. return;
  110. }
  111. // when no filename is given as destination, use the original filename
  112. $c = substr($sDestination, -1, 1);
  113. if( $c == '/' || $c == '\\' )
  114. {
  115. $sDestination .= basename( $this->_sImage );
  116. }
  117. // does the destination has an extension attached ?
  118. if( !in_array( $this->_getExtension( $sDestination ), array('jpg', 'jpeg', 'png', 'gif')))
  119. {
  120. // if not, put the extension of the original file behind it
  121. $sDestination .= '.'.$this->_getExtension($this->_sImage);
  122. }
  123. // get the resource of the original file
  124. $rOrg = $this->_imageCreate( $this->_sImage );
  125. // get the old and new sizes of the image
  126. list($iOrgWidth, $iOrgHeight) = $this->_aSize;
  127. list($iNewWidth, $iNewHeight) = $this->_aNewSize;
  128. // generate the new image
  129. if($this->GDVersion() >= 2)
  130. {
  131. $rImgResized = ImageCreateTrueColor( $iNewWidth, $iNewHeight );
  132. if( $this->_getExtension( $sDestination ) == 'png' )
  133. {
  134. imagealphablending($rImgResized, false);
  135. imagesavealpha($rImgResized, true);
  136. }
  137. ImageCopyResampled( $rImgResized, $rOrg, 0, 0, 0, 0, $iNewWidth, $iNewHeight, $iOrgWidth, $iOrgHeight );
  138. }
  139. else
  140. {
  141. $rImgResized = ImageCreate( $iNewWidth, $iNewHeight );
  142. ImageCopyResized( $rImgResized, $rOrg, 0, 0, 0, 0, $iNewWidth, $iNewHeight, $iOrgWidth, $iOrgHeight );
  143. }
  144. // save the image to file
  145. $this->_saveImage( $rImgResized, $sDestination, $this->_iQuality );
  146. // // set the new width of the image if we are overwriting the original file
  147. if( $sDestination == $this->_sImage )
  148. {
  149. $this->_aSize[0] = $iNewWidth;
  150. $this->_aSize[1] = $iNewHeight;
  151. }
  152. // clean up
  153. ImageDestroy( $rOrg );
  154. ImageDestroy( $rImgResized );
  155. }
  156. }
  157. /**
  158. * ImageConverter::setConstrainProportions()
  159. *
  160. * Should we keep the image proportional when resizing ?
  161. *
  162. * @param bool $status
  163. * @return void
  164. * @access public
  165. * @author Teye Heimans
  166. */
  167. function setConstrainProportions( $status = true )
  168. {
  169. $this->_bConstrainProportions = (bool) $status;
  170. }
  171. /**
  172. * ImageConverter::doMerge()
  173. *
  174. * Merge the image with a stamp
  175. *
  176. * @param string $sStamp: the stamp image
  177. * @param string $sAlign: the horizontal alignment of the stamp (give in percentage or as top, center, bottom)
  178. * @param string $sValign: the vertial alignment of the stamp (give in percentage or as top, middle, bottom)
  179. * @param array $aTransparant: array of rgb color value which should be transparant
  180. * @return void
  181. * @access public
  182. * @author Teye Heimans
  183. */
  184. function doMerge( $sStamp, $sAlign, $sValign, $aTransparant = null )
  185. {
  186. if( file_exists($sStamp))
  187. {
  188. if(!function_exists('imagecopyresampled'))
  189. {
  190. trigger_error(
  191. 'Error, the required function imagecopyresampled does not exists! '.
  192. 'Could not generate new image.',
  193. E_USER_WARNING
  194. );
  195. return;
  196. }
  197. // Open the current file (get the resource )
  198. $rImgSrc = $this->_imageCreate( $this->_sImage );
  199. // create the "new" file recourse
  200. $rImgDest = ImageCreateTrueColor( $this->_aSize[0], $this->_aSize[1] );
  201. // Open the stamp image
  202. $rImgStamp = $this->_imageCreate( $sStamp );
  203. // Transparant color...
  204. if( is_array($aTransparant) )
  205. {
  206. $color = ImageColorAllocate( $rImgStamp, $aTransparant[0], $aTransparant[1], $aTransparant[2] );
  207. ImageColorTransparent($rImgStamp, $color);
  208. }
  209. // Copy the current file to the new one
  210. ImageCopy( $rImgDest, $rImgSrc, 0,0,0,0, $this->_aSize[0], $this->_aSize[1] );
  211. ImageDestroy( $rImgSrc );
  212. // get the new position for the stamp
  213. $x = ImageSX( $rImgStamp );
  214. $y = ImageSY( $rImgStamp );
  215. $posX = $this->_getPos( $this->_aSize[0], $x, $sAlign );
  216. $posY = $this->_getPos( $this->_aSize[1], $y, $sValign );
  217. // copy the stamp to the new image
  218. ImageCopyMerge( $rImgDest, $rImgStamp, $posX, $posY, 0, 0, $x, $y, 100 );
  219. //ImageCopy( $rImgDest, $rImgStamp, $posX, $posY, 0, 0, $x, $y ); # transparant isnt working!
  220. //ImageCopyResampled( $rImgDest, $rImgStamp, 0, 0, $x, $y, $x, $y ); # transparant isnt working!
  221. ImageDestroy( $rImgStamp );
  222. // Save the new image
  223. $this->_saveImage( $rImgDest, $this->_sImage, 100 );
  224. ImageDestroy( $rImgDest );
  225. }
  226. else
  227. {
  228. trigger_error('Error, stamp file does not exists: '. $sStamp, E_USER_WARNING );
  229. }
  230. }
  231. /**
  232. * ImageConverter::GDVersion()
  233. *
  234. * Return the installed GD version
  235. *
  236. * @param int $user_ver: the version needed by the user
  237. * @return int: the installed gd version or 0 on failure
  238. * @access public
  239. * @author Teye Heimans
  240. */
  241. function GDVersion($user_ver = 0)
  242. {
  243. if (!extension_loaded('gd'))
  244. {
  245. return false;
  246. }
  247. static $gd_ver = 0;
  248. // Just accept the specified setting if it's 1.
  249. if ($user_ver == 1)
  250. {
  251. $gd_ver = 1;
  252. return 1;
  253. }
  254. // Use the static variable if function was called previously.
  255. if ($user_ver != 2 && $gd_ver > 0 )
  256. {
  257. return $gd_ver;
  258. }
  259. // Use the gd_info() function if possible.
  260. if (function_exists('gd_info'))
  261. {
  262. $ver_info = gd_info();
  263. preg_match('/\d/', $ver_info['GD Version'], $match);
  264. $gd_ver = $match[0];
  265. return $match[0];
  266. }
  267. // If phpinfo() is disabled use a specified / fail-safe choice...
  268. if (preg_match('/phpinfo/', ini_get('disable_functions')))
  269. {
  270. if ($user_ver == 2)
  271. {
  272. $gd_ver = 2;
  273. return 2;
  274. }
  275. else
  276. {
  277. $gd_ver = 1;
  278. return 1;
  279. }
  280. }
  281. // ...otherwise use phpinfo().
  282. ob_start();
  283. phpinfo(8);
  284. $info = ob_get_contents();
  285. ob_end_clean();
  286. $info = stristr($info, 'gd version');
  287. preg_match('/\d/', $info, $match);
  288. $gd_ver = $match[0];
  289. return $match[0];
  290. }
  291. /******************************
  292. * Private methods *
  293. ******************************/
  294. /**
  295. * ImageConverter::_setSize()
  296. *
  297. * Set the new size of the image and calculate the new size directly
  298. *
  299. * @param int $x: the new width
  300. * @param int $y: the new height
  301. * @return void
  302. * @access private
  303. * @author Teye Heimans
  304. */
  305. function _setSize( $x, $y )
  306. {
  307. // if no errors occourd
  308. if($this->_sError == '')
  309. {
  310. // calculate the new sizes if we have to contrain the proportions
  311. if( $this->_bConstrainProportions )
  312. {
  313. // get the current sizes
  314. list( $iWidth, $iHeight ) = $this->_aSize;
  315. // get the new size
  316. if( $iWidth > $x )
  317. $this->_getNewSize( $iWidth, $iHeight, $x );
  318. if( $iHeight > $y )
  319. $this->_getNewSize( $iHeight, $iWidth, $y );
  320. }
  321. // we dont have to contrain the proportions, just use the sizes
  322. else
  323. {
  324. $iWidth = $x;
  325. $iHeight = $y;
  326. }
  327. $this->_aNewSize = array( $iWidth, $iHeight );
  328. }
  329. }
  330. /**
  331. * ImageConverter::_getPos()
  332. *
  333. * Get the position of the new stamp
  334. *
  335. * @param int $size: the size of the image (width of height)
  336. * @param int $stampSize: the size of the stamp (width of height)
  337. * @param string $where: position where to put the stamp on the image
  338. * @return int
  339. * @access private
  340. * @author Teye Heimans
  341. */
  342. function _getPos( $size, $stampSize, $where )
  343. {
  344. // percentage ?
  345. if(strpos($where, '%') !== false)
  346. {
  347. $percent = str_replace( '%', '', $where );
  348. $part = $size / 100;
  349. $x = ceil( $percent * $part );
  350. }
  351. else
  352. {
  353. // get the pos for the copyright stamp
  354. switch (StrToLower($where))
  355. {
  356. case 'top':
  357. case 'left':
  358. $x = 0;
  359. break;
  360. case 'middle':
  361. case 'center':
  362. $x = ceil($size / 2) - ceil($stampSize / 2);
  363. break;
  364. case 'bottom':
  365. case 'right':
  366. $x = $size - $stampSize;
  367. break;
  368. default:
  369. $x = 0;
  370. }
  371. }
  372. return $x;
  373. }
  374. /**
  375. * ImageConverter::_getNewSize()
  376. *
  377. * Calculate the new size
  378. *
  379. * @param int $x: The old width
  380. * @param int $y: The old height
  381. * @param int $max: The max width/height allowed
  382. * @return void
  383. * @access private
  384. * @author Teye Heimans
  385. */
  386. function _getNewSize( &$x, &$y, $max )
  387. {
  388. $procent = $x / 100;
  389. $scale = $max / $procent;
  390. $x = $scale * $procent;
  391. $y = $scale * ($y / 100);
  392. }
  393. /**
  394. * ImageConverter::_getExtension()
  395. *
  396. * Return the extension of the given file
  397. *
  398. * @param string $sFile: the file where we have to retrieve the extension from
  399. * @return string
  400. * @access private
  401. * @author Teye Heimans
  402. */
  403. function _getExtension( $sFile )
  404. {
  405. $fp = explode( '.', $sFile );
  406. return StrToLower( $fp[ count($fp) -1 ] );
  407. }
  408. /**
  409. * ImageConverter::_imageCreate()
  410. *
  411. * Create a new image resource based on the extension of the given file
  412. *
  413. * @param string $sFile: The file
  414. * @return resource or false on failure
  415. * @author Teye Heimans
  416. * @access private
  417. */
  418. function _imageCreate( $sFile )
  419. {
  420. $sExt = $this->_getExtension( $sFile );
  421. // got extension ?
  422. if( $sExt )
  423. {
  424. if($sExt == 'jpg' || $sExt == 'jpeg')
  425. {
  426. return ImageCreateFromJPEG( $sFile );
  427. }
  428. elseif($sExt == 'png')
  429. {
  430. return ImageCreateFromPNG( $sFile);
  431. }
  432. elseif($sExt == 'gif' && function_exists('imagecreatefromgif'))
  433. {
  434. return ImageCreateFromGIF( $sFile );
  435. }
  436. }
  437. // something went wrong
  438. return false;
  439. }
  440. /**
  441. * ImageConverter::_saveImage()
  442. *
  443. * Function to save the new image
  444. *
  445. * @param resource $rImg: the image to save
  446. * @param string $sDestination: how to save the new image
  447. * @param int $iQuality: the quality of the new image
  448. * @return bool: true of succes and false on failure
  449. * @access private
  450. * @author Teye Heimans
  451. */
  452. function _saveImage( &$rImage, $sDestination, $iQuality = null )
  453. {
  454. $sExt = $this->_getExtension( $sDestination );
  455. if($sExt == 'jpg' || $sExt == 'jpeg')
  456. {
  457. return ImageJPEG($rImage, $sDestination, $iQuality);
  458. }
  459. elseif($sExt == 'png')
  460. {
  461. return ImagePNG($rImage, $sDestination);
  462. }
  463. elseif( $sExt == 'gif' && function_exists('imagegif') )
  464. {
  465. return imagegif($rImage, $sDestination);
  466. }
  467. else
  468. {
  469. trigger_error('Wrong destination given!', E_USER_WARNING );
  470. return false;
  471. }
  472. }
  473. }
  474. ?>