Strip Exif data without Sharp
This commit is contained in:
parent
30c3b7630c
commit
f82012f129
5 changed files with 21 additions and 45 deletions
|
@ -31,11 +31,5 @@ module.exports = ({ config }) => {
|
||||||
net: 'net',
|
net: 'net',
|
||||||
};
|
};
|
||||||
|
|
||||||
config.plugins.unshift(
|
|
||||||
new webpack.IgnorePlugin({
|
|
||||||
resourceRegExp: /sharp$/,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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');
|
||||||
|
|
|
@ -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
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -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
2
ts/window.d.ts
vendored
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue