Option to send photos as high quality

This commit is contained in:
Josh Perez
2021-06-25 12:08:16 -04:00
committed by GitHub
parent 6c56d5a5f1
commit 01eabf9ec6
44 changed files with 1263 additions and 363 deletions

View File

@@ -3,16 +3,12 @@
const is = require('@sindresorhus/is');
const {
arrayBufferToBlob,
blobToArrayBuffer,
dataURLToBlob,
} = require('blob-util');
const { arrayBufferToBlob, blobToArrayBuffer } = require('blob-util');
const AttachmentTS = require('../../../ts/types/Attachment');
const GoogleChrome = require('../../../ts/util/GoogleChrome');
const MIME = require('../../../ts/types/MIME');
const { toLogFormat } = require('./errors');
const { autoOrientImage } = require('../auto_orient_image');
const { scaleImageToLevel } = require('../../../ts/util/scaleImageToLevel');
const {
migrateDataToFileSystem,
} = require('./attachment/migrate_data_to_file_system');
@@ -54,7 +50,7 @@ exports.isValid = rawAttachment => {
// Upgrade steps
// NOTE: This step strips all EXIF metadata from JPEG images as
// part of re-encoding the image:
exports.autoOrientJPEG = async attachment => {
exports.autoOrientJPEG = async (attachment, _, message) => {
if (!MIME.isJPEG(attachment.contentType)) {
return attachment;
}
@@ -68,24 +64,27 @@ exports.autoOrientJPEG = async attachment => {
attachment.data,
attachment.contentType
);
const newDataBlob = await dataURLToBlob(await autoOrientImage(dataBlob));
const newDataArrayBuffer = await blobToArrayBuffer(newDataBlob);
const xcodedDataBlob = await scaleImageToLevel(
dataBlob,
message.sendHQImages
);
const xcodedDataArrayBuffer = await blobToArrayBuffer(xcodedDataBlob);
// IMPORTANT: We overwrite the existing `data` `ArrayBuffer` losing the original
// image data. Ideally, wed preserve the original image data for users who want to
// retain it but due to reports of data loss, we dont want to overburden IndexedDB
// by potentially doubling stored image data.
// See: https://github.com/signalapp/Signal-Desktop/issues/1589
const newAttachment = {
const xcodedAttachment = {
...attachment,
data: newDataArrayBuffer,
size: newDataArrayBuffer.byteLength,
data: xcodedDataArrayBuffer,
size: xcodedDataArrayBuffer.byteLength,
};
// `digest` is no longer valid for auto-oriented image data, so we discard it:
delete newAttachment.digest;
delete xcodedAttachment.digest;
return newAttachment;
return xcodedAttachment;
};
const UNICODE_LEFT_TO_RIGHT_OVERRIDE = '\u202D';

View File

@@ -170,7 +170,7 @@ exports._withSchemaVersion = ({ schemaVersion, upgrade }) => {
// Promise Message
exports._mapAttachments = upgradeAttachment => async (message, context) => {
const upgradeWithContext = attachment =>
upgradeAttachment(attachment, context);
upgradeAttachment(attachment, context, message);
const attachments = await Promise.all(
(message.attachments || []).map(upgradeWithContext)
);

View File

@@ -1,15 +1,15 @@
// Copyright 2018-2020 Signal Messenger, LLC
// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* global document, URL, Blob */
const loadImage = require('blueimp-load-image');
const dataURLToBlobSync = require('blueimp-canvas-to-blob');
const { blobToArrayBuffer } = require('blob-util');
const { toLogFormat } = require('./errors');
const {
arrayBufferToObjectURL,
} = require('../../../ts/util/arrayBufferToObjectURL');
const { canvasToBlob } = require('../../../ts/util/canvasToBlob');
exports.blobToArrayBuffer = blobToArrayBuffer;
@@ -40,7 +40,7 @@ exports.makeImageThumbnail = ({
new Promise((resolve, reject) => {
const image = document.createElement('img');
image.addEventListener('load', () => {
image.addEventListener('load', async () => {
// using components/blueimp-load-image
// first, make the correct size
@@ -63,9 +63,12 @@ exports.makeImageThumbnail = ({
minHeight: size,
});
const blob = dataURLToBlobSync(canvas.toDataURL(contentType));
resolve(blob);
try {
const blob = await canvasToBlob(canvas, contentType);
resolve(blob);
} catch (err) {
reject(err);
}
});
image.addEventListener('error', error => {
@@ -88,7 +91,7 @@ exports.makeVideoScreenshot = ({
video.currentTime = 1.0;
}
function capture() {
async function capture() {
const canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
@@ -96,12 +99,15 @@ exports.makeVideoScreenshot = ({
.getContext('2d')
.drawImage(video, 0, 0, canvas.width, canvas.height);
const image = dataURLToBlobSync(canvas.toDataURL(contentType));
video.addEventListener('loadeddata', seek);
video.removeEventListener('seeked', capture);
resolve(image);
try {
const image = canvasToBlob(canvas, contentType);
resolve(image);
} catch (err) {
reject(err);
}
}
video.addEventListener('loadeddata', seek);