apexify.js 4.5.50 → 4.5.51

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.
@@ -297,7 +297,7 @@ async createGIF(gifFrames: { background: string; duration: number }[], options:
297
297
  }
298
298
  } catch (e: any) {
299
299
  console.error(e.message);
300
- throw e; // Re-throw the error after logging
300
+ throw e;
301
301
  }
302
302
  }
303
303
 
@@ -345,15 +345,12 @@ async createGIF(gifFrames: { background: string; duration: number }[], options:
345
345
  baseImageBuffer: Buffer
346
346
  ): Promise<Buffer> {
347
347
  try {
348
- // Load the base image
349
348
  const baseImage = await loadImage(baseImageBuffer);
350
349
  const canvas = createCanvas(baseImage.width, baseImage.height);
351
350
  const ctx = canvas.getContext('2d');
352
351
 
353
- // Draw the base image
354
352
  ctx.drawImage(baseImage, 0, 0);
355
353
 
356
- // Process each layer
357
354
  for (const layer of layers) {
358
355
  const layerImage = await loadImage(layer.image);
359
356
  ctx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1.0;
@@ -524,8 +521,8 @@ async extractFrames(videoSource: string | Buffer, options: ExtractFramesOptions)
524
521
  console.error('Error extracting frames:', err.message);
525
522
  reject(err);
526
523
  })
527
- .outputOptions([`-vf fps=1/${options.interval / 1000}`, `-q:v 2`]) // Set frame rate
528
- .saveToFile(path.join(frameDir, outputFileTemplate)); // Save frames with a sequence number
524
+ .outputOptions([`-vf fps=1/${options.interval / 1000}`, `-q:v 2`])
525
+ .saveToFile(path.join(frameDir, outputFileTemplate));
529
526
 
530
527
  ffmpeg.ffprobe(videoPath, (err, metadata) => {
531
528
  if (err) {
@@ -562,13 +559,12 @@ async extractFrames(videoSource: string | Buffer, options: ExtractFramesOptions)
562
559
  * @returns {Promise<Buffer>} - The adjusted image buffer.
563
560
  */
564
561
  async setPatternBackground(buffer:Buffer, options: PatternOptions) {
565
- // Load the buffered image onto a canvas
562
+
566
563
  const img = await loadImage(buffer);
567
564
  const canvas = createCanvas(img.width, img.height);
568
565
  const ctx: any = canvas.getContext('2d');
569
566
  ctx.drawImage(img, 0, 0);
570
567
 
571
- // Set up the area to cover (default to full image if not specified)
572
568
  const x = options.x || 0;
573
569
  const y = options.y || 0;
574
570
  const width = options.width || img.width;
@@ -713,20 +709,16 @@ async setPatternBackground(buffer:Buffer, options: PatternOptions) {
713
709
 
714
710
  ctx.fillStyle = color;
715
711
 
716
- // Save the context to apply transformations and restore later
717
712
  ctx.save();
718
713
 
719
- // Translate and rotate the canvas
720
- ctx.translate(x + width / 2, y + height / 2); // Move to the center of the area
721
- ctx.rotate((angle * Math.PI) / 180); // Rotate by the specified angle
722
- ctx.translate(-width / 2, -height / 2); // Translate back to top-left
714
+ ctx.translate(x + width / 2, y + height / 2);
715
+ ctx.rotate((angle * Math.PI) / 180);
716
+ ctx.translate(-width / 2, -height / 2);
723
717
 
724
- // Draw the stripes pattern with the current transformations
725
718
  for (let posX = 0; posX < width; posX += stripeWidth + spacing) {
726
719
  ctx.fillRect(posX, 0, stripeWidth, height);
727
720
  }
728
721
 
729
- // Restore the original context to prevent transformations affecting other drawings
730
722
  ctx.restore();
731
723
  }
732
724
  /**
@@ -2,7 +2,8 @@ import path from 'path'
2
2
  import sharp from 'sharp';
3
3
  import { cropOptions } from './types';
4
4
  import { createCanvas, loadImage } from '@napi-rs/canvas';
5
- import Jimp from 'jimp';
5
+ import fs from "fs";
6
+ import axios from "axios";
6
7
 
7
8
  export async function loadImages(imagePath: string) {
8
9
  try {
@@ -184,95 +185,67 @@ function createGradientImage(width: number, height: number, options: any, opacit
184
185
  return gradientCanvas.toBuffer('image/png');
185
186
  }
186
187
 
187
- export async function imgEffects(imagePath: string, filters: any[]) {
188
- try {
189
- let jimpImage;
190
-
191
- if (imagePath.startsWith("http")) {
192
- const pngBuffer = await converter(imagePath, "png");
193
- jimpImage = await Jimp.read(pngBuffer);
194
- } else {
195
- const imagePathResolved = path.join(process.cwd(), imagePath)
196
- jimpImage = await Jimp.read(imagePathResolved);
197
- }
198
-
199
- for (const filter of filters) {
200
- switch (filter.type) {
201
- case "flip":
202
- jimpImage.flip(filter.horizontal, filter.vertical);
203
- break;
204
- case "mirror":
205
- jimpImage.mirror(filter.horizontal, filter.vertical);
206
- break;
207
- case "rotate":
208
- jimpImage.rotate(filter.deg, filter.mode);
209
- break;
210
- case "brightness":
211
- jimpImage.brightness(filter.value);
212
- break;
213
- case "contrast":
214
- jimpImage.contrast(filter.value);
215
- break;
216
- case "dither565":
217
- jimpImage.dither565();
218
- break;
219
- case "greyscale":
220
- jimpImage.greyscale();
221
- break;
222
- case "invert":
223
- jimpImage.invert();
224
- break;
225
- case "normalize":
226
- jimpImage.normalize();
227
- break;
228
- case "autocrop":
229
- jimpImage.autocrop(filter.tolerance || 0);
230
- break;
231
- case "crop":
232
- jimpImage.crop(filter.x, filter.y, filter.w, filter.h);
233
- break;
234
- case "fade":
235
- jimpImage.fade(filter.factor);
236
- break;
237
- case "opacity":
238
- jimpImage.opacity(filter.factor);
239
- break;
240
- case "opaque":
241
- jimpImage.opaque();
242
- break;
243
- case "gaussian":
244
- jimpImage.gaussian(filter.radius);
245
- break;
246
- case "blur":
247
- jimpImage.blur(filter.radius);
248
- break;
249
- case "posterize":
250
- jimpImage.posterize(filter.levels);
251
- break;
252
- case "sepia":
253
- jimpImage.sepia();
254
- break;
255
- case "pixelate":
256
- jimpImage.pixelate(
257
- filter.size,
258
- filter.x,
259
- filter.y,
260
- filter.w,
261
- filter.h,
262
- );
263
- break;
264
- default:
265
- console.error(`Unsupported filter type: ${filter.type}`);
266
- }
267
- }
268
-
269
- const outputMimeType = Jimp.MIME_PNG;
270
-
271
- return await jimpImage.getBufferAsync(outputMimeType);
272
- } catch (error: any) {
273
- console.error("Error processing image:", error.message);
274
- throw new Error("Failed to process image");
188
+
189
+
190
+ export async function imgEffects(imagePath: string, filters: any[]) {
191
+ try {
192
+ let image;
193
+
194
+ if (imagePath.startsWith("http")) {
195
+ const response = await axios.get(imagePath, { responseType: "arraybuffer" });
196
+ image = await loadImage(response.data);
197
+ } else {
198
+ const imagePathResolved = path.resolve(process.cwd(), imagePath);
199
+ image = await loadImage(fs.readFileSync(imagePathResolved));
275
200
  }
201
+
202
+ const canvas = createCanvas(image.width, image.height);
203
+ const ctx = canvas.getContext("2d");
204
+
205
+ ctx.drawImage(image, 0, 0);
206
+
207
+ for (const filter of filters) {
208
+ switch (filter.type) {
209
+ case "flip":
210
+ flipCanvas(ctx, image.width, image.height, filter.horizontal, filter.vertical);
211
+ break;
212
+ case "rotate":
213
+ rotateCanvas(ctx, canvas, filter.deg);
214
+ break;
215
+ case "brightness":
216
+ adjustBrightness(ctx, filter.value);
217
+ break;
218
+ case "contrast":
219
+ adjustContrast(ctx, filter.value);
220
+ break;
221
+ case "invert":
222
+ invertColors(ctx);
223
+ break;
224
+ case "greyscale":
225
+ grayscale(ctx);
226
+ break;
227
+ case "sepia":
228
+ applySepia(ctx);
229
+ break;
230
+ case "blur":
231
+ applyBlur(ctx, filter.radius);
232
+ break;
233
+ case "posterize":
234
+ posterize(ctx, filter.levels);
235
+ break;
236
+ case "pixelate":
237
+ pixelate(ctx, filter.size, filter.x, filter.y, filter.w, filter.h);
238
+ break;
239
+ default:
240
+ console.error(`Unsupported filter type: ${filter.type}`);
241
+ }
242
+ }
243
+
244
+ return canvas.toBuffer("image/png");
245
+ } catch (error: any) {
246
+ console.error("Error processing image:", error.message);
247
+ throw new Error("Failed to process image");
248
+ }
276
249
  }
277
250
 
278
251
 
@@ -509,3 +482,187 @@ export async function bgRemoval(imgURL: string, API_KEY: string): Promise<Buffer
509
482
  return undefined;
510
483
  }
511
484
  }
485
+
486
+
487
+ function flipCanvas(ctx: any, width: number, height: number, horizontal = false, vertical = false) {
488
+ const imageData = ctx.getImageData(0, 0, width, height);
489
+ const pixels = imageData.data;
490
+
491
+ const newData = new Uint8ClampedArray(pixels.length);
492
+
493
+ for (let y = 0; y < height; y++) {
494
+ for (let x = 0; x < width; x++) {
495
+ const srcIndex = (y * width + x) * 4;
496
+ let destX = horizontal ? width - x - 1 : x;
497
+ let destY = vertical ? height - y - 1 : y;
498
+ const destIndex = (destY * width + destX) * 4;
499
+
500
+ newData[destIndex] = pixels[srcIndex];
501
+ newData[destIndex + 1] = pixels[srcIndex + 1];
502
+ newData[destIndex + 2] = pixels[srcIndex + 2];
503
+ newData[destIndex + 3] = pixels[srcIndex + 3];
504
+ }
505
+ }
506
+
507
+ ctx.putImageData(new ImageData(newData, width, height), 0, 0);
508
+ }
509
+
510
+ function rotateCanvas(ctx: any, canvas: any, degrees: number) {
511
+ const radians = (degrees * Math.PI) / 180;
512
+ const newCanvas = createCanvas(canvas.width, canvas.height);
513
+ const newCtx = newCanvas.getContext("2d");
514
+
515
+ newCtx.translate(canvas.width / 2, canvas.height / 2);
516
+ newCtx.rotate(radians);
517
+ newCtx.drawImage(canvas, -canvas.width / 2, -canvas.height / 2);
518
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
519
+ ctx.drawImage(newCanvas, 0, 0);
520
+ }
521
+
522
+ function adjustBrightness(ctx: any, value: number) {
523
+ const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
524
+ const pixels = imageData.data;
525
+ for (let i = 0; i < pixels.length; i += 4) {
526
+ pixels[i] += 255 * value;
527
+ pixels[i + 1] += 255 * value;
528
+ pixels[i + 2] += 255 * value;
529
+ }
530
+ ctx.putImageData(imageData, 0, 0);
531
+ }
532
+
533
+ function adjustContrast(ctx: any, value: number) {
534
+ const factor = (259 * (value + 255)) / (255 * (259 - value));
535
+ const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
536
+ const pixels = imageData.data;
537
+ for (let i = 0; i < pixels.length; i += 4) {
538
+ pixels[i] = factor * (pixels[i] - 128) + 128;
539
+ pixels[i + 1] = factor * (pixels[i + 1] - 128) + 128;
540
+ pixels[i + 2] = factor * (pixels[i + 2] - 128) + 128;
541
+ }
542
+ ctx.putImageData(imageData, 0, 0);
543
+ }
544
+
545
+ function invertColors(ctx: any) {
546
+ const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
547
+ const pixels = imageData.data;
548
+ for (let i = 0; i < pixels.length; i += 4) {
549
+ pixels[i] = 255 - pixels[i];
550
+ pixels[i + 1] = 255 - pixels[i + 1];
551
+ pixels[i + 2] = 255 - pixels[i + 2];
552
+ }
553
+ ctx.putImageData(imageData, 0, 0);
554
+ }
555
+
556
+ function grayscale(ctx: any) {
557
+ const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
558
+ const pixels = imageData.data;
559
+ for (let i = 0; i < pixels.length; i += 4) {
560
+ const avg = (pixels[i] + pixels[i + 1] + pixels[i + 2]) / 3;
561
+ pixels[i] = pixels[i + 1] = pixels[i + 2] = avg;
562
+ }
563
+ ctx.putImageData(imageData, 0, 0);
564
+ }
565
+
566
+ function applySepia(ctx: any) {
567
+ const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
568
+ const pixels = imageData.data;
569
+ for (let i = 0; i < pixels.length; i += 4) {
570
+ const r = pixels[i];
571
+ const g = pixels[i + 1];
572
+ const b = pixels[i + 2];
573
+
574
+ pixels[i] = r * 0.393 + g * 0.769 + b * 0.189;
575
+ pixels[i + 1] = r * 0.349 + g * 0.686 + b * 0.168;
576
+ pixels[i + 2] = r * 0.272 + g * 0.534 + b * 0.131;
577
+ }
578
+ ctx.putImageData(imageData, 0, 0);
579
+ }
580
+
581
+
582
+ function applyBlur(ctx: any, radius: number) {
583
+ if (radius <= 0) return;
584
+ const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
585
+ const pixels = imageData.data;
586
+ const width = ctx.canvas.width;
587
+ const height = ctx.canvas.height;
588
+
589
+ const blurSize = Math.floor(radius);
590
+ for (let y = blurSize; y < height - blurSize; y++) {
591
+ for (let x = blurSize; x < width - blurSize; x++) {
592
+ let r = 0, g = 0, b = 0, count = 0;
593
+
594
+ for (let dy = -blurSize; dy <= blurSize; dy++) {
595
+ for (let dx = -blurSize; dx <= blurSize; dx++) {
596
+ const index = ((y + dy) * width + (x + dx)) * 4;
597
+ r += pixels[index];
598
+ g += pixels[index + 1];
599
+ b += pixels[index + 2];
600
+ count++;
601
+ }
602
+ }
603
+
604
+ const index = (y * width + x) * 4;
605
+ pixels[index] = r / count;
606
+ pixels[index + 1] = g / count;
607
+ pixels[index + 2] = b / count;
608
+ }
609
+ }
610
+
611
+ ctx.putImageData(imageData, 0, 0);
612
+ }
613
+
614
+ function posterize(ctx: any, levels: number) {
615
+ if (levels < 2 || levels > 255) return;
616
+ const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
617
+ const pixels = imageData.data;
618
+ const factor = 255 / (levels - 1);
619
+
620
+ for (let i = 0; i < pixels.length; i += 4) {
621
+ pixels[i] = Math.round(pixels[i] / factor) * factor;
622
+ pixels[i + 1] = Math.round(pixels[i + 1] / factor) * factor;
623
+ pixels[i + 2] = Math.round(pixels[i + 2] / factor) * factor;
624
+ }
625
+
626
+ ctx.putImageData(imageData, 0, 0);
627
+ }
628
+
629
+ function pixelate(ctx: any, size: number, startX = 0, startY = 0, width = ctx.canvas.width, height = ctx.canvas.height) {
630
+ if (size < 1) return;
631
+ const imageData = ctx.getImageData(startX, startY, width, height);
632
+ const pixels = imageData.data;
633
+
634
+ for (let y = 0; y < height; y += size) {
635
+ for (let x = 0; x < width; x += size) {
636
+ let r = 0, g = 0, b = 0, count = 0;
637
+
638
+ for (let dy = 0; dy < size; dy++) {
639
+ for (let dx = 0; dx < size; dx++) {
640
+ if (x + dx < width && y + dy < height) {
641
+ const index = ((y + dy) * width + (x + dx)) * 4;
642
+ r += pixels[index];
643
+ g += pixels[index + 1];
644
+ b += pixels[index + 2];
645
+ count++;
646
+ }
647
+ }
648
+ }
649
+
650
+ r = Math.floor(r / count);
651
+ g = Math.floor(g / count);
652
+ b = Math.floor(b / count);
653
+
654
+ for (let dy = 0; dy < size; dy++) {
655
+ for (let dx = 0; dx < size; dx++) {
656
+ if (x + dx < width && y + dy < height) {
657
+ const index = ((y + dy) * width + (x + dx)) * 4;
658
+ pixels[index] = r;
659
+ pixels[index + 1] = g;
660
+ pixels[index + 2] = b;
661
+ }
662
+ }
663
+ }
664
+ }
665
+ }
666
+
667
+ ctx.putImageData(imageData, startX, startY);
668
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apexify.js",
3
- "version": "4.5.50",
3
+ "version": "4.5.51",
4
4
  "description": "Unlimited AI models and Canvas library. Supports ts & js (supports front/back end).",
5
5
  "author": "zenith-79",
6
6
  "license": "MIT",
@@ -43,6 +43,8 @@
43
43
  "custom ai",
44
44
  "openai",
45
45
  "ai",
46
+ "ai video",
47
+ "video generating",
46
48
  "image-vision",
47
49
  "vision",
48
50
  "image vision",
@@ -132,6 +134,11 @@
132
134
  "chat bot",
133
135
  "speech recognition",
134
136
  "voice message",
137
+ "text2speech",
138
+ "texttospeech",
139
+ "transcription",
140
+ "speech2text",
141
+ "speechtotext",
135
142
  "trained ai",
136
143
  "trained model",
137
144
  "image",
@@ -222,8 +229,6 @@
222
229
  "@iamtraction/google-translate": "^2.0.1",
223
230
  "@napi-rs/canvas": "^0.1.53",
224
231
  "axios": "^1.7.7",
225
- "canvas": "^3.0.1",
226
- "chart.js": "^4.4.7",
227
232
  "csv-parse": "^5.5.6",
228
233
  "discord.js": "^14.15.3",
229
234
  "fluent-ffmpeg": "^2.1.3",
@@ -232,11 +237,9 @@
232
237
  "groq-sdk": "^0.5.0",
233
238
  "hercai": "^12.4.0",
234
239
  "imgur": "^2.4.2",
235
- "jimp": "^0.22.12",
236
240
  "openai": "^4.71.1",
237
241
  "pdf-parse": "^1.1.1",
238
- "quickchart": "^1.1.4",
239
- "sharp": "^0.33.4",
242
+ "sharp": "^0.33.5",
240
243
  "tesseract.js": "^5.1.0",
241
244
  "verse.db": "^2.2.15"
242
245
  },