Allow toBuffer to resolve Promise with info+data #143

This commit is contained in:
Lovell Fuller 2017-03-04 22:15:31 +00:00
parent 679ce08998
commit 6fe5b307b1
5 changed files with 89 additions and 23 deletions

View File

@ -40,15 +40,17 @@ Write output to a Buffer.
JPEG, PNG, WebP, and RAW output are supported. JPEG, PNG, WebP, and RAW output are supported.
By default, the format will match the input image, except GIF and SVG input which become PNG output. By default, the format will match the input image, except GIF and SVG input which become PNG output.
`callback`, if present, gets three arguments `(err, buffer, info)` where: `callback`, if present, gets three arguments `(err, data, info)` where:
- `err` is an error message, if any. - `err` is an error, if any.
- `buffer` is the output image data. - `data` is the output image data.
- `info` contains the output image `format`, `size` (bytes), `width`, `height` and `channels`. - `info` contains the output image `format`, `size` (bytes), `width`, `height` and `channels`.
A Promises/A+ promise is returned when `callback` is not provided. A Promise is returned when `callback` is not provided.
**Parameters** **Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?**
- `options.resolveWithObject` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Resolve the Promise with an Object containing `data` and `info` properties instead of resolving only with `data`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)?** - `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)?**
Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[Buffer](https://nodejs.org/api/buffer.html)>** when no callback is provided Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[Buffer](https://nodejs.org/api/buffer.html)>** when no callback is provided

View File

@ -4,6 +4,12 @@
Requires libvips v8.4.2. Requires libvips v8.4.2.
#### v0.17.3 - TBD
* Allow toBuffer to optionally resolve a Promise with both info and data.
[#143](https://github.com/lovell/sharp/issues/143)
[@salzhrani](https://github.com/salzhrani)
#### v0.17.2 - 11<sup>th</sup> February 2017 #### v0.17.2 - 11<sup>th</sup> February 2017
* Ensure Readable side of Stream can start flowing after Writable side has finished. * Ensure Readable side of Stream can start flowing after Writable side has finished.

View File

@ -134,6 +134,7 @@ const Sharp = function (input, options) {
streamOut: false, streamOut: false,
withMetadata: false, withMetadata: false,
withMetadataOrientation: -1, withMetadataOrientation: -1,
resolveWithObject: false,
// output format // output format
jpegQuality: 80, jpegQuality: 80,
jpegProgressive: false, jpegProgressive: false,

View File

@ -48,17 +48,24 @@ const toFile = function toFile (fileOut, callback) {
* JPEG, PNG, WebP, and RAW output are supported. * JPEG, PNG, WebP, and RAW output are supported.
* By default, the format will match the input image, except GIF and SVG input which become PNG output. * By default, the format will match the input image, except GIF and SVG input which become PNG output.
* *
* `callback`, if present, gets three arguments `(err, buffer, info)` where: * `callback`, if present, gets three arguments `(err, data, info)` where:
* - `err` is an error message, if any. * - `err` is an error, if any.
* - `buffer` is the output image data. * - `data` is the output image data.
* - `info` contains the output image `format`, `size` (bytes), `width`, `height` and `channels`. * - `info` contains the output image `format`, `size` (bytes), `width`, `height` and `channels`.
* A Promises/A+ promise is returned when `callback` is not provided. * A Promise is returned when `callback` is not provided.
* *
* @param {Object} [options]
* @param {Boolean} [options.resolveWithObject] Resolve the Promise with an Object containing `data` and `info` properties instead of resolving only with `data`.
* @param {Function} [callback] * @param {Function} [callback]
* @returns {Promise<Buffer>} - when no callback is provided * @returns {Promise<Buffer>} - when no callback is provided
*/ */
const toBuffer = function toBuffer (callback) { const toBuffer = function toBuffer (options, callback) {
return this._pipeline(callback); if (is.object(options)) {
if (is.bool(options.resolveWithObject)) {
this.options.resolveWithObject = options.resolveWithObject;
}
}
return this._pipeline(is.fn(options) ? options : callback);
}; };
/** /**
@ -423,24 +430,32 @@ const _pipeline = function _pipeline (callback) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
that.on('finish', function () { that.on('finish', function () {
that._flattenBufferIn(); that._flattenBufferIn();
sharp.pipeline(that.options, function (err, data) { sharp.pipeline(that.options, function (err, data, info) {
if (err) { if (err) {
reject(err); reject(err);
} else {
if (that.options.resolveWithObject) {
resolve({ data: data, info: info });
} else { } else {
resolve(data); resolve(data);
} }
}
}); });
}); });
}); });
} else { } else {
// output=promise, input=file/buffer // output=promise, input=file/buffer
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
sharp.pipeline(that.options, function (err, data) { sharp.pipeline(that.options, function (err, data, info) {
if (err) { if (err) {
reject(err); reject(err);
} else {
if (that.options.resolveWithObject) {
resolve({ data: data, info: info });
} else { } else {
resolve(data); resolve(data);
} }
}
}); });
}); });
} }

View File

@ -77,16 +77,58 @@ describe('Input/output', function () {
readable.pipe(pipeline); readable.pipe(pipeline);
}); });
it('Read from Stream and write to Buffer via Promise', function (done) { it('Read from Stream and write to Buffer via Promise resolved with Buffer', function () {
const readable = fs.createReadStream(fixtures.inputJpg);
const pipeline = sharp().resize(1, 1); const pipeline = sharp().resize(1, 1);
pipeline.toBuffer().then(function (data) { fs.createReadStream(fixtures.inputJpg).pipe(pipeline);
return pipeline
.toBuffer({resolveWithObject: false})
.then(function (data) {
assert.strictEqual(true, data instanceof Buffer);
assert.strictEqual(true, data.length > 0); assert.strictEqual(true, data.length > 0);
done();
}).catch(function (err) {
throw err;
}); });
readable.pipe(pipeline); });
it('Read from Stream and write to Buffer via Promise resolved with Object', function () {
const pipeline = sharp().resize(1, 1);
fs.createReadStream(fixtures.inputJpg).pipe(pipeline);
return pipeline
.toBuffer({resolveWithObject: true})
.then(function (object) {
assert.strictEqual('object', typeof object);
assert.strictEqual('object', typeof object.info);
assert.strictEqual('jpeg', object.info.format);
assert.strictEqual(1, object.info.width);
assert.strictEqual(1, object.info.height);
assert.strictEqual(3, object.info.channels);
assert.strictEqual(true, object.data instanceof Buffer);
assert.strictEqual(true, object.data.length > 0);
});
});
it('Read from File and write to Buffer via Promise resolved with Buffer', function () {
return sharp(fixtures.inputJpg)
.resize(1, 1)
.toBuffer({resolveWithObject: false})
.then(function (data) {
assert.strictEqual(true, data instanceof Buffer);
assert.strictEqual(true, data.length > 0);
});
});
it('Read from File and write to Buffer via Promise resolved with Object', function () {
return sharp(fixtures.inputJpg)
.resize(1, 1)
.toBuffer({resolveWithObject: true})
.then(function (object) {
assert.strictEqual('object', typeof object);
assert.strictEqual('object', typeof object.info);
assert.strictEqual('jpeg', object.info.format);
assert.strictEqual(1, object.info.width);
assert.strictEqual(1, object.info.height);
assert.strictEqual(3, object.info.channels);
assert.strictEqual(true, object.data instanceof Buffer);
assert.strictEqual(true, object.data.length > 0);
});
}); });
it('Read from Stream and write to Stream', function (done) { it('Read from Stream and write to Stream', function (done) {