// Copyright 2020-2021 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import path from 'path'; import { ipcRenderer } from 'electron'; import { v4 as genUuid } from 'uuid'; import { blobToArrayBuffer } from '../types/VisualAttachment'; import type { MIMEType } from '../types/MIME'; import { IMAGE_JPEG, isHeic, stringToMIMEType } from '../types/MIME'; import type { InMemoryAttachmentDraftType } from '../types/Attachment'; import { canBeTranscoded } from '../types/Attachment'; import { imageToBlurHash } from './imageToBlurHash'; import { scaleImageToLevel } from './scaleImageToLevel'; export async function handleImageAttachment( file: File ): Promise { let processedFile: File | Blob = file; if (isHeic(file.type, file.name)) { const uuid = genUuid(); const bytes = new Uint8Array(await file.arrayBuffer()); const convertedFile = await new Promise((resolve, reject) => { ipcRenderer.once(`convert-image:${uuid}`, (_, { error, response }) => { if (response) { resolve(response); } else { reject(error); } }); ipcRenderer.send('convert-image', uuid, bytes); }); processedFile = new Blob([convertedFile]); } const { contentType, file: resizedBlob, fileName, } = await autoScale({ contentType: isHeic(file.type, file.name) ? IMAGE_JPEG : stringToMIMEType(file.type), fileName: file.name, file: processedFile, }); const data = await blobToArrayBuffer(resizedBlob); const blurHash = await imageToBlurHash(resizedBlob); return { blurHash, contentType, data: new Uint8Array(data), fileName: fileName || file.name, path: file.name, pending: false, size: data.byteLength, }; } export async function autoScale({ contentType, file, fileName, }: { contentType: MIMEType; file: File | Blob; fileName: string; }): Promise<{ contentType: MIMEType; file: Blob; fileName: string; }> { if (!canBeTranscoded({ contentType })) { return { contentType, file, fileName }; } const { blob, contentType: newContentType } = await scaleImageToLevel( file, contentType, true ); if (newContentType !== IMAGE_JPEG) { return { contentType, file: blob, fileName, }; } const { name } = path.parse(fileName); return { contentType: IMAGE_JPEG, file: blob, fileName: `${name}.jpg`, }; }