diff --git a/src/OpenCV.cc b/src/OpenCV.cc index a282057..ab8c8a5 100755 --- a/src/OpenCV.cc +++ b/src/OpenCV.cc @@ -11,9 +11,235 @@ void OpenCV::Init(Local target) { target->Set(Nan::New("version").ToLocalChecked(), Nan::New(out, n).ToLocalChecked()); Nan::SetMethod(target, "readImage", ReadImage); + Nan::SetMethod(target, "readImageAsync", ReadImageAsync); Nan::SetMethod(target, "readImageMulti", ReadImageMulti); } + +// worker which decodes an image from data. +class AsyncImDecodeWorker: public Nan::AsyncWorker { +public: + + AsyncImDecodeWorker(Nan::Callback *callback, uint8_t *buf, unsigned len, int flags = -1): + Nan::AsyncWorker(callback), + buf(buf), + len(len), + flags(flags){ + } + + ~AsyncImDecodeWorker() { + } + + void Execute() { +// Local img_to_return = + // Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); + // img = Nan::ObjectWrap::Unwrap(img_to_return); + cv::Mat *mbuf = new cv::Mat(len, 1, CV_64FC1, buf); + outputmat = cv::imdecode(*mbuf, flags); + } + + void HandleOKCallback() { + Nan::HandleScope scope; + + Local im_to_return= Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); + Matrix *img = Nan::ObjectWrap::Unwrap(im_to_return); + img->mat = outputmat; + + Local argv[] = { + Nan::Null(), + im_to_return + }; + + Nan::TryCatch try_catch; + callback->Call(2, argv); + if (try_catch.HasCaught()) { + Nan::FatalException(try_catch); + } + } + +private: + uint8_t *buf; + unsigned len; + int flags; + cv::Mat outputmat; + //Matrix *img; +}; + + +// worker which reads an image from a file. +class AsyncImReadWorker: public Nan::AsyncWorker { +public: + + AsyncImReadWorker(Nan::Callback *callback, std::string filename, int flags = CV_LOAD_IMAGE_UNCHANGED): + Nan::AsyncWorker(callback), + filename(filename), + flags(flags) { + } + + ~AsyncImReadWorker() { + } + + void Execute() { + outputmat = cv::imread(filename, CV_LOAD_IMAGE_UNCHANGED); + } + + void HandleOKCallback() { + Nan::HandleScope scope; + + Local im_to_return= Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); + Matrix *img = Nan::ObjectWrap::Unwrap(im_to_return); + img->mat = outputmat; + + Local argv[] = { + Nan::Null(), + im_to_return + }; + + Nan::TryCatch try_catch; + callback->Call(2, argv); + if (try_catch.HasCaught()) { + Nan::FatalException(try_catch); + } + } + +private: + std::string filename; + int flags; + cv::Mat outputmat; +}; + + + +NAN_METHOD(OpenCV::ReadImageAsync) { + Nan::EscapableHandleScope scope; + + Local argv[2]; + argv[0] = Nan::Null(); + argv[1] = Nan::Null(); + + int callback_arg = -1; + int numargs = info.Length(); + + Local cb; + + // deal with situation where we have int, int, cb + if (info[numargs-1]->IsFunction()){ + callback_arg = numargs-1; + cb = Local::Cast(info[callback_arg]); + } + + try { + + if (info[0]->IsNumber() && info[1]->IsNumber()) { + ////////////////////////////// + // create image from a filename + // always do sync as this take no time? + int width, height; + int type = CV_64FC1; + + // if we have a type arg + if ((numargs > 2) && info[2]->IsNumber()){ + type = info[2]->Uint32Value(); + } + + width = info[0]->Uint32Value(); + height = info[1]->Uint32Value(); + Local img_to_return = + Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); + Matrix *img = Nan::ObjectWrap::Unwrap(img_to_return); + img->mat = *(new cv::Mat(width, height, type)); + if (callback_arg < 0){ + info.GetReturnValue().Set(img_to_return); + return; + } else { + argv[0] = Nan::Null(); + argv[1] = img_to_return; + cb->Call(Nan::GetCurrentContext()->Global(), 2, argv); + return; + } + // WILL have returned by here unless exception + ////////////////////////////// + + } else if (info[0]->IsString()) { + + ////////////////////////////// + // read image from a filename + std::string filename = std::string(*Nan::Utf8String(info[0]->ToString())); + int flags = CV_LOAD_IMAGE_UNCHANGED; + if (numargs > 1){ + if (info[1]->IsNumber()){ + flags = info[1]->Uint32Value(); + } + } + if (callback_arg < 0){ + Local img_to_return = + Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); + Matrix *img = Nan::ObjectWrap::Unwrap(img_to_return); + img->mat = cv::imread(filename, flags); + info.GetReturnValue().Set(img_to_return); + return; + } else { + Nan::Callback *callback = new Nan::Callback(cb.As()); + Nan::AsyncQueueWorker(new AsyncImReadWorker(callback, filename, flags)); + return; + } + // WILL have returned by here unless exception + ////////////////////////////// + + } else if (Buffer::HasInstance(info[0])) { + ////////////////////////////// + // read image from a buffer + // if sync + int flags = CV_LOAD_IMAGE_UNCHANGED; + if (numargs > 1){ + if (info[1]->IsNumber()){ + flags = info[1]->Uint32Value(); + } + } + if (callback_arg < 0){ + Local img_to_return = + Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); + Matrix *img = Nan::ObjectWrap::Unwrap(img_to_return); + uint8_t *buf = (uint8_t *) Buffer::Data(info[0]->ToObject()); + unsigned len = Buffer::Length(info[0]->ToObject()); + cv::Mat *mbuf = new cv::Mat(len, 1, CV_64FC1, buf); + img->mat = cv::imdecode(*mbuf, flags); + info.GetReturnValue().Set(img_to_return); + return; + } else { + // async + uint8_t *buf = (uint8_t *) Buffer::Data(info[0]->ToObject()); + unsigned len = Buffer::Length(info[0]->ToObject()); + Nan::Callback *callback = new Nan::Callback(cb.As()); + Nan::AsyncQueueWorker(new AsyncImDecodeWorker(callback, buf, len, flags)); + return; + } + // WILL have returned by here unless exception + ////////////////////////////// + } + + } catch (cv::Exception& e) { + argv[0] = Nan::Error(e.what()); + argv[1] = Nan::Null(); + } + + Nan::TryCatch try_catch; + // if we got a callback + if (callback_arg >= 0){ + // if using callback + cb->Call(Nan::GetCurrentContext()->Global(), 2, argv); + } else { + // can only get here by exception + info.GetReturnValue().Set(Nan::New(false)); + } + if (try_catch.HasCaught()) { + Nan::FatalException(try_catch); + } + return; +} + + + NAN_METHOD(OpenCV::ReadImage) { Nan::EscapableHandleScope scope; diff --git a/src/OpenCV.h b/src/OpenCV.h index 60739de..6ef42db 100755 --- a/src/OpenCV.h +++ b/src/OpenCV.h @@ -86,6 +86,7 @@ public: static void Init(Local target); static NAN_METHOD(ReadImage); + static NAN_METHOD(ReadImageAsync); static NAN_METHOD(ReadImageMulti); };