diff --git a/ext/opencv/cvmat.cpp b/ext/opencv/cvmat.cpp index ecf4bc0..3e75c56 100644 --- a/ext/opencv/cvmat.cpp +++ b/ext/opencv/cvmat.cpp @@ -921,7 +921,7 @@ rb_square_q(VALUE self) VALUE rb_to_CvMat(VALUE self) { - return DEPEND_OBJECT(rb_klass, cvGetMat(CVARR(self), CVALLOC(CvMat)), self); + return DEPEND_OBJECT(rb_klass, cvGetMat(CVARR(self), RB_CVALLOC(CvMat)), self); } /* @@ -965,7 +965,7 @@ rb_sub_rect(VALUE self, VALUE args) rb_raise(rb_eArgError, "wrong number of arguments (%ld of 1 or 2 or 4)", RARRAY_LEN(args)); } return DEPEND_OBJECT(rb_klass, - cvGetSubRect(CVARR(self), CVALLOC(CvMat), area), + cvGetSubRect(CVARR(self), RB_CVALLOC(CvMat), area), self); } @@ -994,7 +994,7 @@ rb_slice_width(VALUE self, VALUE num) VALUE ary = rb_ary_new2(n); for (int i = 0; i < n; i++) { CvRect rect = {div_x * i, 0, div_x, size.height}; - rb_ary_push(ary, DEPEND_OBJECT(rb_klass, cvGetSubRect(CVARR(self), CVALLOC(CvMat), rect), self)); + rb_ary_push(ary, DEPEND_OBJECT(rb_klass, cvGetSubRect(CVARR(self), RB_CVALLOC(CvMat), rect), self)); } return ary; } @@ -1019,7 +1019,7 @@ rb_slice_height(VALUE self, VALUE num) VALUE ary = rb_ary_new2(n); for (int i = 0; i < n; i++) { CvRect rect = {0, div_y * i, size.width, div_y}; - rb_ary_push(ary, DEPEND_OBJECT(rb_klass, cvGetSubRect(CVARR(self), CVALLOC(CvMat), rect), self)); + rb_ary_push(ary, DEPEND_OBJECT(rb_klass, cvGetSubRect(CVARR(self), RB_CVALLOC(CvMat), rect), self)); } return ary; } @@ -1041,10 +1041,11 @@ rb_row(VALUE self, VALUE args) for (int i = 0; i < len; i++) { VALUE value = rb_ary_entry(args, i); if (FIXNUM_P(value)) { - rb_ary_store(ary, i, DEPEND_OBJECT(rb_klass, cvGetRow(CVARR(self), CVALLOC(CvMat), FIX2INT(value)), self)); + rb_ary_store(ary, i, DEPEND_OBJECT(rb_klass, cvGetRow(CVARR(self), RB_CVALLOC(CvMat), FIX2INT(value)), self)); }else{ CvSlice slice = VALUE_TO_CVSLICE(value); - rb_ary_store(ary, i, DEPEND_OBJECT(rb_klass, cvGetRows(CVARR(self), CVALLOC(CvMat), slice.start_index, slice.end_index), self)); + rb_ary_store(ary, i, DEPEND_OBJECT(rb_klass, cvGetRows(CVARR(self), RB_CVALLOC(CvMat), + slice.start_index, slice.end_index), self)); } } return RARRAY_LEN(ary) > 1 ? ary : rb_ary_entry(ary, 0); @@ -1067,10 +1068,11 @@ rb_col(VALUE self, VALUE args) for (int i = 0; i < len; i++) { VALUE value = rb_ary_entry(args, i); if (FIXNUM_P(value)) { - rb_ary_store(ary, i, DEPEND_OBJECT(rb_klass, cvGetCol(CVARR(self), CVALLOC(CvMat), FIX2INT(value)), self)); + rb_ary_store(ary, i, DEPEND_OBJECT(rb_klass, cvGetCol(CVARR(self), RB_CVALLOC(CvMat), FIX2INT(value)), self)); }else{ CvSlice slice = VALUE_TO_CVSLICE(value); - rb_ary_store(ary, i, DEPEND_OBJECT(rb_klass, cvGetCols(CVARR(self), CVALLOC(CvMat), slice.start_index, slice.end_index), self)); + rb_ary_store(ary, i, DEPEND_OBJECT(rb_klass, cvGetCols(CVARR(self), RB_CVALLOC(CvMat), + slice.start_index, slice.end_index), self)); } } return RARRAY_LEN(ary) > 1 ? ary : rb_ary_entry(ary, 0); @@ -1089,7 +1091,7 @@ rb_each_row(VALUE self) { int rows = CVMAT(self)->rows; for (int i = 0; i < rows; i++) { - rb_yield(DEPEND_OBJECT(rb_klass, cvGetRow(CVARR(self), CVALLOC(CvMat), i), self)); + rb_yield(DEPEND_OBJECT(rb_klass, cvGetRow(CVARR(self), RB_CVALLOC(CvMat), i), self)); } return self; } @@ -1107,7 +1109,7 @@ rb_each_col(VALUE self) { int cols = CVMAT(self)->cols; for (int i = 0; i < cols; i++) { - rb_yield(DEPEND_OBJECT(rb_klass, cvGetCol(CVARR(self), CVALLOC(CvMat), i), self)); + rb_yield(DEPEND_OBJECT(rb_klass, cvGetCol(CVARR(self), RB_CVALLOC(CvMat), i), self)); } return self; } @@ -1127,7 +1129,7 @@ rb_diag(int argc, VALUE *argv, VALUE self) if (rb_scan_args(argc, argv, "01", &val) < 1) { val = INT2FIX(0); } - return DEPEND_OBJECT(rb_klass, cvGetDiag(CVARR(self), CVALLOC(CvMat), NUM2INT(val)), self); + return DEPEND_OBJECT(rb_klass, cvGetDiag(CVARR(self), RB_CVALLOC(CvMat), NUM2INT(val)), self); } /* @@ -1410,7 +1412,8 @@ rb_reshape(VALUE self, VALUE hash) rb_raise(rb_eTypeError, "argument should be Hash that contaion key (:row, :channel)."); VALUE channel = rb_hash_aref(hash, ID2SYM(rb_intern("channel"))); VALUE rows = rb_hash_aref(hash, ID2SYM(rb_intern("rows"))); - return DEPEND_OBJECT(rb_klass, cvReshape(CVARR(self), CVALLOC(CvMat), NIL_P(channel) ? 0 : FIX2INT(channel), NIL_P(rows) ? 0 : FIX2INT(rows)), self); + return DEPEND_OBJECT(rb_klass, cvReshape(CVARR(self), RB_CVALLOC(CvMat), NIL_P(channel) ? 0 : FIX2INT(channel), + NIL_P(rows) ? 0 : FIX2INT(rows)), self); } /* @@ -3212,7 +3215,7 @@ rb_good_features_to_track(int argc, VALUE *argv, VALUE self) int np = GF_MAX(good_features_to_track_option); if(!(np > 0)) rb_raise(rb_eArgError, "option :max should be positive value."); - CvPoint2D32f *p32 = (CvPoint2D32f*)cvAlloc(sizeof(CvPoint2D32f) * np); + CvPoint2D32f *p32 = (CvPoint2D32f*)rb_cvAlloc(sizeof(CvPoint2D32f) * np); if(!p32) rb_raise(rb_eNoMemError, "failed to allocate memory."); cvGoodFeaturesToTrack(src, &eigen, &tmp, p32, &np, NUM2DBL(quality_level), NUM2DBL(min_distance), diff --git a/ext/opencv/cvseq.cpp b/ext/opencv/cvseq.cpp index d6b20d6..e16099f 100644 --- a/ext/opencv/cvseq.cpp +++ b/ext/opencv/cvseq.cpp @@ -333,7 +333,7 @@ rb_seq_push(VALUE self, VALUE args, int flag) cvSeqPush(seq, DATA_PTR(object)); } else if (rb_obj_is_kind_of(object, rb_klass) && CLASS_OF(rb_first(object)) == klass) { // object is CvSeq - buffer = cvCvtSeqToArray(CVSEQ(object), cvAlloc(CVSEQ(object)->total * CVSEQ(object)->elem_size)); + buffer = cvCvtSeqToArray(CVSEQ(object), rb_cvAlloc(CVSEQ(object)->total * CVSEQ(object)->elem_size)); cvSeqPushMulti(seq, buffer, CVSEQ(object)->total, flag); cvFree(&buffer); } diff --git a/ext/opencv/iplimage.cpp b/ext/opencv/iplimage.cpp index 1059b58..57f494f 100644 --- a/ext/opencv/iplimage.cpp +++ b/ext/opencv/iplimage.cpp @@ -90,7 +90,7 @@ rb_initialize(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "22", &width, &height, &depth, &channel); int _depth = argc < 3 ? CV_8U : FIX2INT(depth); int _channel = argc < 4 ? 3 : FIX2INT(channel); - DATA_PTR(self) = cvCreateImage(cvSize(FIX2INT(width), FIX2INT(height)), cvIplDepth(_depth), _channel); + DATA_PTR(self) = rb_cvCreateImage(cvSize(FIX2INT(width), FIX2INT(height)), cvIplDepth(_depth), _channel); return self; } @@ -267,7 +267,7 @@ rb_smoothness(int argc, VALUE *argv, VALUE self) p64DepthImage = NULL; pFourierImage = create_fourier_image(IPLIMAGE(self)); } else { - p64DepthImage = cvCreateImage(cvGetSize(IPLIMAGE(self)), IPL_DEPTH_64F, 1); + p64DepthImage = rb_cvCreateImage(cvGetSize(IPLIMAGE(self)), IPL_DEPTH_64F, 1); cvConvertScale(CVARR(self), p64DepthImage, 1.0, 0.0); pFourierImage = create_fourier_image(p64DepthImage); } @@ -414,9 +414,9 @@ create_fourier_image(const IplImage *im) IplImage *image_Re; IplImage *image_Im; - realInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1); - imaginaryInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1); - complexInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 2); + realInput = rb_cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1); + imaginaryInput = rb_cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1); + complexInput = rb_cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 2); cvScale(im, realInput, 1.0, 0.0); cvZero(imaginaryInput); @@ -426,8 +426,8 @@ create_fourier_image(const IplImage *im) dft_N = cvGetOptimalDFTSize( im->width - 1 ); dft_A = rb_cvCreateMat( dft_M, dft_N, CV_64FC2 ); - image_Re = cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1); - image_Im = cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1); + image_Re = rb_cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1); + image_Im = rb_cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1); // copy A to dft_A and pad dft_A with zeros cvGetSubRect( dft_A, &tmp, cvRect(0,0, im->width, im->height)); @@ -484,8 +484,8 @@ create_frequency_filtered_image(const IplImage *pImage, int low, int high) box.size.width = high; box.size.height = high; - IplImage *pFilterMask = cvCreateImage( cvGetSize(pImage), IPL_DEPTH_64F, 1 ); - IplImage *pFiltered = cvCreateImage( cvGetSize(pImage), IPL_DEPTH_64F, 1 ); + IplImage *pFilterMask = rb_cvCreateImage( cvGetSize(pImage), IPL_DEPTH_64F, 1 ); + IplImage *pFiltered = rb_cvCreateImage( cvGetSize(pImage), IPL_DEPTH_64F, 1 ); cvZero(pFilterMask); cvZero(pFiltered); @@ -525,13 +525,13 @@ high_pass_range(const IplImage *pImage, float lostPercentage, int &outLow, int & VALUE new_object(int width, int height, int type) { - return OPENCV_OBJECT(rb_klass, cvCreateImage(cvSize(width, height), cvIplDepth(type), CV_MAT_CN(type))); + return OPENCV_OBJECT(rb_klass, rb_cvCreateImage(cvSize(width, height), cvIplDepth(type), CV_MAT_CN(type))); } VALUE new_object(CvSize size, int type) { - return OPENCV_OBJECT(rb_klass, cvCreateImage(size, cvIplDepth(type), CV_MAT_CN(type))); + return OPENCV_OBJECT(rb_klass, rb_cvCreateImage(size, cvIplDepth(type), CV_MAT_CN(type))); } __NAMESPACE_END_IPLIMAGE diff --git a/ext/opencv/opencv.cpp b/ext/opencv/opencv.cpp index ebed555..9ef5cdf 100644 --- a/ext/opencv/opencv.cpp +++ b/ext/opencv/opencv.cpp @@ -129,6 +129,35 @@ release_iplconvkernel_object(void *ptr) } } +/* + * Allocates a memory buffer + * When memory allocation is failed, run GC and retry it + */ +void* +rb_cvAlloc(size_t size) +{ + void* ptr = NULL; + try { + ptr = cvAlloc(size); + } + catch(cv::Exception& e) { + if (e.code != CV_StsNoMem) + rb_raise(rb_eRuntimeError, "%s", e.what()); + + rb_gc_start(); + try { + ptr = cvAlloc(size); + } + catch (cv::Exception& e) { + if (e.code == CV_StsNoMem) + rb_raise(rb_eNoMemError, "%s", e.what()); + else + rb_raise(rb_eRuntimeError, "%s", e.what()); + } + } + return ptr; +} + /* * Creates CvMat and underlying data * When memory allocation is failed, run GC and retry it @@ -158,6 +187,35 @@ rb_cvCreateMat(int height, int width, int type) return ptr; } +/* + * Create IplImage header and allocate underlying data + * When memory allocation is failed, run GC and retry it + */ +IplImage* +rb_cvCreateImage(CvSize size, int depth, int channels) +{ + IplImage* ptr = NULL; + try { + ptr = cvCreateImage(size, depth, channels); + } + catch(cv::Exception& e) { + if (e.code != CV_StsNoMem) + rb_raise(rb_eRuntimeError, "%s", e.what()); + + rb_gc_start(); + try { + ptr = cvCreateImage(size, depth, channels); + } + catch (cv::Exception& e) { + if (e.code == CV_StsNoMem) + rb_raise(rb_eNoMemError, "%s", e.what()); + else + rb_raise(rb_eRuntimeError, "%s", e.what()); + } + } + return ptr; +} + VALUE rb_module; VALUE rb_opencv_constants; diff --git a/ext/opencv/opencv.h b/ext/opencv/opencv.h index ba2e4a7..befa0f4 100644 --- a/ext/opencv/opencv.h +++ b/ext/opencv/opencv.h @@ -135,7 +135,7 @@ extern "C"{ #include "mouseevent.h" // memory management wrapper -#define CVALLOC(type) (type*)cvAlloc(sizeof(type)) +#define RB_CVALLOC(type) (type*)rb_cvAlloc(sizeof(type)) // useful macros #define IF_INT(val, ifnone) NIL_P(val) ? ifnone : NUM2INT(val) @@ -185,7 +185,9 @@ void release_iplconvkernel_object(void *ptr); VALUE rb_module_opencv(); void define_ruby_module(); +void* rb_cvAlloc(size_t size); CvMat* rb_cvCreateMat(int height, int width, int type); +IplImage* rb_cvCreateImage(CvSize size, int depth, int channels); // Ruby/OpenCV inline functions inline CvArr* diff --git a/ext/opencv/pointset.cpp b/ext/opencv/pointset.cpp index 9e61051..558bdbe 100644 --- a/ext/opencv/pointset.cpp +++ b/ext/opencv/pointset.cpp @@ -181,16 +181,18 @@ CVPOINTS_FROM_POINT_SET(VALUE object, CvPoint **pointset) CvPoint2D32f p32; if(rb_obj_is_kind_of(object, cCvSeq::rb_class())){ if(CV_IS_SEQ_POINT_SET(CVSEQ(object))){ - *pointset = (CvPoint*)cvCvtSeqToArray(CVSEQ(object), cvAlloc(CVSEQ(object)->total * CVSEQ(object)->elem_size)); + *pointset = (CvPoint*)cvCvtSeqToArray(CVSEQ(object), + rb_cvAlloc(CVSEQ(object)->total * CVSEQ(object)->elem_size)); return CVSEQ(object)->total; }else{ - rb_raise(rb_eTypeError, "sequence is not contain %s or %s.", rb_class2name(cCvPoint::rb_class()), rb_class2name(cCvPoint2D32f::rb_class())); + rb_raise(rb_eTypeError, "sequence is not contain %s or %s.", + rb_class2name(cCvPoint::rb_class()), rb_class2name(cCvPoint2D32f::rb_class())); } }else if(rb_obj_is_kind_of(object, cCvMat::rb_class())){ /* to do */ rb_raise(rb_eNotImpError, "CvMat to CvSeq conversion not implemented."); }else if(rb_obj_is_kind_of(object, rb_cArray)){ - *pointset = (CvPoint*)cvAlloc(RARRAY_LEN(object) * sizeof(CvPoint)); + *pointset = (CvPoint*)rb_cvAlloc(RARRAY_LEN(object) * sizeof(CvPoint)); for(int i = 0; i < RARRAY_LEN(object); i++){ (*pointset)[i].x = NUM2INT(rb_funcall(rb_ary_entry(object, i), rb_intern("x"), 0)); (*pointset)[i].y = NUM2INT(rb_funcall(rb_ary_entry(object, i), rb_intern("y"), 0));