diff --git a/ext/opencv/cvmat.cpp b/ext/opencv/cvmat.cpp index c7d3c03..e84e291 100644 --- a/ext/opencv/cvmat.cpp +++ b/ext/opencv/cvmat.cpp @@ -386,6 +386,8 @@ void define_ruby_class() rb_define_method(rb_klass, "encode_image", RUBY_METHOD_FUNC(rb_encode_imageM), -1); rb_define_alias(rb_klass, "encode", "encode_image"); + rb_define_singleton_method(rb_klass, "decode_image", RUBY_METHOD_FUNC(rb_decode_imageM), -1); + rb_define_alias(rb_singleton_class(rb_klass), "decode", "decode_image"); } @@ -535,6 +537,66 @@ rb_encode_imageM(int argc, VALUE *argv, VALUE self) return array; } +/* + * call-seq: + * decode_image(buf[, iscolor=CV_LOAD_IMAGE_COLOR]) -> CvMat + * + * Reads an image from a buffer in memory. + * + * Parameters: + * buf - Input array + * iscolor - Flags specifying the color type of a decoded image (the same flags as CvMat#load) + */ +VALUE +rb_decode_imageM(int argc, VALUE *argv, VALUE self) +{ + VALUE _buff, _iscolor; + rb_scan_args(argc, argv, "11", &_buff, &_iscolor); + int iscolor = NIL_P(_iscolor) ? CV_LOAD_IMAGE_COLOR : NUM2INT(_iscolor); + + CvMat* buff = NULL; + int need_release = 0; + switch (TYPE(_buff)) { + case T_STRING: + _buff = rb_funcall(_buff, rb_intern("unpack"), 1, rb_str_new("c*", 2)); + case T_ARRAY: { + int cols = RARRAY_LEN(_buff); + need_release = 1; + try { + buff = rb_cvCreateMat(1, cols, CV_8UC1); + for (int i = 0; i < cols; i++) { + CV_MAT_ELEM(*buff, char, 0, i) = NUM2CHR(RARRAY_PTR(_buff)[i]); + } + } + catch (cv::Exception& e) { + raise_cverror(e); + } + break; + } + case T_DATA: + if (rb_obj_is_kind_of(_buff, cCvMat::rb_class()) == Qtrue) { + buff = CVMAT(_buff); + break; + } + default: + raise_typeerror(_buff, "CvMat, Array or String"); + } + + CvMat* mat_ptr = NULL; + try { + mat_ptr = cvDecodeImageM(buff, iscolor); + // mat = cvDecodeImage(); + if (need_release) { + cvReleaseMat(&buff); + } + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return OPENCV_OBJECT(rb_klass, mat_ptr); +} + /* * nodoc */ diff --git a/ext/opencv/cvmat.h b/ext/opencv/cvmat.h index 5e82442..2756e89 100644 --- a/ext/opencv/cvmat.h +++ b/ext/opencv/cvmat.h @@ -27,6 +27,7 @@ VALUE rb_allocate(VALUE klass); VALUE rb_initialize(int argc, VALUE *argv, VALUE self); VALUE rb_load_imageM(int argc, VALUE *argv, VALUE self); VALUE rb_encode_imageM(int argc, VALUE *argv, VALUE self); +VALUE rb_decode_imageM(int argc, VALUE *argv, VALUE self); VALUE rb_method_missing(int argc, VALUE *argv, VALUE self); VALUE rb_to_s(VALUE self); diff --git a/test/test_cvmat.rb b/test/test_cvmat.rb index 403e3f9..7642589 100755 --- a/test/test_cvmat.rb +++ b/test/test_cvmat.rb @@ -135,6 +135,56 @@ class TestCvMat < OpenCVTestCase # } end + def test_decode + data = nil + open(FILENAME_CAT, 'rb') { |f| + data = f.read + } + data_ary = data.unpack("c*") + data_mat = CvMat.new(1, data_ary.size).set_data(data_ary) + expected = CvMat.load(FILENAME_CAT) + + mat1 = CvMat.decode(data) + mat2 = CvMat.decode(data_ary) + mat3 = CvMat.decode(data_mat) + mat4 = CvMat.decode(data, CV_LOAD_IMAGE_COLOR) + mat5 = CvMat.decode(data_ary, CV_LOAD_IMAGE_COLOR) + mat6 = CvMat.decode(data_mat, CV_LOAD_IMAGE_COLOR) + expected_hash = hash_img(expected) + + [mat1, mat2, mat3, mat4, mat5, mat6].each { |mat| + assert_equal(CvMat, mat.class) + assert_equal(expected.rows, mat.rows) + assert_equal(expected.cols, mat.cols) + assert_equal(expected.channel, mat.channel) + assert_equal(expected_hash, hash_img(mat)) + } + + expected_c1 = CvMat.load(FILENAME_CAT, CV_LOAD_IMAGE_GRAYSCALE) + mat1c1 = CvMat.decode(data, CV_LOAD_IMAGE_GRAYSCALE) + mat2c1 = CvMat.decode(data_ary, CV_LOAD_IMAGE_GRAYSCALE) + mat3c1 = CvMat.decode(data_mat, CV_LOAD_IMAGE_GRAYSCALE) + expected_hash_c1 = hash_img(expected_c1) + + [mat1c1, mat2c1, mat3c1].each { |mat| + assert_equal(CvMat, mat.class) + assert_equal(expected_c1.rows, mat.rows) + assert_equal(expected_c1.cols, mat.cols) + assert_equal(expected_c1.channel, mat.channel) + assert_equal(expected_hash_c1, hash_img(mat)) + } + + assert_raise(TypeError) { + CvMat.decode(DUMMY_OBJ) + } + assert_raise(TypeError) { + CvMat.decode(data, DUMMY_OBJ) + } + + # Uncomment the following line to show the result images + # snap mat1, mat2, mat3 + end + def test_GOOD_FEATURES_TO_TRACK_OPTION assert_equal(0xff, CvMat::GOOD_FEATURES_TO_TRACK_OPTION[:max]) assert_nil(CvMat::GOOD_FEATURES_TO_TRACK_OPTION[:mask])