diff options
author | bobzel <zzzman@gmail.com> | 2024-09-11 10:37:03 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2024-09-11 10:37:03 -0400 |
commit | 1ed378a79d545516a42121819d7049c20aecbc8c (patch) | |
tree | b1f112b03b1dbf0c3b23ec7a019c7da06c1aed3f /src/server/DashUploadUtils.ts | |
parent | 62eda6aa6af765526fd065dc271b9d53e2b28002 (diff) | |
parent | d3817d1c03b68ab2c69ab5ccfb5e8d6943df8f25 (diff) |
Merge branch 'master' into zach-starter
Diffstat (limited to 'src/server/DashUploadUtils.ts')
-rw-r--r-- | src/server/DashUploadUtils.ts | 94 |
1 files changed, 53 insertions, 41 deletions
diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index 8f012f783..1e55a885a 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -1,5 +1,5 @@ import axios from 'axios'; -import { spawn, exec } from 'child_process'; +import { exec, spawn } from 'child_process'; import { green, red } from 'colors'; import { ExifData, ExifImage } from 'exif'; import * as exifr from 'exifr'; @@ -8,8 +8,7 @@ import * as formidable from 'formidable'; import { File } from 'formidable'; import * as fs from 'fs'; import { createReadStream, createWriteStream, existsSync, readFileSync, rename, unlinkSync, writeFile } from 'fs'; -import Jimp from 'jimp'; -import * as autorotate from 'jpeg-autorotate'; +import { Jimp } from 'jimp'; import * as md5File from 'md5-file'; import * as path from 'path'; import { basename } from 'path'; @@ -23,6 +22,44 @@ import { AcceptableMedia, Upload } from './SharedMediaTypes'; import { Directory, clientPathToFile, filesDirectory, pathToDirectory, publicDirectory, serverPathToFile } from './SocketData'; import { resolvedServerUrl } from './server_Initialization'; +import { Worker, isMainThread, parentPort } from 'worker_threads'; + +// Create an array to store worker threads +enum workertasks { + JIMP = 'jimp', +} +const JimpWorker: Worker | undefined = isMainThread ? new Worker(__filename) : undefined; +export const workerResample = (imgSourcePath: string, outputPath: string, origSuffix: SizeSuffix, unlinkSource: boolean) => { + JimpWorker?.postMessage({ task: workertasks.JIMP, imgSourcePath, outputPath, origSuffix, unlinkSource }); +}; + +if (isMainThread) { + // main thread code if needed ... +} else { + // Worker thread code - Listens for messages from the main thread + parentPort?.on('message', message => { + switch (message.task) { + case workertasks.JIMP: + return workerResampleImage(message); + default: + } + }); + + async function workerResampleImage(message: { imgSourcePath: string; outputPath: string; origSuffix: string; unlinkSource: boolean }) { + const { imgSourcePath, outputPath, origSuffix, unlinkSource } = message; + const sizes = !origSuffix ? [{ width: 400, suffix: SizeSuffix.Medium }] : DashUploadUtils.imageResampleSizes(path.extname(imgSourcePath)); + // prettier-ignore + Jimp.read(imgSourcePath) + .then(img => + sizes.forEach(({ width, suffix }) => + img.resize({ w: width || img.bitmap.width }) + .write(InjectSize(outputPath, suffix) as `${string}.${string}`) + )) + .catch(e => console.log('Error Jimp:', e)) + .finally(() => unlinkSource && unlinkSync(imgSourcePath)); + } +} + // eslint-disable-next-line @typescript-eslint/no-var-requires const requestImageSize = require('../client/util/request-image-size'); @@ -277,15 +314,6 @@ export namespace DashUploadUtils { } }; - async function correctRotation(imgSourcePath: string) { - const buffer = fs.readFileSync(imgSourcePath); - try { - return (await autorotate.rotate(buffer, { quality: 30 })).buffer; - } catch (e) { - return buffer; - } - } - /** * define the resizers to use * @param ext the extension @@ -310,38 +338,23 @@ export namespace DashUploadUtils { * @param outputDirectory the directory to output to, usually Directory.Images * @returns a map with suffixes as keys and resized filenames as values. */ - export async function outputResizedImages(imgSourcePath: string, outputFileName: string, outputDirectory: string) { + export async function outputResizedImages(imgSourcePath: string, outputFileName: string, unlinkSource: boolean) { const writtenFiles: { [suffix: string]: string } = {}; + const outputPath = path.resolve(pathToDirectory(Directory.images), outputFileName); const sizes = imageResampleSizes(path.extname(outputFileName)); - const imgBuffer = await correctRotation(imgSourcePath); const imgReadStream = new Duplex(); - imgReadStream.push(imgBuffer); + imgReadStream.push(fs.readFileSync(imgSourcePath)); imgReadStream.push(null); - const outputPath = (suffix: SizeSuffix) => { - writtenFiles[suffix] = InjectSize(outputFileName, suffix); - return path.resolve(outputDirectory, writtenFiles[suffix]); - }; await Promise.all( - sizes.filter(({ width }) => !width).map(({ suffix }) => - new Promise<void>(res => { - imgReadStream.pipe(createWriteStream(outputPath(suffix))).on('close', res); - }) + sizes.map(({ suffix }) => + new Promise<unknown>(res => + imgReadStream.pipe(createWriteStream(writtenFiles[suffix] = InjectSize(outputPath, suffix))).on('close', res) + ) )); // prettier-ignore - return Jimp.read(imgBuffer) - .then(async imgIn => { - let img = imgIn; - await Promise.all( sizes.filter(({ width }) => width).map(({ width, suffix }) => { - img = img.resize(width, Jimp.AUTO).write(outputPath(suffix)); - return img; - } )); // prettier-ignore - return writtenFiles; - }) - .catch(e => { - console.log('ERROR' + e); - return writtenFiles; - }); + workerResample(imgSourcePath, outputPath, SizeSuffix.Original, unlinkSource); + return writtenFiles; } /** @@ -387,8 +400,9 @@ export namespace DashUploadUtils { writtenFiles = {}; } } else { + const unlinkSrcWhenFinished = isLocal().test(source) && cleanUp; try { - writtenFiles = await outputResizedImages(metadata.source, resolved, pathToDirectory(Directory.images)); + writtenFiles = await outputResizedImages(metadata.source, resolved, unlinkSrcWhenFinished); } catch (e) { // input is a blob or other, try reading it to create a metadata source file. const reqSource = request(metadata.source); @@ -400,16 +414,14 @@ export namespace DashUploadUtils { .on('close', () => res()) .on('error', () => rej()); }); - writtenFiles = await outputResizedImages(readSource, resolved, pathToDirectory(Directory.images)); + writtenFiles = await outputResizedImages(readSource, resolved, unlinkSrcWhenFinished); fs.unlink(readSource, err => console.log("Couldn't unlink temporary image file:" + readSource, err)); } } Array.from(Object.keys(writtenFiles)).forEach(suffix => { information.accessPaths[suffix] = getAccessPaths(images, writtenFiles[suffix]); }); - if (isLocal().test(source) && cleanUp) { - unlinkSync(source); - } + return information; }; |