From 3d8bbedf1bbd501d3ad5e3c26e5e5005ed2d8371 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 15 May 2019 21:27:20 +0900 Subject: [PATCH] =?UTF-8?q?GIF=E3=81=AE=E3=82=B5=E3=83=A0=E3=83=8D?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E3=81=8C=E7=94=9F=E6=88=90=E3=81=95=E3=82=8C?= =?UTF-8?q?=E3=81=AA=E3=81=84=E3=81=AE=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #4728 --- src/server/proxy/proxy-media.ts | 6 ++-- src/services/drive/add-file.ts | 18 ++++++---- .../drive/generate-video-thumbnail.ts | 4 +-- src/services/drive/image-processor.ts | 33 +++++++++++++++++-- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/server/proxy/proxy-media.ts b/src/server/proxy/proxy-media.ts index 357715bb9..e16665f6c 100644 --- a/src/server/proxy/proxy-media.ts +++ b/src/server/proxy/proxy-media.ts @@ -1,7 +1,7 @@ import * as fs from 'fs'; import * as Koa from 'koa'; import { serverLogger } from '..'; -import { IImage, ConvertToPng, ConvertToJpeg } from '../../services/drive/image-processor'; +import { IImage, convertToPng, convertToJpeg } from '../../services/drive/image-processor'; import { createTemp } from '../../misc/create-temp'; import { downloadUrl } from '../../misc/donwload-url'; import { detectMine } from '../../misc/detect-mine'; @@ -20,9 +20,9 @@ export async function proxyMedia(ctx: Koa.BaseContext) { let image: IImage; if ('static' in ctx.query && ['image/png', 'image/gif'].includes(type)) { - image = await ConvertToPng(path, 498, 280); + image = await convertToPng(path, 498, 280); } else if ('preview' in ctx.query && ['image/jpeg', 'image/png', 'image/gif'].includes(type)) { - image = await ConvertToJpeg(path, 200, 200); + image = await convertToJpeg(path, 200, 200); } else { image = { data: fs.readFileSync(path), diff --git a/src/services/drive/add-file.ts b/src/services/drive/add-file.ts index c67ee475a..949089ede 100644 --- a/src/services/drive/add-file.ts +++ b/src/services/drive/add-file.ts @@ -12,7 +12,7 @@ import config from '../../config'; import { fetchMeta } from '../../misc/fetch-meta'; import { GenerateVideoThumbnail } from './generate-video-thumbnail'; import { driveLogger } from './logger'; -import { IImage, ConvertToJpeg, ConvertToWebp, ConvertToPng } from './image-processor'; +import { IImage, convertToJpeg, convertToWebp, convertToPng, convertToGif, convertToApng } from './image-processor'; import { contentDisposition } from '../../misc/content-disposition'; import { detectMine } from '../../misc/detect-mine'; import { DriveFiles, DriveFolders, Users, Instances, UserProfiles } from '../../models'; @@ -149,11 +149,15 @@ export async function generateAlts(path: string, type: string, generateWeb: bool logger.info(`creating web image`); if (['image/jpeg'].includes(type)) { - webpublic = await ConvertToJpeg(path, 2048, 2048); + webpublic = await convertToJpeg(path, 2048, 2048); } else if (['image/webp'].includes(type)) { - webpublic = await ConvertToWebp(path, 2048, 2048); + webpublic = await convertToWebp(path, 2048, 2048); } else if (['image/png'].includes(type)) { - webpublic = await ConvertToPng(path, 2048, 2048); + webpublic = await convertToPng(path, 2048, 2048); + } else if (['image/apng', 'image/vnd.mozilla.apng'].includes(type)) { + webpublic = await convertToApng(path); + } else if (['image/gif'].includes(type)) { + webpublic = await convertToGif(path); } else { logger.info(`web image not created (not an image)`); } @@ -166,9 +170,11 @@ export async function generateAlts(path: string, type: string, generateWeb: bool let thumbnail: IImage | null = null; if (['image/jpeg', 'image/webp'].includes(type)) { - thumbnail = await ConvertToJpeg(path, 498, 280); + thumbnail = await convertToJpeg(path, 498, 280); } else if (['image/png'].includes(type)) { - thumbnail = await ConvertToPng(path, 498, 280); + thumbnail = await convertToPng(path, 498, 280); + } else if (['image/gif'].includes(type)) { + thumbnail = await convertToGif(path); } else if (type.startsWith('video/')) { try { thumbnail = await GenerateVideoThumbnail(path); diff --git a/src/services/drive/generate-video-thumbnail.ts b/src/services/drive/generate-video-thumbnail.ts index 5d7efff27..c2646182d 100644 --- a/src/services/drive/generate-video-thumbnail.ts +++ b/src/services/drive/generate-video-thumbnail.ts @@ -1,6 +1,6 @@ import * as fs from 'fs'; import * as tmp from 'tmp'; -import { IImage, ConvertToJpeg } from './image-processor'; +import { IImage, convertToJpeg } from './image-processor'; const ThumbnailGenerator = require('video-thumbnail-generator').default; export async function GenerateVideoThumbnail(path: string): Promise { @@ -23,7 +23,7 @@ export async function GenerateVideoThumbnail(path: string): Promise { const outPath = `${outDir}/output.png`; - const thumbnail = await ConvertToJpeg(outPath, 498, 280); + const thumbnail = await convertToJpeg(outPath, 498, 280); // cleanup fs.unlinkSync(outPath); diff --git a/src/services/drive/image-processor.ts b/src/services/drive/image-processor.ts index 89ac331ca..4b8db0e0c 100644 --- a/src/services/drive/image-processor.ts +++ b/src/services/drive/image-processor.ts @@ -1,4 +1,5 @@ import * as sharp from 'sharp'; +import * as fs from 'fs'; export type IImage = { data: Buffer; @@ -10,7 +11,7 @@ export type IImage = { * Convert to JPEG * with resize, remove metadata, resolve orientation, stop animation */ -export async function ConvertToJpeg(path: string, width: number, height: number): Promise { +export async function convertToJpeg(path: string, width: number, height: number): Promise { const data = await sharp(path) .resize(width, height, { fit: 'inside', @@ -34,7 +35,7 @@ export async function ConvertToJpeg(path: string, width: number, height: number) * Convert to WebP * with resize, remove metadata, resolve orientation, stop animation */ -export async function ConvertToWebp(path: string, width: number, height: number): Promise { +export async function convertToWebp(path: string, width: number, height: number): Promise { const data = await sharp(path) .resize(width, height, { fit: 'inside', @@ -57,7 +58,7 @@ export async function ConvertToWebp(path: string, width: number, height: number) * Convert to PNG * with resize, remove metadata, resolve orientation, stop animation */ -export async function ConvertToPng(path: string, width: number, height: number): Promise { +export async function convertToPng(path: string, width: number, height: number): Promise { const data = await sharp(path) .resize(width, height, { fit: 'inside', @@ -73,3 +74,29 @@ export async function ConvertToPng(path: string, width: number, height: number): type: 'image/png' }; } + +/** + * Convert to GIF (Actually just NOP) + */ +export async function convertToGif(path: string): Promise { + const data = await fs.promises.readFile(path); + + return { + data, + ext: 'gif', + type: 'image/gif' + }; +} + +/** + * Convert to APNG (Actually just NOP) + */ +export async function convertToApng(path: string): Promise { + const data = await fs.promises.readFile(path); + + return { + data, + ext: 'apng', + type: 'image/apng' + }; +}