 8b46edeccf
			
		
	
	8b46edeccf
	
	
	
		
			
			* fix(server): /emoji to accept `@.` host expression
* fix(client): use MkEmoji for custom emoji in MkEmojiPicker
* change convertToWebp
* nanka iroiro
* remove
* fix
* nearLosslessは労多くして益少なしなのでやめる
* do not cleanup tmp for development
* update sharp.js to 0.31.3
* mixed: true
* fix MkAutocomplete of 912791b3ab
* clean up
* https://github.com/misskey-dev/misskey/pull/9431#discussion_r1059215943
		
	
		
			
				
	
	
		
			115 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| 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;
 | |
| };
 | |
| 
 | |
| export const webpDefault: sharp.WebpOptions = {
 | |
| 	quality: 85,
 | |
| 	alphaQuality: 95,
 | |
| 	lossless: false,
 | |
| 	nearLossless: false,
 | |
| 	smartSubsample: true,
 | |
| 	mixed: true,
 | |
| };
 | |
| 
 | |
| import { bindThis } from '@/decorators.js';
 | |
| 
 | |
| @Injectable()
 | |
| export class ImageProcessingService {
 | |
| 	constructor(
 | |
| 		@Inject(DI.config)
 | |
| 		private config: Config,
 | |
| 	) {
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Convert to JPEG
 | |
| 	 *   with resize, remove metadata, resolve orientation, stop animation
 | |
| 	 */
 | |
| 	@bindThis
 | |
| 	public async convertToJpeg(path: string, width: number, height: number): Promise<IImage> {
 | |
| 		return this.convertSharpToJpeg(await sharp(path), width, height);
 | |
| 	}
 | |
| 
 | |
| 	@bindThis
 | |
| 	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
 | |
| 	 */
 | |
| 	@bindThis
 | |
| 	public async convertToWebp(path: string, width: number, height: number, options: sharp.WebpOptions = webpDefault): Promise<IImage> {
 | |
| 		return this.convertSharpToWebp(await sharp(path), width, height, options);
 | |
| 	}
 | |
| 
 | |
| 	@bindThis
 | |
| 	public async convertSharpToWebp(sharp: sharp.Sharp, width: number, height: number, options: sharp.WebpOptions = webpDefault): Promise<IImage> {
 | |
| 		const data = await sharp
 | |
| 			.resize(width, height, {
 | |
| 				fit: 'inside',
 | |
| 				withoutEnlargement: true,
 | |
| 			})
 | |
| 			.rotate()
 | |
| 			.webp(options)
 | |
| 			.toBuffer();
 | |
| 
 | |
| 		return {
 | |
| 			data,
 | |
| 			ext: 'webp',
 | |
| 			type: 'image/webp',
 | |
| 		};
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Convert to PNG
 | |
| 	 *   with resize, remove metadata, resolve orientation, stop animation
 | |
| 	 */
 | |
| 	@bindThis
 | |
| 	public async convertToPng(path: string, width: number, height: number): Promise<IImage> {
 | |
| 		return this.convertSharpToPng(await sharp(path), width, height);
 | |
| 	}
 | |
| 
 | |
| 	@bindThis
 | |
| 	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',
 | |
| 		};
 | |
| 	}
 | |
| }
 |