CanvasService.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace service;
  12. use service\FileService;
  13. use app\routine\model\routine\RoutineCode;
  14. use Intervention\Image\AbstractFont;
  15. use Intervention\Image\ImageManagerStatic as ImageManager;
  16. class CanvasService
  17. {
  18. const FILELINK = 'uploads/';
  19. const BGIMG_PATH = 'public/';
  20. //背景图
  21. //const VOTEIMG = 'uploads/voteimg/voteimg.jpg';
  22. //字体
  23. //const BG_FONT = 'wap/first/zsff/font/fzcyjt.ttf';
  24. //const FONT = 'uploads/voteimg/simsunb.ttf';
  25. //const FONT_TWO = 'uploads/voteimg/fz-v4.0.ttf';
  26. //const BORDER = 'uploads/voteimg/border.png';
  27. protected static $canvas = null;
  28. protected static $image = null;
  29. protected static $backgroundWidth = 750;
  30. protected static $backgroundHeight = 1334;
  31. public static function CreatJpeg($file = '')
  32. {
  33. $file = $file ? $file : self::VOTEIMG;
  34. $imagesize = getimagesize($file);
  35. $type = image_type_to_extension($imagesize[2], true);
  36. switch ($type) {
  37. case '.png':
  38. $canvas = imagecreatefrompng($file);
  39. break;
  40. case '.jpeg':
  41. $canvas = imagecreatefromjpeg($file);
  42. break;
  43. case '.jpg':
  44. $canvas = imagecreatefromjpeg($file);
  45. break;
  46. case '.gif':
  47. $canvas = imagecreatefromgif($file);
  48. break;
  49. }
  50. return [$canvas, $imagesize];
  51. }
  52. public static function ReatetrueColor($w = 0, $h = 0)
  53. {
  54. return imagecreatetruecolor($w ? $w : self::$backgroundWidth, $h ? $h : self::$backgroundHeight);
  55. }
  56. public static function foundCode1($special, $url, $backgroundImg, $ext = 'poster_code_')
  57. {
  58. vendor('phpqrcode.phpqrcode');
  59. $bg_path = self::BGIMG_PATH;
  60. //底图尺寸大小
  61. $bg = ImageManager::make($bg_path . 'bgimg/bg.png')->resize(750, 950);
  62. $thumb = $backgroundImg;
  63. //海报尺寸大小
  64. if ($thumb) {
  65. $thumb = ImageManager::make($thumb)->resize(690, 590);
  66. //水印
  67. $font_path = ROOT_PATH.'public/wap/first/zsff/font/';
  68. $title1_font_ttf = $font_path.'PingFang-SC.ttf';
  69. $site_name=SystemConfigService::get('site_name');
  70. $thumb->text($site_name, 600, 570, function (AbstractFont $text) use ($title1_font_ttf){
  71. $text->file($title1_font_ttf);
  72. $text->size(20);
  73. $text->color('#DDDDDD');
  74. $text->align('center');
  75. });
  76. $bg->insert($thumb, 'top-left', 30, 35);
  77. }
  78. $qrcodename = self::FILELINK . time() . 'qrcode.png';
  79. \QRcode::png($url, $qrcodename, 'L', 10, 2);
  80. //二维码位置
  81. if ($qrcodename) {
  82. $qr = ImageManager::make($qrcodename)->resize(150, 150);
  83. $bg->insert($qr, 'top-right', 45, 760);
  84. }
  85. //海报文字位置,活动分享标题
  86. $font_path = ROOT_PATH.'public/wap/first/zsff/font/';
  87. $title1_font_ttf = $font_path.'PingFang-SC.ttf';
  88. $bg->text($special['title'], 50, 750, function (AbstractFont $text) use($title1_font_ttf){
  89. $text->file($title1_font_ttf);
  90. $text->size(14);
  91. $text->color('#333333');
  92. $text->align('left');
  93. });
  94. $bg->text($special['title'], 50, 750, function (AbstractFont $text) use($title1_font_ttf){
  95. $text->file($title1_font_ttf);
  96. $text->size(14);
  97. $text->color('#333333');
  98. $text->align('left');
  99. });
  100. $bg->text($special['fake_sales'] . '人已学习', 625, 750, function (AbstractFont $text) use ($title1_font_ttf) {
  101. $text->file($title1_font_ttf);
  102. $text->size(14);
  103. $text->color('#666');
  104. $text->align('center');
  105. });
  106. $title2_font_ttf = $font_path.'pingfang-sc-blod.ttf';
  107. $bg->text(date("d"), 49, 869, function (AbstractFont $text) use($title2_font_ttf){
  108. $text->file($title2_font_ttf);
  109. $text->size(72);
  110. $text->color('#f30606');
  111. $text->align('left');
  112. });
  113. $month = array(
  114. '01' => '一月',
  115. '02' => '二月',
  116. '03' => '三月',
  117. '04' => '四月',
  118. '05' => '五月',
  119. '06' => '六月',
  120. '07' => '七月',
  121. '08' => '八月',
  122. '09' => '九月',
  123. '10' => '十月',
  124. '11' => '十一月',
  125. '12' => '十二月'
  126. );
  127. $title3_font_ttf = $font_path.'pingfang-sc-blod.ttf';
  128. $bg->text($month[date("m")], 128, 869, function (AbstractFont $text) use($title3_font_ttf){
  129. $text->file($title3_font_ttf);
  130. $text->size(21);
  131. $text->color('#000000');
  132. $text->align('left');
  133. });
  134. $week = date("w");
  135. if ($week == 0) {
  136. $week = 7;
  137. }
  138. $week_path = $bg_path . "bgimg/" . $week . '.png';
  139. $qr = ImageManager::make($week_path)->resize(114, 27);
  140. $bg->insert($qr, 'top-left', 53, 876);
  141. $filename = self::FILELINK . $ext . $special['id'] . ".png";
  142. $bg->save($filename);
  143. return $filename;
  144. }
  145. /**签到海报
  146. * @param $special_id
  147. * @param $url
  148. * @param $backgroundImg
  149. * @param string $ext
  150. * @return string
  151. */
  152. public static function foundSignCode($uid, $url, $sign_info, $ext = 'poster_sign_')
  153. {
  154. vendor('phpqrcode.phpqrcode');
  155. $bg_path = self::BGIMG_PATH;
  156. //底图尺寸大小
  157. $bg = ImageManager::make($bg_path . 'bgimg/bg.png')->resize(750, 950);
  158. $thumb = $sign_info['poster'];
  159. //海报尺寸大小
  160. if ($thumb) {
  161. $thumb = ImageManager::make($thumb)->resize(690, 590);
  162. //水印
  163. $font_path = ROOT_PATH.'public/wap/first/zsff/font/';
  164. $title1_font_ttf = $font_path.'PingFang-SC.ttf';
  165. $site_name=SystemConfigService::get('site_name');
  166. $thumb->text($site_name, 600, 570, function (AbstractFont $text) use ($title1_font_ttf){
  167. $text->file($title1_font_ttf);
  168. $text->size(20);
  169. $text->color('#DDDDDD');
  170. $text->align('center');
  171. });
  172. $bg->insert($thumb, 'top-left', 30, 35);
  173. }
  174. $qrcodename = self::FILELINK .$ext.time() . 'qrcode.png';
  175. \QRcode::png($url, $qrcodename, 'L', 10, 2);
  176. //二维码位置
  177. if ($qrcodename) {
  178. $qr = ImageManager::make($qrcodename)->resize(150, 150);
  179. $bg->insert($qr, 'top-right', 45, 760);
  180. }
  181. //海报文字位置,活动分享标题
  182. $font_path = ROOT_PATH.'public/wap/first/zsff/font/';
  183. $title1_font_ttf = $font_path.'PingFang-SC.ttf';
  184. $bg->text($sign_info['sign_talk'], 50, 750, function (AbstractFont $text) use($title1_font_ttf){
  185. $text->file($title1_font_ttf);
  186. $text->size(14);
  187. $text->color('#333333');
  188. $text->align('left');
  189. });
  190. $bg->text('我们一起风雨兼程', 625, 750, function (AbstractFont $text) use ($title1_font_ttf) {
  191. $text->file($title1_font_ttf);
  192. $text->size(14);
  193. $text->color('#666');
  194. $text->align('center');
  195. });
  196. $title2_font_ttf = $font_path.'pingfang-sc-blod.ttf';
  197. $bg->text(date("d"), 49, 869, function (AbstractFont $text) use($title2_font_ttf){
  198. $text->file($title2_font_ttf);
  199. $text->size(72);
  200. $text->color('#f30606');
  201. $text->align('left');
  202. });
  203. $month = array(
  204. '01' => '一月',
  205. '02' => '二月',
  206. '03' => '三月',
  207. '04' => '四月',
  208. '05' => '五月',
  209. '06' => '六月',
  210. '07' => '七月',
  211. '08' => '八月',
  212. '09' => '九月',
  213. '10' => '十月',
  214. '11' => '十一月',
  215. '12' => '十二月'
  216. );
  217. $title3_font_ttf = $font_path.'pingfang-sc-blod.ttf';
  218. $bg->text($month[date("m")], 128, 869, function (AbstractFont $text) use($title3_font_ttf){
  219. $text->file($title3_font_ttf);
  220. $text->size(21);
  221. $text->color('#000000');
  222. $text->align('left');
  223. });
  224. $week = date("w");
  225. if ($week == 0) {
  226. $week = 7;
  227. }
  228. $week_path = $bg_path . "bgimg/" . $week . '.png';
  229. $qr = ImageManager::make($week_path)->resize(114, 27);
  230. $bg->insert($qr, 'top-left', 53, 876);
  231. $filename = self::FILELINK . $ext .$uid . ".png";
  232. $bg->save($filename);
  233. return $filename;
  234. }
  235. public static function startPosterSpeclialIng($special_id, $backgroundImg, $url)
  236. {
  237. vendor('phpqrcode.phpqrcode');
  238. $qrcodename = time() . '_show_qrcode.png';
  239. \QRcode::png($url, $qrcodename, 'L', 10, 2);
  240. $image = self::ReatetrueColor();
  241. //放背景
  242. list($canvas, $borderRes) = self::CreatJpeg($backgroundImg);
  243. imagecopyresampled($image, $canvas, 0, 0, 0, 0, imagesx($canvas), imagesy($canvas), imagesx($canvas), imagesy($canvas));
  244. list($code, $codeRes) = self::CreatJpeg($qrcodename);
  245. imagecopyresampled($image, $code, 505, 1090, 0, 0, 156, 156, (int)$codeRes[0], (int)$codeRes[1]);
  246. $FileService = new FileService();
  247. $FileService->create_dir(self::FILELINK);
  248. $filename = self::FILELINK . 'poster_' . $special_id . '.jpg';
  249. imagejpeg($image, $filename, 70);
  250. imagedestroy($image);
  251. $FileService->unlink_file($qrcodename);
  252. return $filename;
  253. }
  254. public static function startPosterIng($backgroundImgList, $uid)
  255. {
  256. if (!is_array($backgroundImgList)) return false;
  257. //放二维码
  258. $path = 'public/uploads/routine/' . $uid . '.jpg';
  259. if (!file_exists($path)) file_put_contents($path, RoutineCode::getCode($uid));
  260. $link = [];
  261. foreach ($backgroundImgList as $item) {
  262. if ($item['pic']) {
  263. $image = self::ReatetrueColor();
  264. //放背景
  265. list($canvas, $borderRes) = self::CreatJpeg(ROOT_PATH . $item['pic']);
  266. $color = imagecolorallocate($canvas, 0, 0, 0);
  267. imagefill($canvas, 0, 0, $color);
  268. imagecopyresampled($image, $canvas, 0, 0, 0, 0, imagesx($canvas), imagesy($canvas), imagesx($canvas), imagesy($canvas));
  269. list($code, $codeRes) = self::CreatJpeg($path);
  270. imagecopyresampled($image, $code, 170, 545, 0, 0, 220, 220, (int)$codeRes[0], (int)$codeRes[1]);
  271. $res = pathinfo($item['pic']);
  272. $save_file = self::FILELINK . $res['filename'] . 'haibao_.jpg';
  273. imagejpeg($image, $save_file, 70);
  274. imagedestroy($image);
  275. $link[] = $save_file;
  276. }
  277. }
  278. return $link;
  279. }
  280. public static function startPainting($userinfo = [], $merinfo = [], $mer_id)
  281. {
  282. $image = self::ReatetrueColor();
  283. //放背景
  284. list($canvas, $res) = self::CreatJpeg();
  285. $color = imagecolorallocate($canvas, 0, 0, 0);
  286. imagefill($canvas, 0, 0, $color);
  287. imagecopyresampled($image, $canvas, 0, 0, 0, 0, imagesx($canvas), imagesy($canvas), imagesx($canvas), imagesy($canvas));
  288. //放边框
  289. list($border, $borderRes) = self::CreatJpeg(self::BORDER);
  290. imagecopyresampled($image, $border, 10, 380, 0, 0, 450, 483, (int)$borderRes[0], (int)$borderRes[1]);
  291. //放二维码
  292. $path = 'public/uploads/routine/' . $userinfo['uid'] . '.jpg';
  293. if (!file_exists($path)) file_put_contents($path, RoutineCode::getCode($userinfo['uid']));
  294. list($code, $codeRes) = self::CreatJpeg($path);
  295. imagecopyresampled($image, $code, 150, 950, 0, 0, 180, 180, (int)$codeRes[0], (int)$codeRes[1]);
  296. //放头部
  297. list($heade, $headeRes) = self::CreatJpeg(self::FILELINK . 'heade.png');
  298. imagecopyresampled($image, $heade, 10, 50, 0, 0, 446, 281, (int)$headeRes[0], (int)$headeRes[1]);
  299. //放头像
  300. //下载头像为jpg头像
  301. if (!$userinfo['avatar_name'] && !file_exists($userinfo['avatar_name'])) {
  302. $avatar_name = time() . '.jpg';
  303. FileService::down_remote_file($userinfo['avatar'], self::FILELINK, $avatar_name);
  304. $link_image = self::FILELINK . 'user' . time() . '.png';
  305. self::CutChart(self::FILELINK . $avatar_name, $link_image);
  306. //删除刚下载的图片
  307. if (file_exists(self::FILELINK . $avatar_name)) unlink(self::FILELINK . $avatar_name);
  308. } else {
  309. $link_image = $userinfo['avatar_name'];
  310. }
  311. //放置头像
  312. list($avatar_c, $avatarRes) = self::CreatJpeg($link_image);
  313. imagecopyresampled($image, $avatar_c, 85, 58, 0, 0, 95, 95, (int)$avatarRes[0], (int)$avatarRes[1]);
  314. $text = [
  315. [
  316. 'fontSize' => 20,
  317. 'fontColor' => '231,180,52',
  318. 'left' => 70,
  319. 'top' => 200,
  320. 'text' => self::getUtf8Str($userinfo['nickname']),
  321. 'fontPath' => self::FONT,
  322. 'angle' => 0,
  323. ],
  324. [
  325. 'fontSize' => 19,
  326. 'fontColor' => '255,255,255',
  327. 'left' => 70,
  328. 'top' => 235,
  329. 'text' => self::getUtf8Str('吃货值:' . $userinfo['integral']),
  330. 'fontPath' => self::FONT,
  331. 'angle' => 0,
  332. ],
  333. [
  334. 'fontSize' => 19,
  335. 'fontColor' => '255,255,255',
  336. 'left' => 70,
  337. 'top' => 265,
  338. 'text' => self::getUtf8Str('吃货头衔:' . $userinfo['grade_name']),
  339. 'fontPath' => self::FONT,
  340. 'angle' => 0,
  341. ],
  342. [
  343. 'fontSize' => 19,
  344. 'fontColor' => '255,255,255',
  345. 'left' => 70,
  346. 'top' => 295,
  347. 'text' => self::getUtf8Str('吃货折扣:' . $userinfo['discount_num'] . '折'),
  348. 'fontPath' => self::FONT,
  349. 'angle' => 0,
  350. ],
  351. [
  352. 'fontSize' => 20,
  353. 'fontColor' => '255,255,255',
  354. 'left' => 20,
  355. 'top' => 800,
  356. 'text' => self::getUtf8Str($userinfo['mer_name']),
  357. 'fontPath' => self::FONT,
  358. 'angle' => 0,
  359. ],
  360. [
  361. 'fontSize' => 15,
  362. 'fontColor' => '255,255,255',
  363. 'left' => 20,
  364. 'top' => 838,
  365. 'text' => self::getUtf8Str($userinfo['details_address']),
  366. 'fontPath' => self::FONT,
  367. 'angle' => 0,
  368. ],
  369. [
  370. 'fontSize' => 15,
  371. 'fontColor' => '255,255,255',
  372. 'left' => 159,
  373. 'top' => 900,
  374. 'text' => self::getUtf8Str('(扫码获取吃货值)'),
  375. 'fontPath' => self::FONT,
  376. 'angle' => 0,
  377. ]
  378. ];
  379. $images = [
  380. [
  381. 'url' => isset($merinfo[0]) ? $merinfo[0] : '',
  382. 'left' => 15,
  383. 'top' => 390,
  384. 'right' => 0,
  385. 'stream' => 0,
  386. 'bottom' => 0,
  387. 'width' => 218,
  388. 'height' => 155,
  389. 'opacity' => 100,
  390. ],
  391. [
  392. 'url' => isset($merinfo[1]) ? $merinfo[1] : '',
  393. 'left' => 235,
  394. 'top' => 390,
  395. 'right' => 0,
  396. 'stream' => 0,
  397. 'bottom' => 0,
  398. 'width' => 218,
  399. 'height' => 155,
  400. 'opacity' => 100,
  401. ],
  402. [
  403. 'url' => isset($merinfo[2]) ? $merinfo[2] : '',
  404. 'left' => 15,
  405. 'top' => 548,
  406. 'right' => 0,
  407. 'stream' => 0,
  408. 'bottom' => 0,
  409. 'width' => 218,
  410. 'height' => 155,
  411. 'opacity' => 100,
  412. ],
  413. [
  414. 'url' => isset($merinfo[3]) ? $merinfo[3] : '',
  415. 'left' => 235,
  416. 'top' => 548,
  417. 'right' => 0,
  418. 'bottom' => 0,
  419. 'width' => 218,
  420. 'height' => 155,
  421. 'opacity' => 100,
  422. ]
  423. ];
  424. foreach ($images as $item) {
  425. if ($item['url']) {
  426. list($mer, $Res) = self::CreatJpeg(ROOT_PATH . $item['url']);
  427. if ($mer && $Res) imagecopyresampled($image, $mer, $item['left'], $item['top'], $item['right'], $item['bottom'], $item['width'], $item['height'], (int)$Res[0], (int)$Res[1]);
  428. }
  429. }
  430. foreach ($text as $key => $val) {
  431. list($R, $G, $B) = explode(',', $val['fontColor']);
  432. $fontColor = imagecolorallocate($image, $R, $G, $B);
  433. $val['left'] = $val['left'] < 0 ? self::$backgroundWidth - abs($val['left']) : $val['left'];
  434. $val['top'] = $val['top'] < 0 ? self::$backgroundHeight - abs($val['top']) : $val['top'];
  435. imagettftext($image, $val['fontSize'], $val['angle'], $val['left'], $val['top'], $fontColor, $val['fontPath'], $val['text']);
  436. }
  437. $save_file = self::FILELINK . 'haibao_' . time() . '.jpg';
  438. imagejpeg($image, $save_file, 70);
  439. imagedestroy($image);
  440. return ['file' => $save_file, 'avatar_name' => $link_image];
  441. }
  442. public static function getUtf8Str($str, $utf8len = 28, $chaet = 'UTF-8', $file = '...')
  443. {
  444. if (mb_strlen($str, $chaet) > $utf8len) {
  445. $str = mb_substr($str, 0, $utf8len, $chaet) . $file;
  446. }
  447. return $str;
  448. }
  449. public static function CutChart($imgpath, $savefilename)
  450. {
  451. $ext = pathinfo($imgpath);
  452. $src_img = null;
  453. switch ($ext['extension']) {
  454. case 'jpg':
  455. $src_img = imagecreatefromjpeg($imgpath);
  456. break;
  457. case 'png':
  458. $src_img = imagecreatefrompng($imgpath);
  459. break;
  460. case 'gif':
  461. $src_img = imagecreatefromgif($imgpath);
  462. break;
  463. }
  464. $wh = getimagesize($imgpath);
  465. $w = $wh[0];
  466. $h = $wh[1];
  467. $w = min($w, $h);
  468. $h = $w;
  469. $img = imagecreatetruecolor($w, $h);
  470. //这一句一定要有
  471. imagesavealpha($img, true);
  472. //拾取一个完全透明的颜色,最后一个参数127为全透明
  473. $bg = imagecolorallocatealpha($img, 255, 255, 255, 127);
  474. imagefill($img, 0, 0, $bg);
  475. $r = $w / 2; //圆半径
  476. $y_x = $r; //圆心X坐标
  477. $y_y = $r; //圆心Y坐标
  478. for ($x = 0; $x < $w; $x++) {
  479. for ($y = 0; $y < $h; $y++) {
  480. $rgbColor = imagecolorat($src_img, $x, $y);
  481. if (((($x - $r) * ($x - $r) + ($y - $r) * ($y - $r)) < ($r * $r))) {
  482. imagesetpixel($img, $x, $y, $rgbColor);
  483. }
  484. }
  485. }
  486. imagepng($img, $savefilename, 0);
  487. imagedestroy($img);
  488. }
  489. /*
  490. * 生成画笔
  491. * */
  492. public static function brush($one, $two, $three)
  493. {
  494. if (self::$canvas === null) return false;
  495. return imagecolorallocate(self::$canvas, $one, $two, $three);
  496. }
  497. /*
  498. * 粉丝介绍字体拆分为数组排列
  499. * */
  500. public static function getContentArray($str, $len = 4, $strlen = 24, $chaet = 'UTF-8')
  501. {
  502. $array = [];
  503. for ($i = 0; $i < $len; $i++) {
  504. array_push($array, '');
  505. }
  506. if (mb_strlen($str, $chaet) > $strlen) {
  507. for ($i = 0; $i < $len; $i++) {
  508. $lin = mb_substr($str, $i * $strlen, $strlen, $chaet);
  509. if ($lin) $array[$i] = $lin;
  510. }
  511. } else {
  512. $array[0] = $str;
  513. }
  514. return $array;
  515. }
  516. }