add image generation api
This commit is contained in:
parent
7ef5b0f35a
commit
f3f7288deb
|
@ -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
47
src/api/imageProcessor.ts
Normal 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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,7 +48,7 @@ import {
|
||||||
} from './api/common';
|
} from './api/common';
|
||||||
import { fixHotReloadNext12 } from './utils/preload';
|
import { fixHotReloadNext12 } from './utils/preload';
|
||||||
import { isFolder, getDirFiles } from './api/fs';
|
import { isFolder, getDirFiles } from './api/fs';
|
||||||
import { convertHEIC } from './api/heicConvert';
|
import { convertHEIC, generateImageThumbnail } from './api/imageProcessor';
|
||||||
import { setupLogging } from './utils/logging';
|
import { setupLogging } from './utils/logging';
|
||||||
import { setupRendererProcessStatsLogger } from './utils/processStats';
|
import { setupRendererProcessStatsLogger } from './utils/processStats';
|
||||||
import { runFFmpegCmd } from './api/ffmpeg';
|
import { runFFmpegCmd } from './api/ffmpeg';
|
||||||
|
@ -104,4 +104,5 @@ windowObject['ElectronAPIs'] = {
|
||||||
getSentryUserID,
|
getSentryUserID,
|
||||||
getAppVersion,
|
getAppVersion,
|
||||||
runFFmpegCmd,
|
runFFmpegCmd,
|
||||||
|
generateImageThumbnail,
|
||||||
};
|
};
|
||||||
|
|
|
@ -70,3 +70,59 @@ async function runConvertCommand(
|
||||||
Error(`${process.platform} native heic convert not supported yet`);
|
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`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,10 @@ import { getSentryUserID, logErrorSentry } from '../services/sentry';
|
||||||
import chokidar from 'chokidar';
|
import chokidar from 'chokidar';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { getDirFilePaths } from '../services/fs';
|
import { getDirFilePaths } from '../services/fs';
|
||||||
import { convertHEIC } from '../services/heicConverter';
|
import {
|
||||||
|
convertHEIC,
|
||||||
|
generateImageThumbnail,
|
||||||
|
} from '../services/imageProcessor';
|
||||||
import {
|
import {
|
||||||
getAppVersion,
|
getAppVersion,
|
||||||
skipAppVersion,
|
skipAppVersion,
|
||||||
|
@ -146,4 +149,8 @@ export default function setupIpcComs(
|
||||||
ipcMain.handle('remove-temp-file', (_, tempFilePath: string) => {
|
ipcMain.handle('remove-temp-file', (_, tempFilePath: string) => {
|
||||||
return deleteTempFile(tempFilePath);
|
return deleteTempFile(tempFilePath);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('generate-image-thumbnail', (_, fileData, maxDimension) => {
|
||||||
|
return generateImageThumbnail(fileData, maxDimension);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue