/************************************************************ cvscalar.cpp - $Author: lsxi $ Copyright (C) 2005 Masakazu Yonekura ************************************************************/ #include "cvscalar.h" /* * Document-class: OpenCV::CvScalar * * Element-value of one pixel. * OpenCV supports the image of 4-channels in the maximum. * Therefore, CvScalar has 4-values. * * C structure is here, very simple. * typdef struct CvScalar { * double val[4]; * } CvScalar; * * If obtain CvScalar-object from the method of CvMat(or IplImage), * the channel outside the range is obtained as all 0. * * image = IplImage::load("opencv.jpg") #=> 3-channel 8bit-depth BGR image * pixel = image[10, 20] #=> Get pixel value of (10, 20) of image. pixel is CvScalar-object. * blue, green, red = pixel[0], pixel[1], pixel[2] * # pixel[3] always 0. * * CvColor is alias of CvScalar. */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVSCALAR VALUE rb_klass; VALUE rb_class() { return rb_klass; } void define_ruby_class() { if (rb_klass) return; /* * opencv = rb_define_module("OpenCV"); * * note: this comment is used by rdoc. */ VALUE opencv = rb_module_opencv(); rb_klass = rb_define_class_under(opencv, "CvScalar", rb_cObject); /* CvScalar: class */ rb_define_const(opencv, "CvColor", rb_klass); rb_define_alloc_func(rb_klass, rb_allocate); rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), 1); rb_define_method(rb_klass, "[]=", RUBY_METHOD_FUNC(rb_aset), 2); rb_define_method(rb_klass, "sub", RUBY_METHOD_FUNC(rb_sub), -1); rb_define_alias(rb_klass, "-", "sub"); rb_define_method(rb_klass, "to_s", RUBY_METHOD_FUNC(rb_to_s), 0); rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); rb_define_alias(rb_klass, "to_a", "to_ary"); rb_define_const(rb_klass, "Black", cCvScalar::new_object(cvScalar(0x0,0x0,0x0))); rb_define_const(rb_klass, "Silver", cCvScalar::new_object(cvScalar(0x0c,0x0c,0x0c))); rb_define_const(rb_klass, "Gray", cCvScalar::new_object(cvScalar(0x80,0x80,0x80))); rb_define_const(rb_klass, "White", cCvScalar::new_object(cvScalar(0xff,0xff,0xff))); rb_define_const(rb_klass, "Maroon", cCvScalar::new_object(cvScalar(0x0,0x0,0x80))); rb_define_const(rb_klass, "Red", cCvScalar::new_object(cvScalar(0x0,0x0,0xff))); rb_define_const(rb_klass, "Purple", cCvScalar::new_object(cvScalar(0x80,0x0,0x80))); rb_define_const(rb_klass, "Fuchsia", cCvScalar::new_object(cvScalar(0xff,0x0,0xff))); rb_define_const(rb_klass, "Green", cCvScalar::new_object(cvScalar(0x0,0x80,0x0))); rb_define_const(rb_klass, "Lime", cCvScalar::new_object(cvScalar(0x0,0xff,0x0))); rb_define_const(rb_klass, "Olive", cCvScalar::new_object(cvScalar(0x0,0x80,0x80))); rb_define_const(rb_klass, "Yellow", cCvScalar::new_object(cvScalar(0x0,0xff,0xff))); rb_define_const(rb_klass, "Navy", cCvScalar::new_object(cvScalar(0x80,0x0,0x0))); rb_define_const(rb_klass, "Blue", cCvScalar::new_object(cvScalar(0xff,0x0,0x0))); rb_define_const(rb_klass, "Teal", cCvScalar::new_object(cvScalar(0x80,0x80,0x0))); rb_define_const(rb_klass, "Aqua", cCvScalar::new_object(cvScalar(0xff,0xff,0x0))); } VALUE rb_allocate(VALUE klass) { CvScalar *ptr; return Data_Make_Struct(klass, CvScalar, 0, -1, ptr); } /* * call-seq: * new([d1][,d2][,d3][,d4]) * * Create new Scalar. Argument should be Fixnum (or nil as 0). */ VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { VALUE val[4]; rb_scan_args(argc, argv, "04", &val[0], &val[1], &val[2], &val[3]); CvScalar* self_ptr = CVSCALAR(self); for (int i = 0; i < 4; ++i) { self_ptr->val[i] = NIL_P(val[i]) ? 0 : NUM2DBL(val[i]); } return self; } /* * call-seq: * [index] * * Return value of index dimension. */ VALUE rb_aref(VALUE self, VALUE index) { int idx = NUM2INT(index); if (idx < 0 || idx >= 4) { rb_raise(rb_eIndexError, "scalar index should be 0...4"); } return rb_float_new(CVSCALAR(self)->val[idx]); } /* * call-seq: * [index] = value * * Set value of index dimension to value */ VALUE rb_aset(VALUE self, VALUE index, VALUE value) { int idx = NUM2INT(index); if (idx < 0 || idx >= 4) { rb_raise(rb_eIndexError, "scalar index should be 0...4"); } CVSCALAR(self)->val[idx] = NUM2DBL(value); return self; } /* * call-seq: * sub(val[,mask]) * * Return new CvScalar if val is CvScalar or compatible object. * self[I] - val[I] * Or return new CvMat if val is CvMat or subclass. */ VALUE rb_sub(int argc, VALUE *argv, VALUE self) { VALUE val, mask; rb_scan_args(argc, argv, "11", &val, &mask); if (rb_obj_is_kind_of(val, cCvMat::rb_class())) { CvArr *val_ptr = CVARR(val); VALUE dest = Qnil; try { dest = cCvMat::new_object(cvGetSize(val_ptr), cvGetElemType(val_ptr)); cvSubRS(val_ptr, *CVSCALAR(self), CVARR(dest), MASK(mask)); } catch (cv::Exception& e) { raise_cverror(e); } return dest; } else { CvScalar *src = CVSCALAR(self); CvScalar scl = VALUE_TO_CVSCALAR(val); return new_object(cvScalar(src->val[0] - scl.val[0], src->val[1] - scl.val[1], src->val[2] - scl.val[2], src->val[3] - scl.val[3])); } } /* * call-seq: * to_s -> "" * * Return values by String. */ VALUE rb_to_s(VALUE self) { const int i = 6; VALUE str[i]; str[0] = rb_str_new2("<%s:%g,%g,%g,%g>"); str[1] = rb_str_new2(rb_class2name(CLASS_OF(self))); str[2] = rb_aref(self, INT2FIX(0)); str[3] = rb_aref(self, INT2FIX(1)); str[4] = rb_aref(self, INT2FIX(2)); str[5] = rb_aref(self, INT2FIX(3)); return rb_f_sprintf(i, str); } /* * call-seq: * to_ary -> [self[0],self[1],self[2],self[3]] * * Return values by Array. */ VALUE rb_to_ary(VALUE self) { return rb_ary_new3(4, rb_aref(self, INT2FIX(0)), rb_aref(self, INT2FIX(1)), rb_aref(self, INT2FIX(2)), rb_aref(self, INT2FIX(3))); } VALUE new_object() { VALUE object = rb_allocate(rb_klass); *CVSCALAR(object) = cvScalar(0); return object; } VALUE new_object(CvScalar scalar) { VALUE object = rb_allocate(rb_klass); *CVSCALAR(object) = scalar; return object; } __NAMESPACE_END_CVSCALAR __NAMESPACE_END_OPENCV