apexify.js 4.7.95 → 4.8.0

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 (187) hide show
  1. package/dist/cjs/ai/ApexAI.d.ts.map +1 -1
  2. package/dist/cjs/ai/ApexAI.js +42 -23
  3. package/dist/cjs/ai/ApexAI.js.map +1 -1
  4. package/dist/cjs/ai/ApexModules.d.ts.map +1 -1
  5. package/dist/cjs/ai/ApexModules.js +35 -21
  6. package/dist/cjs/ai/ApexModules.js.map +1 -1
  7. package/dist/cjs/ai/buttons/tools.js +8 -8
  8. package/dist/cjs/ai/buttons/tools.js.map +1 -1
  9. package/dist/cjs/ai/functions/tokenizer.d.ts +10 -0
  10. package/dist/cjs/ai/functions/tokenizer.d.ts.map +1 -0
  11. package/dist/cjs/ai/functions/tokenizer.js +64 -0
  12. package/dist/cjs/ai/functions/tokenizer.js.map +1 -0
  13. package/dist/cjs/ai/modals/electronHub/chatmodels.d.ts.map +1 -0
  14. package/dist/cjs/ai/{modals-chat → modals}/electronHub/chatmodels.js +8 -11
  15. package/dist/cjs/ai/modals/electronHub/chatmodels.js.map +1 -0
  16. package/dist/cjs/ai/modals/electronHub/imageModels.d.ts.map +1 -0
  17. package/dist/cjs/ai/{modals-chat → modals}/electronHub/imageModels.js +9 -5
  18. package/dist/cjs/ai/modals/electronHub/imageModels.js.map +1 -0
  19. package/dist/cjs/ai/modals/electronHub/songModels.d.ts.map +1 -0
  20. package/dist/cjs/ai/modals/electronHub/songModels.js.map +1 -0
  21. package/dist/cjs/ai/modals/electronHub/speechModels.d.ts.map +1 -0
  22. package/dist/cjs/ai/{modals-chat → modals}/electronHub/speechModels.js +4 -1
  23. package/dist/cjs/ai/modals/electronHub/speechModels.js.map +1 -0
  24. package/dist/cjs/ai/modals/electronHub/videoModels.d.ts.map +1 -0
  25. package/dist/cjs/ai/modals/electronHub/videoModels.js.map +1 -0
  26. package/dist/cjs/ai/modals/groq/chatgroq.d.ts.map +1 -0
  27. package/dist/cjs/ai/modals/groq/chatgroq.js.map +1 -0
  28. package/dist/cjs/ai/modals/groq/imageAnalyzer.d.ts.map +1 -0
  29. package/dist/cjs/ai/modals/groq/imageAnalyzer.js.map +1 -0
  30. package/dist/cjs/ai/modals/groq/whisper.d.ts.map +1 -0
  31. package/dist/cjs/ai/{modals-chat → modals}/groq/whisper.js +34 -33
  32. package/dist/cjs/ai/modals/groq/whisper.js.map +1 -0
  33. package/dist/cjs/ai/modals/hercai/chatModels.d.ts.map +1 -0
  34. package/dist/cjs/ai/modals/hercai/chatModels.js.map +1 -0
  35. package/dist/cjs/ai/utils.d.ts +1 -1
  36. package/dist/cjs/ai/utils.d.ts.map +1 -1
  37. package/dist/cjs/ai/utils.js +1 -1
  38. package/dist/cjs/ai/utils.js.map +1 -1
  39. package/dist/cjs/canvas/ApexPainter.d.ts +20 -15
  40. package/dist/cjs/canvas/ApexPainter.d.ts.map +1 -1
  41. package/dist/cjs/canvas/ApexPainter.js +143 -23
  42. package/dist/cjs/canvas/ApexPainter.js.map +1 -1
  43. package/dist/cjs/canvas/utils/Image/imageProperties.d.ts.map +1 -1
  44. package/dist/cjs/canvas/utils/Image/imageProperties.js +47 -24
  45. package/dist/cjs/canvas/utils/Image/imageProperties.js.map +1 -1
  46. package/dist/cjs/canvas/utils/types.d.ts +21 -12
  47. package/dist/cjs/canvas/utils/types.d.ts.map +1 -1
  48. package/dist/cjs/canvas/utils/types.js.map +1 -1
  49. package/dist/cjs/canvas/utils/utils.d.ts +2 -2
  50. package/dist/cjs/canvas/utils/utils.d.ts.map +1 -1
  51. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  52. package/dist/esm/ai/ApexAI.d.ts.map +1 -1
  53. package/dist/esm/ai/ApexAI.js +42 -23
  54. package/dist/esm/ai/ApexAI.js.map +1 -1
  55. package/dist/esm/ai/ApexModules.d.ts.map +1 -1
  56. package/dist/esm/ai/ApexModules.js +35 -21
  57. package/dist/esm/ai/ApexModules.js.map +1 -1
  58. package/dist/esm/ai/buttons/tools.js +8 -8
  59. package/dist/esm/ai/buttons/tools.js.map +1 -1
  60. package/dist/esm/ai/functions/tokenizer.d.ts +10 -0
  61. package/dist/esm/ai/functions/tokenizer.d.ts.map +1 -0
  62. package/dist/esm/ai/functions/tokenizer.js +64 -0
  63. package/dist/esm/ai/functions/tokenizer.js.map +1 -0
  64. package/dist/esm/ai/modals/electronHub/chatmodels.d.ts.map +1 -0
  65. package/dist/esm/ai/{modals-chat → modals}/electronHub/chatmodels.js +8 -11
  66. package/dist/esm/ai/modals/electronHub/chatmodels.js.map +1 -0
  67. package/dist/esm/ai/modals/electronHub/imageModels.d.ts.map +1 -0
  68. package/dist/esm/ai/{modals-chat → modals}/electronHub/imageModels.js +9 -5
  69. package/dist/esm/ai/modals/electronHub/imageModels.js.map +1 -0
  70. package/dist/esm/ai/modals/electronHub/songModels.d.ts.map +1 -0
  71. package/dist/esm/ai/modals/electronHub/songModels.js.map +1 -0
  72. package/dist/esm/ai/modals/electronHub/speechModels.d.ts.map +1 -0
  73. package/dist/esm/ai/{modals-chat → modals}/electronHub/speechModels.js +4 -1
  74. package/dist/esm/ai/modals/electronHub/speechModels.js.map +1 -0
  75. package/dist/esm/ai/modals/electronHub/videoModels.d.ts.map +1 -0
  76. package/dist/esm/ai/modals/electronHub/videoModels.js.map +1 -0
  77. package/dist/esm/ai/modals/groq/chatgroq.d.ts.map +1 -0
  78. package/dist/esm/ai/modals/groq/chatgroq.js.map +1 -0
  79. package/dist/esm/ai/modals/groq/imageAnalyzer.d.ts.map +1 -0
  80. package/dist/esm/ai/modals/groq/imageAnalyzer.js.map +1 -0
  81. package/dist/esm/ai/modals/groq/whisper.d.ts.map +1 -0
  82. package/dist/esm/ai/{modals-chat → modals}/groq/whisper.js +34 -33
  83. package/dist/esm/ai/modals/groq/whisper.js.map +1 -0
  84. package/dist/esm/ai/modals/hercai/chatModels.d.ts.map +1 -0
  85. package/dist/esm/ai/modals/hercai/chatModels.js.map +1 -0
  86. package/dist/esm/ai/utils.d.ts +1 -1
  87. package/dist/esm/ai/utils.d.ts.map +1 -1
  88. package/dist/esm/ai/utils.js +1 -1
  89. package/dist/esm/ai/utils.js.map +1 -1
  90. package/dist/esm/canvas/ApexPainter.d.ts +20 -15
  91. package/dist/esm/canvas/ApexPainter.d.ts.map +1 -1
  92. package/dist/esm/canvas/ApexPainter.js +143 -23
  93. package/dist/esm/canvas/ApexPainter.js.map +1 -1
  94. package/dist/esm/canvas/utils/Image/imageProperties.d.ts.map +1 -1
  95. package/dist/esm/canvas/utils/Image/imageProperties.js +47 -24
  96. package/dist/esm/canvas/utils/Image/imageProperties.js.map +1 -1
  97. package/dist/esm/canvas/utils/types.d.ts +21 -12
  98. package/dist/esm/canvas/utils/types.d.ts.map +1 -1
  99. package/dist/esm/canvas/utils/types.js.map +1 -1
  100. package/dist/esm/canvas/utils/utils.d.ts +2 -2
  101. package/dist/esm/canvas/utils/utils.d.ts.map +1 -1
  102. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  103. package/lib/ai/ApexAI.ts +69 -48
  104. package/lib/ai/ApexModules.ts +45 -33
  105. package/lib/ai/buttons/tools.ts +8 -8
  106. package/lib/ai/functions/tokenizer.ts +69 -0
  107. package/lib/ai/modals/electronHub/chatmodels.ts +57 -0
  108. package/lib/ai/{modals-chat → modals}/electronHub/imageModels.ts +17 -13
  109. package/lib/ai/{modals-chat → modals}/electronHub/speechModels.ts +5 -1
  110. package/lib/ai/modals/groq/whisper.ts +114 -0
  111. package/lib/ai/utils.ts +1 -1
  112. package/lib/canvas/ApexPainter.ts +214 -45
  113. package/lib/canvas/utils/Image/imageProperties.ts +67 -24
  114. package/lib/canvas/utils/types.ts +22 -14
  115. package/lib/canvas/utils/utils.ts +4 -2
  116. package/package.json +2 -2
  117. package/dist/cjs/ai/modals-chat/electronHub/chatmodels.d.ts.map +0 -1
  118. package/dist/cjs/ai/modals-chat/electronHub/chatmodels.js.map +0 -1
  119. package/dist/cjs/ai/modals-chat/electronHub/imageModels.d.ts.map +0 -1
  120. package/dist/cjs/ai/modals-chat/electronHub/imageModels.js.map +0 -1
  121. package/dist/cjs/ai/modals-chat/electronHub/songModels.d.ts.map +0 -1
  122. package/dist/cjs/ai/modals-chat/electronHub/songModels.js.map +0 -1
  123. package/dist/cjs/ai/modals-chat/electronHub/speechModels.d.ts.map +0 -1
  124. package/dist/cjs/ai/modals-chat/electronHub/speechModels.js.map +0 -1
  125. package/dist/cjs/ai/modals-chat/electronHub/videoModels.d.ts.map +0 -1
  126. package/dist/cjs/ai/modals-chat/electronHub/videoModels.js.map +0 -1
  127. package/dist/cjs/ai/modals-chat/groq/chatgroq.d.ts.map +0 -1
  128. package/dist/cjs/ai/modals-chat/groq/chatgroq.js.map +0 -1
  129. package/dist/cjs/ai/modals-chat/groq/imageAnalyzer.d.ts.map +0 -1
  130. package/dist/cjs/ai/modals-chat/groq/imageAnalyzer.js.map +0 -1
  131. package/dist/cjs/ai/modals-chat/groq/whisper.d.ts.map +0 -1
  132. package/dist/cjs/ai/modals-chat/groq/whisper.js.map +0 -1
  133. package/dist/cjs/ai/modals-chat/hercai/chatModels.d.ts.map +0 -1
  134. package/dist/cjs/ai/modals-chat/hercai/chatModels.js.map +0 -1
  135. package/dist/esm/ai/modals-chat/electronHub/chatmodels.d.ts.map +0 -1
  136. package/dist/esm/ai/modals-chat/electronHub/chatmodels.js.map +0 -1
  137. package/dist/esm/ai/modals-chat/electronHub/imageModels.d.ts.map +0 -1
  138. package/dist/esm/ai/modals-chat/electronHub/imageModels.js.map +0 -1
  139. package/dist/esm/ai/modals-chat/electronHub/songModels.d.ts.map +0 -1
  140. package/dist/esm/ai/modals-chat/electronHub/songModels.js.map +0 -1
  141. package/dist/esm/ai/modals-chat/electronHub/speechModels.d.ts.map +0 -1
  142. package/dist/esm/ai/modals-chat/electronHub/speechModels.js.map +0 -1
  143. package/dist/esm/ai/modals-chat/electronHub/videoModels.d.ts.map +0 -1
  144. package/dist/esm/ai/modals-chat/electronHub/videoModels.js.map +0 -1
  145. package/dist/esm/ai/modals-chat/groq/chatgroq.d.ts.map +0 -1
  146. package/dist/esm/ai/modals-chat/groq/chatgroq.js.map +0 -1
  147. package/dist/esm/ai/modals-chat/groq/imageAnalyzer.d.ts.map +0 -1
  148. package/dist/esm/ai/modals-chat/groq/imageAnalyzer.js.map +0 -1
  149. package/dist/esm/ai/modals-chat/groq/whisper.d.ts.map +0 -1
  150. package/dist/esm/ai/modals-chat/groq/whisper.js.map +0 -1
  151. package/dist/esm/ai/modals-chat/hercai/chatModels.d.ts.map +0 -1
  152. package/dist/esm/ai/modals-chat/hercai/chatModels.js.map +0 -1
  153. package/lib/ai/modals-chat/electronHub/chatmodels.ts +0 -64
  154. package/lib/ai/modals-chat/groq/whisper.ts +0 -113
  155. /package/dist/cjs/ai/{modals-chat → modals}/electronHub/chatmodels.d.ts +0 -0
  156. /package/dist/cjs/ai/{modals-chat → modals}/electronHub/imageModels.d.ts +0 -0
  157. /package/dist/cjs/ai/{modals-chat → modals}/electronHub/songModels.d.ts +0 -0
  158. /package/dist/cjs/ai/{modals-chat → modals}/electronHub/songModels.js +0 -0
  159. /package/dist/cjs/ai/{modals-chat → modals}/electronHub/speechModels.d.ts +0 -0
  160. /package/dist/cjs/ai/{modals-chat → modals}/electronHub/videoModels.d.ts +0 -0
  161. /package/dist/cjs/ai/{modals-chat → modals}/electronHub/videoModels.js +0 -0
  162. /package/dist/cjs/ai/{modals-chat → modals}/groq/chatgroq.d.ts +0 -0
  163. /package/dist/cjs/ai/{modals-chat → modals}/groq/chatgroq.js +0 -0
  164. /package/dist/cjs/ai/{modals-chat → modals}/groq/imageAnalyzer.d.ts +0 -0
  165. /package/dist/cjs/ai/{modals-chat → modals}/groq/imageAnalyzer.js +0 -0
  166. /package/dist/cjs/ai/{modals-chat → modals}/groq/whisper.d.ts +0 -0
  167. /package/dist/cjs/ai/{modals-chat → modals}/hercai/chatModels.d.ts +0 -0
  168. /package/dist/cjs/ai/{modals-chat → modals}/hercai/chatModels.js +0 -0
  169. /package/dist/esm/ai/{modals-chat → modals}/electronHub/chatmodels.d.ts +0 -0
  170. /package/dist/esm/ai/{modals-chat → modals}/electronHub/imageModels.d.ts +0 -0
  171. /package/dist/esm/ai/{modals-chat → modals}/electronHub/songModels.d.ts +0 -0
  172. /package/dist/esm/ai/{modals-chat → modals}/electronHub/songModels.js +0 -0
  173. /package/dist/esm/ai/{modals-chat → modals}/electronHub/speechModels.d.ts +0 -0
  174. /package/dist/esm/ai/{modals-chat → modals}/electronHub/videoModels.d.ts +0 -0
  175. /package/dist/esm/ai/{modals-chat → modals}/electronHub/videoModels.js +0 -0
  176. /package/dist/esm/ai/{modals-chat → modals}/groq/chatgroq.d.ts +0 -0
  177. /package/dist/esm/ai/{modals-chat → modals}/groq/chatgroq.js +0 -0
  178. /package/dist/esm/ai/{modals-chat → modals}/groq/imageAnalyzer.d.ts +0 -0
  179. /package/dist/esm/ai/{modals-chat → modals}/groq/imageAnalyzer.js +0 -0
  180. /package/dist/esm/ai/{modals-chat → modals}/groq/whisper.d.ts +0 -0
  181. /package/dist/esm/ai/{modals-chat → modals}/hercai/chatModels.d.ts +0 -0
  182. /package/dist/esm/ai/{modals-chat → modals}/hercai/chatModels.js +0 -0
  183. /package/lib/ai/{modals-chat → modals}/electronHub/songModels.ts +0 -0
  184. /package/lib/ai/{modals-chat → modals}/electronHub/videoModels.ts +0 -0
  185. /package/lib/ai/{modals-chat → modals}/groq/chatgroq.ts +0 -0
  186. /package/lib/ai/{modals-chat → modals}/groq/imageAnalyzer.ts +0 -0
  187. /package/lib/ai/{modals-chat → modals}/hercai/chatModels.ts +0 -0
