apexify.js 4.5.30 → 4.5.31

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.
@@ -1,40 +1,63 @@
1
1
  import { loadImage } from "@napi-rs/canvas";
2
2
  import { CanvasConfig } from './types';
3
- import fs from 'fs';
4
3
  import path from 'path';
5
4
 
6
5
  /**
7
6
  * Draws a solid background color on the canvas.
7
+ * Applies zoom scaling and positioning adjustments.
8
8
  * @param ctx The canvas rendering context.
9
9
  * @param canvas The canvas configuration object.
10
- * @returns A Promise that resolves once the background color is drawn.
11
10
  */
12
11
  export async function drawBackgroundColor(ctx: any, canvas: CanvasConfig): Promise<void> {
12
+ const zoomScale = canvas.zoom?.scale || 1;
13
+ const zoomX = canvas.zoom?.x || 0;
14
+ const zoomY = canvas.zoom?.y || 0;
15
+
16
+ const canvasWidth = canvas.width || 500;
17
+ const canvasHeight = canvas.height || 500;
18
+
19
+ const newWidth = canvasWidth * zoomScale;
20
+ const newHeight = canvasHeight * zoomScale;
21
+
22
+ const drawX = (canvasWidth - newWidth) / 2 - zoomX;
23
+ const drawY = (canvasHeight - newHeight) / 2 - zoomY;
24
+
13
25
  if (canvas.colorBg !== 'transparent') {
14
26
  ctx.fillStyle = canvas.colorBg;
15
- ctx.fillRect(0, 0, canvas.width, canvas.height);
27
+ ctx.fillRect(drawX, drawY, newWidth, newHeight);
16
28
  }
17
29
  }
18
30
 
19
31
  /**
20
32
  * Draws a gradient background on the canvas.
33
+ * Applies zoom scaling and positioning adjustments.
21
34
  * @param ctx The canvas rendering context.
22
35
  * @param canvas The canvas configuration object.
23
- * @returns A Promise that resolves once the gradient background is drawn.
24
36
  */
25
37
  export async function drawBackgroundGradient(ctx: any, canvas: CanvasConfig): Promise<void> {
26
38
  if (canvas.gradientBg) {
27
- const { type, startX, startY, endX, endY, startRadius, endRadius, colors } = canvas.gradientBg;
39
+ const { type, startX = 0, startY = 0, endX = canvas.width || 500, endY = canvas.height || 500, startRadius = 0, endRadius = 0, colors } = canvas.gradientBg;
28
40
 
29
41
  if (!colors || colors.length === 0) {
30
42
  throw new Error('You need to provide colors for the gradient.');
31
43
  }
32
44
 
33
45
  let gradient;
46
+ const zoomScale = canvas.zoom?.scale || 1;
47
+ const zoomX = canvas.zoom?.x || 0;
48
+ const zoomY = canvas.zoom?.y || 0;
49
+
50
+ const newStartX = startX * zoomScale - zoomX;
51
+ const newStartY = startY * zoomScale - zoomY;
52
+ const newEndX = endX * zoomScale - zoomX;
53
+ const newEndY = endY * zoomScale - zoomY;
54
+
34
55
  if (type === 'linear' || type === undefined) {
35
- gradient = ctx.createLinearGradient(startX, startY, endX, endY);
56
+ gradient = ctx.createLinearGradient(newStartX, newStartY, newEndX, newEndY);
36
57
  } else if (type === 'radial') {
37
- gradient = ctx.createRadialGradient(startX, startY, startRadius, endX, endY, endRadius);
58
+ const newStartRadius = startRadius * zoomScale;
59
+ const newEndRadius = endRadius * zoomScale;
60
+ gradient = ctx.createRadialGradient(newStartX, newStartY, newStartRadius, newEndX, newEndY, newEndRadius);
38
61
  } else {
39
62
  throw new Error('Unsupported gradient type.');
40
63
  }
@@ -43,16 +66,21 @@ export async function drawBackgroundGradient(ctx: any, canvas: CanvasConfig): Pr
43
66
  gradient.addColorStop(stop, color);
44
67
  }
45
68
 
69
+ const newWidth = (canvas.width || 500) * zoomScale;
70
+ const newHeight = (canvas.height || 500) * zoomScale;
71
+ const drawX = ((canvas.width || 500) - newWidth) / 2 - zoomX;
72
+ const drawY = ((canvas.height || 500) - newHeight) / 2 - zoomY;
73
+
46
74
  ctx.fillStyle = gradient;
47
- ctx.fillRect(0, 0, canvas.width, canvas.height);
75
+ ctx.fillRect(drawX, drawY, newWidth, newHeight);
48
76
  }
