mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 10:30:15 +02:00
Sends width and height as another parameter to the callback. Fixes issue #67
This commit is contained in:
parent
1cce56b024
commit
d40bdcc6ac
33
README.md
33
README.md
@ -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.
|
||||
|
||||
|
4
index.js
4
index.js
@ -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);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -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": {
|
||||
|
17
src/sharp.cc
17
src/sharp.cc
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user