Sends width and height as another parameter to the callback. Fixes issue #67

This commit is contained in:
Chanon 2014-07-20 23:52:28 +07:00
parent 1cce56b024
commit d40bdcc6ac
5 changed files with 85 additions and 34 deletions

View File

@ -79,51 +79,62 @@ var sharp = require('sharp');
```
```javascript
sharp('input.jpg').resize(300, 200).toFile('output.jpg', function(err) {
sharp('input.jpg').resize(300, 200).toFile('output.jpg', function(err, info) {
if (err) {
throw err;
}
// output.jpg is a 300 pixels wide and 200 pixels high image
// containing a scaled and cropped version of input.jpg
// info.width and info.height contain the final pixel dimensions of the resized image
// in this case they are the same as the input
});
```
```javascript
sharp('input.jpg').rotate().resize(null, 200).progressive().toBuffer(function(err, outputBuffer) {
sharp('input.jpg').rotate().resize(null, 200).progressive().toBuffer(function(err, outputBuffer, info) {
if (err) {
throw err;
}
// outputBuffer contains 200px high progressive JPEG image data, auto-rotated using EXIF Orientation tag
// info.width and info.height contain the final pixel dimensions of the resized image
});
```
```javascript
sharp('input.png').rotate(180).resize(300).sharpen().quality(90).webp().then(function(outputBuffer) {
sharp('input.png').rotate(180).resize(300).sharpen().quality(90).webp().then(function(outputBuffer, info) {
// outputBuffer contains 300px wide, upside down, sharpened, 90% quality WebP image data
// info.width and info.height contain the final pixel dimensions of the resized image
});
```
```javascript
sharp(inputBuffer).resize(200, 300).bicubicInterpolation().embedWhite().toFile('output.tiff').then(function() {
sharp(inputBuffer).resize(200, 300).bicubicInterpolation().embedWhite().toFile('output.tiff').then(function(info) {
// output.tiff is a 200 pixels wide and 300 pixels high image containing a bicubic scaled
// version, embedded on a white canvas, of the image data in buffer
// info.width and info.height contain the final pixel dimensions of the resized image
});
```
```javascript
sharp('input.gif').resize(200, 300).embedBlack().webp(function(err, outputBuffer) {
sharp('input.gif').resize(200, 300).embedBlack().webp(function(err, outputBuffer, info) {
if (err) {
throw err;
}
// outputBuffer contains WebP image data of a 200 pixels wide and 300 pixels high
// containing a scaled version, embedded on a black canvas, of input.gif
// info.width and info.height contain the final pixel dimensions of the resized image
});
```
```javascript
sharp(inputBuffer).resize(200, 200).max().jpeg().then(function(outputBuffer) {
sharp(inputBuffer).resize(200, 200).max().jpeg().then(function(outputBuffer, info) {
// outputBuffer contains JPEG image data no wider than 200 pixels and no higher
// than 200 pixels regardless of the inputBuffer image dimensions
// info.width and info.height contain the final pixel dimensions of the resized image
});
```
@ -216,7 +227,7 @@ An advanced setting that switches the libvips access method to `VIPS_ACCESS_SEQU
`filename` is a String containing the filename to write the image data to. The format is inferred from the extension, with JPEG, PNG, WebP and TIFF supported.
`callback`, if present, is called with a single argument `(err)` containing an error message, if any.
`callback`, if present, is called with two arguments `(err, info)` where `err` contains an error message, if any, and `info` contains the final resized image dimensions in its `width` and `height` properties.
A Promises/A+ promise is returned when `callback` is not provided.
@ -224,7 +235,7 @@ A Promises/A+ promise is returned when `callback` is not provided.
Write image data to a Buffer, the format of which will match the input image. JPEG, PNG and WebP are supported.
`callback`, if present, gets two arguments `(err, buffer)` where `err` is an error message, if any, and `buffer` is the resultant image data.
`callback`, if present, gets three arguments `(err, buffer, info)` where `err` is an error message, if any, `buffer` is the resultant image data, and `info` contains the final resized image dimensions in its `width` and `height` properties.
A Promises/A+ promise is returned when `callback` is not provided.
@ -232,7 +243,7 @@ A Promises/A+ promise is returned when `callback` is not provided.
Write JPEG image data to a Buffer.
`callback`, if present, gets two arguments `(err, buffer)` where `err` is an error message, if any, and `buffer` is the resultant JPEG image data.
`callback`, if present, gets three arguments `(err, buffer, info)` where `err` is an error message, if any, `buffer` is resultant JPEG image data, and `info` contains the final resized image dimensions in its `width` and `height` properties.
A Promises/A+ promise is returned when `callback` is not provided.
@ -240,7 +251,7 @@ A Promises/A+ promise is returned when `callback` is not provided.
Write PNG image data to a Buffer.
`callback`, if present, gets two arguments `(err, buffer)` where `err` is an error message, if any, and `buffer` is the resultant PNG image data.
`callback`, if present, gets three arguments `(err, buffer, info)` where `err` is an error message, if any, `buffer` is resultant PNG image data, and `info` contains the final resized image dimensions in its `width` and `height` properties.
A Promises/A+ promise is returned when `callback` is not provided.
@ -248,7 +259,7 @@ A Promises/A+ promise is returned when `callback` is not provided.
Write WebP image data to a Buffer.
`callback`, if present, gets two arguments `(err, buffer)` where `err` is an error message, if any, and `buffer` is the resultant WebP image data.
`callback`, if present, gets three arguments `(err, buffer, info)` where `err` is an error message, if any, `buffer` is resultant WebP image data, and `info` contains the final resized image dimensions in its `width` and `height` properties.
A Promises/A+ promise is returned when `callback` is not provided.

View File

@ -222,11 +222,11 @@ Sharp.prototype._sharp = function(output, callback) {
// I like promises
var options = this.options;
return new Promise(function(resolve, reject) {
sharp.resize(options, output, function(err, data) {
sharp.resize(options, output, function(err, data, info) {
if (err) {
reject(err);
} else {
resolve(data);
resolve(data, info);
}
});
});

View File

@ -4,7 +4,8 @@
"author": "Lovell Fuller <npm@lovell.info>",
"contributors": [
"Pierre Inglebert <pierre.inglebert@gmail.com>",
"Jonathan Ong <jonathanrichardong@gmail.com>"
"Jonathan Ong <jonathanrichardong@gmail.com>",
"Chanon Sajjamanochai <chanon.s@gmail.com>"
],
"description": "High performance Node.js module to resize JPEG, PNG and WebP images using the libvips library",
"scripts": {

View File

@ -431,17 +431,28 @@ class ResizeWorker : public NanAsyncWorker {
void HandleOKCallback () {
NanScope();
Handle<Value> argv[2] = { NanNull(), NanNull() };
Handle<Value> argv[3] = { NanNull(), NanNull(), NanNull() };
if (!baton->err.empty()) {
// Error
argv[0] = NanNew<String>(baton->err.data(), baton->err.size());
} else if (baton->buffer_out_len > 0) {
} else {
// Info Object
Local<Object> info = NanNew<Object>();
info->Set(NanNew<String>("width"), NanNew<Number>(baton->width));
info->Set(NanNew<String>("height"), NanNew<Number>(baton->height));
if (baton->buffer_out_len > 0) {
// Buffer
argv[1] = NanNewBufferHandle((char *)baton->buffer_out, baton->buffer_out_len);
g_free(baton->buffer_out);
argv[2] = info;
} else {
// File
argv[1] = info;
}
}
delete baton;
callback->Call(2, argv);
callback->Call(3, argv);
// Decrement queue length
g_atomic_int_dec_and_test(&queue_length);
}

View File

@ -21,8 +21,10 @@ var inputJpgWithExif = path.join(fixturesPath, "Landscape_8.jpg"); // https://gi
async.series([
// Resize with exact crop
function(done) {
sharp(inputJpg).resize(320, 240).toFile(outputJpg, function(err) {
sharp(inputJpg).resize(320, 240).toFile(outputJpg, function(err, info) {
if (err) throw err;
assert.strictEqual(320, info.width);
assert.strictEqual(240, info.height);
imagemagick.identify(outputJpg, function(err, features) {
if (err) throw err;
assert.strictEqual(320, features.width);
@ -33,8 +35,10 @@ async.series([
},
// Resize to fixed width
function(done) {
sharp(inputJpg).resize(320).toFile(outputJpg, function(err) {
sharp(inputJpg).resize(320).toFile(outputJpg, function(err, info) {
if (err) throw err;
assert.strictEqual(320, info.width);
assert.strictEqual(261, info.height);
imagemagick.identify(outputJpg, function(err, features) {
if (err) throw err;
assert.strictEqual(320, features.width);
@ -45,8 +49,10 @@ async.series([
},
// Resize to fixed height
function(done) {
sharp(inputJpg).resize(null, 320).toFile(outputJpg, function(err) {
sharp(inputJpg).resize(null, 320).toFile(outputJpg, function(err, info) {
if (err) throw err;
assert.strictEqual(391, info.width);
assert.strictEqual(320, info.height);
imagemagick.identify(outputJpg, function(err, features) {
if (err) throw err;
assert.strictEqual(391, features.width);
@ -69,8 +75,10 @@ async.series([
},
// Upscale
function(done) {
sharp(inputJpg).resize(3000).toFile(outputJpg, function(err) {
sharp(inputJpg).resize(3000).toFile(outputJpg, function(err, info) {
if (err) throw err;
assert.strictEqual(3000, info.width);
assert.strictEqual(2449, info.height);
imagemagick.identify(outputJpg, function(err, features) {
if (err) throw err;
assert.strictEqual(3000, features.width);
@ -118,8 +126,10 @@ async.series([
},
// Resize to max width or height considering ratio (landscape)
function(done) {
sharp(inputJpg).resize(320, 320).max().toFile(outputJpg, function(err) {
sharp(inputJpg).resize(320, 320).max().toFile(outputJpg, function(err, info) {
if (err) throw err;
assert.strictEqual(320, info.width);
assert.strictEqual(261, info.height);
imagemagick.identify(outputJpg, function(err, features) {
if (err) throw err;
assert.strictEqual(320, features.width);
@ -130,8 +140,10 @@ async.series([
},
// Resize to max width or height considering ratio (portrait)
function(done) {
sharp(inputTiff).resize(320, 320).max().toFile(outputJpg, function(err) {
sharp(inputTiff).resize(320, 320).max().toFile(outputJpg, function(err, info) {
if (err) throw err;
assert.strictEqual(243, info.width);
assert.strictEqual(320, info.height);
imagemagick.identify(outputJpg, function(err, features) {
if (err) throw err;
assert.strictEqual(243, features.width);
@ -142,8 +154,10 @@ async.series([
},
// Attempt to resize to max but only provide one dimension, so should default to crop
function(done) {
sharp(inputJpg).resize(320).max().toFile(outputJpg, function(err) {
sharp(inputJpg).resize(320).max().toFile(outputJpg, function(err, info) {
if (err) throw err;
assert.strictEqual(320, info.width);
assert.strictEqual(261, info.height);
imagemagick.identify(outputJpg, function(err, features) {
if (err) throw err;
assert.strictEqual(320, features.width);
@ -161,8 +175,10 @@ async.series([
},
// Rotate by 90 degrees, respecting output input size
function(done) {
sharp(inputJpg).rotate(90).resize(320, 240).toFile(outputJpg, function(err) {
sharp(inputJpg).rotate(90).resize(320, 240).toFile(outputJpg, function(err, info) {
if (err) throw err;
assert.strictEqual(320, info.width);
assert.strictEqual(240, info.height);
imagemagick.identify(outputJpg, function(err, features) {
if (err) throw err;
assert.strictEqual(320, features.width);
@ -173,8 +189,10 @@ async.series([
},
// Input image has Orientation EXIF tag but do not rotate output
function(done) {
sharp(inputJpgWithExif).resize(320).toFile(outputJpg, function(err) {
sharp(inputJpgWithExif).resize(320).toFile(outputJpg, function(err, info) {
if (err) throw err;
assert.strictEqual(320, info.width);
assert.strictEqual(426, info.height);
imagemagick.identify(outputJpg, function(err, features) {
if (err) throw err;
assert.strictEqual(320, features.width);
@ -185,8 +203,10 @@ async.series([
},
// Input image has Orientation EXIF tag value of 8 (270 degrees), auto-rotate
function(done) {
sharp(inputJpgWithExif).rotate().resize(320).toFile(outputJpg, function(err) {
sharp(inputJpgWithExif).rotate().resize(320).toFile(outputJpg, function(err, info) {
if (err) throw err;
assert.strictEqual(320, info.width);
assert.strictEqual(240, info.height);
imagemagick.identify(outputJpg, function(err, features) {
if (err) throw err;
assert.strictEqual(320, features.width);
@ -197,8 +217,10 @@ async.series([
},
// Attempt to auto-rotate using image that has no EXIF
function(done) {
sharp(inputJpg).rotate().resize(320).toFile(outputJpg, function(err) {
sharp(inputJpg).rotate().resize(320).toFile(outputJpg, function(err, info) {
if (err) throw err;
assert.strictEqual(320, info.width);
assert.strictEqual(261, info.height);
imagemagick.identify(outputJpg, function(err, features) {
if (err) throw err;
assert.strictEqual(320, features.width);
@ -219,8 +241,10 @@ async.series([
},
// Do not enlarge the output if the input width is already less than the output width
function(done) {
sharp(inputJpg).resize(2800).withoutEnlargement().toFile(outputJpg, function(err) {
sharp(inputJpg).resize(2800).withoutEnlargement().toFile(outputJpg, function(err, info) {
if (err) throw err;
assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height);
imagemagick.identify(outputJpg, function(err, features) {
if (err) throw err;
assert.strictEqual(2725, features.width);
@ -231,8 +255,10 @@ async.series([
},
// Do not enlarge the output if the input height is already less than the output height
function(done) {
sharp(inputJpg).resize(null, 2300).withoutEnlargement().toFile(outputJpg, function(err) {
sharp(inputJpg).resize(null, 2300).withoutEnlargement().toFile(outputJpg, function(err, info) {
if (err) throw err;
assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height);
imagemagick.identify(outputJpg, function(err, features) {
if (err) throw err;
assert.strictEqual(2725, features.width);
@ -243,7 +269,9 @@ async.series([
},
// Promises/A+
function(done) {
sharp(inputJpg).resize(320, 240).toFile(outputJpg).then(function() {
sharp(inputJpg).resize(320, 240).toFile(outputJpg).then(function(info) {
assert.strictEqual(320, info.width);
assert.strictEqual(240, info.height);
imagemagick.identify(outputJpg, function(err, features) {
assert.strictEqual(320, features.width);
assert.strictEqual(240, features.height);