Option to send photos as high quality
This commit is contained in:
parent
6c56d5a5f1
commit
01eabf9ec6
44 changed files with 1263 additions and 363 deletions
|
@ -1,43 +0,0 @@
|
|||
// Copyright 2018-2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
const loadImage = require('blueimp-load-image');
|
||||
|
||||
const DEFAULT_JPEG_QUALITY = 0.85;
|
||||
|
||||
// File | Blob | URLString -> LoadImageOptions -> Promise<DataURLString>
|
||||
//
|
||||
// Documentation for `options` (`LoadImageOptions`):
|
||||
// https://github.com/blueimp/JavaScript-Load-Image/tree/v2.18.0#options
|
||||
exports.autoOrientImage = (fileOrBlobOrURL, options = {}) => {
|
||||
const optionsWithDefaults = {
|
||||
type: 'image/jpeg',
|
||||
quality: DEFAULT_JPEG_QUALITY,
|
||||
...options,
|
||||
canvas: true,
|
||||
orientation: true,
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
loadImage(
|
||||
fileOrBlobOrURL,
|
||||
canvasOrError => {
|
||||
if (canvasOrError.type === 'error') {
|
||||
const error = new Error('autoOrientImage: Failed to process image');
|
||||
error.originalError = canvasOrError;
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
const canvas = canvasOrError;
|
||||
const dataURL = canvas.toDataURL(
|
||||
optionsWithDefaults.type,
|
||||
optionsWithDefaults.quality
|
||||
);
|
||||
|
||||
resolve(dataURL);
|
||||
},
|
||||
optionsWithDefaults
|
||||
);
|
||||
});
|
||||
};
|
|
@ -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, we’d preserve the original image data for users who want to
|
||||
// retain it but due to reports of data loss, we don’t 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';
|
||||
|
|
|
@ -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)
|
||||
);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue