Image.php 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. <?php
  2. namespace addons\poster\library;
  3. use think\Db;
  4. class Image
  5. {
  6. protected $target; //图像资源
  7. protected $poster_url; //海报url
  8. protected $model; //海报模型
  9. public function __construct()
  10. {
  11. $this->model = new \app\admin\model\Poster;
  12. }
  13. /**
  14. * 创建海报
  15. * @author Created by Xing <464401240@qq.com>
  16. */
  17. public function createPosterImage($poster, $member)
  18. {
  19. $path = $this->model->getDirs($poster['id']);
  20. if (!is_dir($path)) {
  21. $this->mkdirs($path);
  22. }
  23. $md5 = md5(json_encode(array(
  24. 'user_id' => $member['id'],
  25. 'bg' => $poster['bg_image'],
  26. 'data' => $poster['data'],
  27. 'poster_id' => $poster['id']
  28. )));
  29. $file = $md5 . '.png';
  30. $this->poster_url = $path . $file;
  31. if (is_file($this->poster_url)) {
  32. return $this->poster_url; //文件存在则直接返回
  33. }
  34. set_time_limit(0);
  35. @ini_set('memory_limit', '256M');
  36. $this->target = imagecreatetruecolor(640, 1008);
  37. $white = imagecolorallocate($this->target, 255, 255, 255);
  38. imagefill($this->target, 0, 0, $white);
  39. $bg = $this->createImage($poster['bg_image']);
  40. if (!empty($bg)) {
  41. $bgWidth = imagesx($bg);
  42. $bgHeight = imagesy($bg);
  43. $ratio = 640 / $bgWidth;
  44. $newWidth = imagesx($bg) * $ratio;
  45. $newHeight = imagesy($bg) * $ratio;
  46. $bgClone = imagecreatetruecolor($newWidth, $newHeight);
  47. imagecopyresampled($bgClone, $bg, 0, 0, 0, 0, $newWidth, $newHeight, $bgWidth, $bgHeight);
  48. imagecopy($this->target, $bgClone, 0, 0, 0, 0, $newWidth, $newHeight);
  49. imagedestroy($bg);
  50. imagedestroy($bgClone);
  51. }
  52. $data = json_decode(str_replace('&quot;', '\'', $poster['data']), true);
  53. foreach ($data as $d) {
  54. $d = $this->getRealData($d);
  55. if ($d['type'] == 'head') {
  56. $avatar = preg_replace('/\\/0$/i', '/96', $member['avatar']);
  57. $this->mergeImage($d, $avatar);
  58. } elseif ($d['type'] == 'img' && isset($d['src'])) {
  59. $this->mergeImage($d, $d['src']);
  60. } elseif ($d['type'] == 'qr' && isset($d['qr_table']) && isset($d['qr_relation']) && isset($d['qr_field'])) {
  61. $exist = Db::query('show tables like "' . $d['qr_table'] . '"');
  62. if ($exist) {
  63. $fields = Db::getConnection()->getFields($d['qr_table']); //传入数据表名称 $tablename
  64. if (isset($fields[$d['qr_relation']])) {
  65. $qrimg = Db::table($d['qr_table'])->where([$d['qr_relation'] => $member['id']])->value($d['qr_field']);
  66. $this->mergeImage($d, $qrimg);
  67. }
  68. }
  69. } elseif ($d['type'] == 'nickname') {
  70. // $this->mergeText($d, $member['nickname']);
  71. $this->mergeText($d, $d['content']);
  72. }
  73. }
  74. header("Content-Type:image/png");
  75. imagepng($this->target, $path . $file);
  76. imagedestroy($this->target);
  77. $params['poster_id'] = $poster['id'];
  78. $params['user_id'] = $member['id'];
  79. $params['image'] = $this->poster_url;
  80. $posterLog = new \app\admin\model\PosterLog();
  81. $posterLog->save($params);
  82. return $this->poster_url;
  83. }
  84. /**
  85. * 创建海报
  86. * @author Created by Xing <464401240@qq.com>
  87. */
  88. public function createPosterImage_user($poster, $member)
  89. {
  90. $path = $this->model->getDirs($poster['id']);
  91. if (!is_dir($path)) {
  92. $this->mkdirs($path);
  93. }
  94. $md5 = md5(json_encode(array(
  95. 'user_id' => $member['id'],
  96. 'bg' => $poster['bg_image'],
  97. 'data' => $poster['data'],
  98. 'poster_id' => $poster['id']
  99. )));
  100. $file = $md5 . '.png';
  101. $this->poster_url = $path . $file;
  102. if (is_file($this->poster_url)) {
  103. //return $this->poster_url; //文件存在则直接返回
  104. }
  105. set_time_limit(0);
  106. @ini_set('memory_limit', '256M');
  107. $this->target = imagecreatetruecolor(633, 926);
  108. $white = imagecolorallocate($this->target, 255, 255, 255);
  109. imagefill($this->target, 0, 0, $white);
  110. $bg = $this->createImage($poster['bg_image']);
  111. if (!empty($bg)) {
  112. $bgWidth = imagesx($bg);
  113. $bgHeight = imagesy($bg);
  114. $ratio = 640 / $bgWidth;
  115. $newWidth = imagesx($bg) * $ratio;
  116. $newHeight = imagesy($bg) * $ratio;
  117. $bgClone = imagecreatetruecolor($newWidth, $newHeight);
  118. imagecopyresampled($bgClone, $bg, 0, 0, 0, 0, $newWidth, $newHeight, $bgWidth, $bgHeight);
  119. imagecopy($this->target, $bgClone, 0, 0, 0, 0, $newWidth, $newHeight);
  120. imagedestroy($bg);
  121. imagedestroy($bgClone);
  122. }
  123. $data = json_decode(str_replace('&quot;', '\'', $poster['data']), true);
  124. foreach ($data as $d) {
  125. $d = $this->getRealData($d);
  126. if ($d['type'] == 'head') {
  127. $avatar = preg_replace('/\\/0$/i', '/96', $member['avatar']);
  128. $this->mergeImage($d, $avatar);
  129. } elseif ($d['type'] == 'img' && isset($d['src'])) {
  130. $this->mergeImage($d, $d['src']);
  131. } elseif ($d['type'] == 'qr' && isset($d['qr_table']) && isset($d['qr_relation']) && isset($d['qr_field'])) {
  132. $exist = Db::query('show tables like "' . $d['qr_table'] . '"');
  133. if ($exist) {
  134. $fields = Db::getConnection()->getFields($d['qr_table']); //传入数据表名称 $tablename
  135. if (isset($fields[$d['qr_relation']])) {
  136. $qrimg = Db::table($d['qr_table'])->where([$d['qr_relation'] => $member['id']])->value($d['qr_field']);
  137. $this->mergeImage($d, $qrimg);
  138. }
  139. }
  140. } elseif ($d['type'] == 'nickname') {
  141. // $this->mergeText($d, $member['nickname']);
  142. $this->mergeText($d, $d['content']);
  143. }
  144. }
  145. header("Content-Type:image/png");
  146. imagepng($this->target, $path . $file);
  147. imagedestroy($this->target);
  148. $params['poster_id'] = $poster['id'];
  149. $params['user_id'] = $member['id'];
  150. $params['image'] = $this->poster_url;
  151. $posterLog = new \app\admin\model\PosterLog();
  152. $posterLog->save($params);
  153. return $this->poster_url;
  154. }
  155. public function mergeImage($data, $imgurl)
  156. {
  157. $img = $this->createImage($imgurl);
  158. if (!$img) {
  159. return false;
  160. }
  161. $w = imagesx($img);
  162. $h = imagesy($img);
  163. imagecopyresized($this->target, $img, $data['left'], $data['top'], 0, 0, $data['width'], $data['height'], $w, $h);
  164. imagedestroy($img);
  165. }
  166. public function mergeText($data, $text)
  167. {
  168. // $font = ROOT_PATH . 'public/assets/fonts/SourceHanSansK-Regular.ttf';
  169. $font = ROOT_PATH . '/public/assets/fonts/fangzheng.ttf';
  170. if (!isset($data['color'])) {
  171. $data['color'] = '#000';
  172. }
  173. // $text = mb_convert_encoding($text, "GB2312", "UTF-8");
  174. // $text = iconv('gb2312','utf-8',$text);//解决乱码问题
  175. $colors = $this->hex2rgb($data['color']);
  176. $color = imagecolorallocate($this->target, $colors['red'], $colors['green'], $colors['blue']);
  177. imagettftext($this->target, $data['size'], 0, $data['left'], $data['top'] + $data['size'], $color, $font, $text);
  178. }
  179. public function createImage($imgurl)
  180. {
  181. if (strpos($imgurl, 'data:image') !== false) {
  182. $imgurl = '/assets/addons/poster/images/head.jpg';
  183. }
  184. if (strpos($imgurl, '://') === false) {
  185. $imgurl = ROOT_PATH . '/public' . $imgurl;
  186. if (!is_file($imgurl)) {
  187. return '';
  188. }
  189. }
  190. @$content = file_get_contents($imgurl);
  191. if ($content) {
  192. return imagecreatefromstring($content);
  193. }
  194. return '';
  195. }
  196. private function getRealData($data)
  197. {
  198. $data['left'] = isset($data['left']) ? intval(str_replace('px', '', $data['left'])) * 2 : 0;
  199. $data['top'] = isset($data['top']) ? intval(str_replace('px', '', $data['top'])) * 2 : 0;
  200. $data['width'] = isset($data['width']) ? intval(str_replace('px', '', $data['width'])) * 2 : 0;
  201. $data['height'] = isset($data['height']) ? intval(str_replace('px', '', $data['height'])) * 2 : 0;
  202. $data['size'] = isset($data['size']) ? intval(str_replace('px', '', $data['size'])) * 2 : 0;
  203. return $data;
  204. }
  205. /**
  206. * 递归创建文件夹
  207. * @author Created by Xing <464401240@qq.com>
  208. */
  209. private function mkdirs($path)
  210. {
  211. if (!is_dir($path)) {
  212. $this->mkdirs(dirname($path));
  213. mkdir($path);
  214. }
  215. return is_dir($path);
  216. }
  217. /**
  218. * hex转rgb
  219. * @param $colour
  220. * @return array|bool
  221. */
  222. private function hex2rgb($colour)
  223. {
  224. if ($colour[0] == '#') {
  225. $colour = substr($colour, 1);
  226. }
  227. if (strlen($colour) == 6) {
  228. list($r, $g, $b) = array($colour[0] . $colour[1], $colour[2] . $colour[3], $colour[4] . $colour[5]);
  229. } elseif (strlen($colour) == 3) {
  230. list($r, $g, $b) = array($colour[0] . $colour[0], $colour[1] . $colour[1], $colour[2] . $colour[2]);
  231. } else {
  232. return false;
  233. }
  234. $r = hexdec($r);
  235. $g = hexdec($g);
  236. $b = hexdec($b);
  237. return array('red' => $r, 'green' => $g, 'blue' => $b);
  238. }
  239. }