mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 18:40:16 +02:00
Merge pull request #309 from papandreou/feature/extractWithOptionsObject
Add an options object to the extract operation, deprecate existing behaviour.
This commit is contained in:
commit
3de54d897c
12
docs/api.md
12
docs/api.md
@ -78,7 +78,7 @@ to share a single input Stream.
|
|||||||
```javascript
|
```javascript
|
||||||
var pipeline = sharp().rotate();
|
var pipeline = sharp().rotate();
|
||||||
pipeline.clone().resize(800, 600).pipe(firstWritableStream);
|
pipeline.clone().resize(800, 600).pipe(firstWritableStream);
|
||||||
pipeline.clone().extract(20, 20, 100, 100).pipe(secondWritableStream);
|
pipeline.clone().extract({ left: 20, top: 20, width: 100, height: 100 }).pipe(secondWritableStream);
|
||||||
readableStream.pipe(pipeline);
|
readableStream.pipe(pipeline);
|
||||||
// firstWritableStream receives auto-rotated, resized readableStream
|
// firstWritableStream receives auto-rotated, resized readableStream
|
||||||
// secondWritableStream receives auto-rotated, extracted region of readableStream
|
// secondWritableStream receives auto-rotated, extracted region of readableStream
|
||||||
@ -230,11 +230,11 @@ sharp(inputBuffer)
|
|||||||
|
|
||||||
### Operations
|
### Operations
|
||||||
|
|
||||||
#### extract(top, left, width, height)
|
#### extract({ left: left, top: top, width: width, height: height })
|
||||||
|
|
||||||
Extract a region of the image. Can be used with or without a `resize` operation.
|
Extract a region of the image. Can be used with or without a `resize` operation.
|
||||||
|
|
||||||
`top` and `left` are the offset, in pixels, from the top-left corner.
|
`left` and `top` are the offset, in pixels, from the top-left corner.
|
||||||
|
|
||||||
`width` and `height` are the dimensions of the extracted image.
|
`width` and `height` are the dimensions of the extracted image.
|
||||||
|
|
||||||
@ -242,7 +242,7 @@ Use `extract` before `resize` for pre-resize extraction. Use `extract` after `re
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
sharp(input)
|
sharp(input)
|
||||||
.extract(top, left, width, height)
|
.extract({ left: left, top: top, width: width, height: height })
|
||||||
.toFile(output, function(err) {
|
.toFile(output, function(err) {
|
||||||
// Extract a region of the input image, saving in the same format.
|
// Extract a region of the input image, saving in the same format.
|
||||||
});
|
});
|
||||||
@ -250,9 +250,9 @@ sharp(input)
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
sharp(input)
|
sharp(input)
|
||||||
.extract(topOffsetPre, leftOffsetPre, widthPre, heightPre)
|
.extract({ left: leftOffsetPre, top: topOffsetPre, width: widthPre, height: heightPre })
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.extract(topOffsetPost, leftOffsetPost, widthPost, heightPost)
|
.extract({ left: leftOffsetPost, top: topOffsetPost, width: widthPost, height: heightPost })
|
||||||
.toFile(output, function(err) {
|
.toFile(output, function(err) {
|
||||||
// Extract a region, resize, then extract from the resized image
|
// Extract a region, resize, then extract from the resized image
|
||||||
});
|
});
|
||||||
|
24
index.js
24
index.js
@ -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') {
|
||||||
|
// Legacy extract(top,left,width,height) syntax
|
||||||
|
options = {
|
||||||
|
left: arguments[1],
|
||||||
|
top: arguments[0],
|
||||||
|
width: arguments[2],
|
||||||
|
height: arguments[3]
|
||||||
|
};
|
||||||
|
}
|
||||||
var suffix = this.options.width === -1 && this.options.height === -1 ? 'Pre' : 'Post';
|
var suffix = this.options.width === -1 && this.options.height === -1 ? 'Pre' : 'Post';
|
||||||
var values = arguments;
|
['left', 'top', 'width', 'height'].forEach(function (name) {
|
||||||
['topOffset', 'leftOffset', 'width', 'height'].forEach(function(name, index) {
|
var value = options[name];
|
||||||
if (typeof values[index] === 'number' && !Number.isNaN(values[index]) && (values[index] % 1 === 0) && values[index] >= 0) {
|
if (typeof value === 'number' && !Number.isNaN(value) && value % 1 === 0 && value >= 0) {
|
||||||
this.options[name + suffix] = values[index];
|
this.options[name + (name === 'left' || name === 'top' ? 'Offset' : '') + suffix] = value;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Non-integer value for ' + name + ' of ' + values[index]);
|
throw new Error('Non-integer value for ' + name + ' of ' + value);
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}, 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;
|
||||||
|
@ -8,10 +8,33 @@ 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) {
|
||||||
|
sharp(fixtures.inputJpg)
|
||||||
|
.extract(2, 2, 20, 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(300, 200, 400, 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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('JPEG', function(done) {
|
it('JPEG', function(done) {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.extract(2, 2, 20, 20)
|
.extract({ left: 2, top: 2, width: 20, height: 20 })
|
||||||
.toBuffer(function(err, data, info) {
|
.toBuffer(function(err, data, info) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(20, info.width);
|
assert.strictEqual(20, info.width);
|
||||||
@ -22,7 +45,7 @@ describe('Partial image extraction', function() {
|
|||||||
|
|
||||||
it('PNG', function(done) {
|
it('PNG', function(done) {
|
||||||
sharp(fixtures.inputPng)
|
sharp(fixtures.inputPng)
|
||||||
.extract(300, 200, 400, 200)
|
.extract({ left: 200, top: 300, width: 400, height: 200 })
|
||||||
.toBuffer(function(err, data, info) {
|
.toBuffer(function(err, data, info) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(400, info.width);
|
assert.strictEqual(400, info.width);
|
||||||
@ -34,7 +57,7 @@ describe('Partial image extraction', function() {
|
|||||||
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,6 +143,31 @@ 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('String top', function() {
|
||||||
|
assert.throws(function() {
|
||||||
|
sharp(fixtures.inputJpg).extract('spoons', 10, 10, 10);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Non-integral left', function() {
|
||||||
|
assert.throws(function() {
|
||||||
|
sharp(fixtures.inputJpg).extract(10, 10.2, 10, 10);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Negative width - negative', function() {
|
||||||
|
assert.throws(function() {
|
||||||
|
sharp(fixtures.inputJpg).extract(10, 10, -10, 10);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Null height', function() {
|
||||||
|
assert.throws(function() {
|
||||||
|
sharp(fixtures.inputJpg).extract(10, 10, 10, null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Undefined', function() {
|
it('Undefined', function() {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
@ -129,27 +177,26 @@ describe('Partial image extraction', function() {
|
|||||||
|
|
||||||
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({ left: 10, top: 'spoons', width: 10, height: 10 });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Non-integral left', function() {
|
it('Non-integral left', function() {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
sharp(fixtures.inputJpg).extract(10, 10.2, 10, 10);
|
sharp(fixtures.inputJpg).extract({ left: 10.2, top: 10, width: 10, height: 10 });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Negative width - negative', function() {
|
it('Negative width - negative', function() {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
sharp(fixtures.inputJpg).extract(10, 10, -10, 10);
|
sharp(fixtures.inputJpg).extract({ left: 10, top: 10, width: -10, height: 10 });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Null height', function() {
|
it('Null height', function() {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
sharp(fixtures.inputJpg).extract(10, 10, 10, null);
|
sharp(fixtures.inputJpg).extract({ left: 10, top: 10, width: 10, height: null });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user