summaryrefslogtreecommitdiff
path: root/packages/backend/src/core/ImageProcessingService.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/backend/src/core/ImageProcessingService.ts')
-rw-r--r--packages/backend/src/core/ImageProcessingService.ts99
1 files changed, 99 insertions, 0 deletions
diff --git a/packages/backend/src/core/ImageProcessingService.ts b/packages/backend/src/core/ImageProcessingService.ts
new file mode 100644
index 0000000000..d215be2131
--- /dev/null
+++ b/packages/backend/src/core/ImageProcessingService.ts
@@ -0,0 +1,99 @@
+import { Inject, Injectable } from '@nestjs/common';
+import sharp from 'sharp';
+import { DI } from '@/di-symbols.js';
+import { Config } from '@/config.js';
+
+export type IImage = {
+ data: Buffer;
+ ext: string | null;
+ type: string;
+};
+
+@Injectable()
+export class ImageProcessingService {
+ constructor(
+ @Inject(DI.config)
+ private config: Config,
+ ) {
+ }
+
+ /**
+ * Convert to JPEG
+ * with resize, remove metadata, resolve orientation, stop animation
+ */
+ public async convertToJpeg(path: string, width: number, height: number): Promise<IImage> {
+ return this.convertSharpToJpeg(await sharp(path), width, height);
+ }
+
+ public async convertSharpToJpeg(sharp: sharp.Sharp, width: number, height: number): Promise<IImage> {
+ const data = await sharp
+ .resize(width, height, {
+ fit: 'inside',
+ withoutEnlargement: true,
+ })
+ .rotate()
+ .jpeg({
+ quality: 85,
+ progressive: true,
+ })
+ .toBuffer();
+
+ return {
+ data,
+ ext: 'jpg',
+ type: 'image/jpeg',
+ };
+ }
+
+ /**
+ * Convert to WebP
+ * with resize, remove metadata, resolve orientation, stop animation
+ */
+ public async convertToWebp(path: string, width: number, height: number, quality = 85): Promise<IImage> {
+ return this.convertSharpToWebp(await sharp(path), width, height, quality);
+ }
+
+ public async convertSharpToWebp(sharp: sharp.Sharp, width: number, height: number, quality = 85): Promise<IImage> {
+ const data = await sharp
+ .resize(width, height, {
+ fit: 'inside',
+ withoutEnlargement: true,
+ })
+ .rotate()
+ .webp({
+ quality,
+ })
+ .toBuffer();
+
+ return {
+ data,
+ ext: 'webp',
+ type: 'image/webp',
+ };
+ }
+
+ /**
+ * Convert to PNG
+ * with resize, remove metadata, resolve orientation, stop animation
+ */
+ public async convertToPng(path: string, width: number, height: number): Promise<IImage> {
+ return this.convertSharpToPng(await sharp(path), width, height);
+ }
+
+ public async convertSharpToPng(sharp: sharp.Sharp, width: number, height: number): Promise<IImage> {
+ const data = await sharp
+ .resize(width, height, {
+ fit: 'inside',
+ withoutEnlargement: true,
+ })
+ .rotate()
+ .png()
+ .toBuffer();
+
+ return {
+ data,
+ ext: 'png',
+ type: 'image/png',
+ };
+ }
+}