import { Injectable } from '@nestjs/common'; import { FullMime, ImageMime, SupportedMimeCategory } from 'picsur-shared/dist/dto/mimes.dto'; import { AsyncFailable, Fail, FT } from 'picsur-shared/dist/types'; import { QOIColorSpace, QOIencode } from 'qoi-img'; import { ImageResult } from './imageresult'; import { UniversalSharp } from './universal-sharp'; @Injectable() export class ImageProcessorService { public async process( image: Buffer, mime: FullMime, ): AsyncFailable { if (mime.type === SupportedMimeCategory.Image) { return await this.processStill(image, mime); } else if (mime.type === SupportedMimeCategory.Animation) { return await this.processAnimation(image, mime); } else { return Fail(FT.SysValidation, 'Unsupported mime type'); } } private async processStill( image: Buffer, mime: FullMime, ): AsyncFailable { let processedMime = mime.mime; let sharpImage = UniversalSharp(image, mime); processedMime = ImageMime.QOI; sharpImage = sharpImage.toColorspace('srgb'); const processedImage = await sharpImage.raw().toBuffer({ resolveWithObject: true, }); if ( processedImage.info.width >= 32768 || processedImage.info.height >= 32768 ) { return Fail(FT.UsrValidation, 'Image too large'); } // Png can be more efficient than QOI, but its just sooooooo slow const qoiImage = QOIencode(processedImage.data, { channels: processedImage.info.channels, colorspace: QOIColorSpace.SRGB, height: processedImage.info.height, width: processedImage.info.width, }); return { image: qoiImage, mime: processedMime, }; } private async processAnimation( image: Buffer, mime: FullMime, ): AsyncFailable { // Apng and gif are stored as is for now return { image: image, mime: mime.mime, }; } }