summaryrefslogtreecommitdiff
path: root/packages/backend/src/core/ImageProcessingService.ts
blob: 3a50361a42e563f5d7f0516ae3df43da0b10e81d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { Inject, Injectable } from '@nestjs/common';
import sharp from 'sharp';
import { DI } from '@/di-symbols.js';
import type { 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',
		};
	}
}