Avatar.php 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. <?php
  2. namespace app\helpers;
  3. class Avatar
  4. {
  5. private static $spriteZ=128;
  6. public static function get( $id, $size )
  7. {
  8. $csh=hexdec(substr($id,0,1)); // corner sprite shape
  9. $ssh=hexdec(substr($id,1,1)); // side sprite shape
  10. $xsh=hexdec(substr($id,2,1))&7; // center sprite shape
  11. $cro=hexdec(substr($id,3,1))&3; // corner sprite rotation
  12. $sro=hexdec(substr($id,4,1))&3; // side sprite rotation
  13. $xbg=hexdec(substr($id,5,1))%2; // center sprite background
  14. /* corner sprite foreground color */
  15. $cfr=hexdec(substr($id,6,2));
  16. $cfg=hexdec(substr($id,8,2));
  17. $cfb=hexdec(substr($id,10,2));
  18. /* side sprite foreground color */
  19. $sfr=hexdec(substr($id,12,2));
  20. $sfg=hexdec(substr($id,14,2));
  21. $sfb=hexdec(substr($id,16,2));
  22. /* final angle of rotation */
  23. $angle=hexdec(substr($id,18,2));
  24. /* size of each sprite */
  25. /* start with blank 3x3 identicon */
  26. $identicon=imagecreatetruecolor(self::$spriteZ*3,self::$spriteZ*3);
  27. imageantialias($identicon,TRUE);
  28. /* assign white as background */
  29. $bg=imagecolorallocate($identicon,255,255,255);
  30. imagefilledrectangle($identicon,0,0,self::$spriteZ,self::$spriteZ,$bg);
  31. /* generate corner sprites */
  32. $corner=self::getsprite($csh,$cfr,$cfg,$cfb,$cro);
  33. imagecopy($identicon,$corner,0,0,0,0,self::$spriteZ,self::$spriteZ);
  34. $corner=imagerotate($corner,1,$bg);
  35. imagecopy($identicon,$corner,0,self::$spriteZ*2,0,0,self::$spriteZ,self::$spriteZ);
  36. $corner=imagerotate($corner,1,$bg);
  37. imagecopy($identicon,$corner,self::$spriteZ*2,self::$spriteZ*2,0,0,self::$spriteZ,self::$spriteZ);
  38. $corner=imagerotate($corner,1,$bg);
  39. imagecopy($identicon,$corner,self::$spriteZ*2,0,0,0,self::$spriteZ,self::$spriteZ);
  40. /* generate side sprites */
  41. $side=self::getsprite($ssh,$sfr,$sfg,$sfb,$sro);
  42. imagecopy($identicon,$side,self::$spriteZ,0,0,0,self::$spriteZ,self::$spriteZ);
  43. $side=imagerotate($side,1,$bg);
  44. imagecopy($identicon,$side,0,self::$spriteZ,0,0,self::$spriteZ,self::$spriteZ);
  45. $side=imagerotate($side,1,$bg);
  46. imagecopy($identicon,$side,self::$spriteZ,self::$spriteZ*2,0,0,self::$spriteZ,self::$spriteZ);
  47. $side=imagerotate($side,90,$bg);
  48. imagecopy($identicon,$side,self::$spriteZ*2,self::$spriteZ,0,0,self::$spriteZ,self::$spriteZ);
  49. /* generate center sprite */
  50. $center=self::getcenter($xsh,$cfr,$cfg,$cfb,$sfr,$sfg,$sfb,$xbg);
  51. imagecopy($identicon,$center,self::$spriteZ,self::$spriteZ,0,0,self::$spriteZ,self::$spriteZ);
  52. // $identicon=imagerotate($identicon,$angle,$bg);
  53. /* make white transparent */
  54. imagecolortransparent($identicon,$bg);
  55. /* create blank image according to specified dimensions */
  56. $resized=imagecreatetruecolor($size,$size);
  57. imageantialias($resized,TRUE);
  58. imagealphablending($resized, true);
  59. /* assign white as background */
  60. $bg=imagecolorallocate($resized,255,255,255);
  61. imagefilledrectangle($resized,0,0,$size,$size,$bg);
  62. /* resize identicon according to specification */
  63. imagecopyresampled($resized,$identicon,0,0,(imagesx($identicon)-self::$spriteZ*3)/2,(imagesx($identicon)-self::$spriteZ*3)/2,$size,$size,self::$spriteZ*3,self::$spriteZ*3);
  64. //imagefilter($resized, IMG_FILTER_MEAN_REMOVAL, 1);
  65. // imagefilter($resized, IMG_FILTER_SMOOTH, 0.1);
  66. // imagefilter($resized, IMG_FILTER_SELECTIVE_BLUR, 1);
  67. //create masking
  68. /*
  69. * $newwidth = $size;
  70. * $newheight = $newwidth;
  71. * $mask = imagecreatetruecolor($newwidth, $newheight);
  72. * $transparent = imagecolorallocate($mask, 255, 0, 0);
  73. * imagecolortransparent($mask,$transparent);
  74. * imagefilledellipse($mask, $newwidth/2, $newheight/2, $newwidth, $newheight, $transparent);
  75. * $red = imagecolorallocate($mask, 0, 0, 0);
  76. * imagecopymerge($resized, $mask, 0, 0, 0, 0, $newwidth, $newheight, 100);
  77. * imagecolortransparent($resized,$red);
  78. * imagefill($resized, 0, 0, $red);
  79. */
  80. /* make white transparent */
  81. //imagecolortransparent($resized,$bg);
  82. /* and finally, send to standard output */
  83. //header("Content-Type: image/png");
  84. ob_start();
  85. imagepng($resized);
  86. return ob_get_clean();
  87. }
  88. public static function getsprite($shape,$R,$G,$B,$rotation) {
  89. // global self::$spriteZ;
  90. $sprite=imagecreatetruecolor(self::$spriteZ,self::$spriteZ);
  91. imageantialias($sprite,TRUE);
  92. $fg=imagecolorallocate($sprite,$R,$G,$B);
  93. $bg=imagecolorallocate($sprite,255,255,255);
  94. imagefilledrectangle($sprite,0,0,self::$spriteZ,self::$spriteZ,$bg);
  95. switch($shape) {
  96. case 0: // triangle
  97. $shape=array(
  98. 0.5,1,
  99. 1,0,
  100. 1,1
  101. );
  102. break;
  103. case 1: // parallelogram
  104. $shape=array(
  105. 0.5,0,
  106. 1,0,
  107. 0.5,1,
  108. 0,1
  109. );
  110. break;
  111. case 2: // mouse ears
  112. $shape=array(
  113. 0.5,0,
  114. 1,0,
  115. 1,1,
  116. 0.5,1,
  117. 1,0.5
  118. );
  119. break;
  120. case 3: // ribbon
  121. $shape=array(
  122. 0,0.5,
  123. 0.5,0,
  124. 1,0.5,
  125. 0.5,1,
  126. 0.5,0.5
  127. );
  128. break;
  129. case 4: // sails
  130. $shape=array(
  131. 0,0.5,
  132. 1,0,
  133. 1,1,
  134. 0,1,
  135. 1,0.5
  136. );
  137. break;
  138. case 5: // fins
  139. $shape=array(
  140. 1,0,
  141. 1,1,
  142. 0.5,1,
  143. 1,0.5,
  144. 0.5,0.5
  145. );
  146. break;
  147. case 6: // beak
  148. $shape=array(
  149. 0,0,
  150. 1,0,
  151. 1,0.5,
  152. 0,0,
  153. 0.5,1,
  154. 0,1
  155. );
  156. break;
  157. case 7: // chevron
  158. $shape=array(
  159. 0,0,
  160. 0.5,0,
  161. 1,0.5,
  162. 0.5,1,
  163. 0,1,
  164. 0.5,0.5
  165. );
  166. break;
  167. case 8: // fish
  168. $shape=array(
  169. 0.5,0,
  170. 0.5,0.5,
  171. 1,0.5,
  172. 1,1,
  173. 0.5,1,
  174. 0.5,0.5,
  175. 0,0.5
  176. );
  177. break;
  178. case 9: // kite
  179. $shape=array(
  180. 0,0,
  181. 1,0,
  182. 0.5,0.5,
  183. 1,0.5,
  184. 0.5,1,
  185. 0.5,0.5,
  186. 0,1
  187. );
  188. break;
  189. case 10: // trough
  190. $shape=array(
  191. 0,0.5,
  192. 0.5,1,
  193. 1,0.5,
  194. 0.5,0,
  195. 1,0,
  196. 1,1,
  197. 0,1
  198. );
  199. break;
  200. case 11: // rays
  201. $shape=array(
  202. 0.5,0,
  203. 1,0,
  204. 1,1,
  205. 0.5,1,
  206. 1,0.75,
  207. 0.5,0.5,
  208. 1,0.25
  209. );
  210. break;
  211. case 12: // double rhombus
  212. $shape=array(
  213. 0,0.5,
  214. 0.5,0,
  215. 0.5,0.5,
  216. 1,0,
  217. 1,0.5,
  218. 0.5,1,
  219. 0.5,0.5,
  220. 0,1
  221. );
  222. break;
  223. case 13: // crown
  224. $shape=array(
  225. 0,0,
  226. 1,0,
  227. 1,1,
  228. 0,1,
  229. 1,0.5,
  230. 0.5,0.25,
  231. 0.5,0.75,
  232. 0,0.5,
  233. 0.5,0.25
  234. );
  235. break;
  236. case 14: // radioactive
  237. $shape=array(
  238. 0,0.5,
  239. 0.5,0.5,
  240. 0.5,0,
  241. 1,0,
  242. 0.5,0.5,
  243. 1,0.5,
  244. 0.5,1,
  245. 0.5,0.5,
  246. 0,1
  247. );
  248. break;
  249. default: // tiles
  250. $shape=array(
  251. 0,0,
  252. 1,0,
  253. 0.5,0.5,
  254. 0.5,0,
  255. 0,0.5,
  256. 1,0.5,
  257. 0.5,1,
  258. 0.5,0.5,
  259. 0,1
  260. );
  261. break;
  262. }
  263. /* apply ratios */
  264. for ($i=0;$i<count($shape);$i++)
  265. $shape[$i]=$shape[$i]*self::$spriteZ;
  266. imagefilledpolygon($sprite,$shape,count($shape)/2,$fg);
  267. /* rotate the sprite */
  268. for ($i=0;$i<$rotation;$i++)
  269. $sprite=imagerotate($sprite,90,$bg);
  270. return $sprite;
  271. }
  272. /* generate sprite for center block */
  273. public static function getcenter($shape,$fR,$fG,$fB,$bR,$bG,$bB,$usebg) {
  274. // global self::$spriteZ;
  275. $sprite=imagecreatetruecolor(self::$spriteZ,self::$spriteZ);
  276. imageantialias($sprite,TRUE);
  277. $fg=imagecolorallocate($sprite,$fR,$fG,$fB);
  278. /* make sure there's enough contrast before we use background color of side sprite */
  279. if ($usebg>0 && (abs($fR-$bR)>127 || abs($fG-$bG)>127 || abs($fB-$bB)>127))
  280. $bg=imagecolorallocate($sprite,$bR,$bG,$bB);
  281. else
  282. $bg=imagecolorallocate($sprite,255,255,255);
  283. imagefilledrectangle($sprite,0,0,self::$spriteZ,self::$spriteZ,$bg);
  284. switch($shape) {
  285. case 0: // empty
  286. $shape=array();
  287. break;
  288. case 1: // fill
  289. $shape=array(
  290. 0,0,
  291. 1,0,
  292. 1,1,
  293. 0,1
  294. );
  295. break;
  296. case 2: // diamond
  297. $shape=array(
  298. 0.5,0,
  299. 1,0.5,
  300. 0.5,1,
  301. 0,0.5
  302. );
  303. break;
  304. case 3: // reverse diamond
  305. $shape=array(
  306. 0,0,
  307. 1,0,
  308. 1,1,
  309. 0,1,
  310. 0,0.5,
  311. 0.5,1,
  312. 1,0.5,
  313. 0.5,0,
  314. 0,0.5
  315. );
  316. break;
  317. case 4: // cross
  318. $shape=array(
  319. 0.25,0,
  320. 0.75,0,
  321. 0.5,0.5,
  322. 1,0.25,
  323. 1,0.75,
  324. 0.5,0.5,
  325. 0.75,1,
  326. 0.25,1,
  327. 0.5,0.5,
  328. 0,0.75,
  329. 0,0.25,
  330. 0.5,0.5
  331. );
  332. break;
  333. case 5: // morning star
  334. $shape=array(
  335. 0,0,
  336. 0.5,0.25,
  337. 1,0,
  338. 0.75,0.5,
  339. 1,1,
  340. 0.5,0.75,
  341. 0,1,
  342. 0.25,0.5
  343. );
  344. break;
  345. case 6: // small square
  346. $shape=array(
  347. 0.33,0.33,
  348. 0.67,0.33,
  349. 0.67,0.67,
  350. 0.33,0.67
  351. );
  352. break;
  353. case 7: // checkerboard
  354. $shape=array(
  355. 0,0,
  356. 0.33,0,
  357. 0.33,0.33,
  358. 0.66,0.33,
  359. 0.67,0,
  360. 1,0,
  361. 1,0.33,
  362. 0.67,0.33,
  363. 0.67,0.67,
  364. 1,0.67,
  365. 1,1,
  366. 0.67,1,
  367. 0.67,0.67,
  368. 0.33,0.67,
  369. 0.33,1,
  370. 0,1,
  371. 0,0.67,
  372. 0.33,0.67,
  373. 0.33,0.33,
  374. 0,0.33
  375. );
  376. break;
  377. }
  378. /* apply ratios */
  379. for ($i=0;$i<count($shape);$i++)
  380. $shape[$i]=$shape[$i]*self::$spriteZ;
  381. if (count($shape)>0)
  382. imagefilledpolygon($sprite,$shape,count($shape)/2,$fg);
  383. return $sprite;
  384. }
  385. }