sharp/test/unit/overlay.js
Daniel Gasienica ef8db1eebf Premultiply alpha channel to avoid dark artifacts during tranformation
Add `Sharp.compare(file1, file2, callback)` function for comparing images
using mean squared error (MSE). This is useful for unit tests.

See:
- https://github.com/jcupitt/libvips/issues/291
- http://entropymine.com/imageworsener/resizealpha/
2015-06-01 14:21:02 +01:00

151 lines
4.2 KiB
JavaScript

'use strict';
var fixtures = require('../fixtures');
var fs = require('fs');
var sharp = require('../../index');
sharp.cache(0);
// Constants
var MAX_ALLOWED_IMAGE_MAGICK_MEAN_SQUARED_ERROR = 0.3;
// Helpers
var getPaths = function(baseName, extension) {
if (typeof extension === 'undefined') {
extension = 'png';
}
var actual = fixtures.path('output.' + baseName + '.' + extension);
var expected = fixtures.expected(baseName + '.' + extension);
var expectedMagick = fixtures.expected(baseName + '-imagemagick.' + extension);
return {
actual: actual,
expected: expected,
expectedMagick: expectedMagick
};
};
var assertEqual = function (paths, callback) {
if (typeof callback !== 'function') {
throw new TypeError('`callback` must be a function');
}
fixtures.assertEqual(paths.actual, paths.expected, function (error) {
if (error) return callback(error);
sharp.compare(paths.actual, paths.expectedMagick, function (error, info) {
if (error) return callback(error);
if (info.meanSquaredError > MAX_ALLOWED_IMAGE_MAGICK_MEAN_SQUARED_ERROR) {
return callback(new Error('Expected MSE against ImageMagick to be <= ' +
MAX_ALLOWED_IMAGE_MAGICK_MEAN_SQUARED_ERROR + '. Actual: ' +
info.meanSquaredError));
}
callback();
});
});
};
// Test
describe('Overlays', function() {
it('Overlay transparent PNG on solid background', function(done) {
var paths = getPaths('alpha-layer-01');
sharp(fixtures.inputPngOverlayLayer0)
.overlayWith(fixtures.inputPngOverlayLayer1)
.toFile(paths.actual, function (error) {
if (error) return done(error);
assertEqual(paths, done);
});
});
it('Overlay low-alpha transparent PNG on solid background', function(done) {
var paths = getPaths('alpha-layer-01-low-alpha');
sharp(fixtures.inputPngOverlayLayer0)
.overlayWith(fixtures.inputPngOverlayLayer1LowAlpha)
.toFile(paths.actual, function (error) {
if (error) return done(error);
assertEqual(paths, done);
});
});
it('Composite three transparent PNGs into one', function(done) {
var paths = getPaths('alpha-layer-012');
sharp(fixtures.inputPngOverlayLayer0)
.overlayWith(fixtures.inputPngOverlayLayer1)
.toBuffer(function (error, data, info) {
if (error) return done(error);
sharp(data)
.overlayWith(fixtures.inputPngOverlayLayer2)
.toFile(paths.actual, function (error) {
if (error) return done(error);
assertEqual(paths, done);
});
});
});
it('Composite two transparent PNGs into one', function(done) {
var paths = getPaths('alpha-layer-12');
sharp(fixtures.inputPngOverlayLayer1)
.overlayWith(fixtures.inputPngOverlayLayer2)
.toFile(paths.actual, function (error, data, info) {
if (error) return done(error);
assertEqual(paths, done);
});
});
it('Composite two low-alpha transparent PNGs into one', function(done) {
var paths = getPaths('alpha-layer-12-low-alpha');
sharp(fixtures.inputPngOverlayLayer1LowAlpha)
.overlayWith(fixtures.inputPngOverlayLayer2LowAlpha)
.toFile(paths.actual, function (error, data, info) {
if (error) return done(error);
assertEqual(paths, done);
});
});
it('Composite three low-alpha transparent PNGs into one', function(done) {
var paths = getPaths('alpha-layer-012-low-alpha');
sharp(fixtures.inputPngOverlayLayer0)
.overlayWith(fixtures.inputPngOverlayLayer1LowAlpha)
.toBuffer(function (error, data, info) {
if (error) return done(error);
sharp(data)
.overlayWith(fixtures.inputPngOverlayLayer2LowAlpha)
.toFile(paths.actual, function (error, data, info) {
if (error) return done(error);
assertEqual(paths, done);
});
});
});
it('Composite transparent PNG onto JPEG', function(done) {
sharp(fixtures.inputJpg)
.overlayWith(fixtures.inputPngOverlayLayer1)
.toBuffer(function (error, data, info) {
if (error.message !== 'Input image must have an alpha channel') {
return done(new Error('Unexpected error: ' + error.message));
}
done();
});
});
});