sharp/test/unit/affine.js
2023-02-28 17:01:58 +00:00

188 lines
6.2 KiB
JavaScript

// Copyright 2013 Lovell Fuller and others.
// SPDX-License-Identifier: Apache-2.0
'use strict';
const assert = require('assert');
const sharp = require('../../');
const fixtures = require('../fixtures');
describe('Affine transform', () => {
describe('Invalid input', () => {
it('Missing matrix', () => {
assert.throws(() => {
sharp(fixtures.inputJpg)
.affine();
});
});
it('Invalid 1d matrix', () => {
assert.throws(() => {
sharp(fixtures.inputJpg)
.affine(['123', 123, 123, 123]);
});
});
it('Invalid 2d matrix', () => {
assert.throws(() => {
sharp(fixtures.inputJpg)
.affine([[123, 123], [null, 123]]);
});
});
it('Invalid options parameter type', () => {
assert.throws(() => {
sharp(fixtures.inputJpg)
.affine([[1, 0], [0, 1]], 'invalid options type');
});
});
it('Invalid background color', () => {
assert.throws(() => {
sharp(fixtures.inputJpg)
.affine([4, 4, 4, 4], { background: 'not a color' });
});
});
it('Invalid idx offset type', () => {
assert.throws(() => {
sharp(fixtures.inputJpg)
.affine([[4, 4], [4, 4]], { idx: 'invalid idx type' });
});
});
it('Invalid idy offset type', () => {
assert.throws(() => {
sharp(fixtures.inputJpg)
.affine([4, 4, 4, 4], { idy: 'invalid idy type' });
});
});
it('Invalid odx offset type', () => {
assert.throws(() => {
sharp(fixtures.inputJpg)
.affine([[4, 4], [4, 4]], { odx: 'invalid odx type' });
});
});
it('Invalid ody offset type', () => {
assert.throws(() => {
sharp(fixtures.inputJpg)
.affine([[4, 4], [4, 4]], { ody: 'invalid ody type' });
});
});
it('Invalid interpolator', () => {
assert.throws(() => {
sharp(fixtures.inputJpg)
.affine([[4, 4], [4, 4]], { interpolator: 'cubic' });
});
});
});
it('Applies identity matrix', done => {
const input = fixtures.inputJpg;
sharp(input)
.affine([[1, 0], [0, 1]])
.toBuffer((err, data) => {
if (err) throw err;
fixtures.assertSimilar(input, data, done);
});
});
it('Applies resize affine matrix', done => {
const input = fixtures.inputJpg;
const inputWidth = 2725;
const inputHeight = 2225;
sharp(input)
.affine([[0.2, 0], [0, 1.5]])
.toBuffer((err, data, info) => {
if (err) throw err;
fixtures.assertSimilar(input, data, done);
assert.strictEqual(info.width, Math.ceil(inputWidth * 0.2));
assert.strictEqual(info.height, Math.ceil(inputHeight * 1.5));
});
});
it('Resizes and applies affine transform', done => {
const input = fixtures.inputJpg;
sharp(input)
.resize(500, 500)
.affine([[0.5, 1], [1, 0.5]])
.toBuffer((err, data) => {
if (err) throw err;
fixtures.assertSimilar(data, fixtures.expected('affine-resize-expected.jpg'), done);
});
});
it('Extracts and applies affine transform', done => {
sharp(fixtures.inputJpg)
.extract({ left: 300, top: 300, width: 600, height: 600 })
.affine([0.3, 0, -0.5, 0.3])
.toBuffer((err, data) => {
if (err) throw err;
fixtures.assertSimilar(data, fixtures.expected('affine-extract-expected.jpg'), done);
});
});
it('Rotates and applies affine transform', done => {
sharp(fixtures.inputJpg320x240)
.rotate(90)
.affine([[-1.2, 0], [0, -1.2]])
.toBuffer((err, data) => {
if (err) throw err;
fixtures.assertSimilar(data, fixtures.expected('affine-rotate-expected.jpg'), done);
});
});
it('Extracts, rotates and applies affine transform', done => {
sharp(fixtures.inputJpg)
.extract({ left: 1000, top: 1000, width: 200, height: 200 })
.rotate(45, { background: 'blue' })
.affine([[2, 1], [2, -0.5]], { background: 'red' })
.toBuffer((err, data) => {
if (err) throw err;
fixtures.assertSimilar(fixtures.expected('affine-extract-rotate-expected.jpg'), data, done);
});
});
it('Applies affine transform with background color', done => {
sharp(fixtures.inputJpg320x240)
.rotate(180)
.affine([[-1.5, 1.2], [-1, 1]], { background: 'red' })
.toBuffer((err, data) => {
if (err) throw err;
fixtures.assertSimilar(fixtures.expected('affine-background-expected.jpg'), data, done);
});
});
it('Applies affine transform with background color and output offsets', done => {
sharp(fixtures.inputJpg320x240)
.rotate(180)
.affine([[-2, 1.5], [-1, 2]], { background: 'blue', odx: 40, ody: -100 })
.toBuffer((err, data) => {
if (err) throw err;
fixtures.assertSimilar(fixtures.expected('affine-background-output-offsets-expected.jpg'), data, done);
});
});
it('Applies affine transform with background color and all offsets', done => {
sharp(fixtures.inputJpg320x240)
.rotate(180)
.affine([[-1.2, 1.8], [-1, 2]], { background: 'yellow', idx: 10, idy: -40, odx: 10, ody: -50 })
.toBuffer((err, data) => {
if (err) throw err;
fixtures.assertSimilar(fixtures.expected('affine-background-all-offsets-expected.jpg'), data, done);
});
});
it('Animated image rejects', () =>
assert.rejects(() => sharp(fixtures.inputGifAnimated, { animated: true })
.affine([1, 1, 1, 1])
.toBuffer(),
/Affine is not supported for multi-page images/
)
);
describe('Interpolations', () => {
const input = fixtures.inputJpg320x240;
const inputWidth = 320;
const inputHeight = 240;
for (const interp in sharp.interpolators) {
it(`Performs 2x upscale with ${interp} interpolation`, done => {
sharp(input)
.affine([[2, 0], [0, 2]], { interpolator: sharp.interpolators[interp] })
.toBuffer((err, data, info) => {
if (err) throw err;
assert.strictEqual(info.width, Math.ceil(inputWidth * 2));
assert.strictEqual(info.height, Math.ceil(inputHeight * 2));
fixtures.assertSimilar(fixtures.expected(`affine-${sharp.interpolators[interp]}-2x-upscale-expected.jpg`), data, done);
});
});
}
});
});