diff --git a/ext/opencv/cvcapture.cpp b/ext/opencv/cvcapture.cpp index 7fafaf6..42224e5 100644 --- a/ext/opencv/cvcapture.cpp +++ b/ext/opencv/cvcapture.cpp @@ -187,21 +187,25 @@ VALUE rb_retrieve(VALUE self) { VALUE image = Qnil; + IplImage *frame = NULL; try { - IplImage *frame = cvRetrieveFrame(CVCAPTURE(self)); - if (!frame) + if (!(frame = cvRetrieveFrame(CVCAPTURE(self)))) { return Qnil; - image = cIplImage::new_object(cvSize(frame->width, frame->height), - CV_MAKETYPE(CV_8U, frame->nChannels)); - if (frame->origin == IPL_ORIGIN_TL) + } + image = cIplImage::new_object(frame->width, frame->height, + CV_MAKETYPE(IPL2CV_DEPTH(frame->depth), frame->nChannels)); + if (frame->origin == IPL_ORIGIN_TL) { cvCopy(frame, CVARR(image)); - else + } + else { cvFlip(frame, CVARR(image)); + } } catch (cv::Exception& e) { raise_cverror(e); } return image; + } /* @@ -214,16 +218,19 @@ VALUE rb_query(VALUE self) { VALUE image = Qnil; + IplImage *frame = NULL; try { - IplImage *frame = cvQueryFrame(CVCAPTURE(self)); - if (!frame) + if (!(frame = cvQueryFrame(CVCAPTURE(self)))) { return Qnil; - image = cIplImage::new_object(cvSize(frame->width, frame->height), - CV_MAKETYPE(CV_8U, frame->nChannels)); - if (frame->origin == IPL_ORIGIN_TL) + } + image = cIplImage::new_object(frame->width, frame->height, + CV_MAKETYPE(IPL2CV_DEPTH(frame->depth), frame->nChannels)); + if (frame->origin == IPL_ORIGIN_TL) { cvCopy(frame, CVARR(image)); - else + } + else { cvFlip(frame, CVARR(image)); + } } catch (cv::Exception& e) { raise_cverror(e); diff --git a/ext/opencv/cvutils.cpp b/ext/opencv/cvutils.cpp index 98643f4..3f5342a 100644 --- a/ext/opencv/cvutils.cpp +++ b/ext/opencv/cvutils.cpp @@ -35,6 +35,22 @@ raise_compatible_typeerror(VALUE object, const char* expected_class_name) 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 @@ -42,26 +58,7 @@ raise_compatible_typeerror(VALUE object, const char* expected_class_name) 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; + return rbFastMalloc(size); } /* @@ -69,28 +66,31 @@ rb_cvAlloc(size_t size) * When memory allocation is failed, run GC and retry it */ CvMat* -rb_cvCreateMat(int height, int width, int type) +rb_cvCreateMat(int rows, int cols, int type) { - CvMat* ptr = NULL; + CvMat* mat = NULL; try { - ptr = cvCreateMat(height, width, type); + 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 (e.code != CV_StsNoMem) - rb_raise(rb_eRuntimeError, "%s", e.what()); - - rb_gc_start(); - try { - ptr = cvCreateMat(height, width, type); - } - catch (cv::Exception& e) { - if (e.code == CV_StsNoMem) - rb_raise(rb_eNoMemError, "%s", e.what()); - else - rb_raise(rb_eRuntimeError, "%s", e.what()); + if (mat) { + cvReleaseMat(&mat); } + rb_raise(rb_eRuntimeError, "%s", e.what()); } - return ptr; + return mat; } /* @@ -102,22 +102,20 @@ rb_cvCreateImage(CvSize size, int depth, int channels) { IplImage* ptr = NULL; try { - ptr = cvCreateImage(size, depth, channels); + 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 (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()); + if (ptr) { + cvReleaseImage(&ptr); } + rb_raise(rb_eRuntimeError, "%s", e.what()); } return ptr; } diff --git a/ext/opencv/cvutils.h b/ext/opencv/cvutils.h index 95eafab..dad9e35 100644 --- a/ext/opencv/cvutils.h +++ b/ext/opencv/cvutils.h @@ -11,6 +11,7 @@ #include #include "opencv2/core/core_c.h" #include "opencv2/core/core.hpp" +#include "opencv2/core/internal.hpp" #include "opencv2/imgproc/imgproc_c.h" #include "opencv2/imgproc/imgproc.hpp"