signal-desktop/ts/util/handleImageAttachment.ts

104 lines
2.4 KiB
TypeScript
Raw Normal View History

2021-09-24 00:49:05 +00:00
// Copyright 2020-2021 Signal Messenger, LLC
2021-07-28 00:09:10 +00:00
// SPDX-License-Identifier: AGPL-3.0-only
import path from 'path';
2021-08-09 20:06:21 +00:00
import { ipcRenderer } from 'electron';
import { v4 as genUuid } from 'uuid';
2021-09-24 00:49:05 +00:00
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';
2021-07-28 00:09:10 +00:00
import { imageToBlurHash } from './imageToBlurHash';
import { scaleImageToLevel } from './scaleImageToLevel';
export async function handleImageAttachment(
file: File
): Promise<InMemoryAttachmentDraftType> {
2021-08-09 20:06:21 +00:00
let processedFile: File | Blob = file;
if (isHeic(file.type, file.name)) {
2021-08-09 20:06:21 +00:00
const uuid = genUuid();
2021-09-24 00:49:05 +00:00
const bytes = new Uint8Array(await file.arrayBuffer());
2021-08-09 20:06:21 +00:00
const convertedFile = await new Promise<File>((resolve, reject) => {
ipcRenderer.once(`convert-image:${uuid}`, (_, { error, response }) => {
if (response) {
resolve(response);
} else {
reject(error);
}
});
2021-09-24 00:49:05 +00:00
ipcRenderer.send('convert-image', uuid, bytes);
2021-08-09 20:06:21 +00:00
});
processedFile = new Blob([convertedFile]);
}
2021-07-28 00:09:10 +00:00
2021-11-11 22:43:05 +00:00
const {
contentType,
file: resizedBlob,
fileName,
} = await autoScale({
contentType: isHeic(file.type, file.name)
? IMAGE_JPEG
: stringToMIMEType(file.type),
2021-07-28 00:09:10 +00:00
fileName: file.name,
2021-08-09 20:06:21 +00:00
file: processedFile,
2021-07-28 00:09:10 +00:00
});
2021-08-09 20:06:21 +00:00
2021-09-24 00:49:05 +00:00
const data = await blobToArrayBuffer(resizedBlob);
2021-08-09 20:06:21 +00:00
const blurHash = await imageToBlurHash(resizedBlob);
2021-07-28 00:09:10 +00:00
return {
2021-08-30 21:32:56 +00:00
blurHash,
2021-07-28 00:09:10 +00:00
contentType,
2021-09-24 00:49:05 +00:00
data: new Uint8Array(data),
2021-08-30 21:32:56 +00:00
fileName: fileName || file.name,
path: file.name,
pending: false,
2021-07-28 00:09:10 +00:00
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,
};
}
2021-07-28 00:09:10 +00:00
const { name } = path.parse(fileName);
return {
contentType: IMAGE_JPEG,
file: blob,
2021-09-30 16:43:27 +00:00
fileName: `${name}.jpg`,
2021-07-28 00:09:10 +00:00
};
}