49
77
  }
50
78
 
51
79
  /**
52
80
  * Draws a custom background image on the canvas.
81
+ * Zoom logic is applied to scale and position the image.
53
82
  * @param ctx The canvas rendering context.
54
83
  * @param canvas The canvas configuration object.
55
- * @returns A Promise that resolves once the custom background image is drawn.
56
84
  */
57
85
  export async function customBackground(ctx: any, canvas: CanvasConfig): Promise<void> {
58
86
  if (canvas.customBg) {
@@ -68,22 +96,20 @@ export async function customBackground(ctx: any, canvas: CanvasConfig): Promise<
68
96
  const image = await loadImage(imageBuffer);
69
97
  const zoomScale = canvas.zoom?.scale || 1;
70
98
 
71
- if (zoomScale < 0) throw new Error("Invalid scale. Scale can't be a -ve integer.");
99
+ if (zoomScale < 0) throw new Error("Invalid scale. Scale can't be a negative integer.");
72
100
 
73
101
  const zoomX = canvas.zoom?.x || 0;
74
102
  const zoomY = canvas.zoom?.y || 0;
75
103
  const moveX = canvas.x || 0;
76
104
  const moveY = canvas.y || 0;
77
105
 
78
- if (!canvas.height || !canvas.width) {
79
- canvas.height = image.height;
80
- canvas.width = image.width;
81
- }
106
+ const canvasWidth = canvas.width || image.width;
107
+ const canvasHeight = canvas.height || image.height;
82
108
 
83
109
  const newWidth = image.width * zoomScale;
84
110
  const newHeight = image.height * zoomScale;
85
- const drawX = moveX + (canvas.width - newWidth) / 2 - zoomX;
86
- const drawY = moveY + (canvas.height - newHeight) / 2 - zoomY;
111
+ const drawX = moveX + (canvasWidth - newWidth) / 2 - zoomX;
112
+ const drawY = moveY + (canvasHeight - newHeight) / 2 - zoomY;
87
113
 
88
114
  ctx.drawImage(image, drawX, drawY, newWidth, newHeight);
89
115
 
@@ -1,49 +1,94 @@
1
+ import { CustomOptions } from "./types";
1
2
 
2
- export function customLines (ctx: any, options: any) {
3
- for (const customOption of options) {
4
- ctx.beginPath();
5
- ctx.moveTo(customOption.startCoordinates.x, customOption.startCoordinates.y);
6
- ctx.lineTo(customOption.endCoordinates.x, customOption.endCoordinates.y);
7
- ctx.lineWidth = customOption.lineStyle.width || 1;
8
- ctx.strokeStyle = customOption.lineStyle.color || 'black';
9
-
10
- if (typeof customOption.lineStyle.lineRadius === 'number') {
11
- const borderRadius = customOption.lineStyle.lineRadius;
12
- const dx = customOption.endCoordinates.x - customOption.startCoordinates.x;
13
- const dy = customOption.endCoordinates.y - customOption.startCoordinates.y;
14
- const angle = Math.atan2(dy, dx);
15
- const offsetX = Math.cos(angle) * borderRadius;
16
- const offsetY = Math.sin(angle) * borderRadius;
17
- ctx.moveTo(customOption.startCoordinates.x + offsetX, customOption.startCoordinates.y + offsetY);
18
- ctx.lineTo(customOption.endCoordinates.x - offsetX, customOption.endCoordinates.y - offsetY);
19
- } else if (customOption.lineStyle.lineRadius === 'circular') {
20
- const dx = customOption.endCoordinates.x - customOption.startCoordinates.x;
21
- const dy = customOption.endCoordinates.y - customOption.startCoordinates.y;
22
- const length = Math.sqrt(dx * dx + dy * dy);
23
- const angle = Math.atan2(dy, dx);
24
- const halfWidth = customOption.lineStyle.width ? customOption.lineStyle.width / 2 : 1;
25
- ctx.moveTo(customOption.startCoordinates.x + Math.cos(angle - Math.PI / 2) * halfWidth, customOption.startCoordinates.y + Math.sin(angle - Math.PI / 2) * halfWidth);
26
- ctx.arc(customOption.startCoordinates.x, customOption.startCoordinates.y, length / 2, angle - Math.PI / 2, angle + Math.PI / 2);
27
- ctx.lineTo(customOption.endCoordinates.x + Math.cos(angle + Math.PI / 2) * halfWidth, customOption.endCoordinates.y + Math.sin(angle + Math.PI / 2) * halfWidth);
28
- ctx.arc(customOption.endCoordinates.x, customOption.endCoordinates.y, length / 2, angle + Math.PI / 2, angle - Math.PI / 2, true);
29
- ctx.closePath();
30
- }
3
+ export function customLines(ctx: any, options: CustomOptions[]) {
4
+ let previousEndCoordinates = null;
5
+ let currentStyle = null;
6
+ let inSingleLineSequence = false;
31
7
 
32
- ctx.stroke();
8
+ for (let i = 0; i < options.length; i++) {
9
+ const customOption = options[i];
10
+ const { startCoordinates, endCoordinates, lineStyle } = customOption;
11
+ const isSingleLine = lineStyle?.singleLine;
33
12
 
34
- if (customOption.lineStyle.stroke) {
35
- const stroke = customOption.lineStyle.stroke;
36
- ctx.strokeStyle = stroke.color || 'black';
37
- ctx.lineWidth = stroke.width || 1;
38
- ctx.stroke();
13
+ if (isSingleLine && !inSingleLineSequence) {
14
+ currentStyle = lineStyle;
15
+ inSingleLineSequence = true;
16
+ ctx.beginPath();
17
+ ctx.moveTo(startCoordinates.x, startCoordinates.y);
18
+ }
19
+
20
+ if (!isSingleLine && inSingleLineSequence) {
21
+ ctx.stroke();
22
+ applyAdditionalStroke(ctx, currentStyle);
23
+ inSingleLineSequence = false;
24
+ currentStyle = null;
25
+ }
26
+
27
+ const start = inSingleLineSequence && previousEndCoordinates
28
+ ? previousEndCoordinates
29
+ : startCoordinates;
30
+
31
+ if (!inSingleLineSequence) {
32
+ ctx.beginPath();
33
+ ctx.moveTo(start.x, start.y);
34
+ }
35
+
36
+ ctx.lineTo(endCoordinates.x, endCoordinates.y);
37
+
38
+ const appliedStyle = inSingleLineSequence ? currentStyle : lineStyle;
39
+ ctx.lineWidth = appliedStyle?.width || 1;
40
+ ctx.strokeStyle = appliedStyle?.color || 'black';
41
+ ctx.lineJoin = appliedStyle?.lineJoin || 'miter';
42
+ ctx.lineCap = appliedStyle?.lineCap || 'butt';
43
+
44
+ if (appliedStyle?.lineDash) {
45
+ ctx.setLineDash(appliedStyle.lineDash.dashArray || []);
46
+ ctx.lineDashOffset = appliedStyle.lineDash.offset || 0;
47
+ } else {
48
+ ctx.setLineDash([]);
49
+ }
50
+
51
+ if (typeof appliedStyle?.lineRadius === 'number') {
52
+ const borderRadius = appliedStyle.lineRadius;
53
+ const dx = endCoordinates.x - start.x;
54
+ const dy = endCoordinates.y - start.y;
55
+ const angle = Math.atan2(dy, dx);
56
+ const offsetX = Math.cos(angle) * borderRadius;
57
+ const offsetY = Math.sin(angle) * borderRadius;
58
+ ctx.moveTo(start.x + offsetX, start.y + offsetY);
59
+ ctx.lineTo(endCoordinates.x - offsetX, endCoordinates.y - offsetY);
60
+ } else if (appliedStyle?.lineRadius === 'circular') {
61
+ const dx = endCoordinates.x - start.x;
62
+ const dy = endCoordinates.y - start.y;
63
+ const length = Math.sqrt(dx * dx + dy * dy);
64
+ const angle = Math.atan2(dy, dx);
65
+ const halfWidth = appliedStyle.width ? appliedStyle.width / 2 : 1;
66
+ ctx.moveTo(start.x + Math.cos(angle - Math.PI / 2) * halfWidth, start.y + Math.sin(angle - Math.PI / 2) * halfWidth);
67
+ ctx.arc(start.x, start.y, length / 2, angle - Math.PI / 2, angle + Math.PI / 2);
68
+ ctx.lineTo(endCoordinates.x + Math.cos(angle + Math.PI / 2) * halfWidth, endCoordinates.y + Math.sin(angle + Math.PI / 2) * halfWidth);
69
+ ctx.arc(endCoordinates.x, endCoordinates.y, length / 2, angle + Math.PI / 2, angle - Math.PI / 2, true);
70
+ ctx.closePath();
71
+ }
72
+
73
+ if (!inSingleLineSequence || i === options.length - 1) {
74
+ ctx.stroke();
75
+ applyAdditionalStroke(ctx, appliedStyle);
76
+ }
77
+
78
+ previousEndCoordinates = endCoordinates;
79
+
80
+ if (!isSingleLine) {
81
+ currentStyle = null;
82
+ inSingleLineSequence = false;
83
+ }
39
84
  }
85
+ }
40
86
 
41
- if (customOption.lineStyle.shadow) {
42
- const shadow = customOption.lineStyle.shadow;
43
- ctx.shadowOffsetX = shadow.offsetX || 0;
44
- ctx.shadowOffsetY = shadow.offsetY || 0;
45
- ctx.shadowBlur = shadow.blur || 0;
46
- ctx.shadowColor = shadow.color || 'black';
87
+ function applyAdditionalStroke(ctx: any, style: any) {
88
+ if (style.stroke) {
89
+ const { color, width } = style.stroke;
90
+ ctx.strokeStyle = color || 'black';
91
+ ctx.lineWidth = width || 1;
92
+ ctx.stroke();
47
93
  }
48
- }
49
- }
94
+ }
@@ -27,38 +27,38 @@ export async function loadImages(imagePath: string) {
27
27
  }
28
28
  }
29
29
 
30
- export async function resizingImg(resizeOptions: any): Promise<any> {
30
+ export async function resizingImg(resizeOptions: any): Promise<Buffer> {
31
31
  try {
32
- if (!resizeOptions.imagePath) {
33
- throw new Error("Image path is required for resizing.");
34
- }
35
-
36
- let absoluteImagePath: string;
37
-
38
- if (resizeOptions.imagePath.startsWith("http")) {
39
-
40
- absoluteImagePath = resizeOptions.imagePath;
41
- } else {
32
+ if (!resizeOptions.imagePath) {
33
+ throw new Error("Image path is required for resizing.");
34
+ }
42
35
 
43
- absoluteImagePath = path.join(process.cwd(), resizeOptions.imagePath);
44
- }
36
+ let absoluteImagePath;
37
+
38
+ if (resizeOptions.imagePath.startsWith("http")) {
39
+ absoluteImagePath = resizeOptions.imagePath;
40
+ } else {
41
+ absoluteImagePath = path.join(process.cwd(), resizeOptions.imagePath);
42
+ }
45
43
 
46
- const image = await loadImage(absoluteImagePath);
47
- const canvas = createCanvas(resizeOptions.size?.width || 500, resizeOptions.size?.height || 500);
48
- const ctx = canvas.getContext('2d');
44
+ let image = sharp(absoluteImagePath);
49
45
 
50
- if (!ctx) {
51
- throw new Error('Unable to get 2D rendering context from canvas');
52
- }
46
+ const resizeOptionsForSharp = {
47
+ width: resizeOptions.size?.width || 500,
48
+ height: resizeOptions.size?.height || 500,
49
+ fit: resizeOptions.maintainAspectRatio ? sharp.fit.inside : sharp.fit.fill
50
+ };
53
51
 
54
- ctx.drawImage(image, 0, 0, resizeOptions.size?.width || 500, resizeOptions.size?.height || 500);
52
+ const resizedBuffer = await image
53
+ .resize(resizeOptionsForSharp)
54
+ .png()
55
+ .toBuffer();
55
56
 
56
- const resizedBuffer = canvas.toBuffer('image/png');
57
+ return resizedBuffer;
57
58
 
58
- return resizedBuffer;
59
- } catch (error) {
60
- console.error("Error resizing image:", error);
61
- throw new Error("Failed to resize image");
59
+ } catch (error) {
60
+ console.error("Error resizing image:", error);
61
+ throw new Error("Failed to resize image");
62
62
  }
63
63
  }
64
64
 
@@ -97,36 +97,93 @@ export async function converter(imagePath: string, newExtension: string) {
97
97
  }
98
98
  }
99
99
 
100
- export async function applyColorFilters(imagePath: string, filterColor: string) {
101
-
102
- try {
100
+ export async function applyColorFilters(imagePath: string, gradientOptions?: any, opacity: number = 1) {
101
+ try {
103
102
  let image: any;
104
103
 
105
104
  if (imagePath.startsWith("http")) {
106
-
107
- const pngBuffer = await converter(imagePath, "png");
108
- image = sharp(pngBuffer);
105
+ const pngBuffer = await converter(imagePath, "png");
106
+ image = sharp(pngBuffer);
109
107
  } else {
110
-
111
- const imagePathResolved = path.join(process.cwd(), imagePath);
112
- image = sharp(imagePathResolved);
108
+ const imagePathResolved = path.join(process.cwd(), imagePath);
109
+ image = await sharp(imagePathResolved);
113
110
  }
114
111
 
115
- const hexColorRegex = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
116
- if (!hexColorRegex.test(filterColor)) {
117
- throw new Error("Invalid color format. Only hex colors are supported.");
118
- }
112
+ const metadata = await image.metadata();
113
+ let gradientImage: Buffer;
119
114
 
120
- image.tint(filterColor);
115
+ if (typeof gradientOptions === 'string') {
116
+ gradientImage = createSolidColorImage(metadata.width, metadata.height, gradientOptions, opacity);
117
+ } else {
118
+ gradientImage = createGradientImage(metadata.width, metadata.height, gradientOptions, opacity);
119
+ }
121
120
 
122
- const outputBuffer = await image.toBuffer();
121
+ const outputBuffer = await image
122
+ .composite([{ input: gradientImage, blend: 'over' }])
123
+ .toBuffer();
124
+
123
125
  return outputBuffer;
124
- } catch (error) {
126
+ } catch (error) {
125
127
  console.error("Error applying color filter:", error);
126
128
  throw new Error("Failed to apply color filter");
127
129
  }
128
130
  }
129
131
 
132
+ function createSolidColorImage(width: number, height: number, color: string, opacity: number) {
133
+ const solidColorCanvas = createCanvas(width, height);
134
+ const ctx = solidColorCanvas.getContext('2d');
135
+
136
+ ctx.globalAlpha = opacity;
137
+
138
+ ctx.fillStyle = color;
139
+ ctx.fillRect(0, 0, width, height);
140
+
141
+ return solidColorCanvas.toBuffer('image/png');
142
+ }
143
+
144
+ function createGradientImage(width: number, height: number, options: any, opacity: number) {
145
+ const { type, colors } = options;
146
+
147
+ const gradientCanvas = createCanvas(width, height);
148
+ const ctx = gradientCanvas.getContext('2d');
149
+
150
+ if (type === 'linear') {
151
+ const gradient = ctx.createLinearGradient(
152
+ options.startX || 0,
153
+ options.startY || 0,
154
+ options.endX || width,
155
+ options.endY || height
156
+ );
157
+
158
+ colors.forEach(({ stop, color }: any) => {
159
+ gradient.addColorStop(stop, color);
160
+ });
161
+
162
+ ctx.fillStyle = gradient;
163
+ } else if (type === 'radial') {
164
+ const gradient = ctx.createRadialGradient(
165
+ options.startX || width / 2,
166
+ options.startY || height / 2,
167
+ options.startRadius || 0,
168
+ options.endX || width / 2,
169
+ options.endY || height / 2,
170
+ options.endRadius || Math.max(width, height)
171
+ );
172
+
173
+ colors.forEach(({ stop, color }: any) => {
174
+ gradient.addColorStop(stop, color);
175
+ });
176
+
177
+ ctx.fillStyle = gradient;
178
+ }
179
+
180
+ ctx.globalAlpha = opacity;
181
+
182
+ ctx.fillRect(0, 0, width, height);
183
+
184
+ return gradientCanvas.toBuffer('image/png');
185
+ }
186
+
130
187
  export async function imgEffects(imagePath: string, filters: any[]) {
131
188
  try {
132
189
  let jimpImage;
@@ -1,3 +1,4 @@
1
+ import { Canvas } from "@napi-rs/canvas"
1
2
  /**
2
3
  * Configuration option to decide the outputformate from ApexPainter
3
4
  * @param {type} default - 'buffer', other formates: url, blob, base64, dataURL, arraybuffer.
@@ -50,6 +51,7 @@ export interface CanvasConfig {
50
51
  offsetY?: number;
51
52
  blur?: number;
52
53
  opacity?: number;
54
+ borderRadius?: number | "circular";
53
55
  };
54
56
  rotation?: number;
55
57
  borderRadius?: number | "circular";
@@ -260,6 +262,13 @@ export interface CustomOptions {
260
262
  width?: number;
261
263
  color?: string;
262
264
  lineRadius?: number | string;
265
+ lineJoin?: 'round' | 'bevel' | 'miter';
266
+ lineCap?: 'butt' | 'round' | 'square';
267
+ singleLine?: boolean;
268
+ lineDash?: {
269
+ dashArray?: number[];
270
+ offset?: number;
271
+ };
263
272
  stroke?: {
264
273
  color?: string;
265
274
  width?: number;
@@ -475,4 +484,71 @@ export interface cropOptions {
475
484
  imageSource: string;
476
485
  crop: 'inner' | 'outer';
477
486
  radius: number | "circular"
478
- }
487
+ }
488
+
489
+
490
+ export interface GradientConfig{
491
+ type: 'linear' | 'radial';
492
+ startX?: number;
493
+ startY?: number;
494
+ endX?: number;
495
+ endY?: number;
496
+ startRadius?: number;
497
+ endRadius?: number;
498
+ angle?: number; // Optional: angle-based linear gradients
499
+ colors: {
500
+ stop: number;
501
+ color: string;
502
+ }[];
503
+ };
504
+
505
+ export interface Frame{
506
+ backgroundColor?: string; // Static color
507
+ gradient?: GradientConfig;
508
+ pattern?: {
509
+ imagePath: string; // Path to the pattern image
510
+ repeat?: 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat'; // Pattern repetition options
511
+ };
512
+ imagePath?: string; // Path to the image file
513
+ blendMode?: GlobalCompositeOperation; // Blending mode
514
+ transformations?: {
515
+ scaleX?: number;
516
+ scaleY?: number;
517
+ rotate?: number; // Rotation in degrees
518
+ translateX?: number;
519
+ translateY?: number;
520
+ };
521
+ duration?: number; // Custom duration for this frame
522
+ width?: number; // Custom width for the canvas
523
+ height?: number; // Custom height for the canvas
524
+ onDrawCustom?: (ctx: CanvasRenderingContext2D, canvas: Canvas) => void; // Custom draw callback
525
+ };
526
+
527
+
528
+ export interface PatternOptions {
529
+ type: 'dots' | 'stripes' | 'grid' | 'checkerboard' | 'custom';
530
+ color?: string; // Base color for the pattern
531
+ secondaryColor?: string;
532
+ x?: number;
533
+ y?: number;
534
+ width?: number;
535
+ height?: number;
536
+ size?: number; // Size of the pattern (e.g., dot radius, stripe width)
537
+ spacing?: number; // Spacing between patterns
538
+ angle?: number; // Angle for stripes (degrees)
539
+ customPatternImage?: string; // Path to a custom pattern image
540
+ backgroundColor?: string; // Single background color to fill the canvas
541
+ gradient?: GradientConfig; // Gradient options for background
542
+ }
543
+
544
+
545
+ export interface ExtractFramesOptions {
546
+ interval: number;
547
+ outputFormat?: 'jpg' | 'png';
548
+ frameSelection?: {
549
+ start?: number;
550
+ end?: number;
551
+ };
552
+ watermark?: string;
553
+ }
554
+
@@ -10,7 +10,7 @@
10
10
 
11
11
 
12
12
 
13
- import { OutputFormat, CanvasConfig, ImageProperties, TextObject, ImageObject, GIFOptions, GIFResults, CustomOptions, cropOptions } from "./types";
13
+ import { OutputFormat, CanvasConfig, ImageProperties, TextObject, ImageObject, GIFOptions, GIFResults, CustomOptions, cropOptions, GradientConfig, Frame, PatternOptions, ExtractFramesOptions } from "./types";
14
14
  import { radiusBorder } from "./radius";
15
15
  import { circularBorder } from "./circular";
16
16
  import { drawBackgroundColor, drawBackgroundGradient, customBackground } from "./bg";
@@ -62,5 +62,9 @@ export {
62
62
  cropOuter,
63
63
  detectColors,
64
64
  removeColor,
65
- bgRemoval
65
+ bgRemoval,
66
+ GradientConfig,
67
+ Frame,
68
+ PatternOptions,
69
+ ExtractFramesOptions
66
70
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apexify.js",
3
- "version": "4.5.30",
3
+ "version": "4.5.31",
4
4
  "description": "Unlimited AI models and Canvas library. Supports ts & js (supports front/back end).",
5
5
  "main": "./dist/index.js",
6
6
  "author": "zenith-79",
@@ -14,7 +14,8 @@
14
14
  },
15
15
  "files": [
16
16
  "lib",
17
- "dist"
17
+ "dist",
18
+ "examples"
18
19
  ],
19
20
  "keywords": [
20
21
  "chat bot",
@@ -189,6 +190,17 @@
189
190
  "image converter",
190
191
  "converter",
191
192
  "canvas-filters",
193
+ "image mask",
194
+ "image animate",
195
+ "animate",
196
+ "gif",
197
+ "masks",
198
+ "mask",
199
+ "blend",
200
+ "image blend",
201
+ "custom drawing",
202
+ "frames",
203
+ "extract frames",
192
204
  "apexify",
193
205
  "apexify.js"
194
206
  ],
@@ -196,11 +208,11 @@
196
208
  "@google/generative-ai": "^0.14.1",
197
209
  "@iamtraction/google-translate": "^2.0.1",
198
210
  "@napi-rs/canvas": "^0.1.53",
199
- "apexify.js": "^4.5.23",
200
211
  "api": "^6.1.2",
201
212
  "compromise": "^14.14.0",
202
213
  "csv-parse": "^5.5.6",
203
214
  "discord.js": "^14.15.3",
215
+ "fluent-ffmpeg": "^2.1.3",
204
216
  "gifencoder": "^2.0.1",
205
217
  "groq-sdk": "^0.5.0",
206
218
  "hercai": "^12.3.2",
@@ -209,13 +221,14 @@
209
221
  "pdf-parse": "^1.1.1",
210
222
  "sharp": "^0.33.4",
211
223
  "tesseract.js": "^5.1.0",
212
- "ts-node": "^10.9.2",
213
- "typescript": "^5.5.3",
214
224
  "verse.db": "^2.2.15"
215
225
  },
216
226
  "devDependencies": {
227
+ "@types/fluent-ffmpeg": "^2.1.26",
217
228
  "@types/gifencoder": "^2.0.3",
218
229
  "@types/node": "^22.5.4",
219
- "@types/pdf-parse": "^1.1.4"
230
+ "@types/pdf-parse": "^1.1.4",
231
+ "ts-node": "^10.9.2",
232
+ "typescript": "^5.6.2"
220
233
  }
221
234
  }