api.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import gm from 'gm';
  2. import axios from 'axios';
  3. import sizeOf from 'image-size';
  4. import path from 'node:path';
  5. import fs from 'node:fs';
  6. import { getImagicPath, getTempPath } from './utils';
  7. import {
  8. DrawTrackItem,
  9. DrawTrackCircleOption,
  10. DrawTrackLineOption,
  11. DrawTrackTextOption,
  12. } from './types';
  13. // macos install gm imagemagick https://github.com/aheckmann/gm/blob/master/README.md
  14. const gmInst =
  15. process.platform === 'win32'
  16. ? gm.subClass({
  17. imageMagick: '7+',
  18. appPath: getImagicPath(),
  19. })
  20. : gm.subClass({ imageMagick: '7+' });
  21. function cropImage(imgPath: string): Promise<string> {
  22. return new Promise((resolve, reject) => {
  23. const outpath = path.join(getTempPath(), '001.png');
  24. gmInst(imgPath)
  25. .crop(500, 200, 0, 0)
  26. .write(outpath, (err) => {
  27. if (!err) {
  28. return resolve(outpath);
  29. }
  30. return reject(err);
  31. });
  32. });
  33. }
  34. function drawTrack(
  35. imgPath: string,
  36. drawTrackList: DrawTrackItem[],
  37. outpath: string
  38. ): Promise<string> {
  39. return new Promise((resolve, reject) => {
  40. const gmObj = gmInst(imgPath);
  41. const defaultColor = '#f53f3f';
  42. const defaultFontSize = 14;
  43. drawTrackList.forEach((track) => {
  44. // text
  45. if (track.type === 'text') {
  46. const { x, y, text, color, fontSize } =
  47. track.option as DrawTrackTextOption;
  48. gmObj
  49. .fill(color || defaultColor)
  50. .fontSize(fontSize || defaultFontSize)
  51. .drawText(x, y, text);
  52. return;
  53. }
  54. // circle
  55. if (track.type === 'circle') {
  56. const { x0, y0, x1, y1 } = track.option as DrawTrackCircleOption;
  57. gmObj.drawCircle(x0, y0, x1, y1).stroke(defaultColor, 2);
  58. return;
  59. }
  60. // line
  61. if (track.type === 'line') {
  62. const { x0, y0, x1, y1 } = track.option as DrawTrackLineOption;
  63. gmObj.drawLine(x0, y0, x1, y1).stroke(defaultColor, 2);
  64. }
  65. });
  66. gmObj.write(outpath, (err) => {
  67. if (!err) {
  68. return resolve(outpath);
  69. }
  70. return reject(err);
  71. });
  72. });
  73. }
  74. async function downloadFile(url: string, outputPath: string) {
  75. const writer = fs.createWriteStream(outputPath);
  76. const response = await axios({
  77. url,
  78. method: 'GET',
  79. responseType: 'stream',
  80. });
  81. response.data.pipe(writer);
  82. return new Promise((resolve, reject) => {
  83. writer.on('finish', resolve);
  84. writer.on('error', reject);
  85. });
  86. }
  87. async function downloadImage(url: string, outputPath: string) {
  88. await downloadFile(url, outputPath);
  89. const size = sizeOf(outputPath);
  90. return {
  91. url: outputPath,
  92. width: size.width || 100,
  93. height: size.height || 100,
  94. };
  95. }
  96. function joinPath(paths: string[]) {
  97. return path.join(...paths);
  98. }
  99. async function combinePdf(urls: string[], outpath: string) {
  100. // TODO:
  101. console.log(urls, outpath);
  102. }
  103. const commonApi = {
  104. cropImage,
  105. drawTrack,
  106. joinPath,
  107. downloadImage,
  108. combinePdf,
  109. };
  110. export type CommonApi = typeof commonApi;
  111. export default commonApi;