Add support for .extract({left:...,top:...,width:...,height:...}).

This commit is contained in:
Andreas Lind 2015-11-18 11:09:24 +01:00
parent 5842da22d8
commit 60b8b92630
2 changed files with 78 additions and 23 deletions

View File

@ -169,17 +169,25 @@ Sharp.prototype.crop = function(gravity) {
return this; return this;
}; };
Sharp.prototype.extract = function(topOffset, leftOffset, width, height) { Sharp.prototype.extract = function(options) {
/*jslint unused: false */ if (!options || typeof options !== 'object') {
var suffix = this.options.width === -1 && this.options.height === -1 ? 'Pre' : 'Post'; // Legacy extract(top,left,width,height) syntax
var values = arguments; options = {
['topOffset', 'leftOffset', 'width', 'height'].forEach(function(name, index) { left: arguments[1],
if (typeof values[index] === 'number' && !Number.isNaN(values[index]) && (values[index] % 1 === 0) && values[index] >= 0) { top: arguments[0],
this.options[name + suffix] = values[index]; width: arguments[2],
} else { height: arguments[3]
throw new Error('Non-integer value for ' + name + ' of ' + values[index]); };
} }
}.bind(this)); var suffix = this.options.width === -1 && this.options.height === -1 ? 'Pre' : 'Post';
['left', 'top', 'width', 'height'].forEach(function (name) {
var value = options[name];
if (typeof value === 'number' && !Number.isNaN(value) && value % 1 === 0 && value >= 0) {
this.options[name + (name === 'left' || name === 'top' ? 'Offset' : '') + suffix] = value;
} else {
throw new Error('Non-integer value for ' + name + ' of ' + value);
}
}, this);
// Ensure existing rotation occurs before pre-resize extraction // Ensure existing rotation occurs before pre-resize extraction
if (suffix === 'Pre' && this.options.angle !== 0) { if (suffix === 'Pre' && this.options.angle !== 0) {
this.options.rotateBeforePreExtract = true; this.options.rotateBeforePreExtract = true;

View File

@ -8,7 +8,7 @@ var fixtures = require('../fixtures');
sharp.cache(0); sharp.cache(0);
describe('Partial image extraction', function() { describe('Partial image extraction', function() {
describe('using the legacy extract(top,left,width,height) syntax', function () {
it('JPEG', function(done) { it('JPEG', function(done) {
sharp(fixtures.inputJpg) sharp(fixtures.inputJpg)
.extract(2, 2, 20, 20) .extract(2, 2, 20, 20)
@ -30,11 +30,34 @@ describe('Partial image extraction', function() {
fixtures.assertSimilar(fixtures.expected('extract.png'), data, done); fixtures.assertSimilar(fixtures.expected('extract.png'), data, done);
}); });
}); });
});
it('JPEG', function(done) {
sharp(fixtures.inputJpg)
.extract({ left: 2, top: 2, width: 20, height: 20 })
.toBuffer(function(err, data, info) {
if (err) throw err;
assert.strictEqual(20, info.width);
assert.strictEqual(20, info.height);
fixtures.assertSimilar(fixtures.expected('extract.jpg'), data, done);
});
});
it('PNG', function(done) {
sharp(fixtures.inputPng)
.extract({ left: 200, top: 300, width: 400, height: 200 })
.toBuffer(function(err, data, info) {
if (err) throw err;
assert.strictEqual(400, info.width);
assert.strictEqual(200, info.height);
fixtures.assertSimilar(fixtures.expected('extract.png'), data, done);
});
});
if (sharp.format.webp.output.file) { if (sharp.format.webp.output.file) {
it('WebP', function(done) { it('WebP', function(done) {
sharp(fixtures.inputWebP) sharp(fixtures.inputWebP)
.extract(50, 100, 125, 200) .extract({ left: 100, top: 50, width: 125, height: 200 })
.toBuffer(function(err, data, info) { .toBuffer(function(err, data, info) {
if (err) throw err; if (err) throw err;
assert.strictEqual(125, info.width); assert.strictEqual(125, info.width);
@ -46,7 +69,7 @@ describe('Partial image extraction', function() {
it('TIFF', function(done) { it('TIFF', function(done) {
sharp(fixtures.inputTiff) sharp(fixtures.inputTiff)
.extract(63, 34, 341, 529) .extract({ left: 34, top: 63, width: 341, height: 529 })
.jpeg() .jpeg()
.toBuffer(function(err, data, info) { .toBuffer(function(err, data, info) {
if (err) throw err; if (err) throw err;
@ -58,7 +81,7 @@ describe('Partial image extraction', function() {
it('Before resize', function(done) { it('Before resize', function(done) {
sharp(fixtures.inputJpg) sharp(fixtures.inputJpg)
.extract(10, 10, 10, 500, 500) .extract({ left: 10, top: 10, width: 10, height: 500 })
.resize(100, 100) .resize(100, 100)
.toBuffer(function(err, data, info) { .toBuffer(function(err, data, info) {
if (err) throw err; if (err) throw err;
@ -72,7 +95,7 @@ describe('Partial image extraction', function() {
sharp(fixtures.inputJpg) sharp(fixtures.inputJpg)
.resize(500, 500) .resize(500, 500)
.crop(sharp.gravity.north) .crop(sharp.gravity.north)
.extract(10, 10, 100, 100) .extract({ left: 10, top: 10, width: 100, height: 100 })
.toBuffer(function(err, data, info) { .toBuffer(function(err, data, info) {
if (err) throw err; if (err) throw err;
assert.strictEqual(100, info.width); assert.strictEqual(100, info.width);
@ -83,10 +106,10 @@ describe('Partial image extraction', function() {
it('Before and after resize and crop', function(done) { it('Before and after resize and crop', function(done) {
sharp(fixtures.inputJpg) sharp(fixtures.inputJpg)
.extract(0, 0, 700, 700) .extract({ left: 0, top: 0, width: 700, height: 700 })
.resize(500, 500) .resize(500, 500)
.crop(sharp.gravity.north) .crop(sharp.gravity.north)
.extract(10, 10, 100, 100) .extract({ left: 10, top: 10, width: 100, height: 100 })
.toBuffer(function(err, data, info) { .toBuffer(function(err, data, info) {
if (err) throw err; if (err) throw err;
assert.strictEqual(100, info.width); assert.strictEqual(100, info.width);
@ -97,7 +120,7 @@ describe('Partial image extraction', function() {
it('Extract then rotate', function(done) { it('Extract then rotate', function(done) {
sharp(fixtures.inputPngWithGreyAlpha) sharp(fixtures.inputPngWithGreyAlpha)
.extract(10, 20, 380, 280) .extract({ left: 20, top: 10, width: 380, height: 280 })
.rotate(90) .rotate(90)
.toBuffer(function(err, data, info) { .toBuffer(function(err, data, info) {
if (err) throw err; if (err) throw err;
@ -110,7 +133,7 @@ describe('Partial image extraction', function() {
it('Rotate then extract', function(done) { it('Rotate then extract', function(done) {
sharp(fixtures.inputPngWithGreyAlpha) sharp(fixtures.inputPngWithGreyAlpha)
.rotate(90) .rotate(90)
.extract(10, 20, 280, 380) .extract({ left: 20, top: 10, width: 280, height: 380 })
.toBuffer(function(err, data, info) { .toBuffer(function(err, data, info) {
if (err) throw err; if (err) throw err;
assert.strictEqual(280, info.width); assert.strictEqual(280, info.width);
@ -120,13 +143,7 @@ describe('Partial image extraction', function() {
}); });
describe('Invalid parameters', function() { describe('Invalid parameters', function() {
describe('using the legacy extract(top,left,width,height) syntax', function () {
it('Undefined', function() {
assert.throws(function() {
sharp(fixtures.inputJpg).extract();
});
});
it('String top', function() { it('String top', function() {
assert.throws(function() { assert.throws(function() {
sharp(fixtures.inputJpg).extract('spoons', 10, 10, 10); sharp(fixtures.inputJpg).extract('spoons', 10, 10, 10);
@ -150,6 +167,36 @@ describe('Partial image extraction', function() {
sharp(fixtures.inputJpg).extract(10, 10, 10, null); sharp(fixtures.inputJpg).extract(10, 10, 10, null);
}); });
}); });
});
it('Undefined', function() {
assert.throws(function() {
sharp(fixtures.inputJpg).extract();
});
});
it('String top', function() {
assert.throws(function() {
sharp(fixtures.inputJpg).extract({ left: 10, top: 'spoons', width: 10, height: 10 });
});
});
it('Non-integral left', function() {
assert.throws(function() {
sharp(fixtures.inputJpg).extract({ left: 10.2, top: 10, width: 10, height: 10 });
});
});
it('Negative width - negative', function() {
assert.throws(function() {
sharp(fixtures.inputJpg).extract({ left: 10, top: 10, width: -10, height: 10 });
});
});
it('Null height', function() {
assert.throws(function() {
sharp(fixtures.inputJpg).extract({ left: 10, top: 10, width: 10, height: null });
});
});
}); });
}); });