/************************************************************ cvutils.cpp - $Author: ser1zw $ Copyright (C) 2011 ser1zw ************************************************************/ #include "cvutils.h" void raise_typeerror(VALUE object, VALUE expected_class) { raise_typeerror(object, rb_class2name(expected_class)); } void raise_typeerror(VALUE object, const char* expected_class_name) { rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", rb_obj_classname(object), expected_class_name); } void raise_compatible_typeerror(VALUE object, VALUE expected_class) { raise_compatible_typeerror(object, rb_class2name(expected_class)); } void raise_compatible_typeerror(VALUE object, const char* expected_class_name) { rb_raise(rb_eTypeError, "wrong argument type %s (expected %s or compatible object)", rb_obj_classname(object), expected_class_name); } /* * Allocates a memory buffer * see cv::fastMalloc() */ void* rbFastMalloc(size_t size) { uchar* udata = (uchar*)xmalloc(size + sizeof(void*) + CV_MALLOC_ALIGN); if(!udata) { rb_raise(rb_eNoMemError, "Failed to allocate memory"); } uchar** adata = cv::alignPtr((uchar**)udata + 1, CV_MALLOC_ALIGN); adata[-1] = udata; return adata; } /* * Allocates a memory buffer * When memory allocation is failed, run GC and retry it */ void* rb_cvAlloc(size_t size) { return rbFastMalloc(size); } /* * Creates CvMat and underlying data * When memory allocation is failed, run GC and retry it */ CvMat* rb_cvCreateMat(int rows, int cols, int type) { CvMat* mat = NULL; try { mat = cvCreateMatHeader(rows, cols, type); if (mat) { // see OpenCV's cvCreateData() size_t step = mat->step; size_t total_size = step * mat->rows + sizeof(int) + CV_MALLOC_ALIGN; mat->refcount = (int*)rbFastMalloc(total_size); mat->data.ptr = (uchar*)cvAlignPtr(mat->refcount + 1, CV_MALLOC_ALIGN); *mat->refcount = 1; } else { rb_raise(rb_eRuntimeError, "Failed to create mat header"); } } catch(cv::Exception& e) { if (mat) { cvReleaseMat(&mat); } rb_raise(rb_eRuntimeError, "%s", e.what()); } return mat; } /* * 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 = cvCreateImageHeader(size, depth, channels); if (ptr) { // see OpenCV's cvCreateData() ptr->imageData = ptr->imageDataOrigin = (char*)rbFastMalloc((size_t)ptr->imageSize); } else { rb_raise(rb_eRuntimeError, "Failed to create image header"); } } catch(cv::Exception& e) { if (ptr) { cvReleaseImage(&ptr); } rb_raise(rb_eRuntimeError, "%s", e.what()); } return ptr; } /* * Creates a structuring element * When memory allocation is failed, run GC and retry it */ IplConvKernel* rb_cvCreateStructuringElementEx(int cols, int rows, int anchorX, int anchorY, int shape, int *values) { IplConvKernel* ptr = NULL; try { ptr = cvCreateStructuringElementEx(cols, rows, anchorX, anchorY, shape, values); } catch(cv::Exception& e) { if (e.code != CV_StsNoMem) rb_raise(rb_eRuntimeError, "%s", e.what()); rb_gc_start(); try { ptr = cvCreateStructuringElementEx(cols, rows, anchorX, anchorY, shape, values); } 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 memory storage * When memory allocation is failed, run GC and retry it */ CvMemStorage* rb_cvCreateMemStorage(int block_size) { CvMemStorage* ptr = NULL; try { ptr = cvCreateMemStorage(block_size); } catch(cv::Exception& e) { if (e.code != CV_StsNoMem) rb_raise(rb_eRuntimeError, "%s", e.what()); rb_gc_start(); try { ptr = cvCreateMemStorage(block_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; } VALUE rb_get_option_table(VALUE klass, const char* table_name, VALUE option) { VALUE table = rb_const_get(klass, rb_intern(table_name)); if (NIL_P(option)) return table; else return rb_funcall(table, rb_intern("merge"), 1, option); }