PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/veriler/f3/lib/graphics.php

https://gitlab.com/fbi/razyo-api-server
PHP | 450 lines | 312 code | 14 blank | 124 comment | 57 complexity | 0932c0615131f98fa6adfa4dd226cd27 MD5 | raw file
  1. <?php
  2. /**
  3. Graphics plugin for the PHP Fat-Free Framework
  4. The contents of this file are subject to the terms of the GNU General
  5. Public License Version 3.0. You may not use this file except in
  6. compliance with the license. Any of the license terms and conditions
  7. can be waived if you get permission from the copyright holder.
  8. Copyright (c) 2009-2011 F3::Factory
  9. Bong Cosca <bong.cosca@yahoo.com>
  10. @package Graphics
  11. @version 2.0.4
  12. **/
  13. //! Graphics plugin
  14. class Graphics extends Base {
  15. //@{ Locale-specific error/exception messages
  16. const
  17. TEXT_Image='Unsupported image format',
  18. TEXT_Color='Invalid color specified';
  19. //@}
  20. const
  21. // Background color
  22. GFX_BGColor=0xFFF,
  23. // Foreground transparency
  24. GFX_Transparency=0x020,
  25. // Identicon horizontal/vertical blocks
  26. GFX_IdBlocks=4,
  27. // Identicon pixels per block
  28. GFX_IdPixels=64,
  29. //! PNG compression level
  30. PNG_Compress=1;
  31. /**
  32. Convert RGB hex triad to array
  33. @return mixed
  34. @param $int integer
  35. @public
  36. **/
  37. static function rgb($int) {
  38. $hex=str_pad(dechex($int),$int<4096?3:6,'0',STR_PAD_LEFT);
  39. $len=strlen($hex);
  40. if ($len>6) {
  41. trigger_error(self::TEXT_Color);
  42. return FALSE;
  43. }
  44. $color=str_split($hex,$len/3);
  45. foreach ($color as &$hue)
  46. $hue=hexdec(str_repeat($hue,6/$len));
  47. return $color;
  48. }
  49. /**
  50. Generate CAPTCHA image
  51. @param $dimx integer
  52. @param $dimy integer
  53. @param $len integer
  54. @param $ttfs string
  55. @param $var string
  56. @param $die boolean
  57. @public
  58. **/
  59. static function captcha(
  60. $dimx=150,$dimy=50,$len=5,$ttfs='cube',$var='captcha',$die=TRUE) {
  61. $base=self::rgb(self::$vars['BGCOLOR']);
  62. $trans=self::$vars['FGTRANS'];
  63. // Specify Captcha seed
  64. $seed=substr(md5(uniqid()),0,$len);
  65. F3::set('SESSION.'.$var,$seed);
  66. // Font size
  67. $size=.9*min($dimx/$len,$dimy);
  68. // Load TrueType fonts
  69. $fonts=self::split($ttfs);
  70. $file=self::$vars['FONTS'].
  71. self::fixslashes($fonts[array_rand($fonts)]).'.ttf';
  72. $stats=&self::ref('STATS');
  73. if (!isset($stats['FILES']))
  74. $stats['FILES']=array('fonts'=>array());
  75. $stats['FILES']['fonts'][basename($file)]=filesize($file);
  76. $maxdeg=12;
  77. // Create blank image
  78. $captcha=imagecreatetruecolor($dimx,$dimy);
  79. list($r,$g,$b)=$base;
  80. $bg=imagecolorallocate($captcha,$r,$g,$b);
  81. imagefill($captcha,0,0,$bg);
  82. $width=0;
  83. // Insert each Captcha character
  84. for ($i=0;$i<$len;$i++) {
  85. // Random angle
  86. $angle=$maxdeg-mt_rand(0,$maxdeg*2);
  87. // Get CAPTCHA character from session cookie
  88. $char=$seed[$i];
  89. $fg=imagecolorallocatealpha(
  90. $captcha,
  91. mt_rand(0,255-$trans),
  92. mt_rand(0,255-$trans),
  93. mt_rand(0,255-$trans),
  94. $trans
  95. );
  96. // Compute bounding box metrics
  97. $bbox=imagettfbbox($size,0,$file,$char);
  98. $w=max($bbox[2],$bbox[4])-max($bbox[0],$bbox[6]);
  99. $h=max($bbox[1],$bbox[3])-max($bbox[5],$bbox[7]);
  100. $sin=sin(deg2rad($angle));
  101. imagettftext(
  102. $captcha,$size,$angle,
  103. .9*$width+abs($h*$sin),
  104. $dimy-$h/2+abs($w*$sin),
  105. $fg,$file,$char
  106. );
  107. $width+=$w+abs($h*$sin);
  108. imagecolordeallocate($captcha,$fg);
  109. }
  110. // Make the background transparent
  111. imagecolortransparent($captcha,$bg);
  112. // Send output as PNG image
  113. if (PHP_SAPI!='cli' && !headers_sent()) {
  114. header(self::HTTP_Content.': image/png');
  115. header(self::HTTP_Powered.': '.self::TEXT_AppName.' '.
  116. '('.self::TEXT_AppURL.')');
  117. }
  118. imagepng($captcha,NULL,self::PNG_Compress,PNG_NO_FILTER);
  119. if ($die)
  120. die;
  121. }
  122. /**
  123. Invert colors of specified image
  124. @param $file string
  125. @param $die boolean
  126. @public
  127. **/
  128. static function invert($file,$die=TRUE) {
  129. preg_match('/\.(gif|jp[e]*g|png)$/',$file,$ext);
  130. $ext[1]=str_replace('jpg','jpeg',$ext[1]);
  131. $file=self::fixslashes(self::resolve($file));
  132. $img=imagecreatefromstring(self::getfile($file));
  133. imagefilter($img,IMG_FILTER_NEGATE);
  134. if (PHP_SAPI!='cli' && !headers_sent())
  135. header(self::HTTP_Content.': image/'.$ext[1]);
  136. // Send output in same graphics format as original
  137. eval('image'.$ext[1].'($img);');
  138. if ($die)
  139. die;
  140. }
  141. /**
  142. Apply grayscale filter on specified image
  143. @param $file string
  144. @param $die boolean
  145. @public
  146. **/
  147. static function grayscale($file,$die=TRUE) {
  148. preg_match('/\.(gif|jp[e]*g|png)$/',$file,$ext);
  149. $ext[1]=str_replace('jpg','jpeg',$ext[1]);
  150. $file=self::fixslashes(self::resolve($file));
  151. $img=imagecreatefromstring(self::getfile($file));
  152. imagefilter($img,IMG_FILTER_GRAYSCALE);
  153. if (PHP_SAPI!='cli' && !headers_sent())
  154. header(self::HTTP_Content.': image/'.$ext[1]);
  155. // Send output in same graphics format as original
  156. eval('image'.$ext[1].'($img);');
  157. if ($die)
  158. die;
  159. }
  160. /**
  161. Generate thumbnail image
  162. @param $file string
  163. @param $dimx integer
  164. @param $dimy integer
  165. @param $die boolean
  166. @public
  167. **/
  168. static function thumb($file,$dimx,$dimy,$die=TRUE) {
  169. preg_match('/\.(gif|jp[e]*g|png)$/',$file,$ext);
  170. if ($ext) {
  171. $ext[1]=str_replace('jpg','jpeg',$ext[1]);
  172. $file=self::fixslashes(self::resolve($file));
  173. $img=imagecreatefromstring(self::getfile($file));
  174. // Get image dimensions
  175. $oldx=imagesx($img);
  176. $oldy=imagesy($img);
  177. // Adjust dimensions; retain aspect ratio
  178. $ratio=$oldx/$oldy;
  179. if ($dimx<=$oldx && $dimx/$ratio<=$dimy)
  180. // Adjust height
  181. $dimy=$dimx/$ratio;
  182. elseif ($dimy<=$oldy && $dimy*$ratio<=$dimx)
  183. // Adjust width
  184. $dimx=$dimy*$ratio;
  185. else {
  186. // Retain size if dimensions exceed original image
  187. $dimx=$oldx;
  188. $dimy=$oldy;
  189. }
  190. // Create blank image
  191. $tmp=imagecreatetruecolor($dimx,$dimy);
  192. list($r,$g,$b)=self::rgb(self::$vars['BGCOLOR']);
  193. $bg=imagecolorallocate($tmp,$r,$g,$b);
  194. imagefill($tmp,0,0,$bg);
  195. // Resize
  196. imagecopyresampled($tmp,$img,0,0,0,0,$dimx,$dimy,$oldx,$oldy);
  197. // Make the background transparent
  198. imagecolortransparent($tmp,$bg);
  199. if (PHP_SAPI!='cli' && !headers_sent()) {
  200. header(self::HTTP_Content.': image/'.$ext[1]);
  201. header(self::HTTP_Powered.': '.self::TEXT_AppName.' '.
  202. '('.self::TEXT_AppURL.')');
  203. }
  204. // Send output in same graphics format as original
  205. eval('image'.$ext[1].'($tmp);');
  206. }
  207. else
  208. trigger_error(self::TEXT_Image);
  209. if ($die)
  210. die;
  211. }
  212. /**
  213. Generate identicon from an MD5 hash value
  214. @param $hash string
  215. @param $size integer
  216. @param $die boolean
  217. @public
  218. **/
  219. static function identicon($hash,$size=NULL,$die=TRUE) {
  220. $hash=self::resolve($hash);
  221. $blox=self::$vars['IBLOCKS'];
  222. if (is_null($size))
  223. $size=self::$vars['IPIXELS'];
  224. // Rotatable shapes
  225. $dynamic=array(
  226. array(.5,1,1,0,1,1),
  227. array(.5,0,1,0,.5,1,0,1),
  228. array(.5,0,1,0,1,1,.5,1,1,.5),
  229. array(0,.5,.5,0,1,.5,.5,1,.5,.5),
  230. array(0,.5,1,0,1,1,0,1,1,.5),
  231. array(1,0,1,1,.5,1,1,.5,.5,.5),
  232. array(0,0,1,0,1,.5,0,0,.5,1,0,1),
  233. array(0,0,.5,0,1,.5,.5,1,0,1,.5,.5),
  234. array(.5,0,.5,.5,1,.5,1,1,.5,1,.5,.5,0,.5),
  235. array(0,0,1,0,.5,.5,1,.5,.5,1,.5,.5,0,1),
  236. array(0,.5,.5,1,1,.5,.5,0,1,0,1,1,0,1),
  237. array(.5,0,1,0,1,1,.5,1,1,.75,.5,.5,1,.25),
  238. array(0,.5,.5,0,.5,.5,1,0,1,.5,.5,1,.5,.5,0,1),
  239. array(0,0,1,0,1,1,0,1,1,.5,.5,.25,.5,.75,0,.5,.5,.25),
  240. array(0,.5,.5,.5,.5,0,1,0,.5,.5,1,.5,.5,1,.5,.5,0,1),
  241. array(0,0,1,0,.5,.5,.5,0,0,.5,1,.5,.5,1,.5,.5,0,1)
  242. );
  243. // Fixed shapes (for center sprite)
  244. $static=array(
  245. array(),
  246. array(0,0,1,0,1,1,0,1),
  247. array(.5,0,1,.5,.5,1,0,.5),
  248. array(0,0,1,0,1,1,0,1,0,.5,.5,1,1,.5,.5,0,0,.5),
  249. array(.25,0,.75,0,.5,.5,1,.25,1,.75,.5,.5,
  250. .75,1,.25,1,.5,.5,0,.75,0,.25,.5,.5),
  251. array(0,0,.5,.25,1,0,.75,.5,1,1,.5,.75,0,1,.25,.5),
  252. array(.33,.33,.67,.33,.67,.67,.33,.67),
  253. array(0,0,.33,0,.33,.33,.67,.33,.67,0,1,0,1,.33,.67,.33,
  254. .67,.67,1,.67,1,1,.67,1,.67,.67,.33,.67,.33,1,0,1,
  255. 0,.67,.33,.67,.33,.33,0,.33)
  256. );
  257. // Parse MD5 hash
  258. list($bgR,$bgG,$bgB)=self::rgb(self::$vars['BGCOLOR']);
  259. list($fgR,$fgG,$fgB)=self::rgb(hexdec(substr($hash,0,6)));
  260. $shapeC=hexdec($hash[6]);
  261. $angleC=hexdec($hash[7]%4);
  262. $shapeX=hexdec($hash[8]);
  263. for ($i=0;$i<$blox-2;$i++) {
  264. $shapeS[$i]=hexdec($hash[9+$i*2]);
  265. $angleS[$i]=hexdec($hash[10+$i*2]%4);
  266. }
  267. // Start with NxN blank slate
  268. $identicon=imagecreatetruecolor($size*$blox,$size*$blox);
  269. imageantialias($identicon,TRUE);
  270. $bg=imagecolorallocate($identicon,$bgR,$bgG,$bgB);
  271. $fg=imagecolorallocate($identicon,$fgR,$fgG,$fgB);
  272. // Generate corner sprites
  273. $corner=imagecreatetruecolor($size,$size);
  274. imagefill($corner,0,0,$bg);
  275. $sprite=$dynamic[$shapeC];
  276. for ($i=0,$len=count($sprite);$i<$len;$i++)
  277. $sprite[$i]=$sprite[$i]*$size;
  278. imagefilledpolygon($corner,$sprite,$len/2,$fg);
  279. for ($i=0;$i<$angleC;$i++)
  280. $corner=imagerotate($corner,90,$bg);
  281. // Generate side sprites
  282. for ($i=0;$i<$blox-2;$i++) {
  283. $side[$i]=imagecreatetruecolor($size,$size);
  284. imagefill($side[$i],0,0,$bg);
  285. $sprite=$dynamic[$shapeS[$i]];
  286. for ($j=0,$len=count($sprite);$j<$len;$j++)
  287. $sprite[$j]=$sprite[$j]*$size;
  288. imagefilledpolygon($side[$i],$sprite,$len/2,$fg);
  289. for ($j=0;$j<$angleS[$i];$j++)
  290. $side[$i]=imagerotate($side[$i],90,$bg);
  291. }
  292. // Generate center sprites
  293. for ($i=0;$i<$blox-2;$i++) {
  294. $center[$i]=imagecreatetruecolor($size,$size);
  295. imagefill($center[$i],0,0,$bg);
  296. $sprite=$dynamic[$shapeX];
  297. if ($blox%2>0 && $i==$blox-3)
  298. // Odd center sprites
  299. $sprite=$static[$shapeX%8];
  300. $len=count($sprite);
  301. if ($len) {
  302. for ($j=0;$j<$len;$j++)
  303. $sprite[$j]=$sprite[$j]*$size;
  304. imagefilledpolygon($center[$i],$sprite,$len/2,$fg);
  305. }
  306. if ($i<($blox-3))
  307. for ($j=0;$j<$angleS[$i];$j++)
  308. $center[$i]=imagerotate($center[$i],90,$bg);
  309. }
  310. // Paste sprites
  311. for ($i=0;$i<4;$i++) {
  312. imagecopy($identicon,$corner,0,0,0,0,$size,$size);
  313. for ($j=0;$j<$blox-2;$j++) {
  314. imagecopy($identicon,$side[$j],
  315. $size*($j+1),0,0,0,$size,$size);
  316. for ($k=$j;$k<$blox-3-$j;$k++)
  317. imagecopy($identicon,$center[$k],
  318. $size*($k+1),$size*($j+1),0,0,$size,$size);
  319. }
  320. $identicon=imagerotate($identicon,90,$bg);
  321. }
  322. if ($blox%2>0)
  323. // Paste odd center sprite
  324. imagecopy($identicon,$center[$blox-3],
  325. $size*(floor($blox/2)),$size*(floor($blox/2)),0,0,
  326. $size,$size);
  327. // Resize
  328. $resized=imagecreatetruecolor($size,$size);
  329. imagecopyresampled($resized,$identicon,0,0,0,0,$size,$size,
  330. $size*$blox,$size*$blox);
  331. // Make the background transparent
  332. imagecolortransparent($resized,$bg);
  333. if (PHP_SAPI!='cli' && !headers_sent()) {
  334. header(self::HTTP_Content.': image/png');
  335. header(self::HTTP_Powered.': '.self::TEXT_AppName.' '.
  336. '('.self::TEXT_AppURL.')');
  337. }
  338. imagepng($resized,NULL,self::PNG_Compress,PNG_NO_FILTER);
  339. if ($die)
  340. die;
  341. }
  342. /**
  343. Generate a blank image for use as a placeholder
  344. @param $dimx integer
  345. @param $dimy integer
  346. @param $bg string
  347. @param $die boolean
  348. @public
  349. **/
  350. static function fakeImage($dimx,$dimy,$bg=0xEEE,$die=TRUE) {
  351. list($r,$g,$b)=self::rgb($bg);
  352. $img=imagecreatetruecolor($dimx,$dimy);
  353. $bg=imagecolorallocate($img,$r,$g,$b);
  354. imagefill($img,0,0,$bg);
  355. if (PHP_SAPI!='cli' && !headers_sent()) {
  356. header(self::HTTP_Content.': image/png');
  357. header(self::HTTP_Powered.': '.self::TEXT_AppName.' '.
  358. '('.self::TEXT_AppURL.')');
  359. }
  360. imagepng($img,NULL,self::PNG_Compress,PNG_NO_FILTER);
  361. if ($die)
  362. die;
  363. }
  364. /**
  365. Grab HTML page and render using WebKit engine;
  366. Crop image and generate thumbnail, if specified
  367. @param $url string
  368. @param $dimx integer
  369. @param $dimy integer
  370. @param $cropw integer
  371. @param $croph integer
  372. @param $die boolean
  373. @public
  374. **/
  375. static function screenshot(
  376. $url,$dimx=0,$dimy=0,$cropw=0,$croph=0,$die=TRUE) {
  377. $file=self::$vars['TEMP'].$_SERVER['SERVER_NAME'].
  378. '.scr.'.self::hash($url).'.jpg';
  379. // Map OS to folder location
  380. $exec=array(
  381. 'Windows|WINNT'=>'windows',
  382. 'Darwin'=>'osx',
  383. 'Linux'=>'linux'
  384. );
  385. foreach ($exec as $os=>$dir)
  386. if (preg_match('/'.$os.'/i',PHP_OS)) {
  387. $win=($dir=='windows');
  388. // Suppress text output
  389. $null=$win?'nul':'null';
  390. exec(($win?'start /b ':'').
  391. self::$vars['EXTERNAL'].$dir.'/wkhtmltoimage '.
  392. ($cropw?('--crop-w '.$cropw.' '):'').
  393. ($croph?('--crop-h '.$croph.' '):'').
  394. $url.' '.$file.' >'.$null.' 2>'.$null);
  395. break;
  396. }
  397. if (is_file($file)) {
  398. if ($dimx && $dimy)
  399. self::thumb($file,$dimx,$dimy,FALSE);
  400. elseif (PHP_SAPI!='cli' && !headers_sent()) {
  401. header(self::HTTP_Content.': image/png');
  402. header(self::HTTP_Powered.': '.self::TEXT_AppName.' '.
  403. '('.self::TEXT_AppURL.')');
  404. echo self::getfile($file);
  405. }
  406. unlink($file);
  407. }
  408. if ($die)
  409. die;
  410. }
  411. /**
  412. Class initializer
  413. @public
  414. **/
  415. static function onload() {
  416. if (!extension_loaded('gd')) {
  417. // GD extension required
  418. trigger_error(sprintf(self::TEXT_PHPExt,'gd'));
  419. }
  420. if (!isset(self::$vars['EXTERNAL']))
  421. self::$vars['EXTERNAL']=self::$vars['ROOT'];
  422. if (!isset(self::$vars['FONTS']))
  423. self::$vars['FONTS']=self::$vars['ROOT'];
  424. if (!isset(self::$vars['BGCOLOR']))
  425. self::$vars['BGCOLOR']=self::GFX_BGColor;
  426. if (!isset(self::$vars['FGTRANS']))
  427. self::$vars['FGTRANS']=self::GFX_Transparency;
  428. if (!isset(self::$vars['IBLOCKS']))
  429. self::$vars['IBLOCKS']=self::GFX_IdBlocks;
  430. if (!isset(self::$vars['IPIXELS']))
  431. self::$vars['IPIXELS']=self::GFX_IdPixels;
  432. }
  433. }