2021-07-28 00:09:10 +00:00
|
|
|
// Copyright 2021 Signal Messenger, LLC
|
|
|
|
// 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';
|
|
|
|
|
|
|
|
import { IMAGE_JPEG, MIMEType, isHeic, stringToMIMEType } from '../types/MIME';
|
2021-07-28 00:09:10 +00:00
|
|
|
import {
|
|
|
|
InMemoryAttachmentDraftType,
|
|
|
|
canBeTranscoded,
|
|
|
|
} from '../types/Attachment';
|
|
|
|
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)) {
|
|
|
|
const uuid = genUuid();
|
|
|
|
const arrayBuffer = await file.arrayBuffer();
|
|
|
|
|
|
|
|
const convertedFile = await new Promise<File>((resolve, reject) => {
|
|
|
|
ipcRenderer.once(`convert-image:${uuid}`, (_, { error, response }) => {
|
|
|
|
if (response) {
|
|
|
|
resolve(response);
|
|
|
|
} else {
|
|
|
|
reject(error);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
ipcRenderer.send('convert-image', uuid, arrayBuffer);
|
|
|
|
});
|
|
|
|
|
|
|
|
processedFile = new Blob([convertedFile]);
|
|
|
|
}
|
2021-07-28 00:09:10 +00:00
|
|
|
|
|
|
|
const { contentType, file: resizedBlob, fileName } = await autoScale({
|
2021-08-09 20:06:21 +00:00
|
|
|
contentType: isHeic(file.type) ? 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-07-28 00:09:10 +00:00
|
|
|
const data = await window.Signal.Types.VisualAttachment.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,
|
|
|
|
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 };
|
|
|
|
}
|
|
|
|
|
2021-08-23 21:24:52 +00:00
|
|
|
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,
|
|
|
|
fileName: `${name}.jpeg`,
|
|
|
|
};
|
|
|
|
}
|