From b67c96ee31fe7380b609e4cfa18afe671f02e690 Mon Sep 17 00:00:00 2001 From: Simon Hailes Date: Thu, 2 Nov 2017 08:48:59 +0000 Subject: [PATCH 1/3] Matrix: Add aync to resize. If first argument is fn(err, img), then run async. Also add fx,fy arguments. call styles may be: Sync (modify existing image, new image is CV_32FC3) - same interface as before except added fx,fy im.resize( width, height ); im.resize( width, height, fx, fy ); im.resize( width, height, interpolation ); im.resize( width, height, fx, fy, interpolation ); Async (create new image, new image is not forced to CV_32FC3?) im.resize( fn, width, height ); im.resize( fn, width, height, fx, fy ); im.resize( fn, width, height, interpolation ); im.resize( fn, width, height, fx, fy, interpolation ); --- src/Matrix.cc | 145 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 128 insertions(+), 17 deletions(-) diff --git a/src/Matrix.cc b/src/Matrix.cc index 099ffe2..a9aeae3 100755 --- a/src/Matrix.cc +++ b/src/Matrix.cc @@ -1889,27 +1889,138 @@ 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) - 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(); + if (info.Length() < 2) { + return Nan::ThrowError("Matrix.resize requires at least 2 argument2"); + } - 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; + // if we want async + int offset = 0; + if (info[0]->IsFunction()){ + offset = 1; + } - return; + if (info.Length() < 2+offset) { + return Nan::ThrowError("Matrix.resize requires at least x and y size argument2"); + } + + int x = info[offset+0]->Uint32Value(); + int y = info[offset+1]->Uint32Value(); + + cv::Size size(x, y); + + if (size.area() == 0) { + return Nan::ThrowError("Area of size must be > 0"); + } + + double fx = 0; + double fy = 0; + int interpolation = cv::INTER_LINEAR; + + // if 4 or more args, then expect fx, fy next + if (info.Length() >= 4+offset) { + DOUBLE_FROM_ARGS(fx, 2+offset) + DOUBLE_FROM_ARGS(fy, 3+offset) + } + + // if 3 args after possible function, expect interpolation + if (info.Length() == 3+offset) { + INT_FROM_ARGS(interpolation, 3+offset) + } + if (info.Length() == 5+offset) { + INT_FROM_ARGS(interpolation, 5+offset) + } + + // if async + if (offset){ + REQ_FUN_ARG(0, 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) { From 44f175632c4c4a67e9bb75b9ee7eb55789a89d37 Mon Sep 17 00:00:00 2001 From: Simon Hailes Date: Thu, 2 Nov 2017 09:44:57 +0000 Subject: [PATCH 2/3] resize: move async fn to last argument --- src/Matrix.cc | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/Matrix.cc b/src/Matrix.cc index a9aeae3..962230a 100755 --- a/src/Matrix.cc +++ b/src/Matrix.cc @@ -1971,18 +1971,25 @@ NAN_METHOD(Matrix::Resize) { return Nan::ThrowError("Matrix.resize requires at least 2 argument2"); } - // if we want async - int offset = 0; - if (info[0]->IsFunction()){ - offset = 1; + //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+offset) { + if (info.Length() < 2+isAsync) { return Nan::ThrowError("Matrix.resize requires at least x and y size argument2"); } - int x = info[offset+0]->Uint32Value(); - int y = info[offset+1]->Uint32Value(); + int x = info[0]->Uint32Value(); + int y = info[1]->Uint32Value(); cv::Size size(x, y); @@ -1995,22 +2002,22 @@ NAN_METHOD(Matrix::Resize) { int interpolation = cv::INTER_LINEAR; // if 4 or more args, then expect fx, fy next - if (info.Length() >= 4+offset) { - DOUBLE_FROM_ARGS(fx, 2+offset) - DOUBLE_FROM_ARGS(fy, 3+offset) + 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 3 args after possible function, expect interpolation - if (info.Length() == 3+offset) { - INT_FROM_ARGS(interpolation, 3+offset) - } - if (info.Length() == 5+offset) { - INT_FROM_ARGS(interpolation, 5+offset) - } - // if async - if (offset){ - REQ_FUN_ARG(0, cb); + 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()); From 9e4f21444101352043ba873d0bf7e5caa8cc0788 Mon Sep 17 00:00:00 2001 From: Simon Hailes Date: Fri, 3 Nov 2017 08:34:59 +0000 Subject: [PATCH 3/3] Add resize example --- examples/async-resize.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 examples/async-resize.js 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); + } + +});