Add cv.readImageAsync. same interface as readImage, only the callbacks are really Asynchronous, except for matrix creation.

Introduces two Asyn Wrokers, one for readin images from disk, and one for decoding images from buffers.
This commit is contained in:
Simon Hailes 2017-11-04 14:53:44 +00:00
parent 2dd3745c81
commit bc62d03f84
2 changed files with 227 additions and 0 deletions

View File

@ -11,9 +11,235 @@ void OpenCV::Init(Local<Object> target) {
target->Set(Nan::New<String>("version").ToLocalChecked(), Nan::New<String>(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<Object> img_to_return =
// Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked();
// img = Nan::ObjectWrap::Unwrap<Matrix>(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<Object> im_to_return= Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked();
Matrix *img = Nan::ObjectWrap::Unwrap<Matrix>(im_to_return);
img->mat = outputmat;
Local<Value> 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<Object> im_to_return= Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked();
Matrix *img = Nan::ObjectWrap::Unwrap<Matrix>(im_to_return);
img->mat = outputmat;
Local<Value> 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<Value> argv[2];
argv[0] = Nan::Null();
argv[1] = Nan::Null();
int callback_arg = -1;
int numargs = info.Length();
Local<Function> cb;
// deal with situation where we have int, int, cb
if (info[numargs-1]->IsFunction()){
callback_arg = numargs-1;
cb = Local<Function>::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<Object> img_to_return =
Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked();
Matrix *img = Nan::ObjectWrap::Unwrap<Matrix>(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<Object> img_to_return =
Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked();
Matrix *img = Nan::ObjectWrap::Unwrap<Matrix>(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<Function>());
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<Object> img_to_return =
Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked();
Matrix *img = Nan::ObjectWrap::Unwrap<Matrix>(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<Function>());
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<Boolean>(false));
}
if (try_catch.HasCaught()) {
Nan::FatalException(try_catch);
}
return;
}
NAN_METHOD(OpenCV::ReadImage) {
Nan::EscapableHandleScope scope;

View File

@ -86,6 +86,7 @@ public:
static void Init(Local<Object> target);
static NAN_METHOD(ReadImage);
static NAN_METHOD(ReadImageAsync);
static NAN_METHOD(ReadImageMulti);
};