summaryrefslogtreecommitdiff
path: root/packages/backend/src/core/DriveService.ts
diff options
context:
space:
mode:
authortamaina <tamaina@hotmail.co.jp>2023-03-11 14:11:40 +0900
committerGitHub <noreply@github.com>2023-03-11 14:11:40 +0900
commit88e3d3e8cbe26c0280308e819965a64a91491f90 (patch)
tree25c9039f6fa6725af4fa5a7de5decb71f2a3150b /packages/backend/src/core/DriveService.ts
parentUpdate CHANGELOG.md (diff)
downloadsharkey-88e3d3e8cbe26c0280308e819965a64a91491f90.tar.gz
sharkey-88e3d3e8cbe26c0280308e819965a64a91491f90.tar.bz2
sharkey-88e3d3e8cbe26c0280308e819965a64a91491f90.zip
enhance(server): 画像圧縮周り(主にサムネイルの仕様)の変更 (#10287)
* DriveService, is-mime-image * static, previewをavifに, アニメーション画像でもthumbnailを生成 * fallback * animated: true * fix * avatarはwebp * revert ?? file.url --------- Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
Diffstat (limited to 'packages/backend/src/core/DriveService.ts')
-rw-r--r--packages/backend/src/core/DriveService.ts37
1 files changed, 16 insertions, 21 deletions
diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts
index dfaacffc1d..7eccf4b3b1 100644
--- a/packages/backend/src/core/DriveService.ts
+++ b/packages/backend/src/core/DriveService.ts
@@ -2,6 +2,7 @@ import * as fs from 'node:fs';
import { Inject, Injectable } from '@nestjs/common';
import { v4 as uuid } from 'uuid';
import sharp from 'sharp';
+import { sharpBmp } from 'sharp-read-bmp';
import { IsNull } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { DriveFilesRepository, UsersRepository, DriveFoldersRepository, UserProfilesRepository } from '@/models/index.js';
@@ -34,6 +35,7 @@ import { FileInfoService } from '@/core/FileInfoService.js';
import { bindThis } from '@/decorators.js';
import { RoleService } from '@/core/RoleService.js';
import { correctFilename } from '@/misc/correct-filename.js';
+import { isMimeImage } from '@/misc/is-mime-image.js';
import type S3 from 'aws-sdk/clients/s3.js';
type AddFileArgs = {
@@ -274,8 +276,8 @@ export class DriveService {
}
}
- if (!['image/jpeg', 'image/png', 'image/webp', 'image/avif', 'image/svg+xml'].includes(type)) {
- this.registerLogger.debug('web image and thumbnail not created (not an required file)');
+ if (!isMimeImage(type, 'sharp-convertible-image-with-bmp')) {
+ this.registerLogger.debug('web image and thumbnail not created (cannot convert by sharp)');
return {
webpublic: null,
thumbnail: null,
@@ -284,22 +286,16 @@ export class DriveService {
let img: sharp.Sharp | null = null;
let satisfyWebpublic: boolean;
+ let isAnimated: boolean;
try {
- img = sharp(path);
+ img = await sharpBmp(path, type);
const metadata = await img.metadata();
- const isAnimated = metadata.pages && metadata.pages > 1;
-
- // skip animated
- if (isAnimated) {
- return {
- webpublic: null,
- thumbnail: null,
- };
- }
+ isAnimated = !!(metadata.pages && metadata.pages > 1);
satisfyWebpublic = !!(
- type !== 'image/svg+xml' && type !== 'image/avif' &&
+ type !== 'image/svg+xml' && // security reason
+ type !== 'image/avif' && // not supported by Mastodon
!(metadata.exif ?? metadata.iptc ?? metadata.xmp ?? metadata.tifftagPhotoshop) &&
metadata.width && metadata.width <= 2048 &&
metadata.height && metadata.height <= 2048
@@ -315,15 +311,13 @@ export class DriveService {
// #region webpublic
let webpublic: IImage | null = null;
- if (generateWeb && !satisfyWebpublic) {
+ if (generateWeb && !satisfyWebpublic && !isAnimated) {
this.registerLogger.info('creating web image');
try {
- if (type === 'image/jpeg') {
- webpublic = await this.imageProcessingService.convertSharpToJpeg(img, 2048, 2048);
- } else if (['image/webp', 'image/avif'].includes(type)) {
+ if (['image/jpeg', 'image/webp', 'image/avif'].includes(type)) {
webpublic = await this.imageProcessingService.convertSharpToWebp(img, 2048, 2048);
- } else if (['image/png', 'image/svg+xml'].includes(type)) {
+ } else if (['image/png', 'image/bmp', 'image/svg+xml'].includes(type)) {
webpublic = await this.imageProcessingService.convertSharpToPng(img, 2048, 2048);
} else {
this.registerLogger.debug('web image not created (not an required image)');
@@ -333,6 +327,7 @@ export class DriveService {
}
} else {
if (satisfyWebpublic) this.registerLogger.info('web image not created (original satisfies webpublic)');
+ else if (isAnimated) this.registerLogger.info('web image not created (animated image)');
else this.registerLogger.info('web image not created (from remote)');
}
// #endregion webpublic
@@ -341,10 +336,10 @@ export class DriveService {
let thumbnail: IImage | null = null;
try {
- if (['image/jpeg', 'image/webp', 'image/avif', 'image/png', 'image/svg+xml'].includes(type)) {
- thumbnail = await this.imageProcessingService.convertSharpToWebp(img, 498, 280);
+ if (isAnimated) {
+ thumbnail = await this.imageProcessingService.convertSharpToWebp(sharp(path, { animated: true }), 374, 317, { alphaQuality: 70 });
} else {
- this.registerLogger.debug('thumbnail not created (not an required file)');
+ thumbnail = await this.imageProcessingService.convertSharpToAvif(img, 498, 422);
}
} catch (err) {
this.registerLogger.warn('thumbnail not created (an error occured)', err as Error);