MDAvatars.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. <?php
  2. /*
  3. * Material-Design-Avatars
  4. * https://github.com/lincanbin/Material-Design-Avatars
  5. *
  6. * Copyright 2015 Canbin Lin (lincanbin@hotmail.com)
  7. * http://www.94cb.com/
  8. *
  9. * Licensed under the Apache License, Version 2.0:
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Create material deisgn avatars for users just like Gmail or Messager in Android.
  13. */
  14. declare (strict_types = 1);
  15. namespace avatars;
  16. class MDAvatars
  17. {
  18. public $Char;
  19. public $AvatarSize;
  20. public $Shape;
  21. public $Padding;
  22. public $Avatar;
  23. public $FontFile;
  24. public $IsNotLetter;
  25. public $LetterFont;
  26. public $AsianFont;
  27. public $EnableAsianChar;
  28. function __construct($Char, $AvatarSize = 256 ,$Shape = 1)
  29. {
  30. $this->Char = mb_strtoupper(mb_substr($Char, 0, 1, "UTF-8"));
  31. $this->AvatarSize = $AvatarSize;
  32. $this->Shape = $Shape;
  33. $this->Padding = 30 * ($this->AvatarSize / 256);
  34. $this->LetterFont = dirname(__FILE__) . '/fonts/SourceCodePro-Light.ttf';
  35. $this->AsianFont = dirname(__FILE__) . '/fonts/SourceHanSansCN-Normal.ttf';
  36. $this->EnableAsianChar = is_file($this->AsianFont);
  37. $path='./storage/avatars/';
  38. if(!is_dir($path)){
  39. mkdir($path, 0755, true);
  40. }
  41. $CNChar = ord($this->Char);
  42. if (!$this->EnableAsianChar &&
  43. preg_match("/^[\x7f-\xff]/", $this->Char) &&
  44. !($CNChar >= ord("A") && $CNChar <= ord("z"))
  45. ) {
  46. //如果是中文,并且没有中文字体包,则按拼音首字母对其进行转换
  47. $CNByte = iconv("UTF-8", "gb2312", $this->Char);
  48. $Code = ord($CNByte[0]) * 256 + ord($CNByte[1]) - 65536;//求其偏移量
  49. if ($Code >= -20319 and $Code <= -20284) $this->Char = "A";
  50. if ($Code >= -20283 and $Code <= -19776) $this->Char = "B";
  51. if ($Code >= -19775 and $Code <= -19219) $this->Char = "C";
  52. if ($Code >= -19218 and $Code <= -18711) $this->Char = "D";
  53. if ($Code >= -18710 and $Code <= -18527) $this->Char = "E";
  54. if ($Code >= -18526 and $Code <= -18240) $this->Char = "F";
  55. if ($Code >= -18239 and $Code <= -17923) $this->Char = "G";
  56. if ($Code >= -17922 and $Code <= -17418) $this->Char = "H";
  57. if ($Code >= -17417 and $Code <= -16475) $this->Char = "J";
  58. if ($Code >= -16474 and $Code <= -16213) $this->Char = "K";
  59. if ($Code >= -16212 and $Code <= -15641) $this->Char = "L";
  60. if ($Code >= -15640 and $Code <= -15166) $this->Char = "M";
  61. if ($Code >= -15165 and $Code <= -14923) $this->Char = "N";
  62. if ($Code >= -14922 and $Code <= -14915) $this->Char = "O";
  63. if ($Code >= -14914 and $Code <= -14631) $this->Char = "P";
  64. if ($Code >= -14630 and $Code <= -14150) $this->Char = "Q";
  65. if ($Code >= -14149 and $Code <= -14091) $this->Char = "R";
  66. if ($Code >= -14090 and $Code <= -13319) $this->Char = "S";
  67. if ($Code >= -13318 and $Code <= -12839) $this->Char = "T";
  68. if ($Code >= -12838 and $Code <= -12557) $this->Char = "W";
  69. if ($Code >= -12556 and $Code <= -11848) $this->Char = "X";
  70. if ($Code >= -11847 and $Code <= -11056) $this->Char = "Y";
  71. if ($Code >= -11055 and $Code <= -10247) $this->Char = "Z";
  72. }
  73. if (in_array($this->Char, str_split('QWERTYUIOPASDFGHJKLZXCVBNM0123456789', 1))) {
  74. $this->IsNotLetter = false;
  75. $this->FontFile = $this->LetterFont;
  76. } else {
  77. $this->IsNotLetter = true;
  78. $this->FontFile = $this->AsianFont;
  79. }
  80. $this->Initialize();
  81. }
  82. private function Initialize()
  83. {
  84. //extension_loaded('gd')
  85. $Width = $this->AvatarSize;//Width of avatar
  86. $Height = $this->AvatarSize;//Height of avatar
  87. $Padding = $this->Padding;
  88. $this->Avatar = imagecreatetruecolor($Width, $Height);
  89. //全透明背景
  90. imageSaveAlpha($this->Avatar, true);
  91. $BackgroundAlpha = imagecolorallocatealpha($this->Avatar, 255, 255, 255, 127);
  92. imagefill($this->Avatar, 0, 0, $BackgroundAlpha);
  93. //抗锯齿
  94. if (function_exists('imageantialias')) {
  95. imageantialias($this->Avatar, true);
  96. }
  97. //Material Design参考颜色
  98. //http://www.google.com/design/spec/style/color.html#color-color-palette
  99. $MaterialDesignColor = array(
  100. array(239, 154, 154),
  101. array(229, 115, 115),
  102. array(239, 83, 80),
  103. array(244, 67, 54),
  104. array(229, 57, 53),
  105. array(211, 47, 47),
  106. array(198, 40, 40),
  107. array(183, 28, 28),
  108. array(255, 138, 128),
  109. array(255, 82, 82),
  110. array(255, 23, 68),
  111. array(213, 0, 0),
  112. array(248, 187, 208),
  113. array(244, 143, 177),
  114. array(240, 98, 146),
  115. array(236, 64, 122),
  116. array(233, 30, 99),
  117. array(216, 27, 96),
  118. array(194, 24, 91),
  119. array(173, 20, 87),
  120. array(136, 14, 79),
  121. array(255, 128, 171),
  122. array(255, 64, 129),
  123. array(245, 0, 87),
  124. array(197, 17, 98),
  125. array(206, 147, 216),
  126. array(186, 104, 200),
  127. array(171, 71, 188),
  128. array(156, 39, 176),
  129. array(142, 36, 170),
  130. array(123, 31, 162),
  131. array(106, 27, 154),
  132. array(74, 20, 140),
  133. array(234, 128, 252),
  134. array(224, 64, 251),
  135. array(213, 0, 249),
  136. array(170, 0, 255),
  137. array(179, 157, 219),
  138. array(149, 117, 205),
  139. array(126, 87, 194),
  140. array(103, 58, 183),
  141. array(94, 53, 177),
  142. array(81, 45, 168),
  143. array(69, 39, 160),
  144. array(49, 27, 146),
  145. array(179, 136, 255),
  146. array(124, 77, 255),
  147. array(101, 31, 255),
  148. array(98, 0, 234),
  149. array(197, 202, 233),
  150. array(159, 168, 218),
  151. array(121, 134, 203),
  152. array(92, 107, 192),
  153. array(63, 81, 181),
  154. array(57, 73, 171),
  155. array(48, 63, 159),
  156. array(40, 53, 147),
  157. array(26, 35, 126),
  158. array(140, 158, 255),
  159. array(83, 109, 254),
  160. array(61, 90, 254),
  161. array(48, 79, 254),
  162. array(227, 242, 253),
  163. array(187, 222, 251),
  164. array(144, 202, 249),
  165. array(100, 181, 246),
  166. array(66, 165, 245),
  167. array(33, 150, 243),
  168. array(30, 136, 229),
  169. array(25, 118, 210),
  170. array(21, 101, 192),
  171. array(13, 71, 161),
  172. array(130, 177, 255),
  173. array(68, 138, 255),
  174. array(41, 121, 255),
  175. array(41, 98, 255),
  176. array(179, 229, 252),
  177. array(129, 212, 250),
  178. array(79, 195, 247),
  179. array(41, 182, 252),
  180. array(3, 169, 244),
  181. array(3, 155, 229),
  182. array(2, 136, 209),
  183. array(2, 119, 189),
  184. array(1, 87, 155),
  185. array(128, 216, 255),
  186. array(64, 196, 255),
  187. array(0, 176, 255),
  188. array(0, 145, 234),
  189. array(178, 235, 242),
  190. array(128, 222, 234),
  191. array(77, 208, 225),
  192. array(38, 198, 218),
  193. array(0, 188, 212),
  194. array(0, 172, 193),
  195. array(0, 151, 167),
  196. array(0, 131, 143),
  197. array(0, 96, 100),
  198. array(132, 255, 255),
  199. array(24, 255, 255),
  200. array(0, 229, 255),
  201. array(0, 184, 212),
  202. array(178, 223, 219),
  203. array(128, 203, 196),
  204. array(77, 182, 172),
  205. array(38, 166, 154),
  206. array(0, 150, 136),
  207. array(0, 137, 123),
  208. array(0, 121, 107),
  209. array(0, 105, 92),
  210. array(0, 77, 64),
  211. array(167, 255, 235),
  212. array(100, 255, 218),
  213. array(29, 233, 182),
  214. array(0, 191, 165),
  215. array(165, 214, 167),
  216. array(129, 199, 132),
  217. array(102, 187, 106),
  218. array(76, 175, 80),
  219. array(67, 160, 71),
  220. array(56, 142, 60),
  221. array(46, 125, 50),
  222. array(27, 94, 32),
  223. array(185, 246, 202),
  224. array(105, 240, 174),
  225. array(0, 230, 118),
  226. array(0, 200, 83),
  227. array(197, 225, 165),
  228. array(174, 213, 129),
  229. array(156, 204, 101),
  230. array(139, 195, 74),
  231. array(124, 179, 66),
  232. array(104, 159, 56),
  233. array(85, 139, 47),
  234. array(51, 105, 30),
  235. array(178, 255, 89),
  236. array(118, 255, 3),
  237. array(100, 221, 23),
  238. array(249, 251, 231),
  239. array(240, 244, 195),
  240. array(230, 238, 156),
  241. array(220, 231, 117),
  242. array(212, 225, 87),
  243. array(205, 220, 57),
  244. array(192, 202, 51),
  245. array(164, 180, 43),
  246. array(158, 157, 36),
  247. array(130, 119, 23),
  248. array(198, 255, 0),
  249. array(174, 234, 0),
  250. array(251, 192, 45),
  251. array(249, 168, 37),
  252. array(245, 127, 23),
  253. array(255, 179, 0),
  254. array(255, 160, 0),
  255. array(255, 143, 0),
  256. array(255, 111, 0),
  257. array(255, 171, 0),
  258. array(255, 183, 77),
  259. array(255, 167, 38),
  260. array(255, 152, 0),
  261. array(251, 140, 0),
  262. array(245, 124, 0),
  263. array(239, 108, 0),
  264. array(230, 81, 0),
  265. array(255, 171, 64),
  266. array(255, 145, 0),
  267. array(255, 109, 0),
  268. array(255, 171, 145),
  269. array(255, 138, 101),
  270. array(255, 112, 67),
  271. array(255, 87, 34),
  272. array(244, 81, 30),
  273. array(230, 74, 25),
  274. array(216, 67, 21),
  275. array(191, 54, 12),
  276. array(255, 158, 128),
  277. array(255, 110, 64),
  278. array(255, 61, 0),
  279. array(221, 38, 0),
  280. array(188, 170, 164),
  281. array(161, 136, 127),
  282. array(141, 110, 99),
  283. array(121, 85, 72),
  284. array(109, 76, 65),
  285. array(93, 64, 55),
  286. array(78, 52, 46),
  287. array(62, 39, 35),
  288. array(189, 189, 189),
  289. array(158, 158, 158),
  290. array(117, 117, 117),
  291. array(97, 97, 97),
  292. array(66, 66, 66),
  293. array(33, 33, 33),
  294. array(236, 239, 241),
  295. array(176, 187, 197),
  296. array(144, 164, 174),
  297. array(120, 144, 156),
  298. array(96, 125, 139),
  299. array(84, 110, 122),
  300. array(69, 90, 100),
  301. array(55, 71, 79),
  302. array(38, 50, 56)
  303. );
  304. $BackgroundColorIndex = mt_rand(0, count($MaterialDesignColor) - 1);
  305. $BackgroundColor = imagecolorallocate($this->Avatar,
  306. $MaterialDesignColor[$BackgroundColorIndex][0],
  307. $MaterialDesignColor[$BackgroundColorIndex][1],
  308. $MaterialDesignColor[$BackgroundColorIndex][2]
  309. );
  310. if($this->Shape == 1){
  311. //画一个矩形
  312. imagerectangle($this->Avatar,
  313. 0,
  314. 0,
  315. $Width,
  316. $Height,
  317. $BackgroundColor
  318. );
  319. imagefilledrectangle($this->Avatar,
  320. 0,
  321. 0,
  322. $Width,
  323. $Height,
  324. $BackgroundColor
  325. );
  326. }
  327. else{
  328. //画一个居中圆形
  329. imagefilledellipse($this->Avatar,
  330. $Width / 2,
  331. $Height / 2,
  332. $Width,
  333. $Height,
  334. $BackgroundColor
  335. );
  336. }
  337. //字体
  338. $FontColor = imagecolorallocate($this->Avatar, 255, 255, 255);
  339. if ($this->IsNotLetter) {
  340. //中文字符偏移
  341. $FontSize = $Width - $Padding * 3.5;
  342. $X = $Padding + (-2 / 166) * $FontSize;
  343. $Y = $Height - $Padding - (23.5 / 166) * $FontSize;
  344. } else {
  345. $FontSize = $Width - $Padding * 2;
  346. $X = $Padding + (20 / 196) * $FontSize;
  347. $Y = $Height - $Padding - (13 / 196) * $FontSize;
  348. }
  349. // 在圆正中央填入字符
  350. imagettftext($this->Avatar, $FontSize,0,intval($X), intval($Y),$FontColor,$this->FontFile, $this->Char);
  351. }
  352. private function Resize($TargetSize)
  353. {
  354. if (isset($this->Avatar)) {
  355. if ($this->AvatarSize > $TargetSize) {
  356. $Percent = $TargetSize / $this->AvatarSize;
  357. $TargetWidth = round($this->AvatarSize * $Percent);
  358. $TargetHeight = round($this->AvatarSize * $Percent);
  359. $TargetImageData = imagecreatetruecolor($TargetWidth, $TargetHeight);
  360. //全透明背景
  361. imageSaveAlpha($TargetImageData, true);
  362. $BackgroundAlpha = imagecolorallocatealpha($TargetImageData, 255, 255, 255, 127);
  363. imagefill($TargetImageData, 0, 0, $BackgroundAlpha);
  364. imagecopyresampled($TargetImageData, $this->Avatar, 0, 0, 0, 0, $TargetWidth, $TargetHeight, $this->AvatarSize, $this->AvatarSize);
  365. return $TargetImageData;
  366. } else {
  367. return $this->Avatar;
  368. }
  369. } else {
  370. return false;
  371. }
  372. }
  373. public function Free()
  374. {
  375. imagedestroy($this->Avatar);
  376. }
  377. public function Output2Browser($AvatarSize = 0)
  378. {
  379. if (!$AvatarSize) {
  380. $AvatarSize = $this->AvatarSize;
  381. }
  382. header('Content-Type: image/png');
  383. return imagepng($this->Resize($AvatarSize));
  384. }
  385. /**
  386. * Get image resource identifier
  387. * @param int $AvatarSize
  388. * @return resource
  389. */
  390. public function Output2ImageResource($AvatarSize = 0)
  391. {
  392. if (!$AvatarSize) {
  393. $AvatarSize = $this->AvatarSize;
  394. }
  395. return $this->Resize($AvatarSize);
  396. }
  397. /**
  398. * Output Base64 encoded image data
  399. * @param int $AvatarSize
  400. * @return string
  401. */
  402. public function Output2Base64($AvatarSize = 0)
  403. {
  404. if (!$AvatarSize) {
  405. $AvatarSize = $this->AvatarSize;
  406. }
  407. ob_start();
  408. imagepng($this->Resize($AvatarSize));
  409. $content = ob_get_contents();
  410. ob_end_clean();
  411. return 'data:image/png;base64,' . base64_encode($content);
  412. }
  413. public function Save($Path, $AvatarSize = 0)
  414. {
  415. if (!$AvatarSize) {
  416. $AvatarSize = $this->AvatarSize;
  417. }
  418. return imagepng($this->Resize($AvatarSize), $Path);
  419. }
  420. }