Strip Exif data without Sharp

This commit is contained in:
Evan Hahn 2021-09-02 10:59:42 -05:00 committed by GitHub
parent 30c3b7630c
commit f82012f129
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 21 additions and 45 deletions

View file

@ -31,11 +31,5 @@ module.exports = ({ config }) => {
net: 'net', net: 'net',
}; };
config.plugins.unshift(
new webpack.IgnorePlugin({
resourceRegExp: /sharp$/,
})
);
return config; return config;
}; };

View file

@ -414,7 +414,6 @@ try {
window.ReactDOM = require('react-dom'); window.ReactDOM = require('react-dom');
window.moment = require('moment'); window.moment = require('moment');
window.PQueue = require('p-queue').default; window.PQueue = require('p-queue').default;
window.sharp = require('sharp');
const Signal = require('./js/modules/signal'); const Signal = require('./js/modules/signal');
const i18n = require('./js/modules/i18n'); const i18n = require('./js/modules/i18n');

View file

@ -2,31 +2,19 @@
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai'; import { assert } from 'chai';
import loadImage from 'blueimp-load-image';
import { IMAGE_JPEG, IMAGE_PNG } from '../../types/MIME'; import { IMAGE_JPEG, IMAGE_PNG } from '../../types/MIME';
import * as log from '../../logging/log';
import { scaleImageToLevel } from '../../util/scaleImageToLevel'; import { scaleImageToLevel } from '../../util/scaleImageToLevel';
describe('scaleImageToLevel', () => { describe('scaleImageToLevel', () => {
// NOTE: These tests are incomplete. // NOTE: These tests are incomplete.
let objectUrlsToRevoke: Array<string>; async function getBlob(path: string): Promise<Blob> {
function createObjectUrl(blob: Blob): string { const response = await fetch(path);
const result = URL.createObjectURL(blob); return response.blob();
objectUrlsToRevoke.push(result);
return result;
} }
beforeEach(() => {
objectUrlsToRevoke = [];
});
afterEach(() => {
objectUrlsToRevoke.forEach(objectUrl => {
URL.revokeObjectURL(objectUrl);
});
});
it("doesn't scale images that are already small enough", async () => { it("doesn't scale images that are already small enough", async () => {
const testCases = [ const testCases = [
{ {
@ -46,16 +34,11 @@ describe('scaleImageToLevel', () => {
await Promise.all( await Promise.all(
testCases.map( testCases.map(
async ({ path, contentType, expectedWidth, expectedHeight }) => { async ({ path, contentType, expectedWidth, expectedHeight }) => {
const blob = await (await fetch(path)).blob(); const blob = await getBlob(path);
const scaled = await scaleImageToLevel(blob, contentType, true); const scaled = await scaleImageToLevel(blob, contentType, true);
const { const data = await loadImage(scaled.blob, { orientation: true });
width, const { originalWidth: width, originalHeight: height } = data;
height,
} = await window.Signal.Types.VisualAttachment.getImageDimensions({
objectUrl: createObjectUrl(scaled.blob),
logger: log,
});
assert.strictEqual(width, expectedWidth); assert.strictEqual(width, expectedWidth);
assert.strictEqual(height, expectedHeight); assert.strictEqual(height, expectedHeight);
@ -65,4 +48,17 @@ describe('scaleImageToLevel', () => {
) )
); );
}); });
it('removes EXIF data from small images', async () => {
const original = await getBlob('../fixtures/kitten-2-64-64.jpg');
assert.isDefined(
(await loadImage(original, { meta: true, orientation: true })).exif,
'Test setup failure: expected fixture to have EXIF data'
);
const scaled = await scaleImageToLevel(original, IMAGE_JPEG, true);
assert.isUndefined(
(await loadImage(scaled.blob, { meta: true, orientation: true })).exif
);
});
}); });

View file

@ -101,17 +101,6 @@ async function getCanvasBlobAsJPEG(
return canvasToBlob(canvas, IMAGE_JPEG, quality); return canvasToBlob(canvas, IMAGE_JPEG, quality);
} }
async function stripImageFileEXIFData(
file: File | Blob,
type: MIMEType
): Promise<Blob> {
const arrayBuffer = await file.arrayBuffer();
const xArrayBuffer = await window
.sharp(new Uint8Array(arrayBuffer))
.toBuffer();
return new Blob([xArrayBuffer], { type });
}
export async function scaleImageToLevel( export async function scaleImageToLevel(
fileOrBlobOrURL: File | Blob, fileOrBlobOrURL: File | Blob,
contentType: MIMEType, contentType: MIMEType,
@ -143,7 +132,7 @@ export async function scaleImageToLevel(
MEDIA_QUALITY_LEVEL_DATA.get(level) || DEFAULT_LEVEL_DATA; MEDIA_QUALITY_LEVEL_DATA.get(level) || DEFAULT_LEVEL_DATA;
if (fileOrBlobOrURL.size <= thresholdSize) { if (fileOrBlobOrURL.size <= thresholdSize) {
const blob = await stripImageFileEXIFData(fileOrBlobOrURL, contentType); const blob = await canvasToBlob(image, contentType);
return { return {
blob, blob,
contentType, contentType,

2
ts/window.d.ts vendored
View file

@ -7,7 +7,6 @@ import { DeepPartial, Store } from 'redux';
import * as Backbone from 'backbone'; import * as Backbone from 'backbone';
import * as Underscore from 'underscore'; import * as Underscore from 'underscore';
import moment from 'moment'; import moment from 'moment';
import sharp from 'sharp';
import PQueue from 'p-queue/dist'; import PQueue from 'p-queue/dist';
import { Attributes, ComponentClass, FunctionComponent, Ref } from 'react'; import { Attributes, ComponentClass, FunctionComponent, Ref } from 'react';
import { imageToBlurHash } from './util/imageToBlurHash'; import { imageToBlurHash } from './util/imageToBlurHash';
@ -163,7 +162,6 @@ declare global {
_: typeof Underscore; _: typeof Underscore;
$: typeof jQuery; $: typeof jQuery;
sharp: typeof sharp;
moment: typeof moment; moment: typeof moment;
imageToBlurHash: typeof imageToBlurHash; imageToBlurHash: typeof imageToBlurHash;
loadImage: any; loadImage: any;