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

/cms113/phpthumb.class.php

http://cmsfromscratch.googlecode.com/
PHP | 2388 lines | 1927 code | 323 blank | 138 comment | 426 complexity | 290e8cf2252daf3dd0edfdff5db0ae68 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. //////////////////////////////////////////////////////////////
  3. /// phpthumb() by James Heinrich <info@silisoftware.com> //
  4. // available at http://phpthumb.sourceforge.net ///
  5. //////////////////////////////////////////////////////////////
  6. /// //
  7. // See: phpthumb.readme.txt for usage instructions //
  8. // ///
  9. //////////////////////////////////////////////////////////////
  10. ob_start();
  11. if (!include_once(dirname(__FILE__).'/phpthumb.functions.php')) {
  12. ob_end_flush();
  13. die('(phpthumb.class.php) failed to include_once("'.realpath(dirname(__FILE__).'/phpthumb.functions.php').'")');
  14. }
  15. ob_end_clean();
  16. class phpthumb {
  17. // public:
  18. // START PARAMETERS (for object mode and phpthumb.php)
  19. // See phpthumb.readme.txt for descriptions of what each of these values are
  20. var $src = null; // SouRCe filename
  21. var $new = null; // NEW image (phpthumb.php only)
  22. var $w = null; // Width
  23. var $h = null; // Height
  24. var $f = null; // Format
  25. var $q = 75; // Quality
  26. var $sx = null; // Source crop top-left X position
  27. var $sy = null; // Source crop top-left Y position
  28. var $sw = null; // Source crop Width
  29. var $sh = null; // Source crop Height
  30. var $zc = null; // Zoom Crop
  31. var $bc = null; // Border Color
  32. var $bg = null; // BackGround color
  33. var $fltr = array(); // FiLTeRs
  34. var $file = null; // render-to FILEname
  35. var $goto = null; // GO TO url after processing
  36. var $err = null; // default ERRor image filename
  37. var $xto = null; // extract eXif Thumbnail Only
  38. var $ra = null; // Rotate by Angle
  39. var $ar = null; // Auto Rotate
  40. var $aoe = null; // Allow Output Enlargement
  41. var $far = null; // Fixed Aspect Ratio
  42. var $iar = null; // Ignore Aspect Ratio
  43. var $maxb = null; // MAXimum Bytes
  44. var $down = null; // DOWNload thumbnail
  45. var $md5s = null; // MD5 hash of Source image
  46. var $phpthumbDebug = null;
  47. // END PARAMETERS
  48. // public:
  49. // START CONFIGURATION OPTIONS (for object mode only)
  50. // See phpthumb.config.php for descriptions of what each of these settings do
  51. // * Directory Configuration
  52. var $config_cache_directory = null;
  53. var $config_cache_disable_warning = true;
  54. var $config_cache_source_enabled = false;
  55. var $config_cache_source_directory = null;
  56. var $config_temp_directory = null;
  57. var $config_document_root = null;
  58. // * Default output configuration:
  59. var $config_output_format = 'jpeg';
  60. var $config_output_maxwidth = 0;
  61. var $config_output_maxheight = 0;
  62. var $config_output_interlace = true;
  63. // * Error message configuration
  64. var $config_error_image_width = 400;
  65. var $config_error_image_height = 100;
  66. var $config_error_message_image_default = '';
  67. var $config_error_bgcolor = 'CCCCFF';
  68. var $config_error_textcolor = 'FF0000';
  69. var $config_error_fontsize = 1;
  70. var $config_error_die_on_error = true;
  71. var $config_error_silent_die_on_error = false;
  72. var $config_error_die_on_source_failure = true;
  73. // * Anti-Hotlink Configuration:
  74. var $config_nohotlink_enabled = true;
  75. var $config_nohotlink_valid_domains = array();
  76. var $config_nohotlink_erase_image = true;
  77. var $config_nohotlink_text_message = 'Off-server thumbnailing is not allowed';
  78. // * Off-server Linking Configuration:
  79. var $config_nooffsitelink_enabled = false;
  80. var $config_nooffsitelink_valid_domains = array();
  81. var $config_nooffsitelink_require_refer = false;
  82. var $config_nooffsitelink_erase_image = true;
  83. var $config_nooffsitelink_text_message = 'Off-server linking is not allowed';
  84. // * Border & Background default colors
  85. var $config_border_hexcolor = '000000';
  86. var $config_background_hexcolor = 'FFFFFF';
  87. // * TrueType Fonts
  88. var $config_ttf_directory = '.';
  89. var $config_max_source_pixels = 0;
  90. var $config_use_exif_thumbnail_for_speed = true;
  91. var $config_output_allow_enlarging = false;
  92. var $config_imagemagick_path = null;
  93. var $config_cache_maxage = null;
  94. var $config_cache_maxsize = null;
  95. var $config_cache_maxfiles = null;
  96. var $config_cache_source_filemtime_ignore_local = false;
  97. var $config_cache_source_filemtime_ignore_remote = false;
  98. var $config_disable_debug = false;
  99. // END CONFIGURATION OPTIONS
  100. // public: error messages (read-only)
  101. var $debugmessages = array();
  102. var $fatalerror = null;
  103. // private: (should not be modified directly)
  104. var $thumbnailQuality = 75;
  105. var $thumbnailFormat = null;
  106. var $sourceFilename = null;
  107. var $rawImageData = null;
  108. var $gdimg_output = null;
  109. var $gdimg_source = null;
  110. var $getimagesizeinfo = null;
  111. var $source_width = null;
  112. var $source_height = null;
  113. var $thumbnailCropX = null;
  114. var $thumbnailCropY = null;
  115. var $thumbnailCropW = null;
  116. var $thumbnailCropH = null;
  117. var $exif_thumbnail_width = null;
  118. var $exif_thumbnail_height = null;
  119. var $exif_thumbnail_type = null;
  120. var $exif_thumbnail_data = null;
  121. var $thumbnail_width = null;
  122. var $thumbnail_height = null;
  123. var $thumbnail_image_width = null;
  124. var $thumbnail_image_height = null;
  125. var $cache_filename = null;
  126. var $is_alpha = false;
  127. var $iswindows = null;
  128. var $osslash = null;
  129. var $phpthumb_version = '1.5.4-200505261715';
  130. //////////////////////////////////////////////////////////////////////
  131. // public: constructor
  132. function phpthumb() {
  133. if (phpthumb_functions::gd_version() < 1) {
  134. die('No GD support detected');
  135. }
  136. if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
  137. $this->iswindows = true;
  138. $this->osslash = '\\';
  139. } else {
  140. $this->iswindows = false;
  141. $this->osslash = '/';
  142. }
  143. if (!empty($_SERVER['DOCUMENT_ROOT'])) {
  144. $this->config_document_root = $_SERVER['DOCUMENT_ROOT'];
  145. }
  146. }
  147. // public:
  148. function setSourceFilename($sourceFilename) {
  149. $this->rawImageData = null;
  150. $this->sourceFilename = $sourceFilename;
  151. return true;
  152. }
  153. // public:
  154. function setSourceData($rawImageData, $sourceFilename='') {
  155. $this->sourceFilename = null;
  156. $this->rawImageData = $rawImageData;
  157. if ($this->config_cache_source_enabled) {
  158. $sourceFilename = ($sourceFilename ? $sourceFilename : md5($rawImageData));
  159. if (!is_dir($this->config_cache_source_directory) && !$this->phpthumbDebug) {
  160. $this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not a directory');
  161. } elseif (!is_writable($this->config_cache_source_directory) && !$this->phpthumbDebug) {
  162. $this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not writable');
  163. }
  164. $this->DebugMessage('setSourceData() attempting to save source image to "'.$this->config_cache_source_directory.'/'.urlencode($sourceFilename).'"', __FILE__, __LINE__);
  165. if ($fp = @fopen($this->config_cache_source_directory.'/'.urlencode($sourceFilename), 'wb')) {
  166. fwrite($fp, $rawImageData);
  167. fclose($fp);
  168. } elseif (!$this->phpthumbDebug) {
  169. $this->ErrorImage('setSourceData() failed to write to source cache ('.$this->config_cache_source_directory.'/'.urlencode($sourceFilename).')');
  170. }
  171. }
  172. return true;
  173. }
  174. // public:
  175. function setSourceImageResource($gdimg) {
  176. $this->gdimg_source = $gdimg;
  177. return true;
  178. }
  179. // public:
  180. function GenerateThumbnail() {
  181. $this->setOutputFormat();
  182. $this->ResolveSource();
  183. $this->SetCacheFilename();
  184. $this->ExtractEXIFgetImageSize();
  185. if (!$this->SourceImageToGD()) {
  186. return false;
  187. }
  188. $this->Rotate();
  189. $this->CreateGDoutput();
  190. // copy/resize image to appropriate dimensions (either nearest-neighbor or resample, depending on GD version)
  191. phpthumb_functions::ImageResizeFunction(
  192. $this->gdimg_output,
  193. $this->gdimg_source,
  194. round(($this->thumbnail_width - $this->thumbnail_image_width) / 2),
  195. round(($this->thumbnail_height - $this->thumbnail_image_height) / 2),
  196. $this->thumbnailCropX,
  197. $this->thumbnailCropY,
  198. $this->thumbnail_image_width,
  199. $this->thumbnail_image_height,
  200. $this->thumbnailCropW,
  201. $this->thumbnailCropH
  202. );
  203. $this->AntiOffsiteLinking();
  204. $this->ApplyFilters();
  205. $this->AlphaChannelFlatten();
  206. $this->MaxFileSize();
  207. return true;
  208. }
  209. // public:
  210. function RenderToFile($filename) {
  211. if (!is_resource($this->gdimg_output)) {
  212. $this->DebugMessage('RenderToFile('.$filename.') failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__);
  213. return false;
  214. }
  215. if (!$this->thumbnailFormat) {
  216. $this->DebugMessage('RenderToFile() failed because $this->thumbnailFormat is empty', __FILE__, __LINE__);
  217. return false;
  218. }
  219. // render thumbnail to this file only, do not cache, do not output to browser
  220. $ImageOutFunction = 'image'.$this->thumbnailFormat;
  221. //$renderfilename = $this->ResolveFilenameToAbsolute(dirname($filename)).'/'.basename($filename);
  222. $renderfilename = $filename;
  223. if (($filename{0} != '/') && ($filename{0} != '\\') && ($filename{1} != ':')) {
  224. $renderfilename = $this->ResolveFilenameToAbsolute($filename);
  225. }
  226. $this->DebugMessage('RenderToFile('.$filename.') attempting '.$ImageOutFunction.'($this->gdimg_output, '.$renderfilename.')', __FILE__, __LINE__);
  227. ob_start();
  228. switch ($this->thumbnailFormat) {
  229. case 'jpeg':
  230. $ImageOutFunction($this->gdimg_output, $renderfilename, $this->thumbnailQuality);
  231. break;
  232. case 'png':
  233. case 'gif':
  234. $ImageOutFunction($this->gdimg_output, $renderfilename);
  235. break;
  236. }
  237. $errormessage = strip_tags(ob_get_contents());
  238. ob_end_clean();
  239. if ($errormessage) {
  240. $this->DebugMessage('RenderToFile ['.$ImageOutFunction.'('.$renderfilename.')] failed with message "'.$errormessage.'"', __FILE__, __LINE__);
  241. return false;
  242. } elseif (!file_exists($renderfilename)) {
  243. $this->DebugMessage('RenderToFile ['.$ImageOutFunction.'('.$renderfilename.')] did not appear to fail, but the output image does not exist either...', __FILE__, __LINE__);
  244. }
  245. return true;
  246. }
  247. // public:
  248. function OutputThumbnail() {
  249. if (!is_resource($this->gdimg_output)) {
  250. $this->DebugMessage('OutputThumbnail() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__);
  251. return false;
  252. }
  253. if (headers_sent()) {
  254. return $this->ErrorImage('OutputThumbnail() failed - headers already sent');
  255. exit;
  256. }
  257. if (!empty($this->down)) {
  258. $downloadfilename = ereg_replace('[/\\:\*\?"<>|]', '_', $this->down);
  259. if (phpthumb_functions::version_compare_replacement(phpversion(), '4.1.0', '>=')) {
  260. $downloadfilename = trim($downloadfilename, '.');
  261. }
  262. if ($downloadfilename != $this->down) {
  263. $this->DebugMessage('renaming output file for "down" from "'.$this->down.'" to "'.$downloadfilename.'"', __FILE__, __LINE__);
  264. }
  265. if ($downloadfilename) {
  266. header('Content-Disposition: attachment; filename="'.$downloadfilename.'"');
  267. } else {
  268. $this->DebugMessage('failed to send Content-Disposition header because $downloadfilename is empty', __FILE__, __LINE__);
  269. }
  270. }
  271. ImageInterlace($this->gdimg_output, intval($this->config_output_interlace));
  272. $ImageOutFunction = 'image'.$this->thumbnailFormat;
  273. switch ($this->thumbnailFormat) {
  274. case 'jpeg':
  275. header('Content-Type: image/'.$this->thumbnailFormat);
  276. @$ImageOutFunction($this->gdimg_output, '', $this->thumbnailQuality);
  277. break;
  278. case 'png':
  279. case 'gif':
  280. header('Content-Type: image/'.$this->thumbnailFormat);
  281. @$ImageOutFunction($this->gdimg_output);
  282. break;
  283. default:
  284. return false;
  285. break;
  286. }
  287. ImageDestroy($this->gdimg_output);
  288. return true;
  289. }
  290. // public:
  291. function CleanUpCacheDirectory() {
  292. if (($this->config_cache_maxage > 0) || ($this->config_cache_maxsize > 0) || ($this->config_cache_maxfiles > 0)) {
  293. $CacheDirOldFilesAge = array();
  294. $CacheDirOldFilesSize = array();
  295. if ($dirhandle = opendir($this->config_cache_directory)) {
  296. while ($oldcachefile = readdir($dirhandle)) {
  297. if (eregi('^phpthumb_cache_', $oldcachefile)) {
  298. $CacheDirOldFilesAge[$oldcachefile] = fileatime($this->config_cache_directory.'/'.$oldcachefile);
  299. if ($CacheDirOldFilesAge[$oldcachefile] == 0) {
  300. $CacheDirOldFilesAge[$oldcachefile] = filemtime($this->config_cache_directory.'/'.$oldcachefile);
  301. }
  302. $CacheDirOldFilesSize[$oldcachefile] = filesize($this->config_cache_directory.'/'.$oldcachefile);
  303. }
  304. }
  305. }
  306. asort($CacheDirOldFilesAge);
  307. if ($this->config_cache_maxfiles > 0) {
  308. $TotalCachedFiles = count($CacheDirOldFilesAge);
  309. $DeletedKeys = array();
  310. foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) {
  311. if ($TotalCachedFiles > $this->config_cache_maxfiles) {
  312. $TotalCachedFiles--;
  313. if (@unlink($this->config_cache_directory.'/'.$oldcachefile)) {
  314. $DeletedKeys[] = $oldcachefile;
  315. }
  316. } else {
  317. // there are few enough files to keep the rest
  318. break;
  319. }
  320. }
  321. foreach ($DeletedKeys as $oldcachefile) {
  322. unset($CacheDirOldFilesAge[$oldcachefile]);
  323. unset($CacheDirOldFilesSize[$oldcachefile]);
  324. }
  325. }
  326. if ($this->config_cache_maxage > 0) {
  327. $mindate = time() - $this->config_cache_maxage;
  328. $DeletedKeys = array();
  329. foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) {
  330. if ($filedate > 0) {
  331. if ($filedate < $mindate) {
  332. if (@unlink($this->config_cache_directory.'/'.$oldcachefile)) {
  333. $DeletedKeys[] = $oldcachefile;
  334. }
  335. } else {
  336. // the rest of the files are new enough to keep
  337. break;
  338. }
  339. }
  340. }
  341. foreach ($DeletedKeys as $oldcachefile) {
  342. unset($CacheDirOldFilesAge[$oldcachefile]);
  343. unset($CacheDirOldFilesSize[$oldcachefile]);
  344. }
  345. }
  346. if ($this->config_cache_maxsize > 0) {
  347. $TotalCachedFileSize = array_sum($CacheDirOldFilesSize);
  348. $DeletedKeys = array();
  349. foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) {
  350. if ($TotalCachedFileSize > $this->config_cache_maxsize) {
  351. $TotalCachedFileSize -= $CacheDirOldFilesSize[$oldcachefile];
  352. if (@unlink($this->config_cache_directory.'/'.$oldcachefile)) {
  353. $DeletedKeys[] = $oldcachefile;
  354. }
  355. } else {
  356. // the total filesizes are small enough to keep the rest of the files
  357. break;
  358. }
  359. }
  360. foreach ($DeletedKeys as $oldcachefile) {
  361. unset($CacheDirOldFilesAge[$oldcachefile]);
  362. unset($CacheDirOldFilesSize[$oldcachefile]);
  363. }
  364. }
  365. }
  366. return true;
  367. }
  368. //////////////////////////////////////////////////////////////////////
  369. function ResolveSource() {
  370. if (is_resource($this->gdimg_source)) {
  371. return true;
  372. }
  373. if (empty($this->sourceFilename) && empty($this->rawImageData)) {
  374. $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src);
  375. }
  376. return true;
  377. }
  378. function setOutputFormat() {
  379. static $alreadyCalled = false;
  380. if ($this->thumbnailFormat && $alreadyCalled) {
  381. return true;
  382. }
  383. $alreadyCalled = true;
  384. $AvailableImageOutputFormats = array();
  385. $AvailableImageOutputFormats[] = 'text';
  386. $this->thumbnailFormat = 'text';
  387. // Set default output format based on what image types are available
  388. if (!function_exists('ImageTypes')) {
  389. return $this->ErrorImage('ImageTypes() does not exist - GD support might not be enabled?');
  390. }
  391. $imagetypes = ImageTypes();
  392. if ($imagetypes & IMG_WBMP) {
  393. $this->thumbnailFormat = 'wbmp';
  394. $AvailableImageOutputFormats[] = 'wbmp';
  395. }
  396. if ($imagetypes & IMG_GIF) {
  397. $this->thumbnailFormat = 'gif';
  398. $AvailableImageOutputFormats[] = 'gif';
  399. }
  400. if ($imagetypes & IMG_PNG) {
  401. $this->thumbnailFormat = 'png';
  402. $AvailableImageOutputFormats[] = 'png';
  403. }
  404. if ($imagetypes & IMG_JPG) {
  405. $this->thumbnailFormat = 'jpeg';
  406. $AvailableImageOutputFormats[] = 'jpeg';
  407. }
  408. $this->DebugMessage('$AvailableImageOutputFormats = array('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__);
  409. if (strtolower($this->config_output_format) == 'jpg') {
  410. $this->config_output_format = 'jpeg';
  411. }
  412. if (strtolower($this->f) == 'jpg') {
  413. $this->f = 'jpeg';
  414. }
  415. if (in_array(strtolower($this->config_output_format), $AvailableImageOutputFormats)) {
  416. // set output format to config default if that format is available
  417. $this->DebugMessage('$this->thumbnailFormat set to $this->config_output_format "'.strtolower($this->config_output_format).'"', __FILE__, __LINE__);
  418. $this->thumbnailFormat = strtolower($this->config_output_format);
  419. } else {
  420. $this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because "'.strtolower($this->config_output_format).'" ($this->config_output_format) is not in $AvailableImageOutputFormats', __FILE__, __LINE__);
  421. }
  422. if ($this->f && (in_array(strtolower($this->f), $AvailableImageOutputFormats))) {
  423. // override output format if $this->f is set and that format is available
  424. $this->DebugMessage('$this->thumbnailFormat set to $this->f "'.strtolower($this->f).'"', __FILE__, __LINE__);
  425. $this->thumbnailFormat = strtolower($this->f);
  426. } else {
  427. $this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because "'.strtolower($this->f).'" ($this->f) is not in $AvailableImageOutputFormats', __FILE__, __LINE__);
  428. }
  429. // for JPEG images, quality 1 (worst) to 99 (best)
  430. // quality < 25 is nasty, with not much size savings - not recommended
  431. // problems with 100 - invalid JPEG?
  432. $this->thumbnailQuality = max(1, min(99, (!empty($this->q) ? $this->q : 75)));
  433. $this->DebugMessage('$this->thumbnailQuality set to "'.$this->thumbnailQuality.'"', __FILE__, __LINE__);
  434. return true;
  435. }
  436. function setCacheDirectory() {
  437. // resolve cache directory to absolute pathname
  438. if (substr($this->config_cache_directory, 0, 1) == '.') {
  439. if (eregi('^(f|ht)tp[s]?://', $this->src)) {
  440. if (!$this->config_cache_disable_warning && !$this->phpthumbDebug) {
  441. $this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') cannot be used for remote images. Adjust "cache_directory" or "cache_disable_warning" in phpthumb.config.php');
  442. }
  443. } elseif ($this->src) {
  444. // resolve relative cache directory to source image
  445. $this->config_cache_directory = dirname($this->ResolveFilenameToAbsolute($this->src)).'/'.$this->config_cache_directory;
  446. } else {
  447. // $this->new is probably set
  448. }
  449. }
  450. if (substr($this->config_cache_directory, -1) == '/') {
  451. $this->config_cache_directory = substr($this->config_cache_directory, 0, -1);
  452. }
  453. if ($this->iswindows) {
  454. $this->config_cache_directory = str_replace('/', $this->osslash, $this->config_cache_directory);
  455. }
  456. if (!empty($this->config_cache_directory)) {
  457. $real_cache_path = realpath($this->config_cache_directory);
  458. if (!$real_cache_path) {
  459. $this->DebugMessage('realpath($this->config_cache_directory) failed for "'.$this->config_cache_directory.'"', __FILE__, __LINE__);
  460. if (!is_dir($this->config_cache_directory)) {
  461. $this->DebugMessage('!is_dir('.$this->config_cache_directory.')', __FILE__, __LINE__);
  462. }
  463. }
  464. if ($real_cache_path) {
  465. $this->config_cache_directory = $real_cache_path;
  466. }
  467. }
  468. if (!is_dir($this->config_cache_directory)) {
  469. if (!$this->config_cache_disable_warning && !$this->phpthumbDebug) {
  470. $this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') does not exist. Adjust "cache_directory" or "cache_disable_warning" in phpthumb.config.php');
  471. }
  472. $this->DebugMessage('$this->config_cache_directory ('.$this->config_cache_directory.') is not a directory', __FILE__, __LINE__);
  473. $this->config_cache_directory = null;
  474. } elseif (!is_writable($this->config_cache_directory)) {
  475. $this->DebugMessage('$this->config_cache_directory is not writable ('.$this->config_cache_directory.')', __FILE__, __LINE__);
  476. }
  477. return true;
  478. }
  479. function ResolveFilenameToAbsolute($filename) {
  480. if (eregi('^(f|ht)tp[s]?://', $filename)) {
  481. // URL
  482. $AbsoluteFilename = $filename;
  483. } elseif ($this->iswindows && ($filename{1} == ':')) {
  484. // absolute pathname (Windows)
  485. $AbsoluteFilename = $filename;
  486. } elseif ($this->iswindows && ((substr($filename, 0, 2) == '//') || (substr($filename, 0, 2) == '\\\\'))) {
  487. // absolute pathname (Windows)
  488. $AbsoluteFilename = $filename;
  489. } elseif ($filename{0} == '/') {
  490. if (@is_readable($filename) && !@is_readable($this->config_document_root.$filename)) {
  491. // absolute filename (*nix)
  492. $AbsoluteFilename = $filename;
  493. } elseif ($filename{1} == '~') {
  494. // /~user/path
  495. if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray($filename)) {
  496. $AbsoluteFilename = $ApacheLookupURIarray['filename'];
  497. } else {
  498. $AbsoluteFilename = realpath($filename);
  499. if (@is_readable($AbsoluteFilename)) {
  500. $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath($filename)', __FILE__, __LINE__);
  501. } else {
  502. if ($this->phpthumbDebug) {
  503. $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'". This has been known to fail on Apache2 - try using the absolute filename for the source image');
  504. return false;
  505. } else {
  506. return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'". This has been known to fail on Apache2 - try using the absolute filename for the source image');
  507. }
  508. }
  509. }
  510. } else {
  511. // relative filename (any OS)
  512. $AbsoluteFilename = $this->config_document_root.$filename;
  513. }
  514. } else {
  515. // relative to current directory (any OS)
  516. $AbsoluteFilename = $this->config_document_root.dirname(@$_SERVER['PHP_SELF']).'/'.$filename;
  517. //if (!file_exists($AbsoluteFilename) && file_exists(realpath($this->DotPadRelativeDirectoryPath($filename)))) {
  518. // $AbsoluteFilename = realpath($this->DotPadRelativeDirectoryPath($filename));
  519. //}
  520. if (substr(dirname(@$_SERVER['PHP_SELF']), 0, 2) == '/~') {
  521. if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) {
  522. $AbsoluteFilename = $ApacheLookupURIarray['filename'].'/'.$filename;
  523. } else {
  524. $AbsoluteFilename = realpath('.').'/'.$filename;
  525. if (@is_readable($AbsoluteFilename)) {
  526. $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath(.)/$filename', __FILE__, __LINE__);
  527. } else {
  528. return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'". This has been known to fail on Apache2 - try using the absolute filename for the source image');
  529. }
  530. }
  531. }
  532. }
  533. return $AbsoluteFilename;
  534. }
  535. function ImageMagickCommandlineBase() {
  536. static $commandline = null;
  537. if (is_null($commandline)) {
  538. $commandline = '';
  539. $which_convert = trim(phpthumb_functions::SafeBackTick('which convert'));
  540. if ($this->config_imagemagick_path && ($this->config_imagemagick_path != realpath($this->config_imagemagick_path))) {
  541. $this->DebugMessage('Changing $this->config_imagemagick_path ('.$this->config_imagemagick_path.') to realpath($this->config_imagemagick_path) ('.realpath($this->config_imagemagick_path).')', __FILE__, __LINE__);
  542. $this->config_imagemagick_path = realpath($this->config_imagemagick_path);
  543. }
  544. if (file_exists($this->config_imagemagick_path)) {
  545. $this->DebugMessage('using ImageMagick path from $this->config_imagemagick_path ('.$this->config_imagemagick_path.')', __FILE__, __LINE__);
  546. if ($this->iswindows) {
  547. $commandline = substr($this->config_imagemagick_path, 0, 2).' && cd "'.substr(dirname($this->config_imagemagick_path), 2).'" && '.basename($this->config_imagemagick_path);
  548. } else {
  549. $commandline = '"'.$this->config_imagemagick_path.'"';
  550. }
  551. } elseif ($which_convert && ($which_convert{0} == '/') && @file_exists($which_convert)) {
  552. // `which convert` *should* return the path if "convert" exist, or nothing if it doesn't
  553. // other things *may* get returned, like "sh: convert: not found" or "no convert in /usr/local/bin /usr/sbin /usr/bin /usr/ccs/bin"
  554. // so only do this if the value returned exists as a file
  555. $this->DebugMessage('using ImageMagick path from `which convert` ('.$which_convert.')', __FILE__, __LINE__);
  556. $commandline = 'convert';
  557. } else {
  558. $this->DebugMessage('ImageMagickThumbnailToGD() aborting because cannot find convert in $this->config_imagemagick_path ('.$this->config_imagemagick_path.'), and `which convert` returned ('.$which_convert.')', __FILE__, __LINE__);
  559. }
  560. }
  561. return $commandline;
  562. }
  563. function ImageMagickVersion() {
  564. $commandline = $this->ImageMagickCommandlineBase();
  565. if (!empty($commandline)) {
  566. $commandline .= ' -version';
  567. $versionstring = phpthumb_functions::SafeBackTick($commandline);
  568. if (eregi('^Version: (.*) http', $versionstring, $matches)) {
  569. return $matches[1];
  570. }
  571. $this->DebugMessage('ImageMagick did not return recognized version string ('.$versionstring.')', __FILE__, __LINE__);
  572. return $versionstring;
  573. }
  574. return false;
  575. }
  576. function ImageMagickThumbnailToGD() {
  577. // http://freealter.org/doc_distrib/ImageMagick-5.1.1/www/convert.html
  578. if (ini_get('safe_mode')) {
  579. $this->DebugMessage('ImageMagickThumbnailToGD() aborting because safe_mode is enabled', __FILE__, __LINE__);
  580. return false;
  581. }
  582. if (!function_exists('ImageCreateFromPNG')) {
  583. // ImageMagickThumbnailToGD() depends on ImageCreateFromPNG()
  584. $this->DebugMessage('ImageMagickThumbnailToGD() aborting because ImageCreateFromPNG() is not available', __FILE__, __LINE__);
  585. return false;
  586. }
  587. $commandline = $this->ImageMagickCommandlineBase();
  588. if (!empty($commandline)) {
  589. if ($IMtempfilename = $this->phpthumb_tempnam()) {
  590. $IMtempfilename = realpath($IMtempfilename);
  591. $IMwidth = ((intval($this->w) > 0) ? intval($this->w) : 640);
  592. $IMheight = ((intval($this->h) > 0) ? intval($this->h) : 480);
  593. if (!$this->aoe && !$this->iar && ($getimagesize = @GetImageSize($this->sourceFilename))) {
  594. // limit output size to input size unless AllowOutputEnlargement is enabled
  595. $IMwidth = min($IMwidth, $getimagesize[0]);
  596. $IMheight = min($IMheight, $getimagesize[1]);
  597. }
  598. //$commandline .= ' -resize '.$IMwidth.'x'.$IMheight; // behaves badly with IM v5.3.x
  599. $commandline .= ' -geometry '.$IMwidth.'x'.$IMheight;
  600. if (!empty($this->iar) && (intval($this->w) > 0) && (intval($this->h) > 0)) {
  601. $commandline .= '!';
  602. }
  603. $commandline .= ' "'.str_replace('/', $this->osslash, $this->sourceFilename).'"';
  604. $commandline .= ' png:'.$IMtempfilename;
  605. $commandline .= ' 2>&1';
  606. $IMresult = phpthumb_functions::SafeBackTick($commandline);
  607. if (!empty($IMresult)) {
  608. //return $this->ErrorImage('ImageMagick was called as:'."\n".$commandline."\n\n".'but failed with message:'."\n".$IMresult);
  609. $this->DebugMessage('ImageMagick was called as ('.$commandline.') but failed with message ('.$IMresult.')', __FILE__, __LINE__);
  610. } elseif ($this->gdimg_source = @ImageCreateFromPNG($IMtempfilename)) {
  611. unlink($IMtempfilename);
  612. $this->source_width = ImageSX($this->gdimg_source);
  613. $this->source_height = ImageSY($this->gdimg_source);
  614. $this->DebugMessage('ImageMagickThumbnailToGD() succeeded, $this->gdimg_source is now ('.$this->source_width.'x'.$this->source_height.')', __FILE__, __LINE__);
  615. return true;
  616. }
  617. unlink($IMtempfilename);
  618. } else {
  619. $this->DebugMessage('ImageMagickThumbnailToGD() aborting, phpthumb_tempnam() failed', __FILE__, __LINE__);
  620. }
  621. }
  622. $this->DebugMessage('ImageMagickThumbnailToGD() aborting because ImageMagickCommandlineBase() failed', __FILE__, __LINE__);
  623. return false;
  624. }
  625. function Rotate() {
  626. if (!empty($this->ra) || !empty($this->ar)) {
  627. if (!function_exists('ImageRotate')) {
  628. $this->DebugMessage('!function_exists(ImageRotate)', __FILE__, __LINE__);
  629. return false;
  630. }
  631. if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) {
  632. $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__);
  633. return false;
  634. }
  635. $this->config_background_hexcolor = (!empty($this->bg) ? $this->bg : $this->config_background_hexcolor);
  636. if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) {
  637. return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"');
  638. }
  639. $rotate_angle = 0;
  640. if (!empty($this->ra)) {
  641. $rotate_angle = floatval($this->ra);
  642. } else {
  643. if ($this->ar == 'x') {
  644. if (phpthumb_functions::version_compare_replacement(phpversion(), '4.2.0', '>=')) {
  645. if ($this->sourceFilename) {
  646. if (function_exists('exif_read_data')) {
  647. if ($exif_data = @exif_read_data($this->sourceFilename, 'IFD0')) {
  648. // http://sylvana.net/jpegcrop/exif_orientation.html
  649. switch (@$exif_data['Orientation']) {
  650. case 1:
  651. $rotate_angle = 0;
  652. break;
  653. case 3:
  654. $rotate_angle = 180;
  655. break;
  656. case 6:
  657. $rotate_angle = 270;
  658. break;
  659. case 8:
  660. $rotate_angle = 90;
  661. break;
  662. default:
  663. $this->DebugMessage('EXIF auto-rotate failed because unknown $exif_data[Orientation] "'.@$exif_data['Orientation'].'"', __FILE__, __LINE__);
  664. return false;
  665. break;
  666. }
  667. $this->DebugMessage('EXIF auto-rotate set to '.$rotate_angle.' degrees ($exif_data[Orientation] = "'.@$exif_data['Orientation'].'")', __FILE__, __LINE__);
  668. } else {
  669. $this->DebugMessage('failed: exif_read_data('.$this->sourceFilename.')', __FILE__, __LINE__);
  670. return false;
  671. }
  672. } else {
  673. $this->DebugMessage('!function_exists(exif_read_data)', __FILE__, __LINE__);
  674. return false;
  675. }
  676. } else {
  677. $this->DebugMessage('Cannot auto-rotate from EXIF data because $this->sourceFilename is empty', __FILE__, __LINE__);
  678. return false;
  679. }
  680. } else {
  681. $this->DebugMessage('Cannot auto-rotate from EXIF data because PHP is less than v4.2.0 ('.phpversion().')', __FILE__, __LINE__);
  682. return false;
  683. }
  684. } elseif (($this->ar == 'l') && ($this->source_height > $this->source_width)) {
  685. $rotate_angle = 270;
  686. } elseif (($this->ar == 'L') && ($this->source_height > $this->source_width)) {
  687. $rotate_angle = 90;
  688. } elseif (($this->ar == 'p') && ($this->source_width > $this->source_height)) {
  689. $rotate_angle = 90;
  690. } elseif (($this->ar == 'P') && ($this->source_width > $this->source_height)) {
  691. $rotate_angle = 270;
  692. }
  693. }
  694. while ($rotate_angle < 0) {
  695. $rotate_angle += 360;
  696. }
  697. $rotate_angle = $rotate_angle % 360;
  698. if ($rotate_angle != 0) {
  699. $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_source, $this->config_background_hexcolor);
  700. if ((phpthumb_functions::gd_version() >= 2) && ($this->thumbnailFormat == 'png') && !$this->bg && ($rotate_angle % 90)) {
  701. if ($gdimg_rotate_mask = phpthumb_functions::ImageCreateFunction(ImageSX($this->gdimg_source), ImageSY($this->gdimg_source))) {
  702. $this->gdimg_source = ImageRotate($this->gdimg_source, $rotate_angle, $background_color);
  703. $color_mask_opaque = ImageColorAllocate($gdimg_rotate_mask, 0xFF, 0xFF, 0xFF);
  704. $color_mask_transparent = ImageColorAllocate($gdimg_rotate_mask, 0x00, 0x00, 0x00);
  705. ImageFilledRectangle($gdimg_rotate_mask, 0, 0, ImageSX($gdimg_rotate_mask), ImageSY($gdimg_rotate_mask), $color_mask_opaque);
  706. $gdimg_rotate_mask = ImageRotate($gdimg_rotate_mask, $rotate_angle, $color_mask_transparent);
  707. ImageAlphaBlending($this->gdimg_source, false);
  708. if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=')) {
  709. ImageSaveAlpha($this->gdimg_source, true);
  710. }
  711. $this->is_alpha = true;
  712. phpthumb_filters::ApplyMask($gdimg_rotate_mask, $this->gdimg_source);
  713. ImageDestroy($gdimg_rotate_mask);
  714. $this->source_width = ImageSX($this->gdimg_source);
  715. $this->source_height = ImageSY($this->gdimg_source);
  716. } else {
  717. $this->DebugMessage('ImageCreateFromStringReplacement() failed for "'.$MaskFilename.'"', __FILE__, __LINE__);
  718. }
  719. } else {
  720. if (phpthumb_functions::gd_version() >= 2) {
  721. $this->DebugMessage('Using non-alpha rotate because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
  722. } else {
  723. $this->DebugMessage('Using non-alpha rotate because $this->thumbnailFormat is "'.$this->thumbnailFormat.'"', __FILE__, __LINE__);
  724. }
  725. if (ImageColorTransparent($this->gdimg_source) >= 0) {
  726. // ImageRotate() forgets all about an image's transparency and sets the transparent color to black
  727. // To compensate, flood-fill the transparent color of the source image with the specified background color first
  728. // then rotate and the colors should match
  729. if (!function_exists('ImageIsTrueColor') || !ImageIsTrueColor($this->gdimg_source)) {
  730. // convert paletted image to true-color before rotating to prevent nasty aliasing artifacts
  731. $this->source_width = ImageSX($this->gdimg_source);
  732. $this->source_height = ImageSY($this->gdimg_source);
  733. $gdimg_newsrc = phpthumb_functions::ImageCreateFunction($this->source_width, $this->source_height);
  734. $background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $this->config_background_hexcolor);
  735. ImageFilledRectangle($gdimg_newsrc, 0, 0, $this->source_width, $this->source_height, phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $this->config_background_hexcolor));
  736. ImageCopy($gdimg_newsrc, $this->gdimg_source, 0, 0, 0, 0, $this->source_width, $this->source_height);
  737. ImageDestroy($this->gdimg_source);
  738. unset($this->gdimg_source);
  739. $this->gdimg_source = $gdimg_newsrc;
  740. unset($gdimg_newsrc);
  741. } else {
  742. ImageColorSet(
  743. $this->gdimg_source,
  744. ImageColorTransparent($this->gdimg_source),
  745. hexdec(substr($this->config_background_hexcolor, 0, 2)),
  746. hexdec(substr($this->config_background_hexcolor, 2, 2)),
  747. hexdec(substr($this->config_background_hexcolor, 4, 2)));
  748. ImageColorTransparent($this->gdimg_source, -1);
  749. }
  750. }
  751. $this->gdimg_source = ImageRotate($this->gdimg_source, $rotate_angle, $background_color);
  752. $this->source_width = ImageSX($this->gdimg_source);
  753. $this->source_height = ImageSY($this->gdimg_source);
  754. }
  755. }
  756. }
  757. return true;
  758. }
  759. function FixedAspectRatio() {
  760. // optional fixed-dimension images (regardless of aspect ratio)
  761. if (isset($this->far)) {
  762. $this->is_alpha;
  763. if ($this->thumbnail_image_width >= $this->thumbnail_width) {
  764. if (isset($this->w)) {
  765. $aspectratio = $this->thumbnail_image_height / $this->thumbnail_image_width;
  766. $this->thumbnail_image_height = round($this->thumbnail_image_width * $aspectratio);
  767. if (!isset($this->h)) {
  768. $this->thumbnail_height = $this->thumbnail_image_height;
  769. }
  770. } elseif ($this->thumbnail_image_height < $this->thumbnail_height) {
  771. $this->thumbnail_image_height = $this->thumbnail_height;
  772. $this->thumbnail_image_width = round($this->thumbnail_image_height / $aspectratio);
  773. }
  774. } else {
  775. if (isset($this->h)) {
  776. $aspectratio = $this->thumbnail_image_width / $this->thumbnail_image_height;
  777. $this->thumbnail_image_width = round($this->thumbnail_image_height * $aspectratio);
  778. } elseif ($this->thumbnail_image_width < $this->thumbnail_width) {
  779. $this->thumbnail_image_width = $this->thumbnail_width;
  780. $this->thumbnail_image_height = round($this->thumbnail_image_width / $aspectratio);
  781. }
  782. }
  783. }
  784. return true;
  785. }
  786. function AntiOffsiteLinking() {
  787. // Optional anti-offsite hijacking of the thumbnail script
  788. $allow = true;
  789. if ($allow && $this->config_nooffsitelink_enabled && $this->config_nooffsitelink_require_refer) {
  790. $this->DebugMessage('AntiOffsiteLinking() checking $_SERVER[HTTP_REFERER] "'.@$_SERVER['HTTP_REFERER'].'"', __FILE__, __LINE__);
  791. $parsed_url = parse_url(@$_SERVER['HTTP_REFERER']);
  792. if (!in_array(@$parsed_url['host'], $this->config_nooffsitelink_valid_domains)) {
  793. $allow = false;
  794. $erase = $this->config_nooffsitelink_erase_image;
  795. $message = $this->config_nooffsitelink_text_message;
  796. $this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is NOT in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__);
  797. } else {
  798. $this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__);
  799. }
  800. }
  801. if ($allow && $this->config_nohotlink_enabled && eregi('^(f|ht)tp[s]?://', $this->src)) {
  802. $parsed_url = parse_url($this->src);
  803. if (!in_array(@$parsed_url['host'], $this->config_nohotlink_valid_domains)) {
  804. // This domain is not allowed
  805. $allow = false;
  806. $erase = $this->config_nohotlink_erase_image;
  807. $message = $this->config_nohotlink_text_message;
  808. $this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is NOT in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__);
  809. } else {
  810. $this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__);
  811. }
  812. }
  813. if ($allow) {
  814. $this->DebugMessage('AntiOffsiteLinking() says this is allowed', __FILE__, __LINE__);
  815. return true;
  816. }
  817. if (!phpthumb_functions::IsHexColor($this->config_error_bgcolor)) {
  818. return $this->ErrorImage('Invalid hex color string "'.$this->config_error_bgcolor.'" for $this->config_error_bgcolor');
  819. }
  820. if (!phpthumb_functions::IsHexColor($this->config_error_textcolor)) {
  821. return $this->ErrorImage('Invalid hex color string "'.$this->config_error_textcolor.'" for $this->config_error_textcolor');
  822. }
  823. if ($erase) {
  824. return $this->ErrorImage($message, $this->thumbnail_width, $this->thumbnail_height, $this->config_error_bgcolor, $this->config_error_textcolor, $this->config_error_fontsize);
  825. } else {
  826. $nohotlink_text_array = explode("\n", wordwrap($message, floor($this->thumbnail_width / ImageFontWidth($this->config_error_fontsize)), "\n"));
  827. $nohotlink_text_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_error_textcolor);
  828. $topoffset = round(($this->thumbnail_height - (count($nohotlink_text_array) * ImageFontHeight($this->config_error_fontsize))) / 2);
  829. $rowcounter = 0;
  830. $this->DebugMessage('AntiOffsiteLinking() writing '.count($nohotlink_text_array).' lines of text "'.$message.'" (in #'.$this->config_error_textcolor.') on top of image', __FILE__, __LINE__);
  831. foreach ($nohotlink_text_array as $textline) {
  832. $leftoffset = max(0, round(($this->thumbnail_width - (strlen($textline) * ImageFontWidth($this->config_error_fontsize))) / 2));
  833. ImageString($this->gdimg_output, $this->config_error_fontsize, $leftoffset, $topoffset + ($rowcounter++ * ImageFontHeight($this->config_error_fontsize)), $textline, $nohotlink_text_color);
  834. }
  835. }
  836. return true;
  837. }
  838. function AlphaChannelFlatten() {
  839. if (!$this->is_alpha) {
  840. // image doesn't have alpha transparency, no need to flatten
  841. $this->DebugMessage('skipping AlphaChannelFlatten() because !$this->is_alpha', __FILE__, __LINE__);
  842. return false;
  843. }
  844. if ($this->thumbnailFormat == 'png') {
  845. // image has alpha transparency, but output as PNG which can handle it
  846. $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'")', __FILE__, __LINE__);
  847. return false;
  848. } elseif ($this->thumbnailFormat == 'gif') {
  849. // image has alpha transparency, but output as GIF which can handle only single-color transparency
  850. $CurrentImageColorTransparent = ImageColorTransparent($this->gdimg_output);
  851. if ($CurrentImageColorTransparent == -1) {
  852. // no transparent color defined
  853. if (phpthumb_functions::gd_version() < 2.0) {
  854. $this->DebugMessage('AlphaChannelFlatten() failed because GD version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
  855. return false;
  856. }
  857. if ($img_alpha_mixdown_dither = @ImageCreateTrueColor(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output))) {
  858. for ($i = 0; $i <= 255; $i++) {
  859. $dither_color[$i] = ImageColorAllocate($img_alpha_mixdown_dither, $i, $i, $i);
  860. }
  861. // scan through current truecolor image copy alpha channel to temp image as grayscale
  862. for ($x = 0; $x < $this->thumbnail_width; $x++) {
  863. for ($y = 0; $y < $this->thumbnail_height; $y++) {
  864. $PixelColor = phpthumb_functions::GetPixelColor($this->gdimg_output, $x, $y);
  865. ImageSetPixel($img_alpha_mixdown_dither, $x, $y, $dither_color[($PixelColor['alpha'] * 2)]);
  866. }
  867. }
  868. // dither alpha channel grayscale version down to 2 colors
  869. ImageTrueColorToPalette($img_alpha_mixdown_dither, true, 2);
  870. // reduce color palette to 256-1 colors (leave one palette position for transparent color)
  871. ImageTrueColorToPalette($this->gdimg_output, true, 255);
  872. // allocate a new color for transparent color index
  873. $TransparentColor = ImageColorAllocate($this->gdimg_output, 1, 254, 253);
  874. ImageColorTransparent($this->gdimg_output, $TransparentColor);
  875. // scan through alpha channel image and note pixels with >50% transparency
  876. $TransparentPixels = array();
  877. for ($x = 0; $x < $this->thumbnail_width; $x++) {
  878. for ($y = 0; $y < $this->thumbnail_height; $y++) {
  879. $AlphaChannelPixel = phpthumb_functions::GetPixelColor($img_alpha_mixdown_dither, $x, $y);
  880. if ($AlphaChannelPixel['red'] > 127) {
  881. ImageSetPixel($this->gdimg_output, $x, $y, $TransparentColor);
  882. }
  883. }
  884. }
  885. ImageDestroy($img_alpha_mixdown_dither);
  886. $this->DebugMessage('AlphaChannelFlatten() set image to 255+1 colors with transparency for GIF output', __FILE__, __LINE__);
  887. return true;
  888. } else {
  889. $this->DebugMessage('AlphaChannelFlatten() failed ImageCreate('.ImageSX($this->gdimg_output).', '.ImageSY($this->gdimg_output).')', __FILE__, __LINE__);
  890. return false;
  891. }
  892. } else {
  893. // a single transparent color already defined, leave as-is
  894. $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'") and ImageColorTransparent returned "'.$CurrentImageColorTransparent.'"', __FILE__, __LINE__);
  895. return true;
  896. }
  897. }
  898. $this->DebugMessage('continuing AlphaChannelFlatten() for output format "'.$this->thumbnailFormat.'"', __FILE__, __LINE__);
  899. // image has alpha transparency, and is being output in a format that doesn't support it -- flatten
  900. if ($gdimg_flatten_temp = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height)) {
  901. $this->config_background_hexcolor = (!empty($this->bg) ? $this->bg : $this->config_background_hexcolor);
  902. if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) {
  903. return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"');
  904. }
  905. $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor);
  906. ImageFilledRectangle($gdimg_flatten_temp, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color);
  907. ImageCopy($gdimg_flatten_temp, $this->gdimg_output, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height);
  908. ImageAlphaBlending($this->gdimg_output, true);
  909. if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=')) {
  910. ImageSaveAlpha($this->gdimg_output, false);
  911. }
  912. ImageColorTransparent($this->gdimg_output, -1);
  913. ImageCopy($this->gdimg_output, $gdimg_flatten_temp, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height);
  914. ImageDestroy($gdimg_flatten_temp);
  915. return true;
  916. } else {
  917. $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__);
  918. }
  919. return false;
  920. }
  921. function ApplyFilters() {
  922. if (!empty($this->fltr) && is_array($this->fltr)) {
  923. if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) {
  924. $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__);
  925. return false;
  926. }
  927. foreach ($this->fltr as $filtercommand) {
  928. @list($command, $parameter) = explode('|', $filtercommand, 2);
  929. $this->DebugMessage('Attempting to process filter command "'.$command.'"', __FILE__, __LINE__);
  930. switch ($command) {
  931. case 'ds':
  932. phpthumb_filters::Desaturate($this->gdimg_output, $parameter, '');
  933. break;
  934. case 'gray':
  935. phpthumb_filters::Desaturate($this->gdimg_output, 100, '');
  936. break;
  937. case 'clr':
  938. if (phpthumb_functions::gd_version() < 2) {
  939. $this->DebugMessage('Skipping Colorize() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
  940. break;
  941. }
  942. @list($amount, $color) = explode('|', $parameter);
  943. phpthumb_filters::Colorize($this->gdimg_output, $amount, $color);
  944. break;
  945. case 'sep':
  946. if (phpthumb_functions::gd_version() < 2) {
  947. $this->DebugMessage('Skipping Sepia() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
  948. break;
  949. }
  950. @list($amount, $color) = explode('|', $parameter);
  951. phpthumb_filters::Sepia($this->gdimg_output, $amount, $color);
  952. break;
  953. case 'gam':
  954. phpthumb_filters::Gamma($this->gdimg_output, $parameter);
  955. break;
  956. case 'neg':
  957. phpthumb_filters::Negative($this->gdimg_output);
  958. break;
  959. case 'th':
  960. phpthumb_filters::Threshold($this->gdimg_output, $parameter);
  961. break;
  962. case 'flip':
  963. phpthumb_filters::Flip($this->gdimg_output, (strpos(strtolower($parameter), 'x') !== false), (strpos(strtolower($parameter), 'y') !== false));
  964. break;
  965. case 'bvl':
  966. @list($width, $color1, $color2) = explode('|', $parameter);
  967. phpthumb_filters::Bevel($this->gdimg_output, $width, $color1, $color2);
  968. break;
  969. case 'lvl':
  970. @list($band, $min, $max) = explode('|', $parameter);
  971. $band = ($band ? $band : '*');
  972. $min = ((strlen($min) > 0) ? $min : '-1');
  973. $max = ((strlen($max) > 0) ? $max : '-1');
  974. phpthumb_filters::HistogramStretch($this->gdimg_output, $band, $min, $max);
  975. break;
  976. case 'wb':
  977. phpthumb_filters::WhiteBalance($this->gdimg_output, $parameter);
  978. break;
  979. case 'hist':
  980. if (phpthumb_functions::gd_version() < 2) {
  981. $this->DebugMessage('Skipping HistogramOverlay() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
  982. break;
  983. }
  984. @list($bands, $colors, $width, $height, $alignment, $opacity, $margin) = explode('|', $parameter);
  985. $bands = ($bands ? $bands : '*');
  986. $colors = ($colors ? $colors : '');
  987. $width = ($width ? $width : 0.25);
  988. $height = ($height ? $height : 0.25);
  989. $alignment = ($alignment ? $alignment : 'BR');
  990. $opacity = ($opacity ? $opacity : 50);
  991. $margin = ($margin ? $margin : 5);
  992. phpthumb_filters::HistogramOverlay($this->gdimg_output, $bands, $colors, $width, $height, $alignment, $opacity, $margin);
  993. break;
  994. case 'fram':
  995. @list($frame_width, $edge_width, $color_frame, $color1, $color2) = explode('|', $parameter);
  996. phpthumb_filters::Frame($this->gdimg_output, $frame_width, $edge_width, $co

Large files files are truncated, but you can click here to view the full file