DrawImage.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. <?php
  2. namespace App\Traits;
  3. use App\PrintPartImage;
  4. use Endroid\QrCode\QrCode;
  5. use Illuminate\Support\Facades\File;
  6. use Illuminate\Support\Str;
  7. use Intervention\Image\Facades\Image;
  8. use Picqer\Barcode\BarcodeGeneratorJPG;
  9. trait DrawImage
  10. {
  11. public function draw($orderPackage, $template, $img = null)
  12. {
  13. if (!$img) $img = $this->getBgImg($template);
  14. if (!$template) return $img;
  15. $items = array_filter($template->value, function ($item) {
  16. return $item['type'] != 'bg';
  17. });
  18. $array = array_filter($template->value, function ($item) {
  19. return $item['type'] == 'bg';
  20. });
  21. $array = array_shift($array);
  22. // 按照模型比列修改image
  23. $items = (function () use ($items, $img, $array) {
  24. $heightScale = $img->getHeight() / $array['height'];
  25. $weightScale = $img->getWidth() / $array['width'];
  26. // foreach ($items as $key => &$item) {
  27. foreach ($items as &$item) {
  28. if (array_key_exists('width', $item)) $item['width'] = intval($weightScale * floatval($item['width']));
  29. if (array_key_exists('height', $item)) $item['height'] = intval($heightScale * floatval($item['height']));
  30. if (array_key_exists('left', $item)) $item['left'] = intval($weightScale * floatval($item['left']));
  31. if (array_key_exists('top', $item)) $item['top'] = intval($heightScale * floatval($item['top']));
  32. if (array_key_exists('font-size', $item)) $item['font-size'] = intval($heightScale * floatval($item['font-size']));
  33. if (array_key_exists('border-width', $item)) $item['border-width'] = intval($heightScale * floatval($item['border-width']));
  34. $item['heightScale'] = $heightScale;
  35. $item['weightScale'] = $weightScale;
  36. }
  37. return $items;
  38. })();
  39. // 根据下标排序
  40. usort($items, function ($a, $b) {
  41. return $a['z_index'] > $b['z_index'] ? 1 : -1;
  42. });
  43. foreach ($items as $item) {
  44. switch ($item['type']) {
  45. case 'textBox':
  46. $this->setTextBox($img, $item, $orderPackage);
  47. break;
  48. case 'image':
  49. $this->setImage($img, $item);
  50. break;
  51. case 'qRCode':
  52. $this->setQRCode($img, $item, $orderPackage);
  53. break;
  54. case 'stripeCode':
  55. $this->setStripeCode($img, $item, $orderPackage);
  56. break;
  57. default:
  58. break;
  59. }
  60. }
  61. return $img;
  62. }
  63. private function getBgImg($template): \Intervention\Image\Image
  64. {
  65. $bg = array_filter($template->value, function ($item) {
  66. return $item['type'] == 'bg';
  67. });
  68. $values = array_shift($bg);
  69. return Image::canvas($values['width'], $values['height'], '#fff');
  70. }
  71. public function setTextBox($image, $params, $orderPackages): \Intervention\Image\Image
  72. {
  73. $text = $this->getValue($params, $orderPackages);
  74. $bgImage = Image::canvas($params['width'], $params['height'], '#000');
  75. $img = $this->getTextBox($params, $text);
  76. $bgImage = $bgImage->insert($img, 'top-left', $params['border-width'], $params['border-width']);
  77. return $image->insert($bgImage, 'top-left', $params['left'] ?? 0, $params['top'] ?? 0);
  78. }
  79. public function setStripeCode($img, $params, $orderPackages)
  80. {
  81. $code = $this->getValue($params, $orderPackages);
  82. $bgImage = Image::canvas(404, 92, '#fff');
  83. $item = [
  84. 'width' => 404, 'height' => 20,
  85. 'justify-content' => 'center', 'align-items' => 'center',
  86. 'text' => $code, 'border-width' => 0,
  87. 'top' => 58, 'left' => 0, 'font-size' => 20
  88. ];
  89. $textBox = $this->getTextBox($item, $code);
  90. $bgImage->insert($textBox, 'top-left', 0, 68);
  91. $generatorPng = new BarcodeGeneratorJPG();
  92. $barCode = $generatorPng->getBarcode($code, $generatorPng::TYPE_CODE_128_A, 1, 50);
  93. $stripeCode = Image::make($barCode)->resize(382, 50);
  94. $stripeCode_weight = 404 * $params['scale'] * $params['weightScale'];
  95. $stripeCode_height = 92 * $params['scale'] * $params['heightScale'];
  96. $bgImage->insert($stripeCode, 'top-left', 6, 9)->resize($stripeCode_weight, $stripeCode_height);
  97. $left = $params['left'] + ((404 * (1- $params['scale'])) * $params['weightScale']) / 2;
  98. $top = $params['top'] + ((92 * (1-$params['scale'])) * $params['heightScale']) / 2;
  99. return $img->insert($bgImage, 'top-left', intval($left), intval($top));
  100. }
  101. public function setImage($img, $params)
  102. {
  103. $printPartImage = PrintPartImage::query()->where('name', $params['text'])->first();
  104. $path = ['app', 'public'];
  105. $path = join(DIRECTORY_SEPARATOR, $path);
  106. $dirPath = storage_path($path);
  107. $uri = $printPartImage->file['url'];
  108. $uri = str_replace('/', DIRECTORY_SEPARATOR, $uri);
  109. $path = $dirPath . $uri . '.' . $printPartImage->file['type'];
  110. $image = Image::make(File::get($path));
  111. $image->resize($params['width'], $params['height']);
  112. $img->insert($image, 'top-left', $params['left'], $params['top']);
  113. return $img;
  114. }
  115. public function getTextBox($params, $text): \Intervention\Image\Image
  116. {
  117. $bgImg = Image::canvas($params['width'], $params['height'], '#fff');
  118. if ($params['border-width'] !== 0) {
  119. $borderWidth = $params['border-width'] * 2;
  120. $paddingBgImage = Image::canvas($params['width'], $params['height'], '#000');
  121. $paddingImage = Image::canvas($params['width'] - $borderWidth, $params['height'] - $borderWidth, '#fff');
  122. $paddingBgImage->insert($paddingImage, 'top-left', intval($params['border-width'] / 2), intval($params['border-width'] / 2));
  123. $bgImg->insert($paddingBgImage);
  124. }
  125. $path_arr = ['fonts', 'simsun.ttc'];
  126. $x = $params['width'] / 2;
  127. if ($params['justify-content'] == 'center') $x = $params['width'] / 2;
  128. if ($params['justify-content'] == 'flex-start') $x = $params['width'] / 2;
  129. $y = $params['height'] / 2;
  130. if ($params['align-items'] == 'center') $y = $params['height'] / 2;
  131. if ($params['align-items'] == 'flex-start') $y = 0;
  132. if ($params['align-items'] == 'flex-end') $y = ($params['height'] - 22) / 2;
  133. // 字体路径
  134. $path = app('path.public') . (DIRECTORY_SEPARATOR . join(DIRECTORY_SEPARATOR, $path_arr));
  135. $aligns = [
  136. 'flex-start' => 'right',
  137. 'center' => 'center'
  138. ];
  139. $vAligns = [
  140. 'center' => 'center',
  141. 'flex-start' => 'top',
  142. 'flex-end' => 'bottom',
  143. ];
  144. return $bgImg->text($text, intval($x), intval($y), function ($font) use ($params, $path, $aligns, $vAligns) {
  145. $font->file($path);
  146. $font->size($params['font-size'] ?? 24);
  147. $font->align($aligns[$params['justify-content']]); // 水平对齐方式
  148. // center
  149. // right
  150. $font->valign($vAligns[$params['align-items']]); // 垂直对齐方式
  151. // center
  152. // middle
  153. // top
  154. // bottom
  155. });
  156. }
  157. public function setQRCode($img, $params, $orderPackages)
  158. {
  159. $text = $this->getValue($params, $orderPackages);
  160. $qrCode = new QrCode($text);
  161. $qrCode->setSize(100);
  162. $qrCode->setMargin(0);
  163. $scale = $params['scale'] ?? 1;
  164. return $img->insert(Image::make($qrCode->writeString())->resize(100 * $scale * $params['weightScale'], 100 * $scale * $params['heightScale']), 'top-left', $params['left'], $params['top']);
  165. }
  166. // 获取图片
  167. public function getImage($base64, &$path): \Intervention\Image\Image
  168. {
  169. $path = $this->getImagePath();
  170. $img = Image::make($base64);
  171. $img->save($path); // 图片保存
  172. return $img;
  173. }
  174. // 获取打印图片的路径
  175. private function getImagePath(): string
  176. {
  177. $img_name = Str::uuid() . '.jpg';
  178. $path_arr = ['app', 'public', 'print'];
  179. $dir_path = implode(DIRECTORY_SEPARATOR, $path_arr);
  180. if (!file_exists(storage_path($dir_path))) mkdir(storage_path($dir_path));
  181. $path_arr[] = 'image';
  182. $dir_path = implode(DIRECTORY_SEPARATOR, $path_arr);
  183. if (!file_exists(storage_path($dir_path))) mkdir(storage_path($dir_path));
  184. $path_arr[] = $img_name;
  185. return storage_path(implode(DIRECTORY_SEPARATOR, $path_arr));
  186. }
  187. // 保存至保存图片路径下
  188. public function saveImage($image, &$path)
  189. {
  190. $path = $this->getImagePath();
  191. $image->save($path); // 图片保存
  192. }
  193. // 根据图片路径读取而base64编码的图片
  194. public function readImageBase64($path): string
  195. {
  196. if ($fp = fopen($path, "rp", 0)) {
  197. $gambar = fread($fp, filesize($path));
  198. fclose($fp);
  199. return chunk_split(base64_encode($gambar));
  200. }
  201. return "";
  202. }
  203. // 通过设置获取所需参数
  204. private function getValue($params, $orderPackage = [], $k = 'text'): string
  205. {
  206. $key = strtolower($params[$k]);
  207. if ($value = strstr($key, '$')) return $orderPackage[ltrim($value, '$')] ?? '';
  208. else return $params[$k];
  209. }
  210. }