mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 10:30:15 +02:00
Add EventEmitter for queue length changes
Remove unnecessary params from Error handler
This commit is contained in:
parent
711f0fefb6
commit
81c710eaa3
13
README.md
13
README.md
@ -272,6 +272,19 @@ for example:
|
|||||||
output: { file: false, buffer: true, stream: true } } }
|
output: { file: false, buffer: true, stream: true } } }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### queue
|
||||||
|
|
||||||
|
An EventEmitter that emits a `change` event when a task is either:
|
||||||
|
|
||||||
|
* queued, waiting for _libuv_ to provide a worker thread
|
||||||
|
* complete
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
sharp.queue.on('change', function(queueLength) {
|
||||||
|
console.log('Queue contains ' + queueLength + ' task(s)');
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
### Input methods
|
### Input methods
|
||||||
|
|
||||||
#### sharp([input])
|
#### sharp([input])
|
||||||
|
12
index.js
12
index.js
@ -3,6 +3,7 @@
|
|||||||
var path = require('path');
|
var path = require('path');
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
var stream = require('stream');
|
var stream = require('stream');
|
||||||
|
var events = require('events');
|
||||||
|
|
||||||
var semver = require('semver');
|
var semver = require('semver');
|
||||||
var color = require('color');
|
var color = require('color');
|
||||||
@ -68,7 +69,11 @@ var Sharp = function(input) {
|
|||||||
streamOut: false,
|
streamOut: false,
|
||||||
withMetadata: false,
|
withMetadata: false,
|
||||||
tileSize: 256,
|
tileSize: 256,
|
||||||
tileOverlap: 0
|
tileOverlap: 0,
|
||||||
|
// Function to notify of queue length changes
|
||||||
|
queueListener: function(queueLength) {
|
||||||
|
module.exports.queue.emit('change', queueLength);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if (typeof input === 'string') {
|
if (typeof input === 'string') {
|
||||||
// input=file
|
// input=file
|
||||||
@ -85,6 +90,11 @@ var Sharp = function(input) {
|
|||||||
module.exports = Sharp;
|
module.exports = Sharp;
|
||||||
util.inherits(Sharp, stream.Duplex);
|
util.inherits(Sharp, stream.Duplex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
EventEmitter singleton emits queue length 'change' events
|
||||||
|
*/
|
||||||
|
module.exports.queue = new events.EventEmitter();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Supported image formats
|
Supported image formats
|
||||||
*/
|
*/
|
||||||
|
114
src/resize.cc
114
src/resize.cc
@ -146,7 +146,8 @@ static void DeleteBuffer(VipsObject *object, char *buffer) {
|
|||||||
class ResizeWorker : public NanAsyncWorker {
|
class ResizeWorker : public NanAsyncWorker {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ResizeWorker(NanCallback *callback, ResizeBaton *baton) : NanAsyncWorker(callback), baton(baton) {}
|
ResizeWorker(NanCallback *callback, ResizeBaton *baton, NanCallback *queueListener) :
|
||||||
|
NanAsyncWorker(callback), baton(baton), queueListener(queueListener) {}
|
||||||
~ResizeWorker() {}
|
~ResizeWorker() {}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -162,8 +163,8 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
// Latest v2 sRGB ICC profile
|
// Latest v2 sRGB ICC profile
|
||||||
std::string srgbProfile = baton->iccProfilePath + "sRGB_IEC61966-2-1_black_scaled.icc";
|
std::string srgbProfile = baton->iccProfilePath + "sRGB_IEC61966-2-1_black_scaled.icc";
|
||||||
|
|
||||||
// Hang image references from this hook object
|
// Create "hook" VipsObject to hang image references from
|
||||||
VipsObject *hook = reinterpret_cast<VipsObject*>(vips_image_new());
|
hook = reinterpret_cast<VipsObject*>(vips_image_new());
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
ImageType inputImageType = ImageType::UNKNOWN;
|
ImageType inputImageType = ImageType::UNKNOWN;
|
||||||
@ -200,14 +201,14 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (image == NULL || inputImageType == ImageType::UNKNOWN) {
|
if (image == NULL || inputImageType == ImageType::UNKNOWN) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, image);
|
vips_object_local(hook, image);
|
||||||
|
|
||||||
// Limit input images to a given number of pixels, where pixels = width * height
|
// Limit input images to a given number of pixels, where pixels = width * height
|
||||||
if (image->Xsize * image->Ysize > baton->limitInputPixels) {
|
if (image->Xsize * image->Ysize > baton->limitInputPixels) {
|
||||||
(baton->err).append("Input image exceeds pixel limit");
|
(baton->err).append("Input image exceeds pixel limit");
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate angle of rotation
|
// Calculate angle of rotation
|
||||||
@ -223,7 +224,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
if (baton->rotateBeforePreExtract && rotation != Angle::D0) {
|
if (baton->rotateBeforePreExtract && rotation != Angle::D0) {
|
||||||
VipsImage *rotated;
|
VipsImage *rotated;
|
||||||
if (vips_rot(image, &rotated, static_cast<VipsAngle>(rotation), NULL)) {
|
if (vips_rot(image, &rotated, static_cast<VipsAngle>(rotation), NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, rotated);
|
vips_object_local(hook, rotated);
|
||||||
image = rotated;
|
image = rotated;
|
||||||
@ -233,7 +234,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
if (baton->topOffsetPre != -1) {
|
if (baton->topOffsetPre != -1) {
|
||||||
VipsImage *extractedPre;
|
VipsImage *extractedPre;
|
||||||
if (vips_extract_area(image, &extractedPre, baton->leftOffsetPre, baton->topOffsetPre, baton->widthPre, baton->heightPre, NULL)) {
|
if (vips_extract_area(image, &extractedPre, baton->leftOffsetPre, baton->topOffsetPre, baton->widthPre, baton->heightPre, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, extractedPre);
|
vips_object_local(hook, extractedPre);
|
||||||
image = extractedPre;
|
image = extractedPre;
|
||||||
@ -349,11 +350,11 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
VipsImage *shrunkOnLoad;
|
VipsImage *shrunkOnLoad;
|
||||||
if (baton->bufferInLength > 1) {
|
if (baton->bufferInLength > 1) {
|
||||||
if (vips_jpegload_buffer(baton->bufferIn, baton->bufferInLength, &shrunkOnLoad, "shrink", shrink_on_load, NULL)) {
|
if (vips_jpegload_buffer(baton->bufferIn, baton->bufferInLength, &shrunkOnLoad, "shrink", shrink_on_load, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (vips_jpegload((baton->fileIn).c_str(), &shrunkOnLoad, "shrink", shrink_on_load, NULL)) {
|
if (vips_jpegload((baton->fileIn).c_str(), &shrunkOnLoad, "shrink", shrink_on_load, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vips_object_local(hook, shrunkOnLoad);
|
vips_object_local(hook, shrunkOnLoad);
|
||||||
@ -374,7 +375,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
std::string cmykProfile = baton->iccProfilePath + "USWebCoatedSWOP.icc";
|
std::string cmykProfile = baton->iccProfilePath + "USWebCoatedSWOP.icc";
|
||||||
VipsImage *transformed;
|
VipsImage *transformed;
|
||||||
if (vips_icc_transform(image, &transformed, srgbProfile.c_str(), "input_profile", cmykProfile.c_str(), NULL)) {
|
if (vips_icc_transform(image, &transformed, srgbProfile.c_str(), "input_profile", cmykProfile.c_str(), NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, transformed);
|
vips_object_local(hook, transformed);
|
||||||
image = transformed;
|
image = transformed;
|
||||||
@ -392,7 +393,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
VipsImage *flattened;
|
VipsImage *flattened;
|
||||||
if (vips_flatten(image, &flattened, "background", background, NULL)) {
|
if (vips_flatten(image, &flattened, "background", background, NULL)) {
|
||||||
vips_area_unref(reinterpret_cast<VipsArea*>(background));
|
vips_area_unref(reinterpret_cast<VipsArea*>(background));
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_area_unref(reinterpret_cast<VipsArea*>(background));
|
vips_area_unref(reinterpret_cast<VipsArea*>(background));
|
||||||
vips_object_local(hook, flattened);
|
vips_object_local(hook, flattened);
|
||||||
@ -403,7 +404,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
if (baton->gamma >= 1 && baton->gamma <= 3) {
|
if (baton->gamma >= 1 && baton->gamma <= 3) {
|
||||||
VipsImage *gammaEncoded;
|
VipsImage *gammaEncoded;
|
||||||
if (vips_gamma(image, &gammaEncoded, "exponent", 1.0 / baton->gamma, NULL)) {
|
if (vips_gamma(image, &gammaEncoded, "exponent", 1.0 / baton->gamma, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, gammaEncoded);
|
vips_object_local(hook, gammaEncoded);
|
||||||
image = gammaEncoded;
|
image = gammaEncoded;
|
||||||
@ -413,7 +414,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
if (baton->greyscale) {
|
if (baton->greyscale) {
|
||||||
VipsImage *greyscale;
|
VipsImage *greyscale;
|
||||||
if (vips_colourspace(image, &greyscale, VIPS_INTERPRETATION_B_W, NULL)) {
|
if (vips_colourspace(image, &greyscale, VIPS_INTERPRETATION_B_W, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, greyscale);
|
vips_object_local(hook, greyscale);
|
||||||
image = greyscale;
|
image = greyscale;
|
||||||
@ -423,7 +424,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
VipsImage *shrunk;
|
VipsImage *shrunk;
|
||||||
// Use vips_shrink with the integral reduction
|
// Use vips_shrink with the integral reduction
|
||||||
if (vips_shrink(image, &shrunk, shrink, shrink, NULL)) {
|
if (vips_shrink(image, &shrunk, shrink, shrink, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, shrunk);
|
vips_object_local(hook, shrunk);
|
||||||
image = shrunk;
|
image = shrunk;
|
||||||
@ -455,13 +456,13 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
// Create Gaussian function for standard deviation
|
// Create Gaussian function for standard deviation
|
||||||
VipsImage *gaussian;
|
VipsImage *gaussian;
|
||||||
if (vips_gaussmat(&gaussian, sigma, 0.2, "separable", TRUE, "integer", TRUE, NULL)) {
|
if (vips_gaussmat(&gaussian, sigma, 0.2, "separable", TRUE, "integer", TRUE, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, gaussian);
|
vips_object_local(hook, gaussian);
|
||||||
// Apply Gaussian function
|
// Apply Gaussian function
|
||||||
VipsImage *blurred;
|
VipsImage *blurred;
|
||||||
if (vips_convsep(image, &blurred, gaussian, "precision", VIPS_PRECISION_INTEGER, NULL)) {
|
if (vips_convsep(image, &blurred, gaussian, "precision", VIPS_PRECISION_INTEGER, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, blurred);
|
vips_object_local(hook, blurred);
|
||||||
image = blurred;
|
image = blurred;
|
||||||
@ -473,7 +474,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
// Perform affine transformation
|
// Perform affine transformation
|
||||||
VipsImage *affined;
|
VipsImage *affined;
|
||||||
if (vips_affine(image, &affined, residual, 0.0, 0.0, residual, "interpolate", interpolator, NULL)) {
|
if (vips_affine(image, &affined, residual, 0.0, 0.0, residual, "interpolate", interpolator, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, affined);
|
vips_object_local(hook, affined);
|
||||||
image = affined;
|
image = affined;
|
||||||
@ -483,7 +484,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
if (!baton->rotateBeforePreExtract && rotation != Angle::D0) {
|
if (!baton->rotateBeforePreExtract && rotation != Angle::D0) {
|
||||||
VipsImage *rotated;
|
VipsImage *rotated;
|
||||||
if (vips_rot(image, &rotated, static_cast<VipsAngle>(rotation), NULL)) {
|
if (vips_rot(image, &rotated, static_cast<VipsAngle>(rotation), NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, rotated);
|
vips_object_local(hook, rotated);
|
||||||
image = rotated;
|
image = rotated;
|
||||||
@ -493,7 +494,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
if (baton->flip) {
|
if (baton->flip) {
|
||||||
VipsImage *flipped;
|
VipsImage *flipped;
|
||||||
if (vips_flip(image, &flipped, VIPS_DIRECTION_VERTICAL, NULL)) {
|
if (vips_flip(image, &flipped, VIPS_DIRECTION_VERTICAL, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, flipped);
|
vips_object_local(hook, flipped);
|
||||||
image = flipped;
|
image = flipped;
|
||||||
@ -503,7 +504,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
if (baton->flop) {
|
if (baton->flop) {
|
||||||
VipsImage *flopped;
|
VipsImage *flopped;
|
||||||
if (vips_flip(image, &flopped, VIPS_DIRECTION_HORIZONTAL, NULL)) {
|
if (vips_flip(image, &flopped, VIPS_DIRECTION_HORIZONTAL, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, flopped);
|
vips_object_local(hook, flopped);
|
||||||
image = flopped;
|
image = flopped;
|
||||||
@ -517,7 +518,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
// Convert to sRGB colour space
|
// Convert to sRGB colour space
|
||||||
VipsImage *colourspaced;
|
VipsImage *colourspaced;
|
||||||
if (vips_colourspace(image, &colourspaced, VIPS_INTERPRETATION_sRGB, NULL)) {
|
if (vips_colourspace(image, &colourspaced, VIPS_INTERPRETATION_sRGB, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, colourspaced);
|
vips_object_local(hook, colourspaced);
|
||||||
image = colourspaced;
|
image = colourspaced;
|
||||||
@ -527,19 +528,19 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
// Create single-channel transparency
|
// Create single-channel transparency
|
||||||
VipsImage *black;
|
VipsImage *black;
|
||||||
if (vips_black(&black, image->Xsize, image->Ysize, "bands", 1, NULL)) {
|
if (vips_black(&black, image->Xsize, image->Ysize, "bands", 1, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, black);
|
vips_object_local(hook, black);
|
||||||
// Invert to become non-transparent
|
// Invert to become non-transparent
|
||||||
VipsImage *alpha;
|
VipsImage *alpha;
|
||||||
if (vips_invert(black, &alpha, NULL)) {
|
if (vips_invert(black, &alpha, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, alpha);
|
vips_object_local(hook, alpha);
|
||||||
// Append alpha channel to existing image
|
// Append alpha channel to existing image
|
||||||
VipsImage *joined;
|
VipsImage *joined;
|
||||||
if (vips_bandjoin2(image, alpha, &joined, NULL)) {
|
if (vips_bandjoin2(image, alpha, &joined, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, joined);
|
vips_object_local(hook, joined);
|
||||||
image = joined;
|
image = joined;
|
||||||
@ -563,7 +564,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
"extend", VIPS_EXTEND_BACKGROUND, "background", background, NULL
|
"extend", VIPS_EXTEND_BACKGROUND, "background", background, NULL
|
||||||
)) {
|
)) {
|
||||||
vips_area_unref(reinterpret_cast<VipsArea*>(background));
|
vips_area_unref(reinterpret_cast<VipsArea*>(background));
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_area_unref(reinterpret_cast<VipsArea*>(background));
|
vips_area_unref(reinterpret_cast<VipsArea*>(background));
|
||||||
vips_object_local(hook, embedded);
|
vips_object_local(hook, embedded);
|
||||||
@ -577,7 +578,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
int height = std::min(image->Ysize, baton->height);
|
int height = std::min(image->Ysize, baton->height);
|
||||||
VipsImage *extracted;
|
VipsImage *extracted;
|
||||||
if (vips_extract_area(image, &extracted, left, top, width, height, NULL)) {
|
if (vips_extract_area(image, &extracted, left, top, width, height, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, extracted);
|
vips_object_local(hook, extracted);
|
||||||
image = extracted;
|
image = extracted;
|
||||||
@ -590,7 +591,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
if (vips_extract_area(image, &extractedPost,
|
if (vips_extract_area(image, &extractedPost,
|
||||||
baton->leftOffsetPost, baton->topOffsetPost, baton->widthPost, baton->heightPost, NULL
|
baton->leftOffsetPost, baton->topOffsetPost, baton->widthPost, baton->heightPost, NULL
|
||||||
)) {
|
)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, extractedPost);
|
vips_object_local(hook, extractedPost);
|
||||||
image = extractedPost;
|
image = extractedPost;
|
||||||
@ -608,19 +609,19 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
vips_image_set_double(blur, "scale", 9);
|
vips_image_set_double(blur, "scale", 9);
|
||||||
vips_object_local(hook, blur);
|
vips_object_local(hook, blur);
|
||||||
if (vips_conv(image, &blurred, blur, NULL)) {
|
if (vips_conv(image, &blurred, blur, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Slower, accurate Gaussian blur
|
// Slower, accurate Gaussian blur
|
||||||
// Create Gaussian function for standard deviation
|
// Create Gaussian function for standard deviation
|
||||||
VipsImage *gaussian;
|
VipsImage *gaussian;
|
||||||
if (vips_gaussmat(&gaussian, baton->blurSigma, 0.2, "separable", TRUE, "integer", TRUE, NULL)) {
|
if (vips_gaussmat(&gaussian, baton->blurSigma, 0.2, "separable", TRUE, "integer", TRUE, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, gaussian);
|
vips_object_local(hook, gaussian);
|
||||||
// Apply Gaussian function
|
// Apply Gaussian function
|
||||||
if (vips_convsep(image, &blurred, gaussian, "precision", VIPS_PRECISION_INTEGER, NULL)) {
|
if (vips_convsep(image, &blurred, gaussian, "precision", VIPS_PRECISION_INTEGER, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vips_object_local(hook, blurred);
|
vips_object_local(hook, blurred);
|
||||||
@ -639,12 +640,12 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
vips_image_set_double(sharpen, "scale", 24);
|
vips_image_set_double(sharpen, "scale", 24);
|
||||||
vips_object_local(hook, sharpen);
|
vips_object_local(hook, sharpen);
|
||||||
if (vips_conv(image, &sharpened, sharpen, NULL)) {
|
if (vips_conv(image, &sharpened, sharpen, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Slow, accurate sharpen in LAB colour space, with control over flat vs jagged areas
|
// Slow, accurate sharpen in LAB colour space, with control over flat vs jagged areas
|
||||||
if (vips_sharpen(image, &sharpened, "radius", baton->sharpenRadius, "m1", baton->sharpenFlat, "m2", baton->sharpenJagged, NULL)) {
|
if (vips_sharpen(image, &sharpened, "radius", baton->sharpenRadius, "m1", baton->sharpenFlat, "m2", baton->sharpenJagged, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vips_object_local(hook, sharpened);
|
vips_object_local(hook, sharpened);
|
||||||
@ -655,7 +656,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
if (baton->gamma >= 1 && baton->gamma <= 3) {
|
if (baton->gamma >= 1 && baton->gamma <= 3) {
|
||||||
VipsImage *gammaDecoded;
|
VipsImage *gammaDecoded;
|
||||||
if (vips_gamma(image, &gammaDecoded, "exponent", baton->gamma, NULL)) {
|
if (vips_gamma(image, &gammaDecoded, "exponent", baton->gamma, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, gammaDecoded);
|
vips_object_local(hook, gammaDecoded);
|
||||||
image = gammaDecoded;
|
image = gammaDecoded;
|
||||||
@ -666,7 +667,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
// Switch intrepretation to sRGB
|
// Switch intrepretation to sRGB
|
||||||
VipsImage *rgb;
|
VipsImage *rgb;
|
||||||
if (vips_colourspace(image, &rgb, VIPS_INTERPRETATION_sRGB, NULL)) {
|
if (vips_colourspace(image, &rgb, VIPS_INTERPRETATION_sRGB, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, rgb);
|
vips_object_local(hook, rgb);
|
||||||
image = rgb;
|
image = rgb;
|
||||||
@ -674,7 +675,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
if (baton->withMetadata && HasProfile(image)) {
|
if (baton->withMetadata && HasProfile(image)) {
|
||||||
VipsImage *profiled;
|
VipsImage *profiled;
|
||||||
if (vips_icc_transform(image, &profiled, srgbProfile.c_str(), "embedded", TRUE, NULL)) {
|
if (vips_icc_transform(image, &profiled, srgbProfile.c_str(), "embedded", TRUE, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, profiled);
|
vips_object_local(hook, profiled);
|
||||||
image = profiled;
|
image = profiled;
|
||||||
@ -686,7 +687,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
if (baton->progressive) {
|
if (baton->progressive) {
|
||||||
VipsImage *cached;
|
VipsImage *cached;
|
||||||
if (vips_tilecache(image, &cached, "threaded", TRUE, "persistent", TRUE, "max_tiles", -1, NULL)) {
|
if (vips_tilecache(image, &cached, "threaded", TRUE, "persistent", TRUE, "max_tiles", -1, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, cached);
|
vips_object_local(hook, cached);
|
||||||
image = cached;
|
image = cached;
|
||||||
@ -699,7 +700,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
if (vips_jpegsave_buffer(image, &baton->bufferOut, &baton->bufferOutLength, "strip", !baton->withMetadata,
|
if (vips_jpegsave_buffer(image, &baton->bufferOut, &baton->bufferOutLength, "strip", !baton->withMetadata,
|
||||||
"Q", baton->quality, "optimize_coding", TRUE, "no_subsample", baton->withoutChromaSubsampling,
|
"Q", baton->quality, "optimize_coding", TRUE, "no_subsample", baton->withoutChromaSubsampling,
|
||||||
"interlace", baton->progressive, NULL)) {
|
"interlace", baton->progressive, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
baton->outputFormat = "jpeg";
|
baton->outputFormat = "jpeg";
|
||||||
} else if (baton->output == "__png" || (baton->output == "__input" && inputImageType == ImageType::PNG)) {
|
} else if (baton->output == "__png" || (baton->output == "__input" && inputImageType == ImageType::PNG)) {
|
||||||
@ -709,13 +710,13 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
// Write PNG to buffer
|
// Write PNG to buffer
|
||||||
if (vips_pngsave_buffer(image, &baton->bufferOut, &baton->bufferOutLength, "strip", !baton->withMetadata,
|
if (vips_pngsave_buffer(image, &baton->bufferOut, &baton->bufferOutLength, "strip", !baton->withMetadata,
|
||||||
"compression", baton->compressionLevel, "interlace", baton->progressive, "filter", filter, NULL)) {
|
"compression", baton->compressionLevel, "interlace", baton->progressive, "filter", filter, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Write PNG to buffer
|
// Write PNG to buffer
|
||||||
if (vips_pngsave_buffer(image, &baton->bufferOut, &baton->bufferOutLength, "strip", !baton->withMetadata,
|
if (vips_pngsave_buffer(image, &baton->bufferOut, &baton->bufferOutLength, "strip", !baton->withMetadata,
|
||||||
"compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) {
|
"compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
baton->outputFormat = "png";
|
baton->outputFormat = "png";
|
||||||
@ -723,7 +724,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
// Write WEBP to buffer
|
// Write WEBP to buffer
|
||||||
if (vips_webpsave_buffer(image, &baton->bufferOut, &baton->bufferOutLength, "strip", !baton->withMetadata,
|
if (vips_webpsave_buffer(image, &baton->bufferOut, &baton->bufferOutLength, "strip", !baton->withMetadata,
|
||||||
"Q", baton->quality, NULL)) {
|
"Q", baton->quality, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
baton->outputFormat = "webp";
|
baton->outputFormat = "webp";
|
||||||
#if (VIPS_MAJOR_VERSION >= 8 || (VIPS_MAJOR_VERSION >= 7 && VIPS_MINOR_VERSION >= 42))
|
#if (VIPS_MAJOR_VERSION >= 8 || (VIPS_MAJOR_VERSION >= 7 && VIPS_MINOR_VERSION >= 42))
|
||||||
@ -733,7 +734,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
// Extract first band for greyscale image
|
// Extract first band for greyscale image
|
||||||
VipsImage *grey;
|
VipsImage *grey;
|
||||||
if (vips_extract_band(image, &grey, 1, NULL)) {
|
if (vips_extract_band(image, &grey, 1, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, grey);
|
vips_object_local(hook, grey);
|
||||||
image = grey;
|
image = grey;
|
||||||
@ -742,7 +743,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
// Cast pixels to uint8 (unsigned char)
|
// Cast pixels to uint8 (unsigned char)
|
||||||
VipsImage *uchar;
|
VipsImage *uchar;
|
||||||
if (vips_cast(image, &uchar, VIPS_FORMAT_UCHAR, NULL)) {
|
if (vips_cast(image, &uchar, VIPS_FORMAT_UCHAR, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
vips_object_local(hook, uchar);
|
vips_object_local(hook, uchar);
|
||||||
image = uchar;
|
image = uchar;
|
||||||
@ -751,7 +752,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
baton->bufferOut = vips_image_write_to_memory(image, &baton->bufferOutLength);
|
baton->bufferOut = vips_image_write_to_memory(image, &baton->bufferOutLength);
|
||||||
if (baton->bufferOut == NULL) {
|
if (baton->bufferOut == NULL) {
|
||||||
(baton->err).append("Could not allocate enough memory for raw output");
|
(baton->err).append("Could not allocate enough memory for raw output");
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
baton->outputFormat = "raw";
|
baton->outputFormat = "raw";
|
||||||
#endif
|
#endif
|
||||||
@ -767,7 +768,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
if (vips_jpegsave(image, baton->output.c_str(), "strip", !baton->withMetadata,
|
if (vips_jpegsave(image, baton->output.c_str(), "strip", !baton->withMetadata,
|
||||||
"Q", baton->quality, "optimize_coding", TRUE, "no_subsample", baton->withoutChromaSubsampling,
|
"Q", baton->quality, "optimize_coding", TRUE, "no_subsample", baton->withoutChromaSubsampling,
|
||||||
"interlace", baton->progressive, NULL)) {
|
"interlace", baton->progressive, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
baton->outputFormat = "jpeg";
|
baton->outputFormat = "jpeg";
|
||||||
} else if (outputPng || (matchInput && inputImageType == ImageType::PNG)) {
|
} else if (outputPng || (matchInput && inputImageType == ImageType::PNG)) {
|
||||||
@ -777,13 +778,13 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
// Write PNG to file
|
// Write PNG to file
|
||||||
if (vips_pngsave(image, baton->output.c_str(), "strip", !baton->withMetadata,
|
if (vips_pngsave(image, baton->output.c_str(), "strip", !baton->withMetadata,
|
||||||
"compression", baton->compressionLevel, "interlace", baton->progressive, "filter", filter, NULL)) {
|
"compression", baton->compressionLevel, "interlace", baton->progressive, "filter", filter, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Write PNG to file
|
// Write PNG to file
|
||||||
if (vips_pngsave(image, baton->output.c_str(), "strip", !baton->withMetadata,
|
if (vips_pngsave(image, baton->output.c_str(), "strip", !baton->withMetadata,
|
||||||
"compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) {
|
"compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
baton->outputFormat = "png";
|
baton->outputFormat = "png";
|
||||||
@ -791,14 +792,14 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
// Write WEBP to file
|
// Write WEBP to file
|
||||||
if (vips_webpsave(image, baton->output.c_str(), "strip", !baton->withMetadata,
|
if (vips_webpsave(image, baton->output.c_str(), "strip", !baton->withMetadata,
|
||||||
"Q", baton->quality, NULL)) {
|
"Q", baton->quality, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
baton->outputFormat = "webp";
|
baton->outputFormat = "webp";
|
||||||
} else if (outputTiff || (matchInput && inputImageType == ImageType::TIFF)) {
|
} else if (outputTiff || (matchInput && inputImageType == ImageType::TIFF)) {
|
||||||
// Write TIFF to file
|
// Write TIFF to file
|
||||||
if (vips_tiffsave(image, baton->output.c_str(), "strip", !baton->withMetadata,
|
if (vips_tiffsave(image, baton->output.c_str(), "strip", !baton->withMetadata,
|
||||||
"compression", VIPS_FOREIGN_TIFF_COMPRESSION_JPEG, "Q", baton->quality, NULL)) {
|
"compression", VIPS_FOREIGN_TIFF_COMPRESSION_JPEG, "Q", baton->quality, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
baton->outputFormat = "tiff";
|
baton->outputFormat = "tiff";
|
||||||
} else if (outputDz) {
|
} else if (outputDz) {
|
||||||
@ -806,12 +807,12 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
std::string filename_no_extension = baton->output.substr(0, baton->output.length() - 4);
|
std::string filename_no_extension = baton->output.substr(0, baton->output.length() - 4);
|
||||||
if (vips_dzsave(image, filename_no_extension.c_str(), "strip", !baton->withMetadata,
|
if (vips_dzsave(image, filename_no_extension.c_str(), "strip", !baton->withMetadata,
|
||||||
"tile_size", baton->tileSize, "overlap", baton->tileOverlap, NULL)) {
|
"tile_size", baton->tileSize, "overlap", baton->tileOverlap, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
baton->outputFormat = "dz";
|
baton->outputFormat = "dz";
|
||||||
} else {
|
} else {
|
||||||
(baton->err).append("Unsupported output " + baton->output);
|
(baton->err).append("Unsupported output " + baton->output);
|
||||||
return Error(baton, hook);
|
return Error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clean up any dangling image references
|
// Clean up any dangling image references
|
||||||
@ -865,6 +866,9 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
|
|
||||||
// Decrement processing task counter
|
// Decrement processing task counter
|
||||||
g_atomic_int_dec_and_test(&counterProcess);
|
g_atomic_int_dec_and_test(&counterProcess);
|
||||||
|
Handle<Value> queueLength[1] = { NanNew<Uint32>(counterQueue) };
|
||||||
|
queueListener->Call(1, queueLength);
|
||||||
|
delete queueListener;
|
||||||
|
|
||||||
// Return to JavaScript
|
// Return to JavaScript
|
||||||
callback->Call(3, argv);
|
callback->Call(3, argv);
|
||||||
@ -872,6 +876,8 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
ResizeBaton *baton;
|
ResizeBaton *baton;
|
||||||
|
NanCallback *queueListener;
|
||||||
|
VipsObject *hook;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Calculate the angle of rotation and need-to-flip for the output image.
|
Calculate the angle of rotation and need-to-flip for the output image.
|
||||||
@ -941,7 +947,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
Unref all transitional images on the hook.
|
Unref all transitional images on the hook.
|
||||||
Clear all thread-local data.
|
Clear all thread-local data.
|
||||||
*/
|
*/
|
||||||
void Error(ResizeBaton *baton, VipsObject *hook) {
|
void Error() {
|
||||||
// Get libvips' error message
|
// Get libvips' error message
|
||||||
(baton->err).append(vips_error_buffer());
|
(baton->err).append(vips_error_buffer());
|
||||||
// Clean up any dangling image references
|
// Clean up any dangling image references
|
||||||
@ -1033,13 +1039,17 @@ NAN_METHOD(resize) {
|
|||||||
baton->output = *String::Utf8Value(options->Get(NanNew<String>("output"))->ToString());
|
baton->output = *String::Utf8Value(options->Get(NanNew<String>("output"))->ToString());
|
||||||
baton->tileSize = options->Get(NanNew<String>("tileSize"))->Int32Value();
|
baton->tileSize = options->Get(NanNew<String>("tileSize"))->Int32Value();
|
||||||
baton->tileOverlap = options->Get(NanNew<String>("tileOverlap"))->Int32Value();
|
baton->tileOverlap = options->Get(NanNew<String>("tileOverlap"))->Int32Value();
|
||||||
|
// Function to notify of queue length changes
|
||||||
|
NanCallback *queueListener = new NanCallback(Handle<Function>::Cast(options->Get(NanNew<String>("queueListener"))));
|
||||||
|
|
||||||
// Join queue for worker thread
|
// Join queue for worker thread
|
||||||
NanCallback *callback = new NanCallback(args[1].As<Function>());
|
NanCallback *callback = new NanCallback(args[1].As<Function>());
|
||||||
NanAsyncQueueWorker(new ResizeWorker(callback, baton));
|
NanAsyncQueueWorker(new ResizeWorker(callback, baton, queueListener));
|
||||||
|
|
||||||
// Increment queued task counter
|
// Increment queued task counter
|
||||||
g_atomic_int_inc(&counterQueue);
|
g_atomic_int_inc(&counterQueue);
|
||||||
|
Handle<Value> queueLength[1] = { NanNew<Uint32>(counterQueue) };
|
||||||
|
queueListener->Call(1, queueLength);
|
||||||
|
|
||||||
NanReturnUndefined();
|
NanReturnUndefined();
|
||||||
}
|
}
|
||||||
|
@ -684,4 +684,22 @@ describe('Input/output', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Queue length change events', function(done) {
|
||||||
|
var eventCounter = 0;
|
||||||
|
var queueListener = function(queueLength) {
|
||||||
|
assert.strictEqual('number', typeof queueLength);
|
||||||
|
assert.strictEqual(1 - eventCounter, queueLength);
|
||||||
|
eventCounter++;
|
||||||
|
};
|
||||||
|
sharp.queue.on('change', queueListener);
|
||||||
|
sharp(fixtures.inputJpg)
|
||||||
|
.resize(320, 240)
|
||||||
|
.toBuffer(function(err) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(2, eventCounter);
|
||||||
|
sharp.queue.removeListener('change', queueListener);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user