Fill.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. <?php
  2. namespace QrCode\traits;
  3. trait Fill
  4. {
  5. //半角
  6. public function halfCorner($img, $x, $y, $s, $bgColor, $frontColor, $lt = true, $lb = true, $rb = true, $rt = true)
  7. {
  8. //左上半角
  9. if ($lt) {
  10. imagefilledarc($img, $x * $s, $y * $s, $s / 2, $s / 2, 0, 90, $frontColor, IMG_ARC_PIE);
  11. imagefilledarc($img, $x * $s + $s / 4, $y * $s + $s / 4, $s / 2, $s / 2, 180, 270, $bgColor, IMG_ARC_PIE);
  12. }
  13. //左下半角
  14. if ($lb) {
  15. imagefilledarc($img, $x * $s, ($y + 1) * $s, $s / 2, $s / 2, 270, 360, $frontColor, IMG_ARC_PIE);
  16. imagefilledarc($img, $x * $s + $s / 4, ($y + 1) * $s - $s / 4, $s / 2, $s / 2, 90, 180, $bgColor, IMG_ARC_PIE);
  17. }
  18. //右下半角
  19. if ($rb) {
  20. imagefilledarc($img, ($x + 1) * $s, ($y + 1) * $s, $s / 2, $s / 2, 180, 270, $frontColor, IMG_ARC_PIE);
  21. imagefilledarc($img, ($x + 1) * $s - $s / 4, ($y + 1) * $s - $s / 4, $s / 2, $s / 2, 0, 90, $bgColor, IMG_ARC_PIE);
  22. }
  23. //右上半角
  24. if ($rt) {
  25. imagefilledarc($img, ($x + 1) * $s, $y * $s, ($s / 2), ($s / 2), 90, 180, $frontColor, IMG_ARC_PIE);
  26. imagefilledarc($img, ($x + 1) * $s - ($s / 4), $y * $s + ($s / 4), ($s / 2), ($s / 2), 270, 360, $bgColor, IMG_ARC_PIE);
  27. }
  28. }
  29. //半圆
  30. public function halfRounded($img, $x, $y, $s, $color, $t = true, $l = true, $b = true, $r = true)
  31. {
  32. //上半圆
  33. if ($t) {
  34. imagefilledarc($img, ($x * $s) + ($s / 2), ($y * $s) + ($s / 2), $s, $s, 180, 270, $color, IMG_ARC_PIE);
  35. imagefilledarc($img, ($x * $s) + ($s / 2), ($y * $s) + ($s / 2), $s, $s, 270, 360, $color, IMG_ARC_PIE);
  36. imagefilledrectangle($img, $x * $s, ($y * $s) + ($s / 2), ($x + 1) * $s, ($y + 1) * $s, $color);
  37. }
  38. //左半圆
  39. if ($l) {
  40. imagefilledarc($img, ($x * $s) + ($s / 2), ($y * $s) + ($s / 2), $s, $s, 90, 180, $color, IMG_ARC_PIE);
  41. imagefilledarc($img, ($x * $s) + ($s / 2), ($y * $s) + ($s / 2), $s, $s, 180, 270, $color, IMG_ARC_PIE);
  42. imagefilledrectangle($img, ($x * $s) + ($s / 2), ($y * $s), ($x + 1) * $s, ($y + 1) * $s, $color);
  43. }
  44. //下半圆
  45. if ($b) {
  46. imagefilledarc($img, ($x * $s) + ($s / 2), ($y * $s) + ($s / 2), $s, $s, 0, 90, $color, IMG_ARC_PIE);
  47. imagefilledarc($img, ($x * $s) + ($s / 2), ($y * $s) + ($s / 2), $s, $s, 90, 180, $color, IMG_ARC_PIE);
  48. imagefilledrectangle($img, $x * $s, $y * $s, ($x + 1) * $s, ($y * $s) + ($s / 2), $color);
  49. }
  50. //右半圆
  51. if ($r) {
  52. imagefilledarc($img, ($x * $s) + ($s / 2), ($y * $s) + ($s / 2), $s, $s, 270, 360, $color, IMG_ARC_PIE);
  53. imagefilledarc($img, ($x * $s) + ($s / 2), ($y * $s) + ($s / 2), $s, $s, 0, 90, $color, IMG_ARC_PIE);
  54. imagefilledrectangle($img, $x * $s, $y * $s, ($x * $s) + ($s / 2), ($y + 1) * $s, $color);
  55. }
  56. }
  57. /**
  58. * 图片圆角
  59. */
  60. public function roundedCorner($img, $x, $y, $s, $color, $lt = true, $lb = true, $rb = true, $rt = true)
  61. {
  62. if ($lt) {
  63. imagefilledarc($img, ($x * $s) + ($s / 2), ($y * $s) + ($s / 2), $s, $s, 180, 270, $color, IMG_ARC_PIE);
  64. $values = array(($x + 1) * $s, ($y * $s), ($x + 1) * $s, ($y + 1) * $s, ($x * $s), ($y + 1) * $s,);
  65. $values1 = array(($x * $s), ($y + 1) * $s, ($x * $s) + ($s / 2), ($y * $s) + ($s / 2), ($x * $s), ($y * $s) + ($s / 2),);
  66. $values2 = array(($x * $s) + ($s / 2), ($y * $s) + ($s / 2), ($x * $s) + ($s / 2), ($y * $s), ($x + 1) * $s, ($y * $s),);
  67. imagefilledpolygon($img, $values, 3, $color);
  68. imagefilledpolygon($img, $values1, 3, $color);
  69. imagefilledpolygon($img, $values2, 3, $color);
  70. }
  71. if ($lb) {
  72. imagefilledarc($img, ($x * $s) + ($s / 2), ($y * $s) + ($s / 2), $s, $s, 90, 180, $color, IMG_ARC_PIE);
  73. $values = array($x * $s, $y * $s, $x * $s + $s, $y * $s, $x * $s + $s, ($y + 1) * $s,);
  74. $values1 = array($x * $s, $y * $s, $x * $s, $y * $s + ($s / 2), $x * $s + $s, $y * $s + ($s / 2),);
  75. $values2 = array($x * $s + ($s / 2), $y * $s + ($s / 2), $x * $s + ($s / 2), ($y + 1) * $s, $x * $s + $s, ($y + 1) * $s,);
  76. imagefilledpolygon($img, $values, 3, $color);
  77. imagefilledpolygon($img, $values1, 3, $color);
  78. imagefilledpolygon($img, $values2, 3, $color);
  79. }
  80. if ($rb) {
  81. imagefilledarc($img, ($x * $s) + ($s / 2), $y * $s + ($s / 2), $s, $s, 360, 90, $color, IMG_ARC_PIE);
  82. $values = array($x * $s, ($y + 1) * $s, $x * $s, $y * $s, ($x + 1) * $s, $y * $s,);
  83. $values1 = array($x * $s, ($y + 1) * $s, $x * $s + ($s / 2), $y * $s + ($s / 2), $x * $s + ($s / 2), ($y + 1) * $s,);
  84. $values2 = array($x * $s + ($s / 2), $y * $s + ($s / 2), ($x + 1) * $s, $y * $s, ($x + 1) * $s, $y * $s + ($s / 2),);
  85. imagefilledpolygon($img, $values, 3, $color);
  86. imagefilledpolygon($img, $values1, 3, $color);
  87. imagefilledpolygon($img, $values2, 3, $color);
  88. }
  89. if ($rt) {
  90. imagefilledarc($img, ($x * $s) + ($s / 2), $y * $s + ($s / 2), $s, $s, 270, 360, $color, IMG_ARC_PIE);
  91. $values = array($x * $s, $y * $s, $x * $s, $y * $s + $s, ($x + 1) * $s, $y * $s + $s,);
  92. $values1 = array($x * $s, $y * $s, $x * $s + ($s / 2), $y * $s, $x * $s + ($s / 2), $y * $s + ($s / 2),);
  93. $values2 = array($x * $s + ($s / 2), $y * $s + ($s / 2), ($x + 1) * $s, $y * $s + ($s / 2), ($x + 1) * $s, $y * $s + $s,);
  94. imagefilledpolygon($img, $values, 3, $color);
  95. imagefilledpolygon($img, $values1, 3, $color);
  96. imagefilledpolygon($img, $values2, 3, $color);
  97. }
  98. }
  99. /**
  100. * 缩放图片
  101. * @param type $im
  102. * @param type $maxwidth
  103. * @param type $maxheight
  104. * @return type
  105. */
  106. public function resizeImage($im, $maxwidth, $maxheight)
  107. {
  108. $picWidth = imagesx($im);
  109. $picHeight = imagesy($im);
  110. $newIM = imagecreatetruecolor($maxwidth, $maxheight);
  111. ImageCopyResampled($newIM, $im, 0, 0, 0, 0, $maxwidth, $maxheight, $picWidth, $picHeight);
  112. imagedestroy($im);
  113. return $newIM;
  114. }
  115. //增加背景
  116. public function imageAddBG($im, $bgPath)
  117. {
  118. //加载logo
  119. $ext = pathinfo($bgPath, PATHINFO_EXTENSION);
  120. if (empty($ext)) {
  121. return false;
  122. }
  123. switch (strtolower($ext)) {
  124. case 'jpg':
  125. $bgRes = @imagecreatefromjpeg($bgPath);
  126. break;
  127. case 'gif':
  128. $bgRes = @imagecreatefromgif($bgPath);
  129. break;
  130. case 'png':
  131. $bgRes = @imagecreatefrompng($bgPath);
  132. break;
  133. }
  134. return $this->imageAddBGRes($im, $bgRes);
  135. }
  136. /**
  137. * 添加背景,参数都是资源
  138. * @param resource $im 图片资源
  139. * @param resource $bgRes 背景图片
  140. * @return resource
  141. */
  142. public function imageAddBGRes($im, $bgRes)
  143. {
  144. //计算宽和高
  145. $w = imagesx($im);
  146. $h = imagesy($im);
  147. $bgw = imagesx($bgRes);
  148. $bgh = imagesy($bgRes);
  149. imagecopymerge($bgRes, $im, ($bgw / 2) - ($w / 2), ($bgh / 2) - ($h / 2), 0, 0, $w, $h, 100);
  150. imagedestroy($im);
  151. return $bgRes;
  152. }
  153. /**
  154. * 图片增加logo
  155. * @param resource $im 图片资源
  156. * @param resource $logo logo图
  157. * @param int $stroke 是否对logo进行描边
  158. * @return resource
  159. */
  160. public function imageAddLogo($im, $logo, $stroke = 1) {
  161. //加载logo
  162. $ext = pathinfo($logo, PATHINFO_EXTENSION);
  163. if (empty($ext)) {
  164. throw new \Exception('Unsupported image format');
  165. }
  166. switch (strtolower($ext)) {
  167. case 'jpg':
  168. $logoRes = @imagecreatefromjpeg($logo);
  169. break;
  170. case 'gif':
  171. $logoRes = @imagecreatefromgif($logo);
  172. break;
  173. case 'png':
  174. $logoRes = @imagecreatefrompng($logo);
  175. break;
  176. default:
  177. throw new \Exception('Unsupported image format');
  178. break;
  179. }
  180. return $this->imageAddLogoRes($im, $logoRes, $stroke);
  181. }
  182. /**
  183. * 通过图片资源生成
  184. * @param resource $im 图片资源
  185. * @param resource $logoRes Logo资源
  186. * @return resource
  187. */
  188. public function imageAddLogoRes($im, $logoRes, $stroke = 0) {
  189. //计算宽和高
  190. $w = imagesx($im);
  191. $h = imagesy($im);
  192. $logoRes = $this->resizeImage($logoRes, min(36, $w / 5), min(36, $h / 5));
  193. $srcWidth = imagesx($logoRes);
  194. $srcHeight = imagesy($logoRes);
  195. if($stroke) {
  196. //logo边框1 小
  197. $bor1 = ImageCreate($srcWidth + 2, $srcHeight + 2);
  198. ImageColorAllocate($bor1, 237, 234, 237);//背景色
  199. $bor1Width = imagesx($bor1);
  200. $bor1Height = imagesy($bor1);
  201. //logo边框2 中
  202. $bor2 = ImageCreate($bor1Width + 8, $bor1Height + 8);
  203. ImageColorAllocate($bor2, 255, 255, 255);//背景色
  204. $bor2_w = imagesx($bor2);
  205. $bor2_h = imagesy($bor2);
  206. //logo边框3 大
  207. $bor3 = ImageCreate($bor2_w + 2, $bor2_h + 2);
  208. ImageColorAllocate($bor3, 215, 215, 215);//背景色
  209. $bor3Width = imagesx($bor3);
  210. $bor3Height = imagesy($bor3);
  211. //圆角处理
  212. $rounder = new \QrCode\RoundedCorner('', 5);
  213. //二维码与logo边框3合并
  214. $bor3 = $rounder->round_it($bor3);
  215. imagecopymerge($im, $bor3, ($w / 2) - ($bor3Width / 2), ($h / 2) - ($bor3Height / 2), 0, 0, $bor3Width, $bor3Height, 100);
  216. imagedestroy($bor3);
  217. //二维码与logo边框2合并
  218. $bor2 = $rounder->round_it($bor2);
  219. imagecopymerge($im, $bor2, ($w / 2) - ($bor2_w / 2), ($h / 2) - ($bor2_h / 2), 0, 0, $bor2_w, $bor2_h, 100);
  220. imagedestroy($bor2);
  221. //二维码与logo边框1合并
  222. $bor1 = $rounder->round_it($bor1);
  223. imagecopymerge($im, $bor1, ($w / 2) - ($bor1Width / 2), ($h / 2) - ($bor1Height / 2), 0, 0, $bor1Width, $bor1Height, 100);
  224. imagedestroy($bor1);
  225. //二维码与logo合并
  226. $logoRes = $rounder->round_it($logoRes);
  227. }
  228. imagecopymerge($im, $logoRes, ($w / 2) - ($srcWidth / 2), ($h / 2) - ($srcHeight / 2), 0, 0, $srcWidth, $srcHeight, 100);
  229. imagedestroy($logoRes);
  230. return $im;
  231. }
  232. /**
  233. * 在二维码下边生成图片
  234. *
  235. * @param resource $im 图片资源
  236. * @param string $text 文字
  237. * @param int $fontSize 字体
  238. * @param string $fontPath 字体路径
  239. * @param array $options 选型
  240. * @return resource
  241. */
  242. public function imageAddText($im, $text, $fontSize = 14, $fontPath = '', $options = array())
  243. {
  244. $fontSize = $fontSize ?? 14;
  245. if (empty($options['bgColor'])) {
  246. $options['bgColor'] = '#FFFFFF';
  247. }
  248. if (empty($options['fontColor'])) {
  249. $options['fontColor'] = $options['frontColor'] ?? '#000000';
  250. }
  251. //计算宽和高
  252. $w = imagesx($im);
  253. $h = imagesy($im);
  254. $bgColor = $this->hex2rgb($options['bgColor']);
  255. $fontColor = $this->hex2rgb($options['fontColor']);
  256. //自动换行
  257. $text = $this->autoWrap($text, 0, $fontSize, $fontPath, $w);
  258. $box = $this->imageTTFBoxExtended($fontSize, 0, $fontPath, $text);
  259. $maxHeight = $h + $box['height'] + 20;
  260. $newIM = imagecreatetruecolor($w, $maxHeight);
  261. //背景色
  262. $background = imagecolorallocatealpha($newIM, $bgColor['r'], $bgColor['g'], $bgColor['b'], 100);
  263. imagefill($newIM, 0, 0, $background);
  264. imagecopymerge($newIM, $im, 0, 0, 0, 0, $w, $h, 100);
  265. $fontColor = imagecolorallocatealpha($newIM, $fontColor['r'], $fontColor['g'], $fontColor['b'], 50);
  266. imagettftext($newIM, $fontSize, 0, max(0, ($w - $box['width']) / 2), $h + 25, $fontColor, $fontPath, $text);
  267. imagedestroy($im);
  268. return $newIM;
  269. }
  270. /**
  271. * 获取文字的宽高
  272. *
  273. * @param int $size 字体大小
  274. * @param int $angle
  275. * @param string $fontPath 字体路径
  276. * @param string $text 文字
  277. * @return array
  278. */
  279. public function imageTTFBoxExtended($size, $angle, $fontPath, $text)
  280. {
  281. $box = imagettfbbox($size, $angle, $fontPath, $text);
  282. //calculate x baseline
  283. if ($box[0] >= -1) {
  284. $box['x'] = abs($box[0] + 1) * -1;
  285. } else {
  286. //$box['x'] = 0;
  287. $box['x'] = abs($box[0] + 2);
  288. }
  289. //calculate actual text width
  290. $box['width'] = abs($box[2] - $box[0]);
  291. if ($box[0] < -1) {
  292. $box['width'] = abs($box[2]) + abs($box[0]) - 1;
  293. }
  294. //calculate y baseline
  295. $box['y'] = abs($box[5] + 1);
  296. //calculate actual text height
  297. $box['height'] = abs($box[7]) - abs($box[1]);
  298. if ($box[3] > 0) {
  299. $box['height'] = abs($box[7] - $box[1]) - 1;
  300. }
  301. return $box;
  302. }
  303. /**
  304. * 文字自动换行
  305. *
  306. * @param int $fontSize [字体大小]
  307. * @param int $angle [角度]
  308. * @param string $fontFace [字体名称]
  309. * @param string $string [字符串]
  310. * @param int $width [预设宽度]
  311. */
  312. function autoWrap($text, $angle, $fontSize, $fontFace, $width)
  313. {
  314. $content = "";
  315. // 将字符串拆分成一个个单字 保存到数组 letter 中
  316. preg_match_all("/./u", $text, $arr);
  317. $letter = $arr[0];
  318. foreach ($letter as $l) {
  319. $testStr = $content . " " . $l;
  320. $testBox = imagettfbbox($fontSize, $angle, $fontFace, $testStr);
  321. // 判断拼接后的字符串是否超过预设的宽度
  322. if (($testBox[2] > $width) && ($content !== "")) {
  323. $content .= PHP_EOL;
  324. }
  325. $content .= $l;
  326. }
  327. return $content;
  328. }
  329. /**
  330. * 16进制颜色转换为RGB色值
  331. * @param string $hexColor 颜色值
  332. * @return array {r:, g:, b:}
  333. */
  334. public function hex2rgb($hexColor)
  335. {
  336. $color = str_replace('#', '', $hexColor);
  337. if (strlen($color) > 3) {
  338. $rgb = array(
  339. 'r' => hexdec(substr($color, 0, 2)),
  340. 'g' => hexdec(substr($color, 2, 2)),
  341. 'b' => hexdec(substr($color, 4, 2))
  342. );
  343. } else {
  344. $color = str_replace('#', '', $hexColor);
  345. $r = substr($color, 0, 1) . substr($color, 0, 1);
  346. $g = substr($color, 1, 1) . substr($color, 1, 1);
  347. $b = substr($color, 2, 1) . substr($color, 2, 1);
  348. $rgb = array(
  349. 'r' => hexdec($r),
  350. 'g' => hexdec($g),
  351. 'b' => hexdec($b)
  352. );
  353. }
  354. return $rgb;
  355. }
  356. }