add image generation api

This commit is contained in:
Abhinav 2023-01-02 21:08:08 +05:30
parent 7ef5b0f35a
commit f3f7288deb
5 changed files with 113 additions and 11 deletions

View file

@ -1,9 +0,0 @@
import { ipcRenderer } from 'electron/renderer';
export async function convertHEIC(fileData: Uint8Array): Promise<Uint8Array> {
const convertedFileData = await ipcRenderer.invoke(
'convert-heic',
fileData
);
return convertedFileData;
}

47
src/api/imageProcessor.ts Normal file
View file

@ -0,0 +1,47 @@
import { ipcRenderer } from 'electron/renderer';
import { existsSync } from 'fs';
import { logError } from '../services/logging';
import { ElectronFile } from '../types';
export async function convertHEIC(fileData: Uint8Array): Promise<Uint8Array> {
const convertedFileData = await ipcRenderer.invoke(
'convert-heic',
fileData
);
return convertedFileData;
}
export async function generateImageThumbnail(
inputFile: File | ElectronFile,
maxDimension: number
): Promise<Uint8Array> {
let inputFilePath = null;
let createdTempInputFile = null;
try {
if (!existsSync(inputFile.path)) {
const inputFileData = new Uint8Array(await inputFile.arrayBuffer());
inputFilePath = await ipcRenderer.invoke(
'write-temp-file',
inputFileData,
inputFile.name
);
createdTempInputFile = true;
} else {
inputFilePath = inputFile.path;
}
const thumbnail = await ipcRenderer.invoke(
'generate-image-thumbnail',
inputFilePath,
maxDimension
);
return thumbnail;
} finally {
if (createdTempInputFile) {
try {
await ipcRenderer.invoke('remove-temp-file', inputFilePath);
} catch (e) {
logError(e, 'failed to deleteTempFile');
}
}
}
}

View file

@ -48,7 +48,7 @@ import {
} from './api/common';
import { fixHotReloadNext12 } from './utils/preload';
import { isFolder, getDirFiles } from './api/fs';
import { convertHEIC } from './api/heicConvert';
import { convertHEIC, generateImageThumbnail } from './api/imageProcessor';
import { setupLogging } from './utils/logging';
import { setupRendererProcessStatsLogger } from './utils/processStats';
import { runFFmpegCmd } from './api/ffmpeg';
@ -104,4 +104,5 @@ windowObject['ElectronAPIs'] = {
getSentryUserID,
getAppVersion,
runFFmpegCmd,
generateImageThumbnail,
};

View file

@ -70,3 +70,59 @@ async function runConvertCommand(
Error(`${process.platform} native heic convert not supported yet`);
}
}
export async function generateImageThumbnail(
inputFilePath: string,
width: number
): Promise<Uint8Array> {
let tempOutputFilePath: string;
try {
tempOutputFilePath = await generateTempFilePath('.jpeg');
await runThumbnailGenerationCommand(
inputFilePath,
tempOutputFilePath,
width
);
if (!existsSync(tempOutputFilePath)) {
throw new Error('heic convert output file not found');
}
const convertedFileData = new Uint8Array(
await readFile(tempOutputFilePath)
);
return convertedFileData;
} catch (e) {
logErrorSentry(e, 'ffmpeg run command error');
throw e;
} finally {
try {
rmSync(tempOutputFilePath, { force: true });
} catch (e) {
logErrorSentry(e, 'failed to remove tempOutputFile');
}
}
}
async function runThumbnailGenerationCommand(
inputFilePath: string,
tempOutputFilePath: string,
maxDimension: number
) {
if (isPlatform('mac')) {
await asyncExec(
`sips -s format jpeg -Z ${maxDimension} ${inputFilePath} --out ${tempOutputFilePath} `
);
} else if (isPlatform('linux')) {
await asyncExec(
`${getImageMagickStaticPath()} -define jpeg:size=${
2 * maxDimension
}x${2 * maxDimension} ${inputFilePath} -auto-orient
-thumbnail ${maxDimension}x${maxDimension}> -gravity center -unsharp 0x.5 ${tempOutputFilePath}`
);
} else {
Error(
`${process.platform} native thumbnail generation not supported yet`
);
}
}

View file

@ -14,7 +14,10 @@ import { getSentryUserID, logErrorSentry } from '../services/sentry';
import chokidar from 'chokidar';
import path from 'path';
import { getDirFilePaths } from '../services/fs';
import { convertHEIC } from '../services/heicConverter';
import {
convertHEIC,
generateImageThumbnail,
} from '../services/imageProcessor';
import {
getAppVersion,
skipAppVersion,
@ -146,4 +149,8 @@ export default function setupIpcComs(
ipcMain.handle('remove-temp-file', (_, tempFilePath: string) => {
return deleteTempFile(tempFilePath);
});
ipcMain.handle('generate-image-thumbnail', (_, fileData, maxDimension) => {
return generateImageThumbnail(fileData, maxDimension);
});
}