apexify.js 4.8.3 → 4.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/dist/cjs/ai/ApexAI.d.ts +145 -0
  2. package/dist/cjs/ai/ApexAI.d.ts.map +1 -0
  3. package/dist/cjs/ai/ApexAI.js +494 -0
  4. package/dist/cjs/ai/ApexAI.js.map +1 -0
  5. package/dist/cjs/ai/ApexModules.d.ts +53 -0
  6. package/dist/cjs/ai/ApexModules.d.ts.map +1 -0
  7. package/dist/cjs/ai/ApexModules.js +819 -0
  8. package/dist/cjs/ai/ApexModules.js.map +1 -0
  9. package/dist/cjs/ai/functions/readFiles.d.ts +2 -0
  10. package/dist/cjs/ai/functions/readFiles.d.ts.map +1 -0
  11. package/dist/cjs/ai/functions/readFiles.js +96 -0
  12. package/dist/cjs/ai/functions/readFiles.js.map +1 -0
  13. package/dist/cjs/ai/functions/tokenizer.d.ts +10 -0
  14. package/dist/cjs/ai/functions/tokenizer.d.ts.map +1 -0
  15. package/dist/cjs/ai/functions/tokenizer.js +64 -0
  16. package/dist/cjs/ai/functions/tokenizer.js.map +1 -0
  17. package/dist/cjs/ai/functions/validOptions.d.ts +22 -0
  18. package/dist/cjs/ai/functions/validOptions.d.ts.map +1 -0
  19. package/dist/cjs/ai/functions/validOptions.js +103 -0
  20. package/dist/cjs/ai/functions/validOptions.js.map +1 -0
  21. package/dist/cjs/ai/modals/electronHub/chatmodels.d.ts +7 -0
  22. package/dist/cjs/ai/modals/electronHub/chatmodels.d.ts.map +1 -0
  23. package/dist/cjs/ai/modals/electronHub/chatmodels.js +51 -0
  24. package/dist/cjs/ai/modals/electronHub/chatmodels.js.map +1 -0
  25. package/dist/cjs/ai/modals/electronHub/imageModels.d.ts +12 -0
  26. package/dist/cjs/ai/modals/electronHub/imageModels.d.ts.map +1 -0
  27. package/dist/cjs/ai/modals/electronHub/imageModels.js +92 -0
  28. package/dist/cjs/ai/modals/electronHub/imageModels.js.map +1 -0
  29. package/dist/cjs/ai/modals/electronHub/speechModels.d.ts +7 -0
  30. package/dist/cjs/ai/modals/electronHub/speechModels.d.ts.map +1 -0
  31. package/dist/cjs/ai/modals/electronHub/speechModels.js +63 -0
  32. package/dist/cjs/ai/modals/electronHub/speechModels.js.map +1 -0
  33. package/dist/cjs/ai/modals/electronHub/videoModels.d.ts +6 -0
  34. package/dist/cjs/ai/modals/electronHub/videoModels.d.ts.map +1 -0
  35. package/dist/cjs/ai/modals/electronHub/videoModels.js +63 -0
  36. package/dist/cjs/ai/modals/electronHub/videoModels.js.map +1 -0
  37. package/dist/cjs/ai/modals/groq/chatgroq.d.ts +9 -0
  38. package/dist/cjs/ai/modals/groq/chatgroq.d.ts.map +1 -0
  39. package/dist/cjs/ai/modals/groq/chatgroq.js +64 -0
  40. package/dist/cjs/ai/modals/groq/chatgroq.js.map +1 -0
  41. package/dist/cjs/ai/modals/groq/imageAnalyzer.d.ts +8 -0
  42. package/dist/cjs/ai/modals/groq/imageAnalyzer.d.ts.map +1 -0
  43. package/dist/cjs/ai/modals/groq/imageAnalyzer.js +82 -0
  44. package/dist/cjs/ai/modals/groq/imageAnalyzer.js.map +1 -0
  45. package/dist/cjs/ai/modals/groq/whisper.d.ts +5 -0
  46. package/dist/cjs/ai/modals/groq/whisper.d.ts.map +1 -0
  47. package/dist/cjs/ai/modals/groq/whisper.js +108 -0
  48. package/dist/cjs/ai/modals/groq/whisper.js.map +1 -0
  49. package/dist/cjs/ai/modals/hercai/chatModels.d.ts +7 -0
  50. package/dist/cjs/ai/modals/hercai/chatModels.d.ts.map +1 -0
  51. package/dist/cjs/ai/modals/hercai/chatModels.js +23 -0
  52. package/dist/cjs/ai/modals/hercai/chatModels.js.map +1 -0
  53. package/dist/cjs/ai/utils.d.ts +5 -0
  54. package/dist/cjs/ai/utils.d.ts.map +1 -0
  55. package/dist/cjs/ai/utils.js +15 -0
  56. package/dist/cjs/ai/utils.js.map +1 -0
  57. package/dist/cjs/canvas/ApexPainter.d.ts +145 -0
  58. package/dist/cjs/canvas/ApexPainter.d.ts.map +1 -0
  59. package/dist/cjs/canvas/ApexPainter.js +908 -0
  60. package/dist/cjs/canvas/ApexPainter.js.map +1 -0
  61. package/dist/cjs/canvas/utils/Background/bg.d.ts +31 -0
  62. package/dist/cjs/canvas/utils/Background/bg.d.ts.map +1 -0
  63. package/dist/cjs/canvas/utils/Background/bg.js +161 -0
  64. package/dist/cjs/canvas/utils/Background/bg.js.map +1 -0
  65. package/dist/cjs/canvas/utils/Charts/charts.d.ts +8 -0
  66. package/dist/cjs/canvas/utils/Charts/charts.d.ts.map +1 -0
  67. package/dist/cjs/canvas/utils/Charts/charts.js +464 -0
  68. package/dist/cjs/canvas/utils/Charts/charts.js.map +1 -0
  69. package/dist/cjs/canvas/utils/Custom/customLines.d.ts +3 -0
  70. package/dist/cjs/canvas/utils/Custom/customLines.d.ts.map +1 -0
  71. package/dist/cjs/canvas/utils/Custom/customLines.js +109 -0
  72. package/dist/cjs/canvas/utils/Custom/customLines.js.map +1 -0
  73. package/dist/cjs/canvas/utils/General/conversion.d.ts +6 -0
  74. package/dist/cjs/canvas/utils/General/conversion.d.ts.map +1 -0
  75. package/dist/cjs/canvas/utils/General/conversion.js +34 -0
  76. package/dist/cjs/canvas/utils/General/conversion.js.map +1 -0
  77. package/dist/cjs/canvas/utils/General/general functions.d.ts +39 -0
  78. package/dist/cjs/canvas/utils/General/general functions.d.ts.map +1 -0
  79. package/dist/cjs/canvas/utils/General/general functions.js +606 -0
  80. package/dist/cjs/canvas/utils/General/general functions.js.map +1 -0
  81. package/dist/cjs/canvas/utils/Image/imageProperties.d.ts +115 -0
  82. package/dist/cjs/canvas/utils/Image/imageProperties.d.ts.map +1 -0
  83. package/dist/cjs/canvas/utils/Image/imageProperties.js +602 -0
  84. package/dist/cjs/canvas/utils/Image/imageProperties.js.map +1 -0
  85. package/dist/cjs/canvas/utils/Texts/textProperties.d.ts +17 -0
  86. package/dist/cjs/canvas/utils/Texts/textProperties.d.ts.map +1 -0
  87. package/dist/cjs/canvas/utils/Texts/textProperties.js +160 -0
  88. package/dist/cjs/canvas/utils/Texts/textProperties.js.map +1 -0
  89. package/dist/cjs/canvas/utils/types.d.ts +622 -0
  90. package/dist/cjs/canvas/utils/types.d.ts.map +1 -0
  91. package/dist/cjs/canvas/utils/types.js +7 -0
  92. package/dist/cjs/canvas/utils/types.js.map +1 -0
  93. package/dist/cjs/canvas/utils/utils.d.ts +19 -0
  94. package/dist/cjs/canvas/utils/utils.d.ts.map +1 -0
  95. package/dist/cjs/canvas/utils/utils.js +53 -0
  96. package/dist/cjs/canvas/utils/utils.js.map +1 -0
  97. package/dist/cjs/index.d.ts +29 -0
  98. package/dist/cjs/index.d.ts.map +1 -0
  99. package/dist/cjs/index.js +117 -0
  100. package/dist/cjs/index.js.map +1 -0
  101. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -0
  102. package/dist/cjs/utils.d.ts +5 -0
  103. package/dist/cjs/utils.d.ts.map +1 -0
  104. package/dist/cjs/utils.js +16 -0
  105. package/dist/cjs/utils.js.map +1 -0
  106. package/dist/esm/ai/ApexAI.d.ts +145 -0
  107. package/dist/esm/ai/ApexAI.d.ts.map +1 -0
  108. package/dist/esm/ai/ApexAI.js +494 -0
  109. package/dist/esm/ai/ApexAI.js.map +1 -0
  110. package/dist/esm/ai/ApexModules.d.ts +53 -0
  111. package/dist/esm/ai/ApexModules.d.ts.map +1 -0
  112. package/dist/esm/ai/ApexModules.js +819 -0
  113. package/dist/esm/ai/ApexModules.js.map +1 -0
  114. package/dist/esm/ai/functions/readFiles.d.ts +2 -0
  115. package/dist/esm/ai/functions/readFiles.d.ts.map +1 -0
  116. package/dist/esm/ai/functions/readFiles.js +96 -0
  117. package/dist/esm/ai/functions/readFiles.js.map +1 -0
  118. package/dist/esm/ai/functions/tokenizer.d.ts +10 -0
  119. package/dist/esm/ai/functions/tokenizer.d.ts.map +1 -0
  120. package/dist/esm/ai/functions/tokenizer.js +64 -0
  121. package/dist/esm/ai/functions/tokenizer.js.map +1 -0
  122. package/dist/esm/ai/functions/validOptions.d.ts +22 -0
  123. package/dist/esm/ai/functions/validOptions.d.ts.map +1 -0
  124. package/dist/esm/ai/functions/validOptions.js +103 -0
  125. package/dist/esm/ai/functions/validOptions.js.map +1 -0
  126. package/dist/esm/ai/modals/electronHub/chatmodels.d.ts +7 -0
  127. package/dist/esm/ai/modals/electronHub/chatmodels.d.ts.map +1 -0
  128. package/dist/esm/ai/modals/electronHub/chatmodels.js +51 -0
  129. package/dist/esm/ai/modals/electronHub/chatmodels.js.map +1 -0
  130. package/dist/esm/ai/modals/electronHub/imageModels.d.ts +12 -0
  131. package/dist/esm/ai/modals/electronHub/imageModels.d.ts.map +1 -0
  132. package/dist/esm/ai/modals/electronHub/imageModels.js +92 -0
  133. package/dist/esm/ai/modals/electronHub/imageModels.js.map +1 -0
  134. package/dist/esm/ai/modals/electronHub/speechModels.d.ts +7 -0
  135. package/dist/esm/ai/modals/electronHub/speechModels.d.ts.map +1 -0
  136. package/dist/esm/ai/modals/electronHub/speechModels.js +63 -0
  137. package/dist/esm/ai/modals/electronHub/speechModels.js.map +1 -0
  138. package/dist/esm/ai/modals/electronHub/videoModels.d.ts +6 -0
  139. package/dist/esm/ai/modals/electronHub/videoModels.d.ts.map +1 -0
  140. package/dist/esm/ai/modals/electronHub/videoModels.js +63 -0
  141. package/dist/esm/ai/modals/electronHub/videoModels.js.map +1 -0
  142. package/dist/esm/ai/modals/groq/chatgroq.d.ts +9 -0
  143. package/dist/esm/ai/modals/groq/chatgroq.d.ts.map +1 -0
  144. package/dist/esm/ai/modals/groq/chatgroq.js +64 -0
  145. package/dist/esm/ai/modals/groq/chatgroq.js.map +1 -0
  146. package/dist/esm/ai/modals/groq/imageAnalyzer.d.ts +8 -0
  147. package/dist/esm/ai/modals/groq/imageAnalyzer.d.ts.map +1 -0
  148. package/dist/esm/ai/modals/groq/imageAnalyzer.js +82 -0
  149. package/dist/esm/ai/modals/groq/imageAnalyzer.js.map +1 -0
  150. package/dist/esm/ai/modals/groq/whisper.d.ts +5 -0
  151. package/dist/esm/ai/modals/groq/whisper.d.ts.map +1 -0
  152. package/dist/esm/ai/modals/groq/whisper.js +108 -0
  153. package/dist/esm/ai/modals/groq/whisper.js.map +1 -0
  154. package/dist/esm/ai/modals/hercai/chatModels.d.ts +7 -0
  155. package/dist/esm/ai/modals/hercai/chatModels.d.ts.map +1 -0
  156. package/dist/esm/ai/modals/hercai/chatModels.js +23 -0
  157. package/dist/esm/ai/modals/hercai/chatModels.js.map +1 -0
  158. package/dist/esm/ai/utils.d.ts +5 -0
  159. package/dist/esm/ai/utils.d.ts.map +1 -0
  160. package/dist/esm/ai/utils.js +15 -0
  161. package/dist/esm/ai/utils.js.map +1 -0
  162. package/dist/esm/canvas/ApexPainter.d.ts +145 -0
  163. package/dist/esm/canvas/ApexPainter.d.ts.map +1 -0
  164. package/dist/esm/canvas/ApexPainter.js +908 -0
  165. package/dist/esm/canvas/ApexPainter.js.map +1 -0
  166. package/dist/esm/canvas/utils/Background/bg.d.ts +31 -0
  167. package/dist/esm/canvas/utils/Background/bg.d.ts.map +1 -0
  168. package/dist/esm/canvas/utils/Background/bg.js +161 -0
  169. package/dist/esm/canvas/utils/Background/bg.js.map +1 -0
  170. package/dist/esm/canvas/utils/Charts/charts.d.ts +8 -0
  171. package/dist/esm/canvas/utils/Charts/charts.d.ts.map +1 -0
  172. package/dist/esm/canvas/utils/Charts/charts.js +464 -0
  173. package/dist/esm/canvas/utils/Charts/charts.js.map +1 -0
  174. package/dist/esm/canvas/utils/Custom/customLines.d.ts +3 -0
  175. package/dist/esm/canvas/utils/Custom/customLines.d.ts.map +1 -0
  176. package/dist/esm/canvas/utils/Custom/customLines.js +109 -0
  177. package/dist/esm/canvas/utils/Custom/customLines.js.map +1 -0
  178. package/dist/esm/canvas/utils/General/conversion.d.ts +6 -0
  179. package/dist/esm/canvas/utils/General/conversion.d.ts.map +1 -0
  180. package/dist/esm/canvas/utils/General/conversion.js +34 -0
  181. package/dist/esm/canvas/utils/General/conversion.js.map +1 -0
  182. package/dist/esm/canvas/utils/General/general functions.d.ts +39 -0
  183. package/dist/esm/canvas/utils/General/general functions.d.ts.map +1 -0
  184. package/dist/esm/canvas/utils/General/general functions.js +606 -0
  185. package/dist/esm/canvas/utils/General/general functions.js.map +1 -0
  186. package/dist/esm/canvas/utils/Image/imageProperties.d.ts +115 -0
  187. package/dist/esm/canvas/utils/Image/imageProperties.d.ts.map +1 -0
  188. package/dist/esm/canvas/utils/Image/imageProperties.js +602 -0
  189. package/dist/esm/canvas/utils/Image/imageProperties.js.map +1 -0
  190. package/dist/esm/canvas/utils/Texts/textProperties.d.ts +17 -0
  191. package/dist/esm/canvas/utils/Texts/textProperties.d.ts.map +1 -0
  192. package/dist/esm/canvas/utils/Texts/textProperties.js +160 -0
  193. package/dist/esm/canvas/utils/Texts/textProperties.js.map +1 -0
  194. package/dist/esm/canvas/utils/types.d.ts +622 -0
  195. package/dist/esm/canvas/utils/types.d.ts.map +1 -0
  196. package/dist/esm/canvas/utils/types.js +7 -0
  197. package/dist/esm/canvas/utils/types.js.map +1 -0
  198. package/dist/esm/canvas/utils/utils.d.ts +19 -0
  199. package/dist/esm/canvas/utils/utils.d.ts.map +1 -0
  200. package/dist/esm/canvas/utils/utils.js +53 -0
  201. package/dist/esm/canvas/utils/utils.js.map +1 -0
  202. package/dist/esm/index.d.ts +29 -0
  203. package/dist/esm/index.d.ts.map +1 -0
  204. package/dist/esm/index.js +117 -0
  205. package/dist/esm/index.js.map +1 -0
  206. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -0
  207. package/dist/esm/utils.d.ts +5 -0
  208. package/dist/esm/utils.d.ts.map +1 -0
  209. package/dist/esm/utils.js +16 -0
  210. package/dist/esm/utils.js.map +1 -0
  211. package/lib/ai/ApexAI.ts +2 -2
  212. package/lib/ai/ApexModules.ts +8 -8
  213. package/lib/ai/modals/electronHub/chatmodels.ts +1 -1
  214. package/lib/ai/modals/electronHub/imageModels.ts +2 -2
  215. package/lib/ai/modals/electronHub/speechModels.ts +1 -1
  216. package/lib/ai/utils.ts +3 -3
  217. package/lib/canvas/ApexPainter.ts +1 -1
  218. package/lib/canvas/utils/Background/bg.ts +1 -1
  219. package/lib/canvas/utils/Charts/charts.ts +1 -1
  220. package/lib/canvas/utils/Custom/customLines.ts +2 -2
  221. package/lib/canvas/utils/General/general functions.ts +1 -1
  222. package/lib/canvas/utils/Image/imageProperties.ts +1 -1
  223. package/lib/canvas/utils/Texts/textProperties.ts +1 -1
  224. package/lib/canvas/utils/utils.ts +8 -8
  225. package/lib/index.ts +5 -5
  226. package/lib/utils.ts +3 -3
  227. package/package.json +4 -6
  228. package/dist/tsconfig.cjs.tsbuildinfo +0 -1
  229. package/dist/tsconfig.esm.tsbuildinfo +0 -1
@@ -0,0 +1,908 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ApexPainter = void 0;
7
+ const canvas_1 = require("@napi-rs/canvas");
8
+ const gifencoder_1 = __importDefault(require("gifencoder"));
9
+ const fluent_ffmpeg_1 = __importDefault(require("fluent-ffmpeg"));
10
+ const stream_1 = require("stream");
11
+ const axios_1 = __importDefault(require("axios"));
12
+ const fs_1 = __importDefault(require("fs"));
13
+ const path_1 = __importDefault(require("path"));
14
+ const utils_1 = require("./utils/utils");
15
+ class ApexPainter {
16
+ format;
17
+ constructor({ type } = { type: 'buffer' }) {
18
+ this.format = { type: type || 'buffer' };
19
+ }
20
+ /**
21
+ * Creates a canvas with the given configuration.
22
+ * Applies rotation, shadow, border effects, background, and stroke.
23
+ *
24
+ * @param canvas - The configuration options for the canvas.
25
+ * @returns A promise that resolves to an object containing the image buffer and the canvas config.
26
+ * @throws If the 2D context cannot be retrieved.
27
+ */
28
+ async createCanvas(canvas) {
29
+ const { width = 500, height = 500, x = 0, y = 0, rotation = 0, borderRadius = 0, customBg, gradientBg, stroke, shadow, borderPosition = 'all', opacity = 1, zoom, blur } = canvas;
30
+ const canvasInstance = (0, canvas_1.createCanvas)(width, height);
31
+ const ctx = canvasInstance.getContext('2d');
32
+ if (!ctx) {
33
+ throw new Error('Unable to get 2D rendering context from canvas');
34
+ }
35
+ ctx.globalAlpha = opacity;
36
+ (0, utils_1.applyRotation)(ctx, rotation, x, y, width, height);
37
+ (0, utils_1.applyShadow)(ctx, shadow, x, y, width, height);
38
+ ctx.save();
39
+ if (borderRadius) {
40
+ (0, utils_1.backgroundRadius)(ctx, x, y, width, height, borderRadius, borderPosition);
41
+ }
42
+ ctx.translate(x, y);
43
+ if (customBg) {
44
+ await (0, utils_1.customBackground)(ctx, canvas, zoom, blur);
45
+ }
46
+ else if (gradientBg) {
47
+ await (0, utils_1.drawBackgroundGradient)(ctx, canvas, zoom, blur);
48
+ }
49
+ else {
50
+ await (0, utils_1.drawBackgroundColor)(ctx, canvas, zoom, blur);
51
+ }
52
+ ctx.restore();
53
+ (0, utils_1.applyStroke)(ctx, stroke, x, y, width, height);
54
+ return { buffer: canvasInstance.toBuffer('image/png'), canvas };
55
+ }
56
+ /**
57
+ * Draws one or more images (or shapes) on an existing canvas buffer.
58
+ * @param images - A single image properties object or an array of them.
59
+ * @param canvasBuffer - A Buffer or a CanvasResults object containing a buffer.
60
+ * @returns A promise that resolves to a Buffer representing the updated canvas.
61
+ */
62
+ async createImage(images, canvasBuffer) {
63
+ if (!Array.isArray(images)) {
64
+ images = [images];
65
+ }
66
+ let baseImage;
67
+ if (Buffer.isBuffer(canvasBuffer)) {
68
+ baseImage = await (0, canvas_1.loadImage)(canvasBuffer);
69
+ }
70
+ else if (canvasBuffer.buffer) {
71
+ baseImage = await (0, canvas_1.loadImage)(canvasBuffer.buffer);
72
+ }
73
+ else {
74
+ throw new Error('Invalid canvasBuffer provided; expected Buffer or CanvasResults with a buffer');
75
+ }
76
+ if (!baseImage) {
77
+ throw new Error('Unable to load base image from the provided buffer');
78
+ }
79
+ const canvas = (0, canvas_1.createCanvas)(baseImage.width, baseImage.height);
80
+ const ctx = canvas.getContext('2d');
81
+ if (!ctx) {
82
+ throw new Error('Unable to get 2D rendering context from canvas');
83
+ }
84
+ ctx.drawImage(baseImage, 0, 0);
85
+ for (const imageProps of images) {
86
+ await this.drawImage(ctx, imageProps);
87
+ }
88
+ return canvas.toBuffer('image/png');
89
+ }
90
+ async createText(textOptionsArray, buffer) {
91
+ try {
92
+ if (!Array.isArray(textOptionsArray)) {
93
+ textOptionsArray = [textOptionsArray];
94
+ }
95
+ let existingImage;
96
+ if (Buffer.isBuffer(buffer)) {
97
+ existingImage = await (0, canvas_1.loadImage)(buffer);
98
+ }
99
+ else if (buffer && buffer.buffer) {
100
+ existingImage = await (0, canvas_1.loadImage)(buffer.buffer);
101
+ }
102
+ else {
103
+ throw new Error('Invalid canvasBuffer provided. It should be a Buffer or CanvasResults object with a buffer');
104
+ }
105
+ if (!existingImage) {
106
+ throw new Error('Unable to load image from buffer');
107
+ }
108
+ const canvas = (0, canvas_1.createCanvas)(existingImage.width, existingImage.height);
109
+ const ctx = canvas.getContext("2d");
110
+ ctx.drawImage(existingImage, 0, 0);
111
+ for (const textOptions of textOptionsArray) {
112
+ const mergedTextOptions = textOptions;
113
+ if (mergedTextOptions.fontPath) {
114
+ canvas_1.GlobalFonts.registerFromPath(path_1.default.join(process.cwd(), mergedTextOptions.fontPath), (mergedTextOptions.fontName || 'customFont'));
115
+ }
116
+ (0, utils_1.drawText)(ctx, mergedTextOptions);
117
+ }
118
+ return canvas.toBuffer("image/png");
119
+ }
120
+ catch (error) {
121
+ console.error("Error loading existing image:", error);
122
+ throw new Error("Invalid image buffer");
123
+ }
124
+ }
125
+ async createCustom(options, buffer) {
126
+ try {
127
+ if (!Array.isArray(options)) {
128
+ options = [options];
129
+ }
130
+ let existingImage;
131
+ if (Buffer.isBuffer(buffer)) {
132
+ existingImage = await (0, canvas_1.loadImage)(buffer);
133
+ }
134
+ else if (buffer && buffer.buffer) {
135
+ existingImage = await (0, canvas_1.loadImage)(buffer.buffer);
136
+ }
137
+ else {
138
+ throw new Error('Invalid canvasBuffer provided. It should be a Buffer or CanvasResults object with a buffer');
139
+ }
140
+ if (!existingImage) {
141
+ throw new Error('Unable to load image from buffer');
142
+ }
143
+ const canvas = (0, canvas_1.createCanvas)(existingImage.width, existingImage.height);
144
+ const ctx = canvas.getContext("2d");
145
+ ctx.drawImage(existingImage, 0, 0);
146
+ (0, utils_1.customLines)(ctx, options);
147
+ return canvas.toBuffer("image/png");
148
+ }
149
+ catch (error) {
150
+ console.error("Error creating custom image:", error);
151
+ throw new Error("Failed to create custom image");
152
+ }
153
+ }
154
+ async createGIF(gifFrames, options) {
155
+ async function resizeImage(image, targetWidth, targetHeight) {
156
+ const canvas = (0, canvas_1.createCanvas)(targetWidth, targetHeight);
157
+ const ctx = canvas.getContext("2d");
158
+ ctx.drawImage(image, 0, 0, targetWidth, targetHeight);
159
+ return canvas;
160
+ }
161
+ function createOutputStream(outputFile) {
162
+ return fs_1.default.createWriteStream(outputFile);
163
+ }
164
+ function createBufferStream() {
165
+ const bufferStream = new stream_1.PassThrough();
166
+ const chunks = [];
167
+ bufferStream.on('data', (chunk) => {
168
+ chunks.push(chunk);
169
+ });
170
+ return {
171
+ ...bufferStream,
172
+ getBuffer: function () {
173
+ return Buffer.concat(chunks);
174
+ }
175
+ };
176
+ }
177
+ function validateOptions(options) {
178
+ if (options.outputFormat === "file" && !options.outputFile) {
179
+ throw new Error("Output file path is required when using file output format.");
180
+ }
181
+ if (options.repeat !== undefined && (typeof options.repeat !== "number" || options.repeat < 0)) {
182
+ throw new Error("Repeat must be a non-negative number or undefined.");
183
+ }
184
+ if (options.quality !== undefined && (typeof options.quality !== "number" || options.quality < 1 || options.quality > 20)) {
185
+ throw new Error("Quality must be a number between 1 and 20 or undefined.");
186
+ }
187
+ if (options.watermark && typeof options.watermark.enable !== "boolean") {
188
+ throw new Error("Watermark must be a boolean or undefined.");
189
+ }
190
+ if (options.textOverlay) {
191
+ const textOptions = options.textOverlay;
192
+ if (!textOptions.text || typeof textOptions.text !== "string") {
193
+ throw new Error("Text overlay text is required and must be a string.");
194
+ }
195
+ if (textOptions.fontSize !== undefined && (!Number.isInteger(textOptions.fontSize) || textOptions.fontSize <= 0)) {
196
+ throw new Error("Text overlay fontSize must be a positive integer or undefined.");
197
+ }
198
+ if (textOptions.fontColor !== undefined && typeof textOptions.fontColor !== "string") {
199
+ throw new Error("Text overlay fontColor must be a string or undefined.");
200
+ }
201
+ }
202
+ }
203
+ try {
204
+ validateOptions(options);
205
+ const canvasWidth = options.width || 1200;
206
+ const canvasHeight = options.height || 1200;
207
+ const encoder = new gifencoder_1.default(canvasWidth, canvasHeight);
208
+ const outputStream = options.outputFile ? createOutputStream(options.outputFile) : createBufferStream();
209
+ encoder.createReadStream().pipe(outputStream);
210
+ encoder.start();
211
+ encoder.setRepeat(options.repeat || 0);
212
+ encoder.setQuality(options.quality || 10);
213
+ const canvas = (0, canvas_1.createCanvas)(canvasWidth, canvasHeight);
214
+ const ctx = canvas.getContext("2d");
215
+ for (const frame of gifFrames) {
216
+ const image = await (0, canvas_1.loadImage)(frame.background);
217
+ const resizedImage = await resizeImage(image, canvasWidth, canvasHeight);
218
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
219
+ ctx.drawImage(resizedImage, 0, 0);
220
+ if (options.watermark?.enable) {
221
+ const watermark = await (0, canvas_1.loadImage)(options.watermark.url);
222
+ ctx.drawImage(watermark, 10, canvasHeight - watermark.height - 10);
223
+ }
224
+ if (options.textOverlay) {
225
+ ctx.font = `${options.textOverlay.fontSize || 20}px Arial`;
226
+ ctx.fillStyle = options.textOverlay.fontColor || "white";
227
+ ctx.fillText(options.textOverlay.text, options.textOverlay.x || 10, options.textOverlay.y || 30);
228
+ }
229
+ encoder.setDelay(frame.duration);
230
+ encoder.addFrame(ctx);
231
+ }
232
+ encoder.finish();
233
+ outputStream.end();
234
+ if (options.outputFormat === "file") {
235
+ await new Promise((resolve) => outputStream.on("finish", resolve));
236
+ }
237
+ else if (options.outputFormat === "base64") {
238
+ if ('getBuffer' in outputStream) {
239
+ return outputStream.getBuffer().toString("base64");
240
+ }
241
+ }
242
+ else if (options.outputFormat === "attachment") {
243
+ const gifStream = encoder.createReadStream();
244
+ return [{ attachment: gifStream, name: "gif.js" }];
245
+ }
246
+ else if (options.outputFormat === "buffer") {
247
+ if ('getBuffer' in outputStream) {
248
+ return outputStream.getBuffer();
249
+ }
250
+ }
251
+ else {
252
+ throw new Error("Invalid output format. Supported formats are 'file', 'base64', 'attachment', and 'buffer'.");
253
+ }
254
+ }
255
+ catch (e) {
256
+ console.error(e.message);
257
+ throw e;
258
+ }
259
+ }
260
+ async resize(resizeOptions) {
261
+ return (0, utils_1.resizingImg)(resizeOptions);
262
+ }
263
+ async imgConverter(source, newExtension) {
264
+ return (0, utils_1.converter)(source, newExtension);
265
+ }
266
+ async effects(source, filters) {
267
+ return (0, utils_1.imgEffects)(source, filters);
268
+ }
269
+ async colorsFilter(source, filterColor, opacity) {
270
+ return (0, utils_1.applyColorFilters)(source, filterColor, opacity);
271
+ }
272
+ async colorAnalysis(source) {
273
+ return (0, utils_1.detectColors)(source);
274
+ }
275
+ async colorsRemover(source, colorToRemove) {
276
+ return (0, utils_1.removeColor)(source, colorToRemove);
277
+ }
278
+ async removeBackground(imageURL, apiKey) {
279
+ return (0, utils_1.bgRemoval)(imageURL, apiKey);
280
+ }
281
+ async blend(layers, baseImageBuffer, defaultBlendMode = 'source-over') {
282
+ try {
283
+ const baseImage = await (0, canvas_1.loadImage)(baseImageBuffer);
284
+ const canvas = (0, canvas_1.createCanvas)(baseImage.width, baseImage.height);
285
+ const ctx = canvas.getContext('2d');
286
+ ctx.globalCompositeOperation = defaultBlendMode;
287
+ ctx.drawImage(baseImage, 0, 0);
288
+ for (const layer of layers) {
289
+ const layerImage = await (0, canvas_1.loadImage)(layer.image);
290
+ ctx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1.0;
291
+ ctx.globalCompositeOperation = layer.blendMode;
292
+ ctx.drawImage(layerImage, layer.position?.x || 0, layer.position?.y || 0);
293
+ }
294
+ ctx.globalAlpha = 1.0;
295
+ ctx.globalCompositeOperation = defaultBlendMode; // Reset to user-defined default
296
+ return canvas.toBuffer('image/png');
297
+ }
298
+ catch (error) {
299
+ console.error('Error creating layered composition:', error);
300
+ throw new Error('Failed to create layered composition');
301
+ }
302
+ }
303
+ async createChart(data, type) {
304
+ if (!data || Object.keys(data).length === 0) {
305
+ throw new Error('You need to provide datasets to create charts.');
306
+ }
307
+ if (!type || !type.chartNumber || !type.chartType) {
308
+ throw new Error('Type arguments are missing.');
309
+ }
310
+ const { chartType, chartNumber } = type;
311
+ switch (chartType.toLowerCase()) {
312
+ case 'bar':
313
+ switch (chartNumber) {
314
+ case 1:
315
+ return await (0, utils_1.verticalBarChart)(data);
316
+ case 2:
317
+ throw new Error('Type 2 is still under development.');
318
+ default:
319
+ throw new Error('Invalid chart number for chart type "bar".');
320
+ }
321
+ case 'line':
322
+ switch (chartNumber) {
323
+ case 1:
324
+ return await (0, utils_1.lineChart)(data);
325
+ case 2:
326
+ throw new Error('Type 2 is still under development.');
327
+ default:
328
+ throw new Error('Invalid chart number for chart type "line".');
329
+ }
330
+ case 'pie':
331
+ switch (chartNumber) {
332
+ case 1:
333
+ return await (0, utils_1.pieChart)(data);
334
+ case 2:
335
+ throw new Error('Type 2 is still under development.');
336
+ default:
337
+ throw new Error('Invalid chart number for chart type "pie".');
338
+ }
339
+ default:
340
+ throw new Error(`Unsupported chart type "${chartType}".`);
341
+ }
342
+ }
343
+ async cropImage(options) {
344
+ try {
345
+ if (!options.imageSource)
346
+ throw new Error('The "imageSource" option is needed. Please provide the path to the image to crop.');
347
+ if (!options.coordinates || options.coordinates.length < 3)
348
+ throw new Error('The "coordinates" option is needed. Please provide coordinates to crop the image.');
349
+ if (options.crop === 'outer') {
350
+ return await (0, utils_1.cropOuter)(options);
351
+ }
352
+ else if (options.crop === 'inner') {
353
+ return await (0, utils_1.cropInner)(options);
354
+ }
355
+ else {
356
+ throw new Error('Invalid crop option. Please specify "inner" or "outer".');
357
+ }
358
+ }
359
+ catch (error) {
360
+ console.error('An error occurred:', error);
361
+ throw error;
362
+ }
363
+ }
364
+ async drawImage(ctx, image) {
365
+ const { source, x, y, width, height, rotation = 0, borderRadius = 0, stroke, shadow, isFilled, color, gradient, borderPosition = 'all', opacity, perspective, blur = 0, zoom, filling } = image;
366
+ if (perspective)
367
+ throw new Error("`perspective` Feature is under construction. Please refrain from using it.");
368
+ if (!source || typeof x !== 'number' || typeof y !== 'number' || typeof width !== 'number' || typeof height !== 'number') {
369
+ throw new Error('Invalid image properties: source, x, y, width, and height are required.');
370
+ }
371
+ const shapeNames = ['circle', 'square', 'triangle', 'pentagon', 'hexagon', 'heptagon', 'octagon', 'star', 'kite', 'arrow', 'star', 'oval', 'heart', 'diamond', 'trapezoid', 'cloud'];
372
+ const isShape = shapeNames.includes(source.toLowerCase());
373
+ if (isShape) {
374
+ (0, utils_1.drawShape)(ctx, { source, x, y, width, height, opacity, rotation, borderRadius, stroke, shadow, isFilled, color, gradient, borderPosition, filling });
375
+ return;
376
+ }
377
+ let loadedImage;
378
+ try {
379
+ if (source.startsWith('http')) {
380
+ loadedImage = await (0, canvas_1.loadImage)(source);
381
+ }
382
+ else {
383
+ const imagePath = path_1.default.resolve(process.cwd(), source);
384
+ loadedImage = await (0, canvas_1.loadImage)(imagePath);
385
+ }
386
+ }
387
+ catch (e) {
388
+ throw new Error(`Error loading image: ${e.message}`);
389
+ }
390
+ if (!loadedImage) {
391
+ throw new Error('Invalid image source or failed to load image');
392
+ }
393
+ ctx.save();
394
+ const scale = zoom?.scale ?? 1;
395
+ const focusX = zoom?.x ?? 0.5;
396
+ const focusY = zoom?.y ?? 0.5;
397
+ if (scale !== 1) {
398
+ ctx.translate(focusX, focusY);
399
+ ctx.scale(scale, scale);
400
+ }
401
+ if (opacity !== undefined) {
402
+ ctx.globalAlpha = opacity;
403
+ }
404
+ if (blur > 0) {
405
+ ctx.filter = `blur(${blur}px)`;
406
+ }
407
+ (0, utils_1.applyRotation)(ctx, rotation, x, y, width, height);
408
+ (0, utils_1.applyShadow)(ctx, shadow, x, y, width, height);
409
+ if (perspective) {
410
+ throw new Error('Under construction');
411
+ }
412
+ (0, utils_1.imageRadius)(ctx, loadedImage, x, y, width, height, borderRadius, borderPosition);
413
+ ctx.globalAlpha = 1.0;
414
+ if (stroke?.opacity)
415
+ ctx.globalAlpha = stroke.opacity;
416
+ (0, utils_1.applyStroke)(ctx, stroke, x, y, width, height, undefined);
417
+ ctx.globalAlpha = 1.0;
418
+ ctx.restore();
419
+ }
420
+ async extractFrames(videoSource, options) {
421
+ const frames = [];
422
+ const frameDir = path_1.default.join(__dirname, 'frames');
423
+ if (!fs_1.default.existsSync(frameDir)) {
424
+ fs_1.default.mkdirSync(frameDir);
425
+ }
426
+ const videoPath = typeof videoSource === 'string' ? videoSource : path_1.default.join(frameDir, 'temp-video.mp4');
427
+ if (Buffer.isBuffer(videoSource)) {
428
+ fs_1.default.writeFileSync(videoPath, videoSource);
429
+ }
430
+ else if (videoSource.startsWith('http')) {
431
+ await (0, axios_1.default)({
432
+ method: 'get',
433
+ url: videoSource,
434
+ responseType: 'arraybuffer'
435
+ })
436
+ .then((response) => {
437
+ fs_1.default.writeFileSync(videoPath, response.data);
438
+ })
439
+ .catch(err => {
440
+ throw new Error(`Error downloading video: ${err.message}`);
441
+ });
442
+ }
443
+ else if (!fs_1.default.existsSync(videoPath)) {
444
+ throw new Error("Video file not found at specified path.");
445
+ }
446
+ function processVideoExtraction(videoPath, frames, options, resolve, reject) {
447
+ const outputFormat = options.outputFormat || 'jpg';
448
+ const outputFileTemplate = `frame-%03d.${outputFormat}`;
449
+ (0, fluent_ffmpeg_1.default)(videoPath)
450
+ .on('end', () => {
451
+ console.log('Frames extracted successfully.');
452
+ resolve(frames);
453
+ })
454
+ .on('error', (err) => {
455
+ console.error('Error extracting frames:', err.message);
456
+ reject(err);
457
+ })
458
+ .outputOptions([`-vf fps=1/${options.interval / 1000}`, `-q:v 2`])
459
+ .saveToFile(path_1.default.join(frameDir, outputFileTemplate));
460
+ fluent_ffmpeg_1.default.ffprobe(videoPath, (err, metadata) => {
461
+ if (err) {
462
+ return reject(err);
463
+ }
464
+ const duration = metadata?.format?.duration;
465
+ if (duration === undefined) {
466
+ return reject(new Error("Video duration not found in metadata."));
467
+ }
468
+ const totalFrames = Math.floor(duration * 1000 / options.interval);
469
+ for (let i = 0; i < totalFrames; i++) {
470
+ if (options.frameSelection && (i < (options.frameSelection.start || 0) || i > (options.frameSelection.end || totalFrames - 1))) {
471
+ continue;
472
+ }
473
+ frames.push({
474
+ source: path_1.default.join(frameDir, `frame-${String(i).padStart(3, '0')}.${outputFormat}`),
475
+ isRemote: false
476
+ });
477
+ }
478
+ });
479
+ }
480
+ return new Promise((resolve, reject) => {
481
+ processVideoExtraction(videoPath, frames, options, resolve, reject);
482
+ });
483
+ }
484
+ /**
485
+ * Sets a pattern on a specific area of a buffered image.
486
+ * @param {Buffer} buffer - The source image buffer.
487
+ * @param {Object} options - Options to customize the pattern.
488
+ * @returns {Promise<Buffer>} - The adjusted image buffer.
489
+ */
490
+ async patterns(buffer, options) {
491
+ const img = await (0, canvas_1.loadImage)(buffer);
492
+ const canvas = (0, canvas_1.createCanvas)(img.width, img.height);
493
+ const ctx = canvas.getContext('2d');
494
+ ctx.drawImage(img, 0, 0);
495
+ const x = options.x || 0;
496
+ const y = options.y || 0;
497
+ const width = options.width || img.width;
498
+ const height = options.height || img.height;
499
+ ctx.save();
500
+ ctx.beginPath();
501
+ ctx.rect(x, y, width, height);
502
+ ctx.clip();
503
+ if (options.gradient) {
504
+ await this.fillWithGradient(ctx, width, height, options.gradient, x, y);
505
+ }
506
+ else if (options.backgroundColor) {
507
+ ctx.fillStyle = options.backgroundColor;
508
+ ctx.fillRect(x, y, width, height);
509
+ }
510
+ switch (options.type) {
511
+ case 'dots':
512
+ await this.drawDotsPattern(ctx, width, height, options, x, y);
513
+ break;
514
+ case 'stripes':
515
+ await this.drawStripesPattern(ctx, width, height, options, x, y);
516
+ break;
517
+ case 'grid':
518
+ await this.drawGridPattern(ctx, width, height, options, x, y);
519
+ break;
520
+ case 'checkerboard':
521
+ await this.drawCheckerboardPattern(ctx, width, height, options, x, y);
522
+ break;
523
+ case 'custom':
524
+ await this.drawCustomPattern(ctx, width, height, options, x, y);
525
+ break;
526
+ case 'noise':
527
+ await this.drawNoisePattern(ctx, width, height, x, y);
528
+ break;
529
+ case 'waves':
530
+ await this.drawWavePattern(ctx, width, height, options, x, y);
531
+ break;
532
+ case 'diagonal-checkerboard':
533
+ await this.drawDiagonalCheckerboardPattern(ctx, width, height, options, x, y);
534
+ break;
535
+ default:
536
+ throw new Error('Invalid pattern type specified.');
537
+ }
538
+ ctx.restore();
539
+ return canvas.toBuffer('image/png');
540
+ }
541
+ /**
542
+ * Fills the specified area with a gradient.
543
+ * @param ctx The rendering context of the canvas.
544
+ * @param width The width of the area to fill.
545
+ * @param height The height of the area to fill.
546
+ * @param gradient The gradient options.
547
+ * @param x The x offset of the area.
548
+ * @param y The y offset of the area.
549
+ */
550
+ async fillWithGradient(ctx, width, height, gradient, x = 0, y = 0) {
551
+ let grad;
552
+ if (gradient.type === 'linear') {
553
+ grad = ctx.createLinearGradient((gradient.startX || 0) + x, (gradient.startY || 0) + y, (gradient.endX || width) + x, (gradient.endY || height) + y);
554
+ }
555
+ else {
556
+ grad = ctx.createRadialGradient((gradient.startX || width / 2) + x, (gradient.startY || height / 2) + y, gradient.startRadius || 0, (gradient.endX || width / 2) + x, (gradient.endY || height / 2) + y, gradient.endRadius || Math.max(width, height));
557
+ }
558
+ gradient.colors.forEach((stop) => {
559
+ grad.addColorStop(stop.stop, stop.color);
560
+ });
561
+ ctx.fillStyle = grad;
562
+ ctx.fillRect(x, y, width, height);
563
+ }
564
+ /**
565
+ * Draws a dots pattern in the specified area.
566
+ * @param ctx The rendering context of the canvas.
567
+ * @param width The width of the area.
568
+ * @param height The height of the area.
569
+ * @param options Options to customize the dot pattern.
570
+ * @param x The x offset of the area.
571
+ * @param y The y offset of the area.
572
+ */
573
+ async drawDotsPattern(ctx, width, height, options, x = 0, y = 0) {
574
+ const color = options.color || 'black';
575
+ const radius = options.size || 5;
576
+ const spacing = options.spacing || 10;
577
+ ctx.fillStyle = color;
578
+ for (let posY = y; posY < y + height; posY += spacing) {
579
+ for (let posX = x; posX < x + width; posX += spacing) {
580
+ ctx.beginPath();
581
+ ctx.arc(posX, posY, radius, 0, Math.PI * 2);
582
+ ctx.fill();
583
+ }
584
+ }
585
+ }
586
+ /**
587
+ * Draws a stripes pattern in the specified area.
588
+ * @param ctx The rendering context of the canvas.
589
+ * @param width The width of the area.
590
+ * @param height The height of the area.
591
+ * @param options Options to customize the stripes pattern.
592
+ * @param x The x offset of the area.
593
+ * @param y The y offset of the area.
594
+ */
595
+ async drawStripesPattern(ctx, width, height, options, x = 0, y = 0) {
596
+ const color = options.color || 'black';
597
+ const stripeWidth = options.size || 10;
598
+ const spacing = options.spacing || 20;
599
+ const angle = options.angle || 0;
600
+ ctx.fillStyle = color;
601
+ ctx.save();
602
+ ctx.translate(x + width / 2, y + height / 2);
603
+ ctx.rotate((angle * Math.PI) / 180);
604
+ ctx.translate(-width / 2, -height / 2);
605
+ for (let posX = 0; posX < width; posX += stripeWidth + spacing) {
606
+ ctx.fillRect(posX, 0, stripeWidth, height);
607
+ }
608
+ ctx.restore();
609
+ }
610
+ /**
611
+ * Draws a grid pattern in the specified area.
612
+ * @param ctx The rendering context of the canvas.
613
+ * @param width The width of the area.
614
+ * @param height The height of the area.
615
+ * @param options Options to customize the grid pattern.
616
+ * @param x The x offset of the area.
617
+ * @param y The y offset of the area.
618
+ */
619
+ async drawGridPattern(ctx, width, height, options, x = 0, y = 0) {
620
+ const color = options.color || 'black';
621
+ const size = options.size || 20;
622
+ ctx.strokeStyle = color;
623
+ ctx.lineWidth = 1;
624
+ for (let posX = x; posX <= x + width; posX += size) {
625
+ ctx.beginPath();
626
+ ctx.moveTo(posX, y);
627
+ ctx.lineTo(posX, y + height);
628
+ ctx.stroke();
629
+ }
630
+ for (let posY = y; posY <= y + height; posY += size) {
631
+ ctx.beginPath();
632
+ ctx.moveTo(x, posY);
633
+ ctx.lineTo(x + width, posY);
634
+ ctx.stroke();
635
+ }
636
+ }
637
+ /**
638
+ * Draws a checkerboard pattern in the specified area.
639
+ * @param ctx The rendering context of the canvas.
640
+ * @param width The width of the area.
641
+ * @param height The height of the area.
642
+ * @param options Options to customize the checkerboard pattern.
643
+ * @param x The x offset of the area.
644
+ * @param y The y offset of the area.
645
+ */
646
+ async drawCheckerboardPattern(ctx, width, height, options, x = 0, y = 0) {
647
+ const color1 = options.color || 'black';
648
+ const color2 = options.secondaryColor || 'white';
649
+ const size = options.size || 20;
650
+ for (let posY = y; posY < y + height; posY += size) {
651
+ for (let posX = x; posX < x + width; posX += size) {
652
+ ctx.fillStyle = (Math.floor(posX / size) + Math.floor(posY / size)) % 2 === 0 ? color1 : color2;
653
+ ctx.fillRect(posX, posY, size, size);
654
+ }
655
+ }
656
+ }
657
+ /**
658
+ * Draws a custom image pattern in the specified area.
659
+ * @param ctx The rendering context of the canvas.
660
+ * @param width The width of the area.
661
+ * @param height The height of the area.
662
+ * @param options Options to customize the custom pattern.
663
+ * @param x The x offset of the area.
664
+ * @param y The y offset of the area.
665
+ */
666
+ async drawCustomPattern(ctx, width, height, options, x = 0, y = 0) {
667
+ if (!options.customPatternImage) {
668
+ throw new Error('Custom pattern image path is required for custom patterns.');
669
+ }
670
+ const patternImage = await (0, canvas_1.loadImage)(options.customPatternImage);
671
+ const pattern = ctx.createPattern(patternImage, 'repeat');
672
+ ctx.fillStyle = pattern;
673
+ ctx.translate(x, y);
674
+ ctx.fillRect(0, 0, width, height);
675
+ ctx.resetTransform();
676
+ }
677
+ async drawWavePattern(ctx, width, height, options, x = 0, y = 0) {
678
+ const color = options.color || 'black';
679
+ const waveHeight = options.size || 10;
680
+ const frequency = options.spacing || 20;
681
+ ctx.strokeStyle = color;
682
+ ctx.lineWidth = 2;
683
+ for (let posY = y; posY < y + height; posY += frequency) {
684
+ ctx.beginPath();
685
+ for (let posX = x; posX < x + width; posX += 5) {
686
+ const waveY = posY + Math.sin(posX / frequency) * waveHeight;
687
+ ctx.lineTo(posX, waveY);
688
+ }
689
+ ctx.stroke();
690
+ }
691
+ }
692
+ async drawNoisePattern(ctx, width, height, x = 0, y = 0) {
693
+ const imageData = ctx.createImageData(width, height);
694
+ const data = imageData.data;
695
+ for (let i = 0; i < data.length; i += 4) {
696
+ const gray = Math.random() * 255;
697
+ data[i] = gray;
698
+ data[i + 1] = gray;
699
+ data[i + 2] = gray;
700
+ data[i + 3] = Math.random() * 255;
701
+ }
702
+ ctx.putImageData(imageData, x, y);
703
+ }
704
+ async drawDiagonalCheckerboardPattern(ctx, width, height, options, x = 0, y = 0) {
705
+ const color1 = options.color || 'black';
706
+ const color2 = options.secondaryColor || 'white';
707
+ const size = options.size || 20;
708
+ ctx.save();
709
+ ctx.translate(x + width / 2, y + height / 2);
710
+ ctx.rotate(Math.PI / 4);
711
+ ctx.translate(-width / 2, -height / 2);
712
+ for (let posY = 0; posY < height; posY += size) {
713
+ for (let posX = 0; posX < width; posX += size) {
714
+ ctx.fillStyle = (Math.floor(posX / size) + Math.floor(posY / size)) % 2 === 0 ? color1 : color2;
715
+ ctx.fillRect(posX, posY, size, size);
716
+ }
717
+ }
718
+ ctx.restore();
719
+ }
720
+ async masking(source, maskSource, options = { type: "alpha" }) {
721
+ const img = await (0, canvas_1.loadImage)(source);
722
+ const mask = await (0, canvas_1.loadImage)(maskSource);
723
+ const canvas = (0, canvas_1.createCanvas)(img.width, img.height);
724
+ const ctx = canvas.getContext("2d");
725
+ ctx.drawImage(img, 0, 0, img.width, img.height);
726
+ const maskCanvas = (0, canvas_1.createCanvas)(img.width, img.height);
727
+ const maskCtx = maskCanvas.getContext("2d");
728
+ maskCtx.drawImage(mask, 0, 0, img.width, img.height);
729
+ const maskData = maskCtx.getImageData(0, 0, img.width, img.height);
730
+ const imgData = ctx.getImageData(0, 0, img.width, img.height);
731
+ for (let i = 0; i < maskData.data.length; i += 4) {
732
+ let alphaValue = 255;
733
+ if (options.type === "grayscale") {
734
+ const grayscale = maskData.data[i] * 0.3 + maskData.data[i + 1] * 0.59 + maskData.data[i + 2] * 0.11;
735
+ alphaValue = grayscale >= (options.threshold ?? 128) ? 255 : 0;
736
+ }
737
+ else if (options.type === "alpha") {
738
+ alphaValue = maskData.data[i + 3];
739
+ }
740
+ else if (options.type === "color" && options.colorKey) {
741
+ const colorMatch = maskData.data[i] === parseInt(options.colorKey.slice(1, 3), 16) &&
742
+ maskData.data[i + 1] === parseInt(options.colorKey.slice(3, 5), 16) &&
743
+ maskData.data[i + 2] === parseInt(options.colorKey.slice(5, 7), 16);
744
+ alphaValue = colorMatch ? 0 : 255;
745
+ }
746
+ if (options.invert)
747
+ alphaValue = 255 - alphaValue;
748
+ imgData.data[i + 3] = alphaValue;
749
+ }
750
+ ctx.putImageData(imgData, 0, 0);
751
+ return canvas.toBuffer("image/png");
752
+ }
753
+ async gradientBlend(source, options) {
754
+ const img = await (0, canvas_1.loadImage)(source);
755
+ const canvas = (0, canvas_1.createCanvas)(img.width, img.height);
756
+ const ctx = canvas.getContext("2d");
757
+ ctx.drawImage(img, 0, 0, img.width, img.height);
758
+ let gradient;
759
+ if (options.type === "linear") {
760
+ const angle = options.angle ?? 0;
761
+ const radians = (angle * Math.PI) / 180;
762
+ const x1 = img.width / 2 - (Math.cos(radians) * img.width) / 2;
763
+ const y1 = img.height / 2 - (Math.sin(radians) * img.height) / 2;
764
+ const x2 = img.width / 2 + (Math.cos(radians) * img.width) / 2;
765
+ const y2 = img.height / 2 + (Math.sin(radians) * img.height) / 2;
766
+ gradient = ctx.createLinearGradient(x1, y1, x2, y2);
767
+ }
768
+ else if (options.type === "radial") {
769
+ gradient = ctx.createRadialGradient(img.width / 2, img.height / 2, 0, img.width / 2, img.height / 2, Math.max(img.width, img.height));
770
+ }
771
+ else {
772
+ gradient = ctx.createConicGradient(Math.PI, img.width / 2, img.height / 2);
773
+ }
774
+ options.colors.forEach(({ stop, color }) => gradient.addColorStop(stop, color));
775
+ ctx.fillStyle = gradient;
776
+ ctx.globalCompositeOperation = options.blendMode ?? "multiply";
777
+ ctx.fillRect(0, 0, img.width, img.height);
778
+ if (options.maskSource) {
779
+ const mask = await (0, canvas_1.loadImage)(options.maskSource);
780
+ ctx.globalCompositeOperation = "destination-in";
781
+ ctx.drawImage(mask, 0, 0, img.width, img.height);
782
+ }
783
+ ctx.globalCompositeOperation = "source-over";
784
+ return canvas.toBuffer("image/png");
785
+ }
786
+ async animate(frames, defaultDuration, defaultWidth = 800, defaultHeight = 600, options) {
787
+ const buffers = [];
788
+ const isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
789
+ if (options?.onStart)
790
+ options.onStart();
791
+ let encoder = null;
792
+ let gifStream = null;
793
+ if (options?.gif) {
794
+ if (!options.gifPath) {
795
+ throw new Error("GIF generation enabled but no gifPath provided.");
796
+ }
797
+ encoder = new gifencoder_1.default(defaultWidth, defaultHeight);
798
+ gifStream = fs_1.default.createWriteStream(options.gifPath);
799
+ encoder.createReadStream().pipe(gifStream);
800
+ encoder.start();
801
+ encoder.setRepeat(0);
802
+ encoder.setQuality(10);
803
+ }
804
+ for (let i = 0; i < frames.length; i++) {
805
+ const frame = frames[i];
806
+ const width = frame.width || defaultWidth;
807
+ const height = frame.height || defaultHeight;
808
+ const canvas = (0, canvas_1.createCanvas)(width, height);
809
+ const ctx = canvas.getContext('2d');
810
+ if (!isNode) {
811
+ canvas.width = width;
812
+ canvas.height = height;
813
+ document.body.appendChild(canvas);
814
+ }
815
+ ctx.clearRect(0, 0, width, height);
816
+ if (frame.transformations) {
817
+ const { scaleX = 1, scaleY = 1, rotate = 0, translateX = 0, translateY = 0 } = frame.transformations;
818
+ ctx.save();
819
+ ctx.translate(translateX, translateY);
820
+ ctx.rotate((rotate * Math.PI) / 180);
821
+ ctx.scale(scaleX, scaleY);
822
+ }
823
+ let fillStyle = null;
824
+ if (frame.gradient) {
825
+ const { type, startX, startY, endX, endY, startRadius, endRadius, colors } = frame.gradient;
826
+ let gradient = null;
827
+ if (type === 'linear') {
828
+ gradient = ctx.createLinearGradient(startX || 0, startY || 0, endX || width, endY || height);
829
+ }
830
+ else if (type === 'radial') {
831
+ gradient = ctx.createRadialGradient(startX || width / 2, startY || height / 2, startRadius || 0, endX || width / 2, endY || height / 2, endRadius || Math.max(width, height));
832
+ }
833
+ colors.forEach((colorStop) => {
834
+ if (gradient)
835
+ gradient.addColorStop(colorStop.stop, colorStop.color);
836
+ });
837
+ fillStyle = gradient;
838
+ }
839
+ if (frame.pattern) {
840
+ const patternImage = await (0, canvas_1.loadImage)(frame.pattern.source);
841
+ const pattern = ctx.createPattern(patternImage, frame.pattern.repeat || 'repeat');
842
+ fillStyle = pattern;
843
+ }
844
+ if (!fillStyle && frame.backgroundColor) {
845
+ fillStyle = frame.backgroundColor;
846
+ }
847
+ if (fillStyle) {
848
+ ctx.fillStyle = fillStyle;
849
+ ctx.fillRect(0, 0, width, height);
850
+ }
851
+ if (frame.source) {
852
+ const image = await (0, canvas_1.loadImage)(frame.source);
853
+ ctx.globalCompositeOperation = frame.blendMode || 'source-over';
854
+ ctx.drawImage(image, 0, 0, width, height);
855
+ }
856
+ if (frame.onDrawCustom) {
857
+ frame.onDrawCustom(ctx, canvas);
858
+ }
859
+ if (frame.transformations) {
860
+ ctx.restore();
861
+ }
862
+ const buffer = canvas.toBuffer('image/png');
863
+ buffers.push(buffer);
864
+ if (encoder) {
865
+ const frameDuration = frame.duration || defaultDuration;
866
+ encoder.setDelay(frameDuration);
867
+ encoder.addFrame(ctx);
868
+ }
869
+ if (options?.onFrame)
870
+ options.onFrame(i);
871
+ await new Promise(resolve => setTimeout(resolve, frame.duration || defaultDuration));
872
+ }
873
+ if (encoder) {
874
+ encoder.finish();
875
+ }
876
+ if (options?.onEnd)
877
+ options.onEnd();
878
+ return options?.gif ? undefined : buffers;
879
+ }
880
+ validHex(hexColor) {
881
+ const hexPattern = /^#[0-9a-fA-F]{6}$/;
882
+ if (!hexPattern.test(hexColor)) {
883
+ throw new Error("Invalid hexadecimal color format. It should be in the format '#RRGGBB'.");
884
+ }
885
+ return true;
886
+ }
887
+ async outPut(results) {
888
+ const formatType = this.format?.type || 'buffer';
889
+ switch (formatType) {
890
+ case 'buffer':
891
+ return results;
892
+ case 'url':
893
+ return await (0, utils_1.url)(results);
894
+ case 'dataURL':
895
+ return (0, utils_1.dataURL)(results);
896
+ case 'blob':
897
+ return (0, utils_1.blob)(results);
898
+ case 'base64':
899
+ return (0, utils_1.base64)(results);
900
+ case 'arraybuffer':
901
+ return (0, utils_1.arrayBuffer)(results);
902
+ default:
903
+ throw new Error('Unsupported format');
904
+ }
905
+ }
906
+ }
907
+ exports.ApexPainter = ApexPainter;
908
+ //# sourceMappingURL=ApexPainter.js.map