diff --git a/examples/files/distanceTransform.png b/examples/files/distanceTransform.png new file mode 100644 index 0000000..c1072d5 Binary files /dev/null and b/examples/files/distanceTransform.png differ diff --git a/examples/files/multipage.tif b/examples/files/multipage.tif new file mode 100644 index 0000000..17d286c Binary files /dev/null and b/examples/files/multipage.tif differ diff --git a/src/Constants.cc b/src/Constants.cc index f492a2f..d6f0ff1 100644 --- a/src/Constants.cc +++ b/src/Constants.cc @@ -4,6 +4,9 @@ #define CONST(C) \ obj->Set(Nan::New(#C).ToLocalChecked(), Nan::New(C)); +#define CONST_INT(C) \ + obj->Set(Nan::New(#C).ToLocalChecked(), Nan::New((int)C)); + #define CONST_DOUBLE(C) \ obj->Set(Nan::New(#C).ToLocalChecked(), Nan::New(C)); @@ -90,6 +93,14 @@ void Constants::Init(Local target) { CONST_ENUM(RETR_CCOMP); CONST_ENUM(RETR_TREE); + CONST_INT(CV_DIST_C); + CONST_INT(CV_DIST_L1); + CONST_INT(CV_DIST_L2); + + CONST_INT(CV_DIST_MASK_3); + CONST_INT(CV_DIST_MASK_5); + CONST_INT(CV_DIST_MASK_PRECISE); + target->Set(Nan::New("Constants").ToLocalChecked(), obj); } diff --git a/src/ImgProc.cc b/src/ImgProc.cc index 8fa3ffb..cc56658 100644 --- a/src/ImgProc.cc +++ b/src/ImgProc.cc @@ -9,11 +9,44 @@ void ImgProc::Init(Local target) { Nan::SetMethod(obj, "undistort", Undistort); Nan::SetMethod(obj, "initUndistortRectifyMap", InitUndistortRectifyMap); Nan::SetMethod(obj, "remap", Remap); + Nan::SetMethod(obj, "distanceTransform", DistanceTransform); Nan::SetMethod(obj, "getStructuringElement", GetStructuringElement); target->Set(Nan::New("imgproc").ToLocalChecked(), obj); } +// cv::distanceTransform +NAN_METHOD(ImgProc::DistanceTransform) { + Nan::EscapableHandleScope scope; + + try { + // Arg 0 is the image + Matrix* m0 = Nan::ObjectWrap::Unwrap(info[0]->ToObject()); + cv::Mat inputImage = m0->mat; + + // Arg 1 is the distance type (CV_DIST_L1, CV_DIST_L2, etc.) + int distType = info[1]->IntegerValue();; + + // Make a mat to hold the result image + cv::Mat outputImage; + + // Perform distance transform + cv::distanceTransform(inputImage, outputImage, distType, 0); + + // Wrap the output image + Local outMatrixWrap = Nan::New(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *outMatrix = Nan::ObjectWrap::Unwrap(outMatrixWrap); + outMatrix->mat = outputImage; + + // Return the output image + info.GetReturnValue().Set(outMatrixWrap); + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + Nan::ThrowError(err_msg); + return; + } +} + // cv::undistort NAN_METHOD(ImgProc::Undistort) { Nan::EscapableHandleScope scope; diff --git a/src/ImgProc.h b/src/ImgProc.h index 48f031f..8754fdd 100644 --- a/src/ImgProc.h +++ b/src/ImgProc.h @@ -9,6 +9,7 @@ class ImgProc: public Nan::ObjectWrap { public: static void Init(Local target); + static NAN_METHOD(DistanceTransform); static NAN_METHOD(Undistort); static NAN_METHOD(InitUndistortRectifyMap); static NAN_METHOD(Remap); diff --git a/src/OpenCV.cc b/src/OpenCV.cc index 14a498d..c0e666b 100755 --- a/src/OpenCV.cc +++ b/src/OpenCV.cc @@ -11,6 +11,7 @@ void OpenCV::Init(Local target) { target->Set(Nan::New("version").ToLocalChecked(), Nan::New(out, n).ToLocalChecked()); Nan::SetMethod(target, "readImage", ReadImage); + Nan::SetMethod(target, "readImageMulti", ReadImageMulti); } NAN_METHOD(OpenCV::ReadImage) { @@ -66,3 +67,54 @@ NAN_METHOD(OpenCV::ReadImage) { return; } + +#if CV_MAJOR_VERSION >= 3 +NAN_METHOD(OpenCV::ReadImageMulti) { + Nan::EscapableHandleScope scope; + + REQ_FUN_ARG(1, cb); + + Local argv[2]; + argv[0] = Nan::Null(); + + std::vector mats; + try { + if (info[0]->IsString()) { + std::string filename = std::string(*Nan::Utf8String(info[0]->ToString())); + cv::imreadmulti(filename, mats); + + if (mats.empty()) { + argv[0] = Nan::Error("Error loading file"); + } + } + } catch (cv::Exception& e) { + argv[0] = Nan::Error(e.what()); + argv[1] = Nan::Null(); + } + + Local output = Nan::New(mats.size()); + argv[1] = output; + + for (std::vector::size_type i = 0; i < mats.size(); i ++) { + Local im_h = Nan::New(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *img = Nan::ObjectWrap::Unwrap(im_h); + img->mat = mats[i]; + + output->Set(i, im_h); + } + + Nan::TryCatch try_catch; + cb->Call(Nan::GetCurrentContext()->Global(), 2, argv); + + if (try_catch.HasCaught()) { + Nan::FatalException(try_catch); + } + + return; +} +#else +NAN_METHOD(OpenCV::ReadImageMulti) { + info.GetReturnValue().Set(Nan::New(false)); + return; +} +#endif diff --git a/src/OpenCV.h b/src/OpenCV.h index f0ff9d3..cc9a2b9 100755 --- a/src/OpenCV.h +++ b/src/OpenCV.h @@ -67,6 +67,7 @@ public: static void Init(Local target); static NAN_METHOD(ReadImage); + static NAN_METHOD(ReadImageMulti); }; #endif diff --git a/test/unit.js b/test/unit.js index 97767f3..77adf18 100755 --- a/test/unit.js +++ b/test/unit.js @@ -216,6 +216,36 @@ test("Image read from file", function(assert){ }) }) +test("Multi-page image read from file", function(assert){ + if (parseInt(cv.version) >= 3) { + cv.readImageMulti("./examples/files/multipage.tif", function(err, imgs){ + assert.ok(imgs); + assert.equal(imgs.length, 10); + for (var i = 0; i < imgs.length; i++) { + assert.ok(imgs[i]); + assert.equal(imgs[i].width(), 800); + assert.equal(imgs[i].height(), 600); + assert.equal(imgs[i].channels(), 3); + assert.equal(imgs[i].empty(), false); + } + assert.end(); + }) + } else { + assert.equal(cv.readImageMulti("./examples/files/multipage.tif"), false); + assert.end(); + } +}) + +test("Distance transform", function(assert){ + cv.readImage("./examples/files/distanceTransform.png", function(err, img){ + assert.ok(img); + + // 50px image with single black pixel on right side + var result = cv.imgproc.distanceTransform(img, cv.Constants.CV_DIST_L2, cv.Constants.CV_DIST_MASK_PRECISE); + assert.equal(result.get(0,0), 49); + assert.end(); + }) +}) test("read Image from buffer", function(assert){ cv.readImage(fs.readFileSync('./examples/files/opencv.png'), function(err, im){