Update to 2.0.0 tree from current Fremantle build
[opencv] / interfaces / swig / octave / octhelpers.cpp
1 #include "octhelpers.h"
2 #include <iostream>
3 #include <sstream>
4
5 int OctSwigObject_Check(octave_value op);
6
7 octave_value OctTuple_FromIntArray(int * arr, int len){
8   octave_value obj = OctTuple_New(len);
9   for(int i=0; i<len; i++){
10     OctTuple_SetItem(obj, i, OctLong_FromLong( arr[i] ) );
11   }
12   return obj;
13 }
14
15 octave_value SWIG_SetResult(octave_value result, octave_value obj){
16   result = OctTuple_New(1);
17   OctTuple_SetItem(result, 0, obj);
18   return result;
19 }
20
21 octave_value_list* SWIG_AppendResult(octave_value_list* result, octave_value* to_add, int num){
22   for (int j=0;j<num;++j)
23     result->append(to_add[j]);
24   return result;
25 }
26
27 template <typename T>
28 std::ostream & cv_arr_write(std::ostream & out, T * data, int rows, int nch, int step){
29   int i,j,k;
30   char * cdata = (char *) data;
31   std::string chdelim1="", chdelim2="";
32
33   // only output channel parens if > 1
34   if(nch>1){
35     chdelim1="(";
36     chdelim2=")";
37   }
38
39   out<<"[\n";
40   for(i=0; i<rows; i++){
41     out<<"[";
42
43     // first element
44     out<<chdelim1;
45     out<<double(((T*)(cdata+i*step))[0]);
46     for(k=1; k<nch; k++){
47       out<<", "<<double(((T*)(cdata+i*step))[k]);
48     }
49     out<<chdelim2;
50
51     // remaining elements
52     for(j=nch*sizeof(T); j<step; j+=(nch*sizeof(T))){
53       out<<", "<<chdelim1;
54       out<<double(((T*)(cdata+i*step+j))[0]);
55       for(k=1; k<nch; k++){
56         out<<", "<<double(((T*)(cdata+i*step+j))[k]);
57       }
58       out<<chdelim2;
59     }
60     out<<"]\n";
61   }
62   out<<"]";
63   return out;
64 }
65
66 void cvArrPrint(CvArr * arr){
67   CV_FUNCNAME( "cvArrPrint" );
68             
69   __BEGIN__;
70   CvMat * mat;
71   CvMat stub;
72
73   mat = cvGetMat(arr, &stub);
74
75   int cn = CV_MAT_CN(mat->type);
76   int depth = CV_MAT_DEPTH(mat->type);
77   int step = MAX(mat->step, cn*mat->cols*CV_ELEM_SIZE(depth));
78   std::ostringstream str;
79
80   switch(depth){
81   case CV_8U:
82     cv_arr_write(str, (uchar *)mat->data.ptr, mat->rows, cn, step);
83     break;
84   case CV_8S:
85     cv_arr_write(str, (char *)mat->data.ptr, mat->rows, cn, step);
86     break;
87   case CV_16U:
88     cv_arr_write(str, (ushort *)mat->data.ptr, mat->rows, cn, step);
89     break;
90   case CV_16S:
91     cv_arr_write(str, (short *)mat->data.ptr, mat->rows, cn, step);
92     break;
93   case CV_32S:
94     cv_arr_write(str, (int *)mat->data.ptr, mat->rows, cn, step);
95     break;
96   case CV_32F:
97     cv_arr_write(str, (float *)mat->data.ptr, mat->rows, cn, step);
98     break;
99   case CV_64F:
100     cv_arr_write(str, (double *)mat->data.ptr, mat->rows, cn, step);
101     break;
102   default:
103     CV_ERROR( CV_StsError, "Unknown element type");
104     break;
105   }
106   std::cout<<str.str()<<std::endl;
107
108   __END__;
109 }
110
111 // deal with negative array indices
112 int OctLong_AsIndex( octave_value idx_object, int len ){
113   int idx = OctLong_AsLong( idx_object );
114   if(idx<0) return len+idx;
115   return idx;
116 }
117
118 CvRect OctSlice_to_CvRect(CvArr * src, octave_value idx_object){
119   CvSize sz = cvGetSize(src);
120   //printf("Size %dx%d\n", sz.height, sz.width);
121   int lower[2], upper[2];
122   Oct_ssize_t len, start, stop, step, slicelength;
123
124   if(OctInt_Check(idx_object) || OctLong_Check(idx_object)){
125     // if array is a row vector, assume index into columns
126     if(sz.height>1){
127       lower[0] = OctLong_AsIndex( idx_object, sz.height );
128       upper[0] = lower[0] + 1;
129       lower[1] = 0;
130       upper[1] = sz.width;
131     }
132     else{
133       lower[0] = 0;
134       upper[0] = sz.height;
135       lower[1] = OctLong_AsIndex( idx_object, sz.width );
136       upper[1] = lower[1]+1;
137     }
138   }
139
140   // 1. Slice
141   else if(OctSlice_Check(idx_object)){
142     len = sz.height;
143     if(OctSlice_GetIndicesEx( idx_object, len, &start, &stop, &step, &slicelength )!=0){
144       error("Error in OctSlice_GetIndicesEx: returning NULL");
145       return cvRect(0,0,0,0);
146     }
147     // if array is a row vector, assume index bounds are into columns
148     if(sz.height>1){
149       lower[0] = (int) start; // use c convention of start index = 0
150       upper[0] = (int) stop;    // use c convention
151       lower[1] = 0;
152       upper[1] = sz.width;
153     }
154     else{
155       lower[1] = (int) start; // use c convention of start index = 0
156       upper[1] = (int) stop;    // use c convention
157       lower[0] = 0;
158       upper[0] = sz.height;
159     }
160   }
161
162   // 2. Tuple
163   else if(OctTuple_Check(idx_object)){
164     //printf("OctTuple{\n");
165     if(OctObject_Length(idx_object)!=2){
166       error("Expected a sequence with 2 elements");
167       return cvRect(0,0,0,0);
168     }
169     for(int i=0; i<2; i++){
170       octave_value o = OctTuple_GetItem(idx_object, i);
171
172       // 2a. Slice -- same as above
173       if(OctSlice_Check(o)){
174         //printf("OctSlice\n");
175         len = (i==0 ? sz.height : sz.width);
176         if(OctSlice_GetIndicesEx(o, len, &start, &stop, &step, &slicelength )!=0){
177           error("Error in OctSlice_GetIndicesEx: returning NULL");
178           return cvRect(0,0,0,0);
179         }
180         //printf("OctSlice_GetIndecesEx(%d, %d, %d, %d, %d)\n", len, start, stop, step, slicelength);
181         lower[i] = start;
182         upper[i] = stop;
183
184       }
185
186       // 2b. Integer
187       else if(OctInt_Check(o) || OctLong_Check(o)){
188         //printf("OctInt\n");
189         lower[i] = OctLong_AsIndex(o, i==0 ? sz.height : sz.width);
190         upper[i] = lower[i]+1;
191       }
192
193       else {
194         error("Expected a slice or int as sequence item: returning NULL");
195         return cvRect(0,0,0,0);
196       }
197     }
198   }
199
200   else {
201     error("Expected a slice or sequence: returning NULL");
202     return cvRect(0,0,0,0);
203   }
204
205   return cvRect(lower[1], lower[0], upper[1]-lower[1], upper[0]-lower[0]);
206 }
207
208 double OctObject_AsDouble(octave_value obj){
209   if(OctNumber_Check(obj)){
210     if(OctFloat_Check(obj)){
211       return OctFloat_AsDouble(obj);
212     }
213     else if(OctInt_Check(obj) || OctLong_Check(obj)){
214       return (double) OctLong_AsLong(obj);
215     }
216   }
217   error("Could not convert octave object to Double");
218   return -1;
219 }
220
221 long OctObject_AsLong(octave_value obj){
222   if(OctNumber_Check(obj)){
223     if(OctFloat_Check(obj)){
224       return (long) OctFloat_AsDouble(obj);
225     }
226     else if(OctInt_Check(obj) || OctLong_Check(obj)){
227       return OctLong_AsLong(obj);
228     }
229   }
230   error("Could not convert octave object to Long");
231   return -1;
232 }
233
234 // standard python container routines, adapted to octave
235
236 // * should matrix conversions happen here or at typemap layer? or both
237
238 bool OctNumber_Check(const octave_value& ov) {
239   return ov.is_scalar_type();
240 }
241
242 octave_value OctBool_FromLong (long v) {
243   return !!v;
244 }
245
246 bool OctInt_Check(const octave_value& ov) {
247   return ov.is_integer_type();
248 }
249
250 long OctInt_AsLong (const octave_value& ov) {
251   return ov.long_value();
252 }
253
254 octave_value OctInt_FromLong (long v) {
255   return v;
256 }
257
258 bool OctLong_Check(const octave_value& ov) {
259   return ov.is_scalar_type();
260 }
261
262 long OctLong_AsLong(const octave_value& ov) {
263   return ov.long_value();
264 }
265
266 octave_value OctLong_FromLong(long v) {
267   return v;
268 }
269
270 octave_value OctLong_FromUnsignedLong(unsigned long v) {
271   return v;
272 }
273
274 bool OctFloat_Check(const octave_value& ov) {
275   return ov.is_scalar_type();
276 }
277
278 octave_value OctFloat_FromDouble(double v) {
279   return v;
280 }
281
282 double OctFloat_AsDouble (const octave_value& ov) {
283   return ov.scalar_value();
284 }
285
286 octave_value OctSequence_New(int n) {
287   return n ? Cell(1,n) : Cell(dim_vector(0,0));
288 }
289
290 bool OctSequence_Check(const octave_value& ov) {
291   return ov.is_cell();
292 }
293
294 int OctSequence_Size(const octave_value& ov) {
295   Cell c(ov.cell_value());
296   return ov.cell_value().numel();
297 }
298
299 octave_value OctSequence_GetItem(const octave_value& ov,int i) {
300   Cell c(ov.cell_value());
301   if (i<0||i>=c.numel()) {
302     error("index out of bounds");
303     return octave_value();
304   }
305   return c(i);
306 }
307
308 void OctSequence_SetItem(octave_value& ov,int i,const octave_value& v) {
309   Cell c(ov.cell_value());
310   if (i<0||i>=c.numel())
311     error("index out of bounds");
312   else {
313     c(i)=v;
314     ov=c;
315   }
316 }
317
318 octave_value OctTuple_New(int n) {
319   return OctSequence_New(n);
320 }
321
322 bool OctTuple_Check(const octave_value& ov) {
323   return OctSequence_Check(ov);
324 }
325
326 int OctTuple_Size(const octave_value& ov) {
327   return OctSequence_Size(ov);
328 }
329
330 void OctTuple_SetItem(octave_value& ov,int i,const octave_value& v) {
331   OctSequence_SetItem(ov,i,v);
332 }
333
334 octave_value OctTuple_GetItem(const octave_value& ov,int i) {
335   return OctSequence_GetItem(ov,i);
336 }
337
338 octave_value OctList_New(int n) {
339   return OctSequence_New(n);
340 }
341
342 bool OctList_Check(const octave_value& ov) {
343   return OctSequence_Check(ov);
344 }
345
346 int OctList_Size(const octave_value& ov) {
347   return OctSequence_Size(ov);
348 }
349
350 void OctList_SetItem(octave_value& ov,int i,const octave_value& v) {
351   OctSequence_SetItem(ov,i,v);
352 }
353
354 octave_value OctList_GetItem(const octave_value& ov,int i) {
355   return OctSequence_GetItem(ov,i);
356 }
357
358 bool OctSlice_Check(const octave_value& ov) {
359   return false; // todo have these map to range and magic-colon types
360 }
361
362 int OctObject_Length(const octave_value& ov) {
363   return 0;
364 }
365
366 bool OctSlice_GetIndicesEx(const octave_value& ov, Oct_ssize_t len, Oct_ssize_t* start, Oct_ssize_t* stop, Oct_ssize_t* step, Oct_ssize_t* slicelength ) {
367   return false;
368 }