Preserve blob content type when stripping EXIF data

This commit is contained in:
Evan Hahn 2021-08-24 14:38:20 -05:00 committed by GitHub
parent fab883c2a6
commit 48cc2b5f11
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 3 deletions

View file

@ -0,0 +1,68 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai';
import { IMAGE_JPEG, IMAGE_PNG } from '../../types/MIME';
import * as log from '../../logging/log';
import { scaleImageToLevel } from '../../util/scaleImageToLevel';
describe('scaleImageToLevel', () => {
// NOTE: These tests are incomplete.
let objectUrlsToRevoke: Array<string>;
function createObjectUrl(blob: Blob): string {
const result = URL.createObjectURL(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 () => {
const testCases = [
{
path: '../fixtures/kitten-1-64-64.jpg',
contentType: IMAGE_JPEG,
expectedWidth: 64,
expectedHeight: 64,
},
{
path: '../fixtures/20x200-yellow.png',
contentType: IMAGE_PNG,
expectedWidth: 20,
expectedHeight: 200,
},
];
await Promise.all(
testCases.map(
async ({ path, contentType, expectedWidth, expectedHeight }) => {
const blob = await (await fetch(path)).blob();
const scaled = await scaleImageToLevel(blob, contentType, true);
const {
width,
height,
} = await window.Signal.Types.VisualAttachment.getImageDimensions({
objectUrl: createObjectUrl(scaled.blob),
logger: log,
});
assert.strictEqual(width, expectedWidth);
assert.strictEqual(height, expectedHeight);
assert.strictEqual(scaled.contentType, contentType);
assert.strictEqual(scaled.blob.type, contentType);
}
)
);
});
});

View file

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