@@ -0,0 +1,114 @@
1
+ import Groq from "groq-sdk";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import { URL } from "url";
5
+ import https from "https";
6
+
7
+ /**
8
+ * Gets the file size of a given path.
9
+ */
10
+ function getFileSize(filePath: string): number {
11
+ return fs.statSync(filePath).size;
12
+ }
13
+
14
+ /**
15
+ * Creates a readable stream from a local file or a remote URL.
16
+ */
17
+ async function createReadableStream(filepathOrUrl: string): Promise<{ stream: fs.ReadStream | null; tempFilePath?: string; error?: string }> {
18
+ const maxFileSizeBytes = 25 * 1024 * 1024; // 25MB limit
19
+
20
+ if (filepathOrUrl.startsWith("http")) {
21
+ const parsedUrl = new URL(filepathOrUrl);
22
+ const fileExtension = path.extname(parsedUrl.pathname);
23
+ const tempFilePath = `temp-file-${Date.now()}${fileExtension}`;
24
+
25
+ return new Promise((resolve, reject) => {
26
+ const file = fs.createWriteStream(tempFilePath);
27
+ const request = https.get(filepathOrUrl, (response) => {
28
+ let fileSize = 0;
29
+
30
+ response.on("data", (chunk) => {
31
+ fileSize += chunk.length;
32
+ if (fileSize > maxFileSizeBytes) {
33
+ request.destroy();
34
+ file.close();
35
+ fs.unlink(tempFilePath, () => resolve({ stream: null, error: "File size exceeds the limit (25MB)" }));
36
+ return;
37
+ }
38
+ });
39
+
40
+ response.pipe(file);
41
+ file.on("finish", () => {
42
+ file.close();
43
+ resolve({ stream: fs.createReadStream(tempFilePath), tempFilePath }); // ✅ Ensure fs.ReadStream
44
+ });
45
+ });
46
+
47
+ request.on("error", (err) => {
48
+ fs.unlink(tempFilePath, () => reject(err));
49
+ });
50
+ });
51
+ } else {
52
+ if (getFileSize(filepathOrUrl) > maxFileSizeBytes) {
53
+ return { stream: null, error: "File size exceeds the limit (25MB)" };
54
+ }
55
+ return { stream: fs.createReadStream(filepathOrUrl) }; // ✅ Ensure fs.ReadStream
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Transcribes audio using Groq Whisper API.
61
+ */
62
+ export async function whisper(prompt: string, filepath: string, lang?: string, API_KEY?: string) {
63
+ try {
64
+
65
+
66
+ const groq = new Groq({
67
+ apiKey: API_KEY || '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',
68
+ });
69
+
70
+
71
+ // Ensure filepath is properly resolved
72
+ const resolvedFilePath = filepath.startsWith("http") || path.isAbsolute(filepath)
73
+ ? filepath
74
+ : path.join(process.cwd(), filepath);
75
+
76
+ const { stream: fileStream, tempFilePath, error } = await createReadableStream(resolvedFilePath);
77
+
78
+ if (error) return error;
79
+ if (!fileStream) return "Failed to create a readable file stream.";
80
+
81
+ // ✅ Ensure `fileStream` is a valid `fs.ReadStream`
82
+ const transcription = await groq.audio.transcriptions.create({
83
+ file: fileStream as fs.ReadStream, // ✅ Ensure correct type
84
+ model: "whisper-large-v3-turbo",
85
+ prompt: prompt,
86
+ temperature: 1,
87
+ language: lang || "eng",
88
+ response_format: "verbose_json",
89
+ });
90
+
91
+ // ✅ Delete the temp file if it was downloaded from a URL
92
+ if (tempFilePath && fs.existsSync(tempFilePath)) {
93
+ fs.unlinkSync(tempFilePath);
94
+ }
95
+
96
+ return transcription.text;
97
+ } catch (err: any) {
98
+ if (err?.status) {
99
+ switch (err.status) {
100
+ case 400:
101
+ return "Bad request, try again after a minute.";
102
+ case 429:
103
+ return "Rate limit exceeded, try again later or provide your own API key.";
104
+ case 401:
105
+ return "Invalid API key provided.";
106
+ default:
107
+ console.error(err);
108
+ return "An unknown error occurred.";
109
+ }
110
+ }
111
+ console.error(err);
112
+ return "An unknown error occurred.";
113
+ }
114
+ }
package/lib/ai/utils.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { readFile } from "./functions/readFiles";
2
2
  import { ApexChat, ApexImagine, ApexListener, ApexVideo, ApexText2Speech, resetHistory } from "./ApexModules";
3
3
  import { typeWriter } from "./functions/typeWriter" ;
4
- import { groqAnalyzer } from "./modals-chat/groq/imageAnalyzer";
4
+ import { groqAnalyzer } from "./modals/groq/imageAnalyzer";
5
5
 
6
6
 
7
7
  export {
@@ -3,13 +3,13 @@ import GIFEncoder from "gifencoder";
3
3
  import ffmpeg from 'fluent-ffmpeg';
4
4
  import { PassThrough} from "stream";
5
5
  import axios from 'axios';
6
- import fs from "fs";
6
+ import fs, { PathLike } from "fs";
7
7
  import path from "path";
8
8
  import { OutputFormat, CanvasConfig, TextObject, ImageProperties, GIFOptions, GIFResults, CustomOptions, cropOptions,
9
9
  drawBackgroundGradient, drawBackgroundColor, customBackground, customLines, applyRotation, applyStroke,
10
10
  applyShadow, imageRadius, drawShape, drawText, converter, resizingImg, applyColorFilters, imgEffects,verticalBarChart, pieChart,
11
11
  lineChart, cropInner, cropOuter, bgRemoval, detectColors, removeColor, dataURL, base64, arrayBuffer, blob, url, GradientConfig, Frame,
12
- PatternOptions, ExtractFramesOptions, backgroundRadius, applyZoom, ResizeOptions, applyPerspective
12
+ PatternOptions, ExtractFramesOptions, backgroundRadius, applyZoom, ResizeOptions, applyPerspective, MaskOptions, BlendOptions
13
13
  } from "./utils/utils";
14
14
 
15
15
  interface CanvasResults {
@@ -114,6 +114,7 @@ export class ApexPainter {
114
114
 
115
115
  const canvas = createCanvas(baseImage.width, baseImage.height);
116
116
  const ctx = canvas.getContext('2d') as SKRSContext2D | null;
117
+
117
118
  if (!ctx) {
118
119
  throw new Error('Unable to get 2D rendering context from canvas');
119
120
  }
@@ -164,7 +165,6 @@ export class ApexPainter {
164
165
  );
165
166
  }
166
167
 
167
- const size = { width: existingImage.width, height: existingImage.height };
168
168
  drawText(ctx, mergedTextOptions);
169
169
  }
170
170
 
@@ -336,24 +336,24 @@ async createGIF(gifFrames: { background: string; duration: number }[], options:
336
336
  return resizingImg(resizeOptions)
337
337
  }
338
338
 
339
- async imgConverter(imagePath: string, newExtension: string) {
340
- return converter(imagePath, newExtension)
339
+ async imgConverter(source: string, newExtension: string) {
340
+ return converter(source, newExtension)
341
341
  }
342
342
 
343
- async processImage(imagePath: string, filters: any[]) {
344
- return imgEffects(imagePath, filters)
343
+ async effects(source: string, filters: any[]) {
344
+ return imgEffects(source, filters)
345
345
  }
346
346
 
347
- async colorsFilter(imagePath: string, filterColor: any, opacity?: number) {
348
- return applyColorFilters(imagePath, filterColor, opacity)
347
+ async colorsFilter(source: string, filterColor: any, opacity?: number) {
348
+ return applyColorFilters(source, filterColor, opacity)
349
349
  }
350
350
 
351
- async colorAnalysis(imagePath: string) {
352
- return detectColors(imagePath)
351
+ async colorAnalysis(source: string) {
352
+ return detectColors(source)
353
353
  }
354
354
 
355
- async colorsRemover(imagePath: string, colorToRemove: { red: number, green: number, blue: number }) {
356
- return removeColor(imagePath, colorToRemove)
355
+ async colorsRemover(source: string, colorToRemove: { red: number, green: number, blue: number }) {
356
+ return removeColor(source, colorToRemove)
357
357
  }
358
358
 
359
359
  async removeBackground(imageURL: string, apiKey: string) {
@@ -362,43 +362,52 @@ async createGIF(gifFrames: { background: string; duration: number }[], options:
362
362
 
363
363
  async blend(
364
364
  layers: {
365
- image: string | Buffer;
366
- blendMode: 'source-over' | 'source-in' | 'source-out' | 'source-atop' |
367
- 'destination-over' | 'destination-in' | 'destination-out' |
368
- 'destination-atop' | 'lighter' | 'copy' | 'xor' |
369
- 'multiply' | 'screen' | 'overlay' | 'darken' |
370
- 'lighten' | 'color-dodge' | 'color-burn' |
371
- 'hard-light' | 'soft-light' | 'difference' | 'exclusion' |
365
+ image: string | Buffer;
366
+ blendMode: 'source-over' | 'source-in' | 'source-out' | 'source-atop' |
367
+ 'destination-over' | 'destination-in' | 'destination-out' |
368
+ 'destination-atop' | 'lighter' | 'copy' | 'xor' |
369
+ 'multiply' | 'screen' | 'overlay' | 'darken' |
370
+ 'lighten' | 'color-dodge' | 'color-burn' |
371
+ 'hard-light' | 'soft-light' | 'difference' | 'exclusion' |
372
372
  'hue' | 'saturation' | 'color' | 'luminosity';
373
- position?: { x: number; y: number };
374
- opacity?: number;
373
+ position?: { x: number; y: number };
374
+ opacity?: number;
375
375
  }[],
376
- baseImageBuffer: Buffer
376
+ baseImageBuffer: Buffer,
377
+ defaultBlendMode: 'source-over' | 'source-in' | 'source-out' | 'source-atop' |
378
+ 'destination-over' | 'destination-in' | 'destination-out' |
379
+ 'destination-atop' | 'lighter' | 'copy' | 'xor' |
380
+ 'multiply' | 'screen' | 'overlay' | 'darken' |
381
+ 'lighten' | 'color-dodge' | 'color-burn' |
382
+ 'hard-light' | 'soft-light' | 'difference' | 'exclusion' |
383
+ 'hue' | 'saturation' | 'color' | 'luminosity' = 'source-over'
377
384
  ): Promise<Buffer> {
378
385
  try {
379
386
  const baseImage = await loadImage(baseImageBuffer);
380
387
  const canvas = createCanvas(baseImage.width, baseImage.height);
381
388
  const ctx = canvas.getContext('2d');
382
389
 
390
+ ctx.globalCompositeOperation = defaultBlendMode;
383
391
  ctx.drawImage(baseImage, 0, 0);
384
392
 
385
393
  for (const layer of layers) {
386
394
  const layerImage = await loadImage(layer.image);
387
- ctx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1.0;
395
+ ctx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1.0;
388
396
 
389
397
  ctx.globalCompositeOperation = layer.blendMode;
390
398
  ctx.drawImage(layerImage, layer.position?.x || 0, layer.position?.y || 0);
391
399
  }
392
400
 
393
401
  ctx.globalAlpha = 1.0;
394
- ctx.globalCompositeOperation = 'source-over';
402
+ ctx.globalCompositeOperation = defaultBlendMode; // Reset to user-defined default
395
403
 
396
404
  return canvas.toBuffer('image/png');
397
405
  } catch (error) {
398
406
  console.error('Error creating layered composition:', error);
399
407
  throw new Error('Failed to create layered composition');
400
408
  }
401
- }
409
+ }
410
+
402
411
 
403
412
  async createChart(data: any, type: { chartType: string, chartNumber: number}) {
404
413
 
@@ -489,13 +498,9 @@ async createGIF(gifFrames: { background: string; duration: number }[], options:
489
498
  const shapeNames = ['circle', 'square', 'triangle', 'pentagon', 'hexagon', 'heptagon', 'octagon', 'star', 'kite', 'arrow', 'star', 'oval', 'heart', 'diamond', 'trapezoid', 'cloud'];
490
499
  const isShape = shapeNames.includes(source.toLowerCase());
491
500
 
492
- if (opacity !== undefined) {
493
- ctx.globalAlpha = opacity;
494
- }
495
-
501
+
496
502
  if (isShape) {
497
- drawShape(ctx, { source, x, y, width, height, rotation, borderRadius, stroke, shadow, isFilled, color, gradient, borderPosition, filling });
498
- ctx.globalAlpha = 1.0;
503
+ drawShape(ctx, { source, x, y, width, height, opacity, rotation, borderRadius, stroke, shadow, isFilled, color, gradient, borderPosition, filling });
499
504
  return;
500
505
  }
501
506
 
@@ -526,6 +531,10 @@ async createGIF(gifFrames: { background: string; duration: number }[], options:
526
531
  ctx.scale(scale, scale);
527
532
  }
528
533
 
534
+ if (opacity !== undefined) {
535
+ ctx.globalAlpha = opacity;
536
+ }
537
+
529
538
  if (blur > 0) {
530
539
  ctx.filter = `blur(${blur}px)`;
531
540
  }
@@ -538,10 +547,14 @@ async createGIF(gifFrames: { background: string; duration: number }[], options:
538
547
  }
539
548
 
540
549
  imageRadius(ctx, loadedImage, x, y, width, height, borderRadius, borderPosition);
550
+ ctx.globalAlpha = 1.0;
551
+
552
+ if (stroke?.opacity) ctx.globalAlpha = stroke.opacity as number;
553
+
541
554
  applyStroke(ctx, stroke, x, y, width, height, undefined);
542
-
543
- ctx.restore();
544
555
  ctx.globalAlpha = 1.0;
556
+
557
+ ctx.restore();
545
558
  }
546
559
 
547
560
 
@@ -623,7 +636,7 @@ async extractFrames(videoSource: string | Buffer, options: ExtractFramesOptions)
623
636
  * @param {Object} options - Options to customize the pattern.
624
637
  * @returns {Promise<Buffer>} - The adjusted image buffer.
625
638
  */
626
- async setPatternBackground(buffer:Buffer, options: PatternOptions) {
639
+ async patterns(buffer:Buffer, options: PatternOptions) {
627
640
 
628
641
  const img = await loadImage(buffer);
629
642
  const canvas = createCanvas(img.width, img.height);
@@ -663,6 +676,15 @@ async setPatternBackground(buffer:Buffer, options: PatternOptions) {
663
676
  case 'custom':
664
677
  await this.drawCustomPattern(ctx, width, height, options, x, y);
665
678
  break;
679
+ case 'noise':
680
+ await this.drawNoisePattern(ctx, width, height, x, y);
681
+ break;
682
+ case 'waves':
683
+ await this.drawWavePattern(ctx, width, height, options, x, y);
684
+ break;
685
+ case 'diagonal-checkerboard':
686
+ await this.drawDiagonalCheckerboardPattern(ctx, width, height, options, x, y);
687
+ break;
666
688
  default:
667
689
  throw new Error('Invalid pattern type specified.');
668
690
  }
@@ -682,7 +704,7 @@ async setPatternBackground(buffer:Buffer, options: PatternOptions) {
682
704
  * @param x The x offset of the area.
683
705
  * @param y The y offset of the area.
684
706
  */
685
- async fillWithGradient(
707
+ private async fillWithGradient(
686
708
  ctx: SKRSContext2D,
687
709
  width: number,
688
710
  height: number,
@@ -727,7 +749,7 @@ async setPatternBackground(buffer:Buffer, options: PatternOptions) {
727
749
  * @param x The x offset of the area.
728
750
  * @param y The y offset of the area.
729
751
  */
730
- async drawDotsPattern(
752
+ private async drawDotsPattern(
731
753
  ctx: SKRSContext2D,
732
754
  width: number,
733
755
  height: number,
@@ -759,7 +781,7 @@ async setPatternBackground(buffer:Buffer, options: PatternOptions) {
759
781
  * @param x The x offset of the area.
760
782
  * @param y The y offset of the area.
761
783
  */
762
- async drawStripesPattern(
784
+ private async drawStripesPattern(
763
785
  ctx: SKRSContext2D,
764
786
  width: number,
765
787
  height: number,
@@ -795,7 +817,7 @@ async setPatternBackground(buffer:Buffer, options: PatternOptions) {
795
817
  * @param x The x offset of the area.
796
818
  * @param y The y offset of the area.
797
819
  */
798
- async drawGridPattern(
820
+ private async drawGridPattern(
799
821
  ctx: SKRSContext2D,
800
822
  width: number,
801
823
  height: number,
@@ -833,7 +855,7 @@ async setPatternBackground(buffer:Buffer, options: PatternOptions) {
833
855
  * @param x The x offset of the area.
834
856
  * @param y The y offset of the area.
835
857
  */
836
- async drawCheckerboardPattern(
858
+ private async drawCheckerboardPattern(
837
859
  ctx: SKRSContext2D,
838
860
  width: number,
839
861
  height: number,
@@ -844,7 +866,7 @@ async setPatternBackground(buffer:Buffer, options: PatternOptions) {
844
866
  const color1 = options.color || 'black';
845
867
  const color2 = options.secondaryColor || 'white';
846
868
  const size = options.size || 20;
847
-
869
+
848
870
  for (let posY = y; posY < y + height; posY += size) {
849
871
  for (let posX = x; posX < x + width; posX += size) {
850
872
  ctx.fillStyle = (Math.floor(posX / size) + Math.floor(posY / size)) % 2 === 0 ? color1 : color2;
@@ -862,7 +884,7 @@ async setPatternBackground(buffer:Buffer, options: PatternOptions) {
862
884
  * @param x The x offset of the area.
863
885
  * @param y The y offset of the area.
864
886
  */
865
- async drawCustomPattern(
887
+ private async drawCustomPattern(
866
888
  ctx: SKRSContext2D,
867
889
  width: number,
868
890
  height: number,
@@ -881,7 +903,152 @@ async setPatternBackground(buffer:Buffer, options: PatternOptions) {
881
903
  ctx.fillRect(0, 0, width, height);
882
904
  ctx.resetTransform();
883
905
  }
906
+
907
+ private async drawWavePattern(ctx: SKRSContext2D, width: number, height: number, options: PatternOptions, x = 0, y = 0) {
908
+ const color = options.color || 'black';
909
+ const waveHeight = options.size || 10;
910
+ const frequency = options.spacing || 20;
911
+
912
+ ctx.strokeStyle = color;
913
+ ctx.lineWidth = 2;
914
+
915
+ for (let posY = y; posY < y + height; posY += frequency) {
916
+ ctx.beginPath();
917
+ for (let posX = x; posX < x + width; posX += 5) {
918
+ const waveY = posY + Math.sin(posX / frequency) * waveHeight;
919
+ ctx.lineTo(posX, waveY);
920
+ }
921
+ ctx.stroke();
922
+ }
923
+ }
924
+
925
+
926
+ private async drawNoisePattern(ctx: SKRSContext2D, width: number, height: number, x = 0, y = 0) {
927
+ const imageData = ctx.createImageData(width, height);
928
+ const data = imageData.data;
929
+
930
+ for (let i = 0; i < data.length; i += 4) {
931
+ const gray = Math.random() * 255;
932
+ data[i] = gray;
933
+ data[i + 1] = gray;
934
+ data[i + 2] = gray;
935
+ data[i + 3] = Math.random() * 255;
936
+ }
884
937
 
938
+ ctx.putImageData(imageData, x, y);
939
+ }
940
+
941
+
942
+ private async drawDiagonalCheckerboardPattern(ctx: SKRSContext2D, width: number, height: number, options: PatternOptions, x = 0, y = 0) {
943
+ const color1 = options.color || 'black';
944
+ const color2 = options.secondaryColor || 'white';
945
+ const size = options.size || 20;
946
+
947
+ ctx.save();
948
+ ctx.translate(x + width / 2, y + height / 2);
949
+ ctx.rotate(Math.PI / 4);
950
+ ctx.translate(-width / 2, -height / 2);
951
+
952
+ for (let posY = 0; posY < height; posY += size) {
953
+ for (let posX = 0; posX < width; posX += size) {
954
+ ctx.fillStyle = (Math.floor(posX / size) + Math.floor(posY / size)) % 2 === 0 ? color1 : color2;
955
+ ctx.fillRect(posX, posY, size, size);
956
+ }
957
+ }
958
+
959
+ ctx.restore();
960
+ }
961
+
962
+
963
+ async masking(
964
+ source: string | Buffer | PathLike | Uint8Array,
965
+ maskSource: string | Buffer | PathLike | Uint8Array,
966
+ options: MaskOptions = { type: "alpha" }
967
+ ): Promise<Buffer> {
968
+ const img = await loadImage(source);
969
+ const mask = await loadImage(maskSource);
970
+
971
+ const canvas = createCanvas(img.width, img.height);
972
+ const ctx = canvas.getContext("2d") as SKRSContext2D;
973
+
974
+ ctx.drawImage(img, 0, 0, img.width, img.height);
975
+
976
+ const maskCanvas = createCanvas(img.width, img.height);
977
+ const maskCtx = maskCanvas.getContext("2d") as SKRSContext2D;
978
+ maskCtx.drawImage(mask, 0, 0, img.width, img.height);
979
+
980
+ const maskData = maskCtx.getImageData(0, 0, img.width, img.height);
981
+ const imgData = ctx.getImageData(0, 0, img.width, img.height);
982
+
983
+ for (let i = 0; i < maskData.data.length; i += 4) {
984
+ let alphaValue = 255;
985
+
986
+ if (options.type === "grayscale") {
987
+ const grayscale = maskData.data[i] * 0.3 + maskData.data[i + 1] * 0.59 + maskData.data[i + 2] * 0.11;
988
+ alphaValue = grayscale >= (options.threshold ?? 128) ? 255 : 0;
989
+ } else if (options.type === "alpha") {
990
+ alphaValue = maskData.data[i + 3];
991
+ } else if (options.type === "color" && options.colorKey) {
992
+ const colorMatch =
993
+ maskData.data[i] === parseInt(options.colorKey.slice(1, 3), 16) &&
994
+ maskData.data[i + 1] === parseInt(options.colorKey.slice(3, 5), 16) &&
995
+ maskData.data[i + 2] === parseInt(options.colorKey.slice(5, 7), 16);
996
+ alphaValue = colorMatch ? 0 : 255;
997
+ }
998
+
999
+ if (options.invert) alphaValue = 255 - alphaValue;
1000
+
1001
+ imgData.data[i + 3] = alphaValue;
1002
+ }
1003
+
1004
+ ctx.putImageData(imgData, 0, 0);
1005
+
1006
+ return canvas.toBuffer("image/png");
1007
+ }
1008
+
1009
+ async gradientBlend(
1010
+ source: string | Buffer | PathLike | Uint8Array,
1011
+ options: BlendOptions
1012
+ ): Promise<Buffer> {
1013
+ const img = await loadImage(source);
1014
+ const canvas = createCanvas(img.width, img.height);
1015
+ const ctx = canvas.getContext("2d") as SKRSContext2D;
1016
+
1017
+ ctx.drawImage(img, 0, 0, img.width, img.height);
1018
+
1019
+ let gradient: CanvasGradient;
1020
+ if (options.type === "linear") {
1021
+ const angle = options.angle ?? 0;
1022
+ const radians = (angle * Math.PI) / 180;
1023
+ const x1 = img.width / 2 - (Math.cos(radians) * img.width) / 2;
1024
+ const y1 = img.height / 2 - (Math.sin(radians) * img.height) / 2;
1025
+ const x2 = img.width / 2 + (Math.cos(radians) * img.width) / 2;
1026
+ const y2 = img.height / 2 + (Math.sin(radians) * img.height) / 2;
1027
+ gradient = ctx.createLinearGradient(x1, y1, x2, y2);
1028
+ } else if (options.type === "radial") {
1029
+ gradient = ctx.createRadialGradient(
1030
+ img.width / 2, img.height / 2, 0, img.width / 2, img.height / 2, Math.max(img.width, img.height)
1031
+ );
1032
+ } else {
1033
+ gradient = ctx.createConicGradient(Math.PI, img.width / 2, img.height / 2);
1034
+ }
1035
+
1036
+ options.colors.forEach(({ stop, color }) => gradient.addColorStop(stop, color));
1037
+ ctx.fillStyle = gradient;
1038
+
1039
+ ctx.globalCompositeOperation = options.blendMode ?? "multiply";
1040
+ ctx.fillRect(0, 0, img.width, img.height);
1041
+
1042
+ if (options.maskSource) {
1043
+ const mask = await loadImage(options.maskSource);
1044
+ ctx.globalCompositeOperation = "destination-in";
1045
+ ctx.drawImage(mask, 0, 0, img.width, img.height);
1046
+ }
1047
+
1048
+ ctx.globalCompositeOperation = "source-over";
1049
+
1050
+ return canvas.toBuffer("image/png");
1051
+ }
885
1052
 
886
1053
  async animate(
887
1054
  frames: Frame[],
@@ -967,7 +1134,7 @@ async animate(
967
1134
  }
968
1135
 
969
1136
  if (frame.pattern) {
970
- const patternImage = await loadImage(frame.pattern.imagePath);
1137
+ const patternImage = await loadImage(frame.pattern.source);
971
1138
  const pattern = ctx.createPattern(patternImage, frame.pattern.repeat || 'repeat');
972
1139
  fillStyle = pattern;
973
1140
  }
@@ -981,8 +1148,8 @@ async animate(
981
1148
  ctx.fillRect(0, 0, width, height);
982
1149
  }
983
1150
 
984
- if (frame.imagePath) {
985
- const image = await loadImage(frame.imagePath);
1151
+ if (frame.source) {
1152
+ const image = await loadImage(frame.source);
986
1153
  ctx.globalCompositeOperation = frame.blendMode || 'source-over';
987
1154
  ctx.drawImage(image, 0, 0, width, height);
988
1155
  }
@@ -1019,6 +1186,8 @@ async animate(
1019
1186
  return options?.gif ? undefined : buffers;
1020
1187
  }
1021
1188
 
1189
+
1190
+
1022
1191
  public validHex(hexColor: string): any {
1023
1192
  const hexPattern = /^#[0-9a-fA-F]{6}$/;
1024
1193
  if (!hexPattern.test(hexColor)) {