Update the changelog
[opencv] / interfaces / matlab / src / funcs.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 #include "funcs.h"
43
44 //-----------------------------------------------------------------------------
45
46 std::string get_string( const mxArray *mxArr )
47 {
48         int l = mxGetN(mxArr);
49         char* buf = new char[l + 2];
50         mxGetString(mxArr, buf, l + 1);
51         std::string s(buf);
52         delete[] buf;
53         return s;
54 }
55
56 //------------------------------------------------------------------------------
57 //                                verifyDepth
58 //
59 void verifyDepth( mxClassID classID, bool bAnyDepth, int &depth )
60 {
61         int _depth = depth;
62         switch( classID )
63         {
64                 case mxUINT8_CLASS:
65                         depth = IPL_DEPTH_8U;
66                         break;
67                 case mxUINT16_CLASS:
68                         depth = IPL_DEPTH_16U;
69                         break;
70                 case mxSINGLE_CLASS:
71                         depth = IPL_DEPTH_32F;
72                         break;
73                 case mxINT8_CLASS:
74                         depth = IPL_DEPTH_8S;
75                         break;
76                 case mxINT16_CLASS:
77                         depth = IPL_DEPTH_16S;
78                         break;
79                 case mxINT32_CLASS:
80                         depth = IPL_DEPTH_32S;
81                         break;
82                 default:
83                         throw_error( "Unsupported image format." );
84                         return;
85                         break;
86         }
87         if( !bAnyDepth && depth != _depth )
88         {
89                 throw_error( "Incorrect image type." );
90                 return;
91         }
92 }
93
94 //------------------------------------------------------------------------------
95 //                                verifyArray
96 //
97 void verifyArray( mxArray *mxArr, int *dims, int &ndim, bool bAllowEmpty,
98                                   bool bAnyClass, mxClassID &classID )
99 {
100         bool bEmpty = mxIsEmpty( mxArr );
101         if( !bAllowEmpty && bEmpty )
102         {
103                 throw_error( "Array should be not empty." );
104                 return;
105         }
106         
107         if( bEmpty )
108         {
109                 if( ndim <= 0 )
110                 {
111                         ndim = mxGetNumberOfDimensions( mxArr );
112                 }
113                 int dim = 0;
114                 for( dim = 0; dim < ndim; dim++ )
115                 {
116                         if( dims[dim] < 0 )
117                         {
118                                 dims[dim] = 0;
119                         }
120                 }
121                 return;
122         }
123         
124         mxClassID _classID = classID;
125         classID    = mxGetClassID( mxArr );
126         if( !bAnyClass && classID != _classID )
127         {
128                 throw_error( "Incorrect array type." );
129                 return;
130         }
131         
132         int _ndim = ndim;
133         ndim      = mxGetNumberOfDimensions( mxArr );
134         if( _ndim > 0 && ndim != _ndim )
135         {
136                 std::ostringstream ostr;
137                 ostr << "Incorrect array size. " <<
138                         "Array should have " << _ndim << " dimensions.";
139                 throw_error( ostr.str() );
140                 return;
141         }
142         const int *_dims = mxGetDimensions( mxArr );
143         int dim = 0;
144         for( dim = 0; dim < ndim; dim++ )
145         {
146                 if( dims[dim] > 0 && dims[dim] != _dims[dim] )
147                 {
148                         std::ostringstream ostr;
149                         ostr << "Incorrect array size. " <<
150                                 "Dimension: " << (dim + 1) << ".";
151                         throw_error( ostr.str() );
152                         return;
153                 }
154                 dims[dim] = _dims[dim];
155         } // for each dimension
156 }
157
158 //------------------------------------------------------------------------------
159 //                                verifyMatrix
160 //
161 void verifyMatrix( mxArray *mxArr, int &rows, int &cols, bool bAllowEmpty,
162                                   bool bAnyClass, mxClassID &classID )
163 {
164         int ndim = 2;
165         int dims[2];
166         dims[0] = rows;
167         dims[1] = cols;
168         verifyArray( mxArr, dims, ndim, bAllowEmpty, bAnyClass, classID );
169         rows = dims[0];
170         cols = dims[1];
171 }
172
173 //------------------------------------------------------------------------------
174 //                                verifyVector
175 //
176 void verifyVector( mxArray *mxArr, int &num, VecType &type, bool bAllowEmpty,
177                                    bool bAnyClass, mxClassID &classID )
178 {
179         bool bEmpty = mxIsEmpty( mxArr );
180         if( !bAllowEmpty && bEmpty )
181         {
182                 throw_error( "Vector should be not empty." );
183                 return;
184         }
185         
186         if( bEmpty )
187         {
188                 if( num < 0 )
189                 {
190                         num = 0;
191                 }
192                 return;
193         }
194         
195         mxClassID _classID = classID;
196         classID    = mxGetClassID( mxArr );
197         if( !bAnyClass && classID != _classID )
198         {
199                 throw_error( "Incorrect vector type." );
200                 return;
201         }
202         
203         const int *dims = mxGetDimensions( mxArr );
204         if( type == any )
205         {
206                 type = ( dims[0] > dims[1] ) ? col : row;
207         }
208         
209         int _num = num;
210         num = mxGetNumberOfElements( mxArr );
211         if( _num > 0 && _num != num )
212         {
213                 std::ostringstream ostr;
214                 ostr << "Incorrect vector size. " <<
215                         "Vector should have " << _num << " element(s).";
216                 throw_error( ostr.str() );
217                 return;
218         }
219
220         if( mxGetNumberOfDimensions( mxArr ) != 2 ||
221                 ( type == row && dims[0] != 1 ) ||
222                 ( type == col && dims[1] != 1 ) )
223         {
224                 std::ostringstream ostr;
225                 ostr << "Should be " << (( type == row ) ? "row" : "column") <<
226                         " vector.";
227                 throw_error( ostr.str() );
228                 return;
229         }
230 }
231
232 //------------------------------------------------------------------------------
233 //                                verifySeq
234 //
235 void verifySeq( mxArray *mxArr, int maxIndex, int index,
236                                 mxClassID &dataClass, void *&dataPtr, int &dataNum,
237                                 CvRect &rect, int &type,
238                                 int &h_prev, int &h_next, int &v_prev, int &v_next )
239 {
240         if( index >= maxIndex || index < 0 )
241         {
242                 throw_error( "Invalid index." );
243                 return;
244         }
245         mxArray *mxFdata   = mxGetField( mxArr, index, "data" );
246         mxArray *mxFrect   = mxGetField( mxArr, index, "rect" );
247         mxArray *mxFtype   = mxGetField( mxArr, index, "type" );
248         mxArray *mxFh_prev = mxGetField( mxArr, index, "h_prev" );
249         mxArray *mxFh_next = mxGetField( mxArr, index, "h_next" );
250         mxArray *mxFv_prev = mxGetField( mxArr, index, "v_prev" );
251         mxArray *mxFv_next = mxGetField( mxArr, index, "v_next" );
252
253         /* data */
254         if( !mxFdata || mxIsEmpty( mxFdata ) || 
255                 mxGetNumberOfDimensions( mxFdata ) != 2 ||
256                 !mxIsNumeric( mxFdata ) )
257         {
258                 std::ostringstream ostr;
259                 ostr << "Invalid 'data' field in struct number " << index
260                          << ". It should be n by 2 numeric array.";
261                 throw_error( ostr.str() );
262                 return;
263         }
264         dataClass = mxGetClassID( mxFdata );
265         dataPtr   = (void *)mxGetData( mxFdata );
266         dataNum   = mxGetM( mxFdata );
267         
268         /* rect */
269         if( !mxFrect || mxIsEmpty( mxFrect ) || 
270                 mxGetNumberOfDimensions( mxFrect ) != 2 ||
271                 !mxIsNumeric( mxFrect ) || mxGetM( mxFrect ) != 1 ||
272                 mxGetN( mxFrect ) != 4 )
273         {
274                 std::ostringstream ostr;
275                 ostr << "Invalid 'rect' field in struct number " << index
276                          << ". It should be 1 by 4 numeric array.";
277                 throw_error( ostr.str() );
278                 return;
279         }
280         MXTYPE_DATAPTR( mxGetClassID( mxFrect ), ;, rectData, mxGetData( mxFrect );
281                 castCopy( rectData, (int *)(&rect), 1, 4, 1, 1, 1, 1 ); );
282
283         /* type */
284         if( !mxFtype || mxIsEmpty( mxFtype ) || 
285                 mxGetNumberOfDimensions( mxFtype ) != 2 ||
286                 !mxIsNumeric( mxFtype ) || mxGetM( mxFtype ) != 1 ||
287                 mxGetN( mxFtype ) != 1 )
288         {
289                 std::ostringstream ostr;
290                 ostr << "Invalid 'type' field in struct number " << index
291                          << ". It should be 1 by 1 numeric array.";
292                 throw_error( ostr.str() );
293                 return;
294         }
295         MXTYPE_DATAPTR( mxGetClassID( mxFtype ), ;, typeData, mxGetData( mxFtype );
296                 castCopy( typeData, (int *)(&type), 1, 1, 1, 1, 1, 1 ); );
297
298         /* h_prev */
299         if( !mxFh_prev || mxIsEmpty( mxFh_prev ) || 
300                 mxGetNumberOfDimensions( mxFh_prev ) != 2 ||
301                 !mxIsNumeric( mxFh_prev ) || mxGetM( mxFh_prev ) != 1 ||
302                 mxGetN( mxFh_prev ) != 1 )
303         {
304                 std::ostringstream ostr;
305                 ostr << "Invalid 'h_prev' field in struct number " << index
306                          << ". It should be 1 by 1 numeric array.";
307                 throw_error( ostr.str() );
308                 return;
309         }
310         MXTYPE_DATAPTR( mxGetClassID( mxFh_prev ), ;, 
311                 h_prevData, mxGetData( mxFh_prev );
312                 castCopy( h_prevData, (int *)(&h_prev), 1, 1, 1, 1, 1, 1 ); );
313         if( h_prev > maxIndex || h_prev < 0 )
314         {
315                 std::ostringstream ostr;
316                 ostr << "Invalid 'h_prev' value in struct number " << index
317                          << ".";
318                 throw_error( ostr.str() );
319                 return;
320         }
321
322         /* h_next */
323         if( !mxFh_next || mxIsEmpty( mxFh_next ) || 
324                 mxGetNumberOfDimensions( mxFh_next ) != 2 ||
325                 !mxIsNumeric( mxFh_next ) || mxGetM( mxFh_next ) != 1 ||
326                 mxGetN( mxFh_next ) != 1 )
327         {
328                 std::ostringstream ostr;
329                 ostr << "Invalid 'h_next' field in struct number " << index
330                          << ". It should be 1 by 1 numeric array.";
331                 throw_error( ostr.str() );
332                 return;
333         }
334         MXTYPE_DATAPTR( mxGetClassID( mxFh_next ), ;, 
335                 h_nextData, mxGetData( mxFh_next );
336                 castCopy( h_nextData, (int *)(&h_next), 1, 1, 1, 1, 1, 1 ); );
337         if( h_next > maxIndex || h_next < 0 )
338         {
339                 std::ostringstream ostr;
340                 ostr << "Invalid 'h_next' value in struct number " << index
341                          << ".";
342                 throw_error( ostr.str() );
343                 return;
344         }
345
346         /* v_prev */
347         if( !mxFv_prev || mxIsEmpty( mxFv_prev ) || 
348                 mxGetNumberOfDimensions( mxFv_prev ) != 2 ||
349                 !mxIsNumeric( mxFv_prev ) || mxGetM( mxFv_prev ) != 1 ||
350                 mxGetN( mxFv_prev ) != 1 )
351         {
352                 std::ostringstream ostr;
353                 ostr << "Invalid 'v_prev' field in struct number " << index
354                          << ". It should be 1 by 1 numeric array.";
355                 throw_error( ostr.str() );
356                 return;
357         }
358         MXTYPE_DATAPTR( mxGetClassID( mxFv_prev ), ;, 
359                 v_prevData, mxGetData( mxFv_prev );
360                 castCopy( v_prevData, (int *)(&v_prev), 1, 1, 1, 1, 1, 1 ); );
361         if( v_prev > maxIndex || v_prev < 0 )
362         {
363                 std::ostringstream ostr;
364                 ostr << "Invalid 'v_prev' value in struct number " << index
365                          << ".";
366                 throw_error( ostr.str() );
367                 return;
368         }
369
370         /* v_next */
371         if( !mxFv_next || mxIsEmpty( mxFv_next ) || 
372                 mxGetNumberOfDimensions( mxFv_next ) != 2 ||
373                 !mxIsNumeric( mxFv_next ) || mxGetM( mxFv_next ) != 1 ||
374                 mxGetN( mxFv_next ) != 1 )
375         {
376                 std::ostringstream ostr;
377                 ostr << "Invalid 'v_next' field in struct number " << index
378                          << ". It should be 1 by 1 numeric array.";
379                 throw_error( ostr.str() );
380                 return;
381         }
382         MXTYPE_DATAPTR( mxGetClassID( mxFv_next ), ;, 
383                 v_nextData, mxGetData( mxFv_next );
384                 castCopy( v_nextData, (int *)(&v_next), 1, 1, 1, 1, 1, 1 ); );
385         if( v_next > maxIndex || v_next < 0 )
386         {
387                 std::ostringstream ostr;
388                 ostr << "Invalid 'v_next' value in struct number " << index
389                          << ".";
390                 throw_error( ostr.str() );
391                 return;
392         }
393 }