C_NggLegacy_Thumbnail

PHP class for dynamically resizing, cropping, and rotating images for thumbnail purposes and either displaying them on-the-fly or saving them.

Defined (1)

The class is defined in the following location(s).

/products/photocrati_nextgen/modules/nextgen_data/package.module.nextgen_data.php  
  1. class C_NggLegacy_Thumbnail 
  2. /** 
  3. * Error message to display, if any 
  4. * @var string 
  5. */ 
  6. var $errmsg; 
  7. /** 
  8. * Whether or not there is an error 
  9. * @var boolean 
  10. */ 
  11. var $error; 
  12. /** 
  13. * Format of the image file 
  14. * @var string 
  15. */ 
  16. var $format; 
  17. /** 
  18. * File name and path of the image file 
  19. * @var string 
  20. */ 
  21. var $fileName; 
  22. /** 
  23. * Current dimensions of working image 
  24. * @var array 
  25. */ 
  26. var $currentDimensions; 
  27. /** 
  28. * New dimensions of working image 
  29. * @var array 
  30. */ 
  31. var $newDimensions; 
  32. /** 
  33. * Image resource for newly manipulated image 
  34. * @var resource 
  35. * @access private 
  36. */ 
  37. var $newImage; 
  38. /** 
  39. * Image resource for image before previous manipulation 
  40. * @var resource 
  41. * @access private 
  42. */ 
  43. var $oldImage; 
  44. /** 
  45. * Image resource for image being currently manipulated 
  46. * @var resource 
  47. * @access private 
  48. */ 
  49. var $workingImage; 
  50. /** 
  51. * Percentage to resize image by 
  52. * @var int 
  53. * @access private 
  54. */ 
  55. var $percent; 
  56. /** 
  57. * Maximum width of image during resize 
  58. * @var int 
  59. * @access private 
  60. */ 
  61. var $maxWidth; 
  62. /** 
  63. * Maximum height of image during resize 
  64. * @var int 
  65. * @access private 
  66. */ 
  67. var $maxHeight; 
  68. /** 
  69. * Image for Watermark 
  70. * @var string 
  71. *  
  72. */ 
  73. var $watermarkImgPath; 
  74. /** 
  75. * Text for Watermark 
  76. * @var string 
  77. *  
  78. */ 
  79. var $watermarkText; 
  80. /** 
  81. * Image Resource ID for Watermark 
  82. * @var string 
  83. *  
  84. */ 
  85. function __construct($fileName, $no_ErrorImage = false) 
  86. //make sure the GD library is installed 
  87. if (!function_exists("gd_info")) { 
  88. echo 'You do not have the GD Library installed. This class requires the GD library to function properly.' . "\n"; 
  89. echo 'visit http://us2.php.net/manual/en/ref.image.php for more information'; 
  90. throw new E_No_Image_Library_Exception(); 
  91. //initialize variables 
  92. $this->errmsg = ''; 
  93. $this->error = false; 
  94. $this->currentDimensions = array(); 
  95. $this->newDimensions = array(); 
  96. $this->fileName = $fileName; 
  97. $this->percent = 100; 
  98. $this->maxWidth = 0; 
  99. $this->maxHeight = 0; 
  100. $this->watermarkImgPath = ''; 
  101. $this->watermarkText = ''; 
  102. //check to see if file exists 
  103. if (!@file_exists($this->fileName)) { 
  104. $this->errmsg = 'File not found'; 
  105. $this->error = true; 
  106. } elseif (!is_readable($this->fileName)) { 
  107. $this->errmsg = 'File is not readable'; 
  108. $this->error = true; 
  109. //if there are no errors, determine the file format 
  110. if ($this->error == false) { 
  111. @ini_set('memory_limit', -1); 
  112. $data = @getimagesize($this->fileName); 
  113. if (isset($data) && is_array($data)) { 
  114. $extensions = array('1' => 'GIF', '2' => 'JPG', '3' => 'PNG'); 
  115. $extension = array_key_exists($data[2], $extensions) ? $extensions[$data[2]] : ''; 
  116. if ($extension) { 
  117. $this->format = $extension; 
  118. } else { 
  119. $this->errmsg = 'Unknown file format'; 
  120. $this->error = true; 
  121. } else { 
  122. $this->errmsg = 'File is not an image'; 
  123. $this->error = true; 
  124. // increase memory-limit if possible, GD needs this for large images 
  125. if (!extension_loaded('suhosin')) { 
  126. @ini_set('memory_limit', '512M'); 
  127. if ($this->error == false) { 
  128. // Check memory consumption if file exists 
  129. $this->checkMemoryForImage($this->fileName); 
  130. //initialize resources if no errors 
  131. if ($this->error == false) { 
  132. $img_err = null; 
  133. switch ($this->format) { 
  134. case 'GIF': 
  135. if (function_exists('ImageCreateFromGif')) { 
  136. $this->oldImage = @ImageCreateFromGif($this->fileName); 
  137. } else { 
  138. $img_err = __('Support for GIF format is missing.', 'nggallery'); 
  139. break; 
  140. case 'JPG': 
  141. if (function_exists('ImageCreateFromJpeg')) { 
  142. $this->oldImage = @ImageCreateFromJpeg($this->fileName); 
  143. } else { 
  144. $img_err = __('Support for JPEG format is missing.', 'nggallery'); 
  145. break; 
  146. case 'PNG': 
  147. if (function_exists('ImageCreateFromPng')) { 
  148. $this->oldImage = @ImageCreateFromPng($this->fileName); 
  149. } else { 
  150. $img_err = __('Support for PNG format is missing.', 'nggallery'); 
  151. break; 
  152. if (!$this->oldImage) { 
  153. if ($img_err == null) { 
  154. $img_err = __('Check memory limit', 'nggallery'); 
  155. $this->errmsg = sprintf(__('Create Image failed. %1$s', 'nggallery'), $img_err); 
  156. $this->error = true; 
  157. } else { 
  158. $size = GetImageSize($this->fileName); 
  159. $this->currentDimensions = array('width' => $size[0], 'height' => $size[1]); 
  160. $this->newImage = $this->oldImage; 
  161. if ($this->error == true) { 
  162. if (!$no_ErrorImage) { 
  163. $this->showErrorImage(); 
  164. return; 
  165. /** 
  166. * Calculate the memory limit 
  167. */ 
  168. function checkMemoryForImage($filename) 
  169. if (function_exists('memory_get_usage') && ini_get('memory_limit')) { 
  170. $imageInfo = getimagesize($filename); 
  171. switch ($this->format) { 
  172. case 'GIF': 
  173. // measured factor 1 is better 
  174. $CHANNEL = 1; 
  175. break; 
  176. case 'JPG': 
  177. $CHANNEL = $imageInfo['channels']; 
  178. break; 
  179. case 'PNG': 
  180. // didn't get the channel for png 
  181. $CHANNEL = 3; 
  182. break; 
  183. $MB = 1048576; 
  184. // number of bytes in 1M 
  185. $K64 = 65536; 
  186. // number of bytes in 64K 
  187. $TWEAKFACTOR = 1.68; 
  188. // Or whatever works for you 
  189. $bits = !empty($imageInfo['bits']) ? $imageInfo['bits'] : 32; 
  190. // imgInfo[bits] is not always available 
  191. $memoryNeeded = round(($imageInfo[0] * $imageInfo[1] * $bits * $CHANNEL / 8 + $K64) * $TWEAKFACTOR); 
  192. $memoryNeeded = memory_get_usage() + $memoryNeeded; 
  193. // get memory limit 
  194. $memory_limit = ini_get('memory_limit'); 
  195. // PHP docs : Note that to have no memory limit, set this directive to -1. 
  196. if ($memory_limit == -1) { 
  197. return; 
  198. // Just check megabyte limits, not higher 
  199. if (strtolower(substr($memory_limit, -1)) == 'm') { 
  200. if ($memory_limit != '') { 
  201. $memory_limit = substr($memory_limit, 0, -1) * 1024 * 1024; 
  202. if ($memoryNeeded > $memory_limit) { 
  203. $memoryNeeded = round($memoryNeeded / 1024 / 1024, 2); 
  204. $this->errmsg = 'Exceed Memory limit. Require : ' . $memoryNeeded . " MByte"; 
  205. $this->error = true; 
  206. return; 
  207. function __destruct() 
  208. $this->destruct(); 
  209. /** 
  210. * Must be called to free up allocated memory after all manipulations are done 
  211. */ 
  212. function destruct() 
  213. if (is_resource($this->newImage)) { 
  214. @ImageDestroy($this->newImage); 
  215. if (is_resource($this->oldImage)) { 
  216. @ImageDestroy($this->oldImage); 
  217. if (is_resource($this->workingImage)) { 
  218. @ImageDestroy($this->workingImage); 
  219. /** 
  220. * Returns the current width of the image 
  221. * @return int 
  222. */ 
  223. function getCurrentWidth() 
  224. return $this->currentDimensions['width']; 
  225. /** 
  226. * Returns the current height of the image 
  227. * @return int 
  228. */ 
  229. function getCurrentHeight() 
  230. return $this->currentDimensions['height']; 
  231. /** 
  232. * Calculates new image width 
  233. * @param int $width 
  234. * @param int $height 
  235. * @return array 
  236. */ 
  237. function calcWidth($width, $height) 
  238. $newWp = 100 * $this->maxWidth / $width; 
  239. $newHeight = $height * $newWp / 100; 
  240. if (intval($newHeight) == $this->maxHeight - 1) { 
  241. $newHeight = $this->maxHeight; 
  242. return array('newWidth' => intval($this->maxWidth), 'newHeight' => intval($newHeight)); 
  243. /** 
  244. * Calculates new image height 
  245. * @param int $width 
  246. * @param int $height 
  247. * @return array 
  248. */ 
  249. function calcHeight($width, $height) 
  250. $newHp = 100 * $this->maxHeight / $height; 
  251. $newWidth = $width * $newHp / 100; 
  252. if (intval($newWidth) == $this->maxWidth - 1) { 
  253. $newWidth = $this->maxWidth; 
  254. return array('newWidth' => intval($newWidth), 'newHeight' => intval($this->maxHeight)); 
  255. /** 
  256. * Calculates new image size based on percentage 
  257. * @param int $width 
  258. * @param int $height 
  259. * @return array 
  260. */ 
  261. function calcPercent($width, $height) 
  262. $newWidth = $width * $this->percent / 100; 
  263. $newHeight = $height * $this->percent / 100; 
  264. return array('newWidth' => intval($newWidth), 'newHeight' => intval($newHeight)); 
  265. /** 
  266. * Calculates new image size based on width and height, while constraining to maxWidth and maxHeight 
  267. * @param int $width 
  268. * @param int $height 
  269. */ 
  270. function calcImageSize($width, $height) 
  271. // $width and $height are the CURRENT image resolutions 
  272. $ratio_w = $this->maxWidth / $width; 
  273. $ratio_h = $this->maxHeight / $height; 
  274. if ($ratio_w >= $ratio_h) { 
  275. $width = $this->maxWidth; 
  276. $height = (int) round($height * $ratio_h, 0); 
  277. } else { 
  278. $height = $this->maxHeight; 
  279. $width = (int) round($width * $ratio_w, 0); 
  280. $this->newDimensions = array('newWidth' => $width, 'newHeight' => $height); 
  281. /** 
  282. * Calculates new image size based percentage 
  283. * @param int $width 
  284. * @param int $height 
  285. */ 
  286. function calcImageSizePercent($width, $height) 
  287. if ($this->percent > 0) { 
  288. $this->newDimensions = $this->calcPercent($width, $height); 
  289. /** 
  290. * Displays error image 
  291. */ 
  292. function showErrorImage() 
  293. header('Content-type: image/png'); 
  294. $errImg = ImageCreate(220, 25); 
  295. $bgColor = imagecolorallocate($errImg, 0, 0, 0); 
  296. $fgColor1 = imagecolorallocate($errImg, 255, 255, 255); 
  297. $fgColor2 = imagecolorallocate($errImg, 255, 0, 0); 
  298. imagestring($errImg, 3, 6, 6, 'Error:', $fgColor2); 
  299. imagestring($errImg, 3, 55, 6, $this->errmsg, $fgColor1); 
  300. imagepng($errImg); 
  301. imagedestroy($errImg); 
  302. /** 
  303. * Resizes image to fixed Width x Height 
  304. *  
  305. * @param int $Width 
  306. * @param int $Height 
  307. */ 
  308. function resizeFix($Width = 0, $Height = 0, $deprecated = 3) 
  309. $this->newWidth = $Width; 
  310. $this->newHeight = $Height; 
  311. if (function_exists("ImageCreateTrueColor")) { 
  312. $this->workingImage = ImageCreateTrueColor($this->newWidth, $this->newHeight); 
  313. } else { 
  314. $this->workingImage = ImageCreate($this->newWidth, $this->newHeight); 
  315. // ImageCopyResampled( 
  316. $this->imagecopyresampled($this->workingImage, $this->oldImage, 0, 0, 0, 0, $this->newWidth, $this->newHeight, $this->currentDimensions['width'], $this->currentDimensions['height']); 
  317. $this->oldImage = $this->workingImage; 
  318. $this->newImage = $this->workingImage; 
  319. $this->currentDimensions['width'] = $this->newWidth; 
  320. $this->currentDimensions['height'] = $this->newHeight; 
  321. /** 
  322. * Resizes image to maxWidth x maxHeight 
  323. * @param int $maxWidth 
  324. * @param int $maxHeight 
  325. */ 
  326. function resize($maxWidth = 0, $maxHeight = 0, $deprecated = 3) 
  327. $this->maxWidth = $maxWidth; 
  328. $this->maxHeight = $maxHeight; 
  329. $this->calcImageSize($this->currentDimensions['width'], $this->currentDimensions['height']); 
  330. if (function_exists("ImageCreateTrueColor")) { 
  331. $this->workingImage = ImageCreateTrueColor($this->newDimensions['newWidth'], $this->newDimensions['newHeight']); 
  332. } else { 
  333. $this->workingImage = ImageCreate($this->newDimensions['newWidth'], $this->newDimensions['newHeight']); 
  334. // ImageCopyResampled( 
  335. $this->imagecopyresampled($this->workingImage, $this->oldImage, 0, 0, 0, 0, $this->newDimensions['newWidth'], $this->newDimensions['newHeight'], $this->currentDimensions['width'], $this->currentDimensions['height']); 
  336. $this->oldImage = $this->workingImage; 
  337. $this->newImage = $this->workingImage; 
  338. $this->currentDimensions['width'] = $this->newDimensions['newWidth']; 
  339. $this->currentDimensions['height'] = $this->newDimensions['newHeight']; 
  340. /** 
  341. * Resizes the image by $percent percent 
  342. * @param int $percent 
  343. */ 
  344. function resizePercent($percent = 0) 
  345. $this->percent = $percent; 
  346. $this->calcImageSizePercent($this->currentDimensions['width'], $this->currentDimensions['height']); 
  347. if (function_exists("ImageCreateTrueColor")) { 
  348. $this->workingImage = ImageCreateTrueColor($this->newDimensions['newWidth'], $this->newDimensions['newHeight']); 
  349. } else { 
  350. $this->workingImage = ImageCreate($this->newDimensions['newWidth'], $this->newDimensions['newHeight']); 
  351. $this->ImageCopyResampled($this->workingImage, $this->oldImage, 0, 0, 0, 0, $this->newDimensions['newWidth'], $this->newDimensions['newHeight'], $this->currentDimensions['width'], $this->currentDimensions['height']); 
  352. $this->oldImage = $this->workingImage; 
  353. $this->newImage = $this->workingImage; 
  354. $this->currentDimensions['width'] = $this->newDimensions['newWidth']; 
  355. $this->currentDimensions['height'] = $this->newDimensions['newHeight']; 
  356. /** 
  357. * Crops the image from calculated center in a square of $cropSize pixels 
  358. * @param int $cropSize 
  359. */ 
  360. function cropFromCenter($cropSize) 
  361. if ($cropSize > $this->currentDimensions['width']) { 
  362. $cropSize = $this->currentDimensions['width']; 
  363. if ($cropSize > $this->currentDimensions['height']) { 
  364. $cropSize = $this->currentDimensions['height']; 
  365. $cropX = intval(($this->currentDimensions['width'] - $cropSize) / 2); 
  366. $cropY = intval(($this->currentDimensions['height'] - $cropSize) / 2); 
  367. if (function_exists("ImageCreateTrueColor")) { 
  368. $this->workingImage = ImageCreateTrueColor($cropSize, $cropSize); 
  369. } else { 
  370. $this->workingImage = ImageCreate($cropSize, $cropSize); 
  371. $this->imagecopyresampled($this->workingImage, $this->oldImage, 0, 0, $cropX, $cropY, $cropSize, $cropSize, $cropSize, $cropSize); 
  372. $this->oldImage = $this->workingImage; 
  373. $this->newImage = $this->workingImage; 
  374. $this->currentDimensions['width'] = $cropSize; 
  375. $this->currentDimensions['height'] = $cropSize; 
  376. /** 
  377. * Advanced cropping function that crops an image using $startX and $startY as the upper-left hand corner. 
  378. * @param int $startX 
  379. * @param int $startY 
  380. * @param int $width 
  381. * @param int $height 
  382. */ 
  383. function crop($startX, $startY, $width, $height) 
  384. //make sure the cropped area is not greater than the size of the image 
  385. if ($width > $this->currentDimensions['width']) { 
  386. $width = $this->currentDimensions['width']; 
  387. if ($height > $this->currentDimensions['height']) { 
  388. $height = $this->currentDimensions['height']; 
  389. //make sure not starting outside the image 
  390. if ($startX + $width > $this->currentDimensions['width']) { 
  391. $startX = $this->currentDimensions['width'] - $width; 
  392. if ($startY + $height > $this->currentDimensions['height']) { 
  393. $startY = $this->currentDimensions['height'] - $height; 
  394. if ($startX < 0) { 
  395. $startX = 0; 
  396. if ($startY < 0) { 
  397. $startY = 0; 
  398. if (function_exists("ImageCreateTrueColor")) { 
  399. $this->workingImage = ImageCreateTrueColor($width, $height); 
  400. } else { 
  401. $this->workingImage = ImageCreate($width, $height); 
  402. $this->imagecopyresampled($this->workingImage, $this->oldImage, 0, 0, $startX, $startY, $width, $height, $width, $height); 
  403. $this->oldImage = $this->workingImage; 
  404. $this->newImage = $this->workingImage; 
  405. $this->currentDimensions['width'] = $width; 
  406. $this->currentDimensions['height'] = $height; 
  407. /** 
  408. * Outputs the image to the screen, or saves to $name if supplied. Quality of JPEG images can be controlled with the $quality variable 
  409. * @param int $quality 
  410. * @param string $name 
  411. */ 
  412. function show($quality = 100, $name = '') 
  413. switch ($this->format) { 
  414. case 'GIF': 
  415. if ($name != '') { 
  416. @ImageGif($this->newImage, $name) or $this->error = true; 
  417. } else { 
  418. header('Content-type: image/gif'); 
  419. ImageGif($this->newImage); 
  420. break; 
  421. case 'JPG': 
  422. if ($name != '') { 
  423. @ImageJpeg($this->newImage, $name, $quality) or $this->error = true; 
  424. } else { 
  425. header('Content-type: image/jpeg'); 
  426. ImageJpeg($this->newImage, NULL, $quality); 
  427. break; 
  428. case 'PNG': 
  429. if ($name != '') { 
  430. @ImagePng($this->newImage, $name) or $this->error = true; 
  431. } else { 
  432. header('Content-type: image/png'); 
  433. ImagePng($this->newImage); 
  434. break; 
  435. /** 
  436. * Saves image as $name (can include file path), with quality of # percent if file is a jpeg 
  437. * @param string $name 
  438. * @param int $quality 
  439. * @return bool errorstate 
  440. */ 
  441. function save($name, $quality = 100) 
  442. $this->show($quality, $name); 
  443. if ($this->error == true) { 
  444. $this->errmsg = 'Create Image failed. Check safe mode settings'; 
  445. return false; 
  446. if (function_exists('do_action')) { 
  447. do_action('ngg_ajax_image_save', $name); 
  448. return true; 
  449. /** 
  450. * Creates Apple-style reflection under image, optionally adding a border to main image 
  451. * @param int $percent 
  452. * @param int $reflection 
  453. * @param int $white 
  454. * @param bool $border 
  455. * @param string $borderColor 
  456. */ 
  457. function createReflection($percent, $reflection, $white, $border = true, $borderColor = '#a4a4a4') 
  458. $width = $this->currentDimensions['width']; 
  459. $height = $this->currentDimensions['height']; 
  460. $reflectionHeight = intval($height * ($reflection / 100)); 
  461. $newHeight = $height + $reflectionHeight; 
  462. $reflectedPart = $height * ($percent / 100); 
  463. $this->workingImage = ImageCreateTrueColor($width, $newHeight); 
  464. ImageAlphaBlending($this->workingImage, true); 
  465. $colorToPaint = ImageColorAllocateAlpha($this->workingImage, 255, 255, 255, 0); 
  466. ImageFilledRectangle($this->workingImage, 0, 0, $width, $newHeight, $colorToPaint); 
  467. imagecopyresampled($this->workingImage, $this->newImage, 0, 0, 0, $reflectedPart, $width, $reflectionHeight, $width, $height - $reflectedPart); 
  468. $this->imageFlipVertical(); 
  469. imagecopy($this->workingImage, $this->newImage, 0, 0, 0, 0, $width, $height); 
  470. imagealphablending($this->workingImage, true); 
  471. for ($i = 0; $i < $reflectionHeight; $i++) { 
  472. $colorToPaint = imagecolorallocatealpha($this->workingImage, 255, 255, 255, ($i / $reflectionHeight * -1 + 1) * $white); 
  473. imagefilledrectangle($this->workingImage, 0, $height + $i, $width, $height + $i, $colorToPaint); 
  474. if ($border == true) { 
  475. $rgb = $this->hex2rgb($borderColor, false); 
  476. $colorToPaint = imagecolorallocate($this->workingImage, $rgb[0], $rgb[1], $rgb[2]); 
  477. imageline($this->workingImage, 0, 0, $width, 0, $colorToPaint); 
  478. //top line 
  479. imageline($this->workingImage, 0, $height, $width, $height, $colorToPaint); 
  480. //bottom line 
  481. imageline($this->workingImage, 0, 0, 0, $height, $colorToPaint); 
  482. //left line 
  483. imageline($this->workingImage, $width - 1, 0, $width - 1, $height, $colorToPaint); 
  484. //right line 
  485. $this->oldImage = $this->workingImage; 
  486. $this->newImage = $this->workingImage; 
  487. $this->currentDimensions['width'] = $width; 
  488. $this->currentDimensions['height'] = $newHeight; 
  489. /** 
  490. * Flip an image. 
  491. * @param bool $horz flip the image in horizontal mode 
  492. * @param bool $vert flip the image in vertical mode 
  493. */ 
  494. function flipImage($horz = false, $vert = false) 
  495. $sx = $vert ? $this->currentDimensions['width'] - 1 : 0; 
  496. $sy = $horz ? $this->currentDimensions['height'] - 1 : 0; 
  497. $sw = $vert ? -$this->currentDimensions['width'] : $this->currentDimensions['width']; 
  498. $sh = $horz ? -$this->currentDimensions['height'] : $this->currentDimensions['height']; 
  499. $this->workingImage = imagecreatetruecolor($this->currentDimensions['width'], $this->currentDimensions['height']); 
  500. $this->imagecopyresampled($this->workingImage, $this->oldImage, 0, 0, $sx, $sy, $this->currentDimensions['width'], $this->currentDimensions['height'], $sw, $sh); 
  501. $this->oldImage = $this->workingImage; 
  502. $this->newImage = $this->workingImage; 
  503. return true; 
  504. /** 
  505. * Rotate an image clockwise or counter clockwise 
  506. * @param string $direction could be CW or CCW 
  507. */ 
  508. function rotateImage($dir = 'CW') 
  509. $angle = $dir == 'CW' ? 90 : -90; 
  510. return $this->rotateImageAngle($angle); 
  511. /** 
  512. * Rotate an image clockwise or counter clockwise 
  513. * @param string $direction could be CW or CCW 
  514. */ 
  515. function rotateImageAngle($angle = 90) 
  516. if (function_exists('imagerotate')) { 
  517. $this->workingImage = imagerotate($this->oldImage, 360 - $angle, 0); 
  518. // imagerotate() rotates CCW 
  519. $this->currentDimensions['width'] = imagesx($this->workingImage); 
  520. $this->currentDimensions['height'] = imagesy($this->workingImage); 
  521. $this->oldImage = $this->workingImage; 
  522. $this->newImage = $this->workingImage; 
  523. return true; 
  524. $this->workingImage = imagecreatetruecolor($this->currentDimensions['height'], $this->currentDimensions['width']); 
  525. imagealphablending($this->workingImage, false); 
  526. imagesavealpha($this->workingImage, true); 
  527. switch ($angle) { 
  528. case 90: 
  529. for ($x = 0; $x < $this->currentDimensions['width']; $x++) { 
  530. for ($y = 0; $y < $this->currentDimensions['height']; $y++) { 
  531. if (!imagecopy($this->workingImage, $this->oldImage, $this->currentDimensions['height'] - $y - 1, $x, $x, $y, 1, 1)) { 
  532. return false; 
  533. break; 
  534. case -90: 
  535. for ($x = 0; $x < $this->currentDimensions['width']; $x++) { 
  536. for ($y = 0; $y < $this->currentDimensions['height']; $y++) { 
  537. if (!imagecopy($this->workingImage, $this->oldImage, $y, $this->currentDimensions['width'] - $x - 1, $x, $y, 1, 1)) { 
  538. return false; 
  539. break; 
  540. default: 
  541. return false; 
  542. $this->currentDimensions['width'] = imagesx($this->workingImage); 
  543. $this->currentDimensions['height'] = imagesy($this->workingImage); 
  544. $this->oldImage = $this->workingImage; 
  545. $this->newImage = $this->workingImage; 
  546. return true; 
  547. /** 
  548. * Inverts working image, used by reflection function 
  549. *  
  550. * @access private 
  551. */ 
  552. function imageFlipVertical() 
  553. $x_i = imagesx($this->workingImage); 
  554. $y_i = imagesy($this->workingImage); 
  555. for ($x = 0; $x < $x_i; $x++) { 
  556. for ($y = 0; $y < $y_i; $y++) { 
  557. imagecopy($this->workingImage, $this->workingImage, $x, $y_i - $y - 1, $x, $y, 1, 1); 
  558. /** 
  559. * Converts hexidecimal color value to rgb values and returns as array/string 
  560. * @param string $hex 
  561. * @param bool $asString 
  562. * @return array|string 
  563. */ 
  564. function hex2rgb($hex, $asString = false) 
  565. // strip off any leading # 
  566. if (0 === strpos($hex, '#')) { 
  567. $hex = substr($hex, 1); 
  568. } else { 
  569. if (0 === strpos($hex, '&H')) { 
  570. $hex = substr($hex, 2); 
  571. // break into hex 3-tuple 
  572. $cutpoint = ceil(strlen($hex) / 2) - 1; 
  573. $rgb = explode(':', wordwrap($hex, $cutpoint, ':', $cutpoint), 3); 
  574. // convert each tuple to decimal 
  575. $rgb[0] = isset($rgb[0]) ? hexdec($rgb[0]) : 0; 
  576. $rgb[1] = isset($rgb[1]) ? hexdec($rgb[1]) : 0; 
  577. $rgb[2] = isset($rgb[2]) ? hexdec($rgb[2]) : 0; 
  578. return $asString ? "{$rgb[0]} {$rgb[1]} {$rgb[2]}" : $rgb; 
  579. /** 
  580. * Based on the Watermark function by Marek Malcherek  
  581. * http://www.malcherek.de 
  582. * @param string $color 
  583. * @param string $wmFont 
  584. * @param int $wmSize 
  585. * @param int $wmOpaque 
  586. */ 
  587. function watermarkCreateText($color = '000000', $wmFont, $wmSize = 10, $wmOpaque = 90) 
  588. // set font path 
  589. $wmFontPath = NGGALLERY_ABSPATH . "fonts/" . $wmFont; 
  590. if (!is_readable($wmFontPath)) { 
  591. return; 
  592. // This function requires both the GD library and the FreeType library. 
  593. if (!function_exists('ImageTTFBBox')) { 
  594. return; 
  595. $words = preg_split('/ /', $this->watermarkText); 
  596. $lines = array(); 
  597. $line = ''; 
  598. $watermark_image_width = 0; 
  599. // attempt adding a new word until the width is too large; then start a new line and start again 
  600. foreach ($words as $word) { 
  601. // sanitize the text being input; imagettftext() can be sensitive 
  602. $TextSize = $this->ImageTTFBBoxDimensions($wmSize, 0, $this->correct_gd_unc_path($wmFontPath), $line . preg_replace('~^(&([a-zA-Z0-9]);)~', htmlentities('${1}'), mb_convert_encoding($word, "HTML-ENTITIES", "UTF-8"))); 
  603. if ($watermark_image_width == 0) { 
  604. $watermark_image_width = $TextSize['width']; 
  605. if ($TextSize['width'] > $this->newDimensions['newWidth']) { 
  606. $lines[] = trim($line); 
  607. $line = ''; 
  608. } else { 
  609. if ($TextSize['width'] > $watermark_image_width) { 
  610. $watermark_image_width = $TextSize['width']; 
  611. $line .= $word . ' '; 
  612. $lines[] = trim($line); 
  613. // use this string to determine our largest possible line height 
  614. $line_dimensions = $this->ImageTTFBBoxDimensions($wmSize, 0, $this->correct_gd_unc_path($wmFontPath), 'MXQJALYmxqjabdfghjklpqry019`@$^&*(, !132'); 
  615. $line_height = $line_dimensions['height'] * 1.05; 
  616. // Create an image to apply our text to 
  617. $this->workingImage = ImageCreateTrueColor($watermark_image_width, count($lines) * $line_height); 
  618. ImageSaveAlpha($this->workingImage, true); 
  619. ImageAlphaBlending($this->workingImage, false); 
  620. $bgText = imagecolorallocatealpha($this->workingImage, 255, 255, 255, 127); 
  621. imagefill($this->workingImage, 0, 0, $bgText); 
  622. $wmTransp = 127 - $wmOpaque * 1.27; 
  623. $rgb = $this->hex2rgb($color, false); 
  624. $TextColor = imagecolorallocatealpha($this->workingImage, $rgb[0], $rgb[1], $rgb[2], $wmTransp); 
  625. // Put text on the image, line-by-line 
  626. $y_pos = $wmSize; 
  627. foreach ($lines as $line) { 
  628. imagettftext($this->workingImage, $wmSize, 0, 0, $y_pos, $TextColor, $this->correct_gd_unc_path($wmFontPath), $line); 
  629. $y_pos += $line_height; 
  630. $this->watermarkImgPath = $this->workingImage; 
  631. return; 
  632. /** 
  633. * Returns a path that can be used with imagettftext() and ImageTTFBBox() 
  634. * imagettftext() and ImageTTFBBox() cannot load resources from Windows UNC paths 
  635. * and require they be mangled to be like //server\filename instead of \\server\filename 
  636. * @param string $path Absolute file path 
  637. * @return string $path Mangled absolute file path 
  638. */ 
  639. public function correct_gd_unc_path($path) 
  640. if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && substr($path, 0, 2) === '\\\\') { 
  641. $path = ltrim($path, '\\\\'); 
  642. $path = '//' . $path; 
  643. return $path; 
  644. /** 
  645. * Calculates the width & height dimensions of ImageTTFBBox(). 
  646. * Note: ImageTTFBBox() is unreliable with large font sizes 
  647. * @param $wmSize 
  648. * @param $fontAngle 
  649. * @param $wmFontPath 
  650. * @param $text 
  651. * @return array 
  652. */ 
  653. function ImageTTFBBoxDimensions($wmSize, $fontAngle, $wmFontPath, $text) 
  654. $box = @ImageTTFBBox($wmSize, $fontAngle, $this->correct_gd_unc_path($wmFontPath), $text); 
  655. $max_x = max(array($box[0], $box[2], $box[4], $box[6])); 
  656. $max_y = max(array($box[1], $box[3], $box[5], $box[7])); 
  657. $min_x = min(array($box[0], $box[2], $box[4], $box[6])); 
  658. $min_y = min(array($box[1], $box[3], $box[5], $box[7])); 
  659. return array("width" => $max_x - $min_x, "height" => $max_y - $min_y); 
  660. function applyFilter($filterType) 
  661. $args = func_get_args(); 
  662. array_unshift($args, $this->newImage); 
  663. return call_user_func_array('imagefilter', $args); 
  664. /** 
  665. * Modfied Watermark function by Steve Peart  
  666. * http://parasitehosting.com/ 
  667. * @param string $relPOS 
  668. * @param int $xPOS 
  669. * @param int $yPOS 
  670. */ 
  671. function watermarkImage($relPOS = 'botRight', $xPOS = 0, $yPOS = 0) 
  672. // if it's a resource ID take it as watermark text image 
  673. if (is_resource($this->watermarkImgPath)) { 
  674. $this->workingImage = $this->watermarkImgPath; 
  675. } else { 
  676. // (possibly) search for the file from the document root 
  677. if (!is_file($this->watermarkImgPath)) { 
  678. $fs = C_Fs::get_instance(); 
  679. if (is_file($fs->join_paths($fs->get_document_root('content'), $this->watermarkImgPath))) { 
  680. $this->watermarkImgPath = $fs->get_document_root('content') . $this->watermarkImgPath; 
  681. // Would you really want to use anything other than a png? 
  682. $this->workingImage = @imagecreatefrompng($this->watermarkImgPath); 
  683. // if it's not a valid file die... 
  684. if (empty($this->workingImage) or !$this->workingImage) { 
  685. return; 
  686. imagealphablending($this->workingImage, false); 
  687. imagesavealpha($this->workingImage, true); 
  688. $sourcefile_width = imageSX($this->oldImage); 
  689. $sourcefile_height = imageSY($this->oldImage); 
  690. $watermarkfile_width = imageSX($this->workingImage); 
  691. $watermarkfile_height = imageSY($this->workingImage); 
  692. switch (substr($relPOS, 0, 3)) { 
  693. case 'top': 
  694. $dest_y = 0 + $yPOS; 
  695. break; 
  696. case 'mid': 
  697. $dest_y = $sourcefile_height / 2 - $watermarkfile_height / 2; 
  698. break; 
  699. case 'bot': 
  700. $dest_y = $sourcefile_height - $watermarkfile_height - $yPOS; 
  701. break; 
  702. default: 
  703. $dest_y = 0; 
  704. break; 
  705. switch (substr($relPOS, 3)) { 
  706. case 'Left': 
  707. $dest_x = 0 + $xPOS; 
  708. break; 
  709. case 'Center': 
  710. $dest_x = $sourcefile_width / 2 - $watermarkfile_width / 2; 
  711. break; 
  712. case 'Right': 
  713. $dest_x = $sourcefile_width - $watermarkfile_width - $xPOS; 
  714. break; 
  715. default: 
  716. $dest_x = 0; 
  717. break; 
  718. // debug 
  719. // $this->errmsg = 'X '.$dest_x.' Y '.$dest_y; 
  720. // $this->showErrorImage(); 
  721. // if a gif, we have to upsample it to a truecolor image 
  722. if ($this->format == 'GIF') { 
  723. $tempimage = imagecreatetruecolor($sourcefile_width, $sourcefile_height); 
  724. imagecopy($tempimage, $this->oldImage, 0, 0, 0, 0, $sourcefile_width, $sourcefile_height); 
  725. $this->newImage = $tempimage; 
  726. $this->imagecopymerge_alpha($this->newImage, $this->workingImage, $dest_x, $dest_y, 0, 0, $watermarkfile_width, $watermarkfile_height, 100); 
  727. /** 
  728. * Wrapper to imagecopymerge() that allows PNG transparency 
  729. */ 
  730. function imagecopymerge_alpha($destination_image, $source_image, $destination_x, $destination_y, $source_x, $source_y, $source_w, $source_h, $pct) 
  731. $cut = imagecreatetruecolor($source_w, $source_h); 
  732. imagecopy($cut, $destination_image, 0, 0, $destination_x, $destination_y, $source_w, $source_h); 
  733. imagecopy($cut, $source_image, 0, 0, $source_x, $source_y, $source_w, $source_h); 
  734. imagecopymerge($destination_image, $cut, $destination_x, $destination_y, 0, 0, $source_w, $source_h, $pct); 
  735. /** 
  736. * Modfied imagecopyresampled function to save transparent images 
  737. * See : http://www.akemapa.com/2008/07/10/php-gd-resize-transparent-image-png-gif/ 
  738. * @since 1.9.0 
  739. *  
  740. * @param resource $dst_image 
  741. * @param resource $src_image 
  742. * @param int $dst_x 
  743. * @param int $dst_y 
  744. * @param int $src_x 
  745. * @param int $src_y 
  746. * @param int $dst_w 
  747. * @param int $dst_h 
  748. * @param int $src_w 
  749. * @param int $src_h 
  750. * @return bool 
  751. */ 
  752. function imagecopyresampled(&$dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) 
  753. // Check if this image is PNG or GIF, then set if Transparent 
  754. if ($this->format == 'GIF' || $this->format == 'PNG') { 
  755. imagealphablending($dst_image, false); 
  756. imagesavealpha($dst_image, true); 
  757. $transparent = imagecolorallocatealpha($dst_image, 255, 255, 255, 127); 
  758. imagefilledrectangle($dst_image, 0, 0, $dst_w, $dst_h, $transparent); 
  759. imagecopyresampled($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); 
  760. return true;