VulpesOS/gaia/apps/sharedtest/test/unit/image_utils_test.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

587 lines
35 KiB
JavaScript
Executable file

'use strict';
/* global ImageUtils */
require('/shared/js/image_utils.js');
suite('ImageUtils', function() {
const testImages = [
{
type: 'image/jpeg',
width: 25,
height: 24,
base64: '/9j/4AAQSkZJRgABAQEASABIAAD/4ge4SUNDX1BST0ZJTEUAAQEAAAeoYXBwbAIgAABtbnRyUkdCIFhZWiAH2QACABkACwAaAAthY3NwQVBQTAAAAABhcHBsAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWFwcGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtkZXNjAAABCAAAAG9kc2NtAAABeAAABWxjcHJ0AAAG5AAAADh3dHB0AAAHHAAAABRyWFlaAAAHMAAAABRnWFlaAAAHRAAAABRiWFlaAAAHWAAAABRyVFJDAAAHbAAAAA5jaGFkAAAHfAAAACxiVFJDAAAHbAAAAA5nVFJDAAAHbAAAAA5kZXNjAAAAAAAAABRHZW5lcmljIFJHQiBQcm9maWxlAAAAAAAAAAAAAAAUR2VuZXJpYyBSR0IgUHJvZmlsZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbWx1YwAAAAAAAAAeAAAADHNrU0sAAAAoAAABeGhySFIAAAAoAAABoGNhRVMAAAAkAAAByHB0QlIAAAAmAAAB7HVrVUEAAAAqAAACEmZyRlUAAAAoAAACPHpoVFcAAAAWAAACZGl0SVQAAAAoAAACem5iTk8AAAAmAAAComtvS1IAAAAWAAACyGNzQ1oAAAAiAAAC3mhlSUwAAAAeAAADAGRlREUAAAAsAAADHmh1SFUAAAAoAAADSnN2U0UAAAAmAAAConpoQ04AAAAWAAADcmphSlAAAAAaAAADiHJvUk8AAAAkAAADomVsR1IAAAAiAAADxnB0UE8AAAAmAAAD6G5sTkwAAAAoAAAEDmVzRVMAAAAmAAAD6HRoVEgAAAAkAAAENnRyVFIAAAAiAAAEWmZpRkkAAAAoAAAEfHBsUEwAAAAsAAAEpHJ1UlUAAAAiAAAE0GFyRUcAAAAmAAAE8mVuVVMAAAAmAAAFGGRhREsAAAAuAAAFPgBWAWEAZQBvAGIAZQBjAG4A/QAgAFIARwBCACAAcAByAG8AZgBpAGwARwBlAG4AZQByAGkBDQBrAGkAIABSAEcAQgAgAHAAcgBvAGYAaQBsAFAAZQByAGYAaQBsACAAUgBHAEIAIABnAGUAbgDoAHIAaQBjAFAAZQByAGYAaQBsACAAUgBHAEIAIABHAGUAbgDpAHIAaQBjAG8EFwQwBDMEMAQ7BEwEPQQ4BDkAIAQ/BEAEPgREBDAEOQQ7ACAAUgBHAEIAUAByAG8AZgBpAGwAIABnAOkAbgDpAHIAaQBxAHUAZQAgAFIAVgBCkBp1KAAgAFIARwBCACCCcl9pY8+P8ABQAHIAbwBmAGkAbABvACAAUgBHAEIAIABnAGUAbgBlAHIAaQBjAG8ARwBlAG4AZQByAGkAcwBrACAAUgBHAEIALQBwAHIAbwBmAGkAbMd8vBgAIABSAEcAQgAg1QS4XNMMx3wATwBiAGUAYwBuAP0AIABSAEcAQgAgAHAAcgBvAGYAaQBsBeQF6AXVBeQF2QXcACAAUgBHAEIAIAXbBdwF3AXZAEEAbABsAGcAZQBtAGUAaQBuAGUAcwAgAFIARwBCAC0AUAByAG8AZgBpAGwAwQBsAHQAYQBsAOEAbgBvAHMAIABSAEcAQgAgAHAAcgBvAGYAaQBsZm6QGgAgAFIARwBCACBjz4/wZYdO9k4AgiwAIABSAEcAQgAgMNcw7TDVMKEwpDDrAFAAcgBvAGYAaQBsACAAUgBHAEIAIABnAGUAbgBlAHIAaQBjA5MDtQO9A7kDugPMACADwAPBA78DxgOvA7sAIABSAEcAQgBQAGUAcgBmAGkAbAAgAFIARwBCACAAZwBlAG4A6QByAGkAYwBvAEEAbABnAGUAbQBlAGUAbgAgAFIARwBCAC0AcAByAG8AZgBpAGUAbA5CDhsOIw5EDh8OJQ5MACAAUgBHAEIAIA4XDjEOSA4nDkQOGwBHAGUAbgBlAGwAIABSAEcAQgAgAFAAcgBvAGYAaQBsAGkAWQBsAGUAaQBuAGUAbgAgAFIARwBCAC0AcAByAG8AZgBpAGkAbABpAFUAbgBpAHcAZQByAHMAYQBsAG4AeQAgAHAAcgBvAGYAaQBsACAAUgBHAEIEHgQxBEkEOAQ5ACAEPwRABD4ERAQ4BDsETAAgAFIARwBCBkUGRAZBACAGKgY5BjEGSgZBACAAUgBHAEIAIAYnBkQGOQYnBkUARwBlAG4AZQByAGkAYwAgAFIARwBCACAAUAByAG8AZgBpAGwAZQBHAGUAbgBlAHIAZQBsACAAUgBHAEIALQBiAGUAcwBrAHIAaQB2AGUAbABzAGV0ZXh0AAAAAENvcHlyaWdodCAyMDA3IEFwcGxlIEluYy4sIGFsbCByaWdodHMgcmVzZXJ2ZWQuAFhZWiAAAAAAAADzUgABAAAAARbPWFlaIAAAAAAAAHRNAAA97gAAA9BYWVogAAAAAAAAWnUAAKxzAAAXNFhZWiAAAAAAAAAoGgAAFZ8AALg2Y3VydgAAAAAAAAABAc0AAHNmMzIAAAAAAAEMQgAABd7///MmAAAHkgAA/ZH///ui///9owAAA9wAAMBs/+EAnkV4aWYAAE1NACoAAAAIAAYBEgADAAAAAQABAAABGgAFAAAAAQAAAFYBGwAFAAAAAQAAAF4BKAADAAAAAQACAAABMQACAAAAEQAAAGaHaQAEAAAAAQAAAHgAAAAAAAAASAAAAAEAAABIAAAAAUFkb2JlIEltYWdlUmVhZHkAAAACoAIABAAAAAEAAAAZoAMABAAAAAEAAAAYAAAAAP/bAEMAIBYYHBgUIBwaHCQiICYwUDQwLCwwYkZKOlB0Znp4cmZwboCQuJyAiK6KbnCg2qKuvsTO0M58muLy4MjwuMrOxv/bAEMBIiQkMCowXjQ0XsaEcITGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxv/AABEIABgAGQMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/ANu5m8iEyYzjoPWsuXU5YzuJHrjHFaF/C01qyp94cgetc5JGJDtOFJ4OQcikpcstdi/Z88dNzqIZBLGrjuM1JVWxD+SGcbc4CjvirVEW2tSWrMrOblXYqoYZOAfSmZuASxhRienHSiimIlJm38Zxnpip6KKAP//Z' // jshint ignore:line
},
{
type: 'image/png',
width: 25,
height: 24,
base64: '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' // jshint ignore:line
},
{
type: 'image/gif',
width: 25,
height: 24,
base64: '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' // jshint ignore:line
},
{
type: 'image/bmp',
width: 25,
height: 24,
base64: 'Qk1WBwAAAAAAADYAAAAoAAAAGQAAABgAAAABABgAAAAAACAHAAATCwAAEwsAAAAAAAAAAAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////AP///0c5OUBAQAAAAEY+PkBAQFUrK0BAQEU9PUQ8PEBAQEY6OkRAPEBAOkNDNkY+Pkc9Pf///0M/P0BAQEBAQERAPEY+Pv///wAAAAD///9DPT1DPj7///9CPjxEPj5DPz9CPT1CPzxDQD1EPz1CPj5DPz1CPT1CPjxDPjxHPT1EQDxEPj5DPj5CPz9AQEBDPj5EPj7///8A////Qj87Qj48QTw8Qz89Qj09QT09Qz49Qz09RD49Qz89Qj48Qj87Qz09Qz09Qz48////RD4+////Qz09Qj09RDw8Qj48QTs7////AP///0M8PEM+PUM9PUI8PEM/PUI+PEQ9PUE9PUM9PUM+PEM+PkM9PUI/PEI9PUM+PkNDQ0I9PUU7O0E8PEM+PkI+PkBAQP///wAAAAD///9CPT1DPjxDPj5CPT1HOTn///9AQED///9EPj5CPT9COkoAAP8AAP////////////9EPj5DPj5EPj5CPT1DPj5EPT1GRkb///8A////////Szw8QEBAQjk5QEBA////////////////SkoggIAA////////////////////////REQzVSsr////SUk3Q0ND////////AP///////////////////////wAAAAAAqgBAAAAAAAAAMgoAXBcNaBAKVg4AOwAAAP///0BAv////////0BAQP///////////////wD///8AAABVVVVVVVVVVVX///8AAGYAAAAMAD8XEHobGJAcH5sdJKQcJaMcJqMeIIoYAEgAAAAkJEmAgID///+AgICAgID///////8A////////////////////AAD/////Fw5xHBaRHyOsHyuyHzK4Hze9HzvCHz3EIznAHyyhFCKM////////AAAA////////////////AP///////////////wAAv////x0Xlx0bnCAosR8yth06wRxDyxxIzB1Lyx1X0x5a1B9JzSA6uiIxrP///wAAgP///////////////wD///////////8AAID///////8dIaIgKrYeNLkePsMgRMIqPJ8xLGkuKWMpP5Uha84gctgkWM4lNKAhC5D///8AAID///////////8A////////////MzOZ////HCiqHimrHjS7Hj7DH0TGID+1JSmEMwA9PAAAPAAAL0VjGaLcGpjdI2bFJBuy////QEC/////////////AP///////wAA/wAAgP///x8zsyA1wR09wR9CwxlPzCFUxS1TuhxnxDVmm0whIz0NAC+WuyHL8Ra37Rh84P///wCAv////////////wD///////8AgP////////8eOrsgPcshRcUYPr4tP7BeNVdmMCdeVG9eUmZWJyJIAAA7Z3o02/cq5P4plMn///////8AAP////////8A////////AID/////////HkPFIEPQIU3IHE/GKkmsZExihC4AhSsAeSUAajEjVgAAdnp5d+36cO//SpK2////////AP//////////AP///////wD//////////x5PzSFL1x9QyCRczAd42j5+x5JiX51RKJNKMII9JnQnAI1aUHrN14r6/0y33v///////wAAAP///////wD///////////8AQL////8dVdUeT84iU8smZM8jfdAlaMdeer6iaEuuXRGcVjKYRBWMQyOL1d1r/P8A6vz///8zzMz///////////8A////////////AEC/////IjOqIES+AFTaAGjZAIzheXSTrHBTu3w4w3oct28upEwAwJmNv///ZN7wANbr////Vaqq////////////AP///////////wCA/////1VVqg5Ev3JgoIxogGGDq3ycpNaPBNmRI9COLsF6HrNlIszHv7Td7Wedx////////////////////////wD///////////////////////8AY+/BlHXRhiLXiTDGnGjaoFbmoUfin0TfljDYo3HOx7mfpsL///////8AAP////////////////8A/////////////////////////////////9eu5KVb56BC5aRT5ahb46VW36BV57qG/+Nx////////AAD/////////////////////AP///////////////////////wCA/7+AgP//////////0fO/eu22bfO7dv//tv///////8zMzP///////////////////////////wD/////////////////////////////////qlWqVQD///////////////////+/v4D/qqr///////////////////////////////8A' // jshint ignore:line
}
];
suite('MIME type constants', function() {
test('JPEG', function() { assert.equal(ImageUtils.JPEG, 'image/jpeg'); });
test('PNG', function() { assert.equal(ImageUtils.PNG, 'image/png'); });
test('GIF', function() { assert.equal(ImageUtils.GIF, 'image/gif'); });
test('BMP', function() { assert.equal(ImageUtils.BMP, 'image/bmp'); });
});
suite('getSizeAndType', function() {
function makeBlobFromString(binaryString, type) {
var buffer = new ArrayBuffer(binaryString.length);
var bytes = new Uint8Array(buffer);
for (var i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return new Blob([buffer], { type: type });
}
suiteSetup(function() {
// Create blobs for each of the test images
testImages.forEach(function(image) {
image.blob = makeBlobFromString(atob(image.base64), image.type);
});
});
test('rejects string argument', function(done) {
ImageUtils.getSizeAndType('data:foo').then(null, function() { done(); });
});
test('rejects numeric argument', function(done) {
ImageUtils.getSizeAndType(1).then(null, function() { done(); });
});
test('rejects object argument', function(done) {
ImageUtils.getSizeAndType({size:100}).then(null, function() { done(); });
});
// Test that we can get the width and height of each test image
testImages.forEach(function(image) {
test(image.type, function(done) {
ImageUtils.getSizeAndType(image.blob).then(function resolve(data) {
try {
assert.equal(data.type, image.type);
assert.equal(data.width, image.width);
assert.equal(data.height, image.height);
done();
}
catch (e) {
done(e);
}
}, function reject(e) { done(new Error(e)); });
});
});
// Test that we can get the size of a JPEG file even if it has a large
// EXIF metadata segment before the segments that hold image size.
test('jpeg with large EXIF segments', function(done) {
// Splice some fake EXIF data in at the start of the JPEG file
// to force the image size data to be beyond the 32kb boundary
var jpeg = testImages[0];
var exif = new ArrayBuffer(40 * 1024);
var view = new DataView(exif);
view.setUint8(0, 0xFF);
view.setUint8(1, 0xE0); // APP0 segment for EXIF
view.setUint16(2, (40 * 1024) - 2);
var newblob = new Blob([jpeg.blob.slice(0, 2),
exif, exif, jpeg.blob.slice(2)],
{ type: 'image/jpeg' });
ImageUtils.getSizeAndType(newblob).then(
function resolve(data) {
try {
assert.equal(data.type, jpeg.type);
assert.equal(data.width, jpeg.width);
assert.equal(data.height, jpeg.height);
done();
}
catch (e) {
done(e);
}
},
function reject(e) {
done(new Error(e));
}
);
});
test('reject zero-length blob', function(done) {
var empty = new Blob([''], { type: 'image/jpeg' });
ImageUtils.getSizeAndType(empty).then(
function resolve() {
done(new Error('failed to reject an empty blob'));
},
function reject() {
done();
}
);
});
test('reject any blob < 16 bytes', function(done) {
var empty = new Blob(['0123456789012345'], { type: 'image/jpeg' });
ImageUtils.getSizeAndType(empty).then(
function resolve() {
done(new Error('failed to reject a short blob'));
},
function reject() {
done();
}
);
});
// Test that if we truncate the test images we can't get their size
testImages.forEach(function(image) {
// We can't meaningfully test truncated gif files
if (image.type === 'image/gif') {
return;
}
test('reject truncated ' + image.type, function(done) {
var truncated = image.blob.slice(0, 20);
ImageUtils.getSizeAndType(truncated).then(
function resolve(data) {
done(new Error('failed to reject a truncated blob'));
},
function reject() {
done();
}
);
});
});
// Here are some files that are not image files and should be rejected
var bogusFiles = [
'This is a text file not an image file. It does not have a size',
'GIF85a This is not a gif: the header is not correct',
'\xff\xd8 Not a jpeg file because it does not have segments',
'BM not really a BMP file since. File length data is not correct',
'\x89PNG\r\n\x1a\n Not a PNG file: does not have an ihdr segment'
];
bogusFiles.forEach(function(file, index) {
test('Reject bogus file ' + index, function(done) {
var bogus = makeBlobFromString(file, 'text/plain');
ImageUtils.getSizeAndType(bogus).then(
function resolve(data) {
done(new Error('failed to reject bogus text:' + file));
},
function reject() {
done();
}
);
});
});
});
suite('Downsample tests', function() {
test('Check API', function() {
assert.typeOf(ImageUtils.Downsample, 'object');
assert.typeOf(ImageUtils.Downsample.sizeAtLeast, 'function');
assert.typeOf(ImageUtils.Downsample.sizeNoMoreThan, 'function');
assert.typeOf(ImageUtils.Downsample.areaAtLeast, 'function');
assert.typeOf(ImageUtils.Downsample.areaNoMoreThan, 'function');
assert.typeOf(ImageUtils.Downsample.MAX_SIZE_REDUCTION, 'number');
assert.typeOf(ImageUtils.Downsample.MAX_AREA_REDUCTION, 'number');
assert.typeOf(ImageUtils.Downsample.NONE, 'object');
assert.equal(ImageUtils.Downsample.NONE.dimensionScale, 1);
assert.equal(ImageUtils.Downsample.NONE.areaScale, 1);
assert.equal(ImageUtils.Downsample.NONE.toString(), '');
});
var scales = [
10, 2, 1,
1 / 8, 2 / 8, 3 / 8, 4 / 8, 5 / 8, 6 / 8, 7 / 8,
0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1,
0.09, 0.08, 0.07, 0.06, 0.05, 0.04, 0.03, 0.02, 0.01
];
// This is the same function we use in downsample.js
function round(x) {
return Math.round(x * 100) / 100;
}
test('sizeAtLeast', function() {
var min = 1 / ImageUtils.Downsample.MAX_SIZE_REDUCTION;
scales.forEach(function(scale) {
var ds = ImageUtils.Downsample.sizeAtLeast(scale);
assert.operator(ds.dimensionScale, '<=', round(Math.max(scale, min)));
assert.equal(ds.scale(100), ds.dimensionScale * 100);
assert.ok(ds === ImageUtils.Downsample.NONE ||
ds.toString()[0] === '#');
});
});
test('areaAtLeast', function() {
var min = 1 / ImageUtils.Downsample.MAX_AREA_REDUCTION;
scales.forEach(function(scale) {
var ds = ImageUtils.Downsample.areaAtLeast(scale);
assert.operator(ds.areaScale, '<=', round(Math.max(scale, min)));
ds = ImageUtils.Downsample.areaAtLeast(scale * scale);
assert.operator(ds.areaScale, '<=',
round(Math.max(scale * scale, min)));
assert.equal(ds.scale(100), ds.dimensionScale * 100);
assert.ok(ds === ImageUtils.Downsample.NONE ||
ds.toString()[0] === '#');
});
});
test('sizeNoMoreThan', function() {
scales.forEach(function(scale) {
var ds = ImageUtils.Downsample.sizeNoMoreThan(scale);
assert.operator(ds.dimensionScale, '>=', round(Math.min(scale, 1)));
assert.equal(ds.scale(100), ds.dimensionScale * 100);
assert.ok(ds === ImageUtils.Downsample.NONE ||
ds.toString()[0] === '#');
});
});
test('areaNoMoreThan', function() {
scales.forEach(function(scale) {
var ds = ImageUtils.Downsample.areaNoMoreThan(scale);
assert.operator(ds.areaScale, '>=', round(Math.min(scale, 1)));
ds = ImageUtils.Downsample.areaNoMoreThan(scale * scale);
assert.operator(ds.areaScale, '>=', round(Math.min(scale * scale, 1)));
assert.equal(ds.scale(100), ds.dimensionScale * 100);
assert.ok(ds === ImageUtils.Downsample.NONE ||
ds.toString()[0] === '#');
});
});
test('max reduction amounts', function() {
var ds = ImageUtils.Downsample.sizeNoMoreThan(0);
assert.equal(ds.dimensionScale,
round(1 / ImageUtils.Downsample.MAX_SIZE_REDUCTION));
assert.equal(ds.areaScale,
round(1 / ImageUtils.Downsample.MAX_AREA_REDUCTION));
});
});
function runResizeAndCropToCoverTests(imageWidth, imageHeight, imageType,
encoderOptions) {
var suitename = 'resizeAndCropToCover ' + imageType + ' ' +
imageWidth + 'x' + imageHeight;
suite(suitename, function() {
const W = imageWidth, H = imageHeight; // The size of the test image
const inputImageType = imageType;
const encoderOptions = encoderOptions;
suiteSetup(function(done) {
// We begin by creating a special image where each pixel value
// encodes the coordinates of that pixel. This allows us to inspect
// the pixels in the output image to verify that cropping
// was done correctly.
var canvas = document.createElement('canvas');
canvas.width = W;
canvas.height = H;
var context = canvas.getContext('2d');
var imageData = context.createImageData(W, H);
var pixels = imageData.data;
for (var x = 0; x < canvas.width; x++) {
for (var y = 0; y < canvas.height; y++) {
var offset = (x + y * canvas.width) * 4;
pixels[offset] = x; // Encode x coordinate as red value
pixels[offset + 1] = y; // Encode y coodrdinate as green value
imageData.data[offset + 3] = 255; // Make it opaque
}
}
context.putImageData(imageData, 0, 0);
// Create an encoded version of the input image
var self = this;
canvas.toBlob(function(blob) {
self.inputBlob = blob;
done();
}, inputImageType);
});
// Decode the image blob and verify that its size is as expected and
// that its upper-left pixel has red and green values near r0 and g0
// and that its lower-right pixel has values near r1 and g1. We do a
// fuzzy match because jpeg is a lossy format and because sometimes
// we're working with downsampled or upscaled images.
function verifyImage(blob, expectedWidth, expectedHeight,
r0, g0, r1, g1, tolerance, callback) {
var image = new Image();
var url = URL.createObjectURL(blob);
image.src = url;
image.onerror = function() {
callback(Error('failed to load image from blob'));
};
image.onload = function() {
try {
assert.equal(image.width, expectedWidth, 'image width');
assert.equal(image.height, expectedHeight, 'image height');
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
var imageData = context.getImageData(0, 0,
canvas.width, canvas.height);
var pixels = imageData.data;
isNear(pixels[0], r0, 'red component of upper-left');
isNear(pixels[1], g0, 'green component of upper-left');
var offset = 4 * (image.width * image.height - 1);
isNear(pixels[offset], r1,
'red component of lower right');
isNear(pixels[offset + 1], g1,
'green component of lower right');
image.src = '';
URL.revokeObjectURL(url);
canvas.width = 0;
callback();
}
catch (e) {
callback(e);
}
};
// Return true if x is close enough to the target
function isNear(x, target, message) {
if (target - tolerance <= x && x <= target + tolerance) {
return;
}
throw Error(message + ' ' + x + ' is not near ' + target);
}
}
test('test images created', function(done) {
assert.instanceOf(this.inputBlob, Blob, 'got Blob');
assert.equal(this.inputBlob.type, inputImageType);
verifyImage(this.inputBlob, W, H, 0, 0, W - 1, H - 1, 4, done);
});
function onResolve(value) {
throw Error('Must be rejected');
}
test('throw for invalid input image', function(done) {
function checkNotBlob(promise) {
return promise.then(
onResolve,
(err) => { assert.equal(err.name, 'TypeError'); }
);
}
Promise.all([
checkNotBlob(ImageUtils.resizeAndCropToCover(null, 1, 10)),
checkNotBlob(ImageUtils.resizeAndCropToCover('not a blob', 1, 10))
]).then(() => done(), done);
});
test('throw for invalid input dimension', function(done) {
function ensureReject(promise) {
return promise.then(
onResolve,
(err) => { assert.equal(err.message, 'invalid output dimensions'); }
);
}
Promise.all([
ensureReject(ImageUtils.resizeAndCropToCover(this.inputBlob)),
ensureReject(ImageUtils.resizeAndCropToCover(this.inputBlob, 0, 10)),
ensureReject(ImageUtils.resizeAndCropToCover(this.inputBlob, 10, 0)),
ensureReject(ImageUtils.resizeAndCropToCover(this.inputBlob,
-10, 10)),
ensureReject(ImageUtils.resizeAndCropToCover(this.inputBlob,
10, -10)),
ensureReject(ImageUtils.resizeAndCropToCover(this.inputBlob,
Infinity, 10)),
ensureReject(ImageUtils.resizeAndCropToCover(this.inputBlob,
10, Infinity)),
ensureReject(ImageUtils.resizeAndCropToCover(this.inputBlob, {}, 10)),
ensureReject(ImageUtils.resizeAndCropToCover(this.inputBlob, 10, {}))
]).then(() => done(), done);
});
// Verify that if the output size is the same as the input size then
// the output blob is the same as the input blob
test('input returned if no resize needed', function(done) {
var self = this;
ImageUtils.resizeAndCropToCover(this.inputBlob, W, H).then(
function resolve(outputBlob) {
try {
assert.equal(self.inputBlob, outputBlob);
done();
}
catch (ex) {
done(ex);
}
});
});
test('unspecified output type', function(done) {
var self = this;
ImageUtils.resizeAndCropToCover(this.inputBlob, 10, 10)
.then(function resolve(outputBlob) {
assert.equal(outputBlob.type, self.inputBlob.type);
done();
});
});
test('jpeg output type with encondig options', function(done) {
ImageUtils.resizeAndCropToCover(this.inputBlob, 10, 10, ImageUtils.JPEG,
encoderOptions)
.then(function resolve(outputBlob) {
assert.equal(outputBlob.type, ImageUtils.JPEG);
done();
});
});
test('png output type', function(done) {
ImageUtils.resizeAndCropToCover(this.inputBlob, 10, 10, ImageUtils.PNG)
.then(function resolve(outputBlob) {
assert.equal(outputBlob.type, ImageUtils.PNG);
done();
});
});
test('shrink no crop', function(done) {
ImageUtils.resizeAndCropToCover(this.inputBlob, W / 3, H / 3)
.then(function resolve(outputBlob) {
verifyImage(outputBlob, Math.round(W / 3), Math.round(H / 3),
0, 0, W, H, 4, done);
});
});
test('enlarge no crop', function(done) {
ImageUtils.resizeAndCropToCover(this.inputBlob, W * 3, H * 3)
.then(function resolve(outputBlob) {
verifyImage(outputBlob, W * 3, H * 3, 0, 0, W, H, 4, done);
});
});
var delta = 100;
test('reduce height', function(done) {
ImageUtils.resizeAndCropToCover(this.inputBlob, W, H - delta)
.then(function resolve(outputBlob) {
verifyImage(outputBlob, W, H - delta,
0, delta / 2, W, H - delta / 2, 4, done);
});
});
test('reduce width', function(done) {
ImageUtils.resizeAndCropToCover(this.inputBlob, W - delta, H)
.then(function resolve(outputBlob) {
verifyImage(outputBlob, W - delta, H,
delta / 2, 0, W - delta / 2, H, 4, done);
});
});
test('enlarge height', function(done) {
ImageUtils.resizeAndCropToCover(this.inputBlob, W, H + delta)
.then(function resolve(outputBlob) {
var ratio = (H + delta) / H;
var margin = ((ratio - 1) * W) / (2 * ratio);
verifyImage(outputBlob, W, H + delta,
margin, 0, W - margin, H,
4, done);
});
});
test('enlarge width', function(done) {
ImageUtils.resizeAndCropToCover(this.inputBlob, W + delta, H)
.then(function resolve(outputBlob) {
var ratio = (W + delta) / W;
var margin = ((ratio - 1) * H) / (2 * ratio);
verifyImage(outputBlob, W + delta, H,
0, margin, W, H - margin,
4, done);
});
});
suite('#-moz-samplesize', function() {
var spy;
setup(function() {
spy = this.sinon.spy(ImageUtils.Downsample, 'sizeNoMoreThan');
});
function checkResolve(promise, checkValue) {
return promise.then(
function resolve(outputBlob) {
sinon.assert.calledOnce(spy);
assert.equal(spy.returnValues[0].toString(), checkValue);
},
function reject(outputBlob) {
throw Error('Must be resolved');
}
);
}
if (inputImageType === 'image/jpeg') {
test('uses it at half size', function(done) {
checkResolve(ImageUtils.resizeAndCropToCover(
this.inputBlob, W / 2, H / 2),
'#-moz-samplesize=2').then(done,done);
});
test('uses it at third size', function(done) {
checkResolve(ImageUtils.resizeAndCropToCover(
this.inputBlob, W / 3, H / 3),
'#-moz-samplesize=3').then(done,done);
});
test('uses it at fifth size', function(done) {
checkResolve(ImageUtils.resizeAndCropToCover(
this.inputBlob, W / 5, H / 5),
'#-moz-samplesize=4').then(done,done);
});
test('does not use at three quarters size', function(done) {
checkResolve(ImageUtils.resizeAndCropToCover(
this.inputBlob, W * 0.75, H * 0.75),
'').then(done,done);
});
}
else {
test('does not use for non-jpeg', function(done) {
ImageUtils.resizeAndCropToCover(this.inputBlob, W / 2, H / 2)
.then(() => sinon.assert.notCalled(spy)).then(done, done);
});
}
});
});
}
// We run the resizeAndCropToCover test suite six times for for three
// different input image sizes and two different input image types
([
[240, 180], // 4x3
[180, 240], // 3x4
[250, 250] // square
]).forEach(function(size) {
runResizeAndCropToCoverTests(size[0], size[1], 'image/jpeg', 0.95);
runResizeAndCropToCoverTests(size[0], size[1], 'image/png');
});
});