diff --git a/examples/async-resize.js b/examples/async-resize.js new file mode 100644 index 0000000..70a1c7d --- /dev/null +++ b/examples/async-resize.js @@ -0,0 +1,34 @@ +var cv = require('../lib/opencv'); + +cv.readImage("./files/mona.png", function(err, im) { + if (err) throw err; + + var width = im.width(); + var height = im.height(); + if (width < 1 || height < 1) throw new Error('Image has no size'); + + console.log('Image loaded from ./files/mona.png at '+im.width()+'x'+im.height()); + + var AfterResize = function(err, img){ + if (err){ + console.log('Error in resize:' + err); + return; + } + img.save("./tmp/resize-async-image.png"); + console.log('Image saved to ./tmp/resize-async-image.png at '+img.width()+'x'+img.height()); + }; + + var newwidth = width*0.95; + var newheight = height*0.95; + + var Async = true; + if (Async){ + // note - generates a new image + im.resize(newwidth, newheight, AfterResize); + } else { + // sync - note - modifies the input image + im.resize(newwidth, newheight); + AfterResize(null, im); + } + +}); diff --git a/src/Matrix.cc b/src/Matrix.cc index 099ffe2..962230a 100755 --- a/src/Matrix.cc +++ b/src/Matrix.cc @@ -1889,27 +1889,145 @@ cv::Rect* setRect(Local objRect, cv::Rect &result) { return &result; } + +class ResizeASyncWorker: public Nan::AsyncWorker { +public: + ResizeASyncWorker(Nan::Callback *callback, Matrix *image, cv::Size size, double fx, double fy, int interpolation) : + Nan::AsyncWorker(callback), + image(image), + size(size), + fx(fx), + fy(fy), + interpolation(interpolation), + success(0){ + } + + ~ResizeASyncWorker() { + } + + void Execute() { + try { + dest = new Matrix(); + cv::resize(image->mat, dest->mat, size, fx, fy, interpolation); + success = 1; + } catch(...){ + success = 0; + } + } + + void HandleOKCallback() { + Nan::HandleScope scope; + + if (success){ + Local im_to_return= Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); + Matrix *img = Nan::ObjectWrap::Unwrap(im_to_return); + img->mat = dest->mat; + delete dest; + + //delete dest; + + Local argv[] = { + Nan::Null(), // err + im_to_return //result + }; + + Nan::TryCatch try_catch; + callback->Call(2, argv); + if (try_catch.HasCaught()) { + Nan::FatalException(try_catch); + } + } else { + delete dest; + + Local argv[] = { + Nan::New("C++ exception").ToLocalChecked(), // err + Nan::Null() //result + }; + + Nan::TryCatch try_catch; + callback->Call(2, argv); + if (try_catch.HasCaught()) { + Nan::FatalException(try_catch); + } + } + } + +private: + Matrix *image; + Matrix *dest; + cv::Size size; + double fx; + double fy; + int interpolation; + int success; + +}; + + NAN_METHOD(Matrix::Resize) { - Nan::HandleScope scope; + SETUP_FUNCTION(Matrix) + + if (info.Length() < 2) { + return Nan::ThrowError("Matrix.resize requires at least 2 argument2"); + } + + //im.resize( width, height ); + //im.resize( width, height, fx, fy ); + //im.resize( width, height, interpolation ); + //im.resize( width, height, fx, fy, interpolation ); + // if fn is added on the end, makes it Async + + int numargs = info.Length(); + int isAsync = 0; + + if (info[numargs-1]->IsFunction()){ + isAsync = 1; + } + + if (info.Length() < 2+isAsync) { + return Nan::ThrowError("Matrix.resize requires at least x and y size argument2"); + } int x = info[0]->Uint32Value(); int y = info[1]->Uint32Value(); - /* - CV_INTER_NN =0, - CV_INTER_LINEAR =1, - CV_INTER_CUBIC =2, - CV_INTER_AREA =3, - CV_INTER_LANCZOS4 =4 - */ - int interpolation = (info.Length() < 3) ? (int)cv::INTER_LINEAR : info[2]->Uint32Value(); - Matrix *self = Nan::ObjectWrap::Unwrap(info.This()); - cv::Mat res = cv::Mat(x, y, CV_32FC3); - cv::resize(self->mat, res, cv::Size(x, y), 0, 0, interpolation); - ~self->mat; - self->mat = res; + cv::Size size(x, y); + + if (size.area() == 0) { + return Nan::ThrowError("Area of size must be > 0"); + } - return; + double fx = 0; + double fy = 0; + int interpolation = cv::INTER_LINEAR; + + // if 4 or more args, then expect fx, fy next + if (numargs >= 4+isAsync) { + DOUBLE_FROM_ARGS(fx, 2) + DOUBLE_FROM_ARGS(fy, 3) + if (numargs == 5+isAsync) { + INT_FROM_ARGS(interpolation, 5) + } + } else { + // if 3 args after possible function, expect interpolation + if (numargs == 3+isAsync) { + INT_FROM_ARGS(interpolation, 3) + } + } + + // if async + if (isAsync){ + REQ_FUN_ARG(numargs-1, cb); + Nan::Callback *callback = new Nan::Callback(cb.As()); + Nan::AsyncQueueWorker(new ResizeASyncWorker(callback, self, size, fx, fy, interpolation)); + info.GetReturnValue().Set(Nan::Null()); + } else { + Matrix *self = Nan::ObjectWrap::Unwrap(info.This()); + cv::Mat res = cv::Mat(x, y, CV_32FC3); + cv::resize(self->mat, res, cv::Size(x, y), 0, 0, interpolation); + ~self->mat; + self->mat = res; + } } NAN_METHOD(Matrix::Rotate) {