[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

vigra/matlab.hxx |

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*                  Copyright 2008 by Ullrich Koethe                    */
    00004 /*                                                                      */
    00005 /*    This file is part of the VIGRA computer vision library.           */
    00006 /*    The VIGRA Website is                                              */
    00007 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
    00008 /*    Please direct questions, bug reports, and contributions to        */
    00009 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
    00010 /*        vigra@informatik.uni-hamburg.de                               */
    00011 /*                                                                      */
    00012 /*    Permission is hereby granted, free of charge, to any person       */
    00013 /*    obtaining a copy of this software and associated documentation    */
    00014 /*    files (the "Software"), to deal in the Software without           */
    00015 /*    restriction, including without limitation the rights to use,      */
    00016 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
    00017 /*    sell copies of the Software, and to permit persons to whom the    */
    00018 /*    Software is furnished to do so, subject to the following          */
    00019 /*    conditions:                                                       */
    00020 /*                                                                      */
    00021 /*    The above copyright notice and this permission notice shall be    */
    00022 /*    included in all copies or substantial portions of the             */
    00023 /*    Software.                                                         */
    00024 /*                                                                      */
    00025 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
    00026 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
    00027 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
    00028 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
    00029 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
    00030 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
    00031 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
    00032 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
    00033 /*                                                                      */
    00034 /************************************************************************/
    00035
    00036
    00037 #ifndef VIGRA_MATLAB_HXX
    00038 #define VIGRA_MATLAB_HXX
    00039
    00040 #include <string>
    00041 #include <mex.h>
    00042 #include "array_vector.hxx"
    00043 #include "sized_int.hxx"
    00044 #include "matrix.hxx"
    00045 #include <map>
    00046 #include <time.h>
    00047 #include "matlab_FLEXTYPE.hxx"
    00048
    00049 namespace vigra {
    00050
    00051 namespace matlab {
    00052
    00053 template <class T>
    00054 struct ValueType;
    00055
    00056 #define VIGRA_MATLAB_VALUETYPE_UTIL(type, functionName, typeID, matTypeName) \
    00057 template <> \
    00058 struct ValueType<type> \
    00059 { \
    00060     static bool check(mxArray const * t) \
    00061     { \
    00062         return mxIs##functionName(t); \
    00063     } \
    00064     \
    00065     static mxClassID const classID = typeID; \
    00066     \
    00067     static std::string typeName() \
    00068     { \
    00069         return #matTypeName; \
    00070     } \
    00071 };
    00072
    00073 VIGRA_MATLAB_VALUETYPE_UTIL(double, Double, mxDOUBLE_CLASS, double)
    00074 VIGRA_MATLAB_VALUETYPE_UTIL(float, Single, mxSINGLE_CLASS, single)
    00075 VIGRA_MATLAB_VALUETYPE_UTIL(Int8,  Int8, mxINT8_CLASS, int8)
    00076 VIGRA_MATLAB_VALUETYPE_UTIL(UInt8,  Uint8, mxUINT8_CLASS, uint8)
    00077 VIGRA_MATLAB_VALUETYPE_UTIL(Int16, Int16, mxINT16_CLASS, int16)
    00078 VIGRA_MATLAB_VALUETYPE_UTIL(UInt16, Uint16, mxUINT16_CLASS, uint16)
    00079
    00080 #if VIGRA_BITSOF_INT == 32
    00081 VIGRA_MATLAB_VALUETYPE_UTIL(int, Int32, mxINT32_CLASS, int32)
    00082 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned int, Uint32, mxUINT32_CLASS, uint32)
    00083 #elif VIGRA_BITSOF_INT == 64
    00084 VIGRA_MATLAB_VALUETYPE_UTIL(int, Int64, mxINT64_CLASS, int64)
    00085 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned int, Uint64, mxUINT64_CLASS, uint64)
    00086 #endif
    00087
    00088 #if VIGRA_BITSOF_LONG == 32
    00089 VIGRA_MATLAB_VALUETYPE_UTIL(long, Int32, mxINT32_CLASS, int32)
    00090 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long, Uint32, mxUINT32_CLASS, uint32)
    00091 #elif VIGRA_BITSOF_LONG == 64
    00092 VIGRA_MATLAB_VALUETYPE_UTIL(long, Int64, mxINT64_CLASS, int64)
    00093 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long, Uint64, mxUINT64_CLASS, uint64)
    00094 #endif
    00095
    00096 #if VIGRA_BITSOF_LONG_LONG == 32
    00097 VIGRA_MATLAB_VALUETYPE_UTIL(long long, Int32, mxINT32_CLASS, int32)
    00098 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long long, Uint32, mxUINT32_CLASS, uint32)
    00099 #elif VIGRA_BITSOF_LONG_LONG == 64
    00100 VIGRA_MATLAB_VALUETYPE_UTIL(long long, Int64, mxINT64_CLASS, int64)
    00101 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long long, Uint64, mxUINT64_CLASS, uint64)
    00102 #endif
    00103
    00104 #undef VIGRA_MATLAB_VALUETYPE_UTIL
    00105
    00106 class ConstStructArray
    00107 {
    00108   protected:
    00109     mxArray * matPointer_;
    00110
    00111   public:
    00112
    00113     struct Proxy
    00114     {
    00115         mxArray * matPointer_;
    00116         int index_;
    00117
    00118         Proxy(mxArray * matPointer, int index)
    00119         : matPointer_(matPointer),
    00120           index_(index)
    00121         {}
    00122
    00123         operator const mxArray *() const
    00124         {
    00125             return mxGetFieldByNumber(matPointer_, 0, index_);
    00126         }
    00127     };
    00128
    00129     ConstStructArray(const mxArray * matPointer = 0)
    00130     : matPointer_(const_cast<mxArray *>(matPointer))
    00131     {
    00132         if(matPointer != 0 && !mxIsStruct(matPointer))
    00133             mexErrMsgTxt("StructArray(mxArray *): Argument must be a Matlab struct array.");
    00134     }
    00135
    00136     Proxy operator[](const char * field_name) const
    00137     {
    00138         if(matPointer_ == 0)
    00139             mexErrMsgTxt("StructArray::operator[]: Cannot access uninitialized struct array.");
    00140
    00141         int i = mxGetFieldNumber(matPointer_, field_name);
    00142         if(i == -1)
    00143             mexErrMsgTxt("StructArray::operator[]: Unknown field name.");
    00144
    00145         return Proxy(matPointer_, i);
    00146     }
    00147
    00148     Proxy operator[](std::string field_name) const
    00149     {
    00150         return operator[](field_name.c_str());
    00151     }
    00152
    00153     bool isValid() const
    00154     {
    00155         return matPointer_ != 0;
    00156     }
    00157
    00158     bool isValid(const char * field_name) const
    00159     {
    00160         return isValid() && mxGetFieldNumber(matPointer_, field_name) != -1;
    00161     }
    00162
    00163     bool isValid(std::string field_name) const
    00164     {
    00165         return isValid(field_name.c_str());
    00166     }
    00167 };
    00168
    00169 class ConstCellArray
    00170 {
    00171   protected:
    00172     mxArray * matPointer_;
    00173     int size_;
    00174
    00175   public:
    00176
    00177     struct Proxy
    00178     {
    00179         mxArray * matPointer_;
    00180         int index_;
    00181
    00182         Proxy(mxArray * matPointer, int index)
    00183         : matPointer_(matPointer),
    00184           index_(index)
    00185         {}
    00186
    00187         operator const mxArray *() const
    00188         {
    00189             return mxGetCell(matPointer_, index_);
    00190         }
    00191     };
    00192
    00193     ConstCellArray(const mxArray * matPointer = 0)
    00194     : matPointer_(const_cast<mxArray *>(matPointer)),
    00195       size_(0)
    00196     {
    00197         if(matPointer != 0 && !mxIsCell(matPointer))
    00198             mexErrMsgTxt("CellArray(mxArray *): Argument must be a Matlab cell array.");
    00199         if(matPointer != 0)
    00200             size_ = mxGetNumberOfElements(matPointer);
    00201         else
    00202             size_ = -1;
    00203     }
    00204
    00205     Proxy operator[](int i) const
    00206     {
    00207         if(!isValid(i))
    00208             mexErrMsgTxt("CellArray::operator[]: Index out of range.");
    00209         return Proxy(matPointer_, i);
    00210     }
    00211
    00212     int size() const
    00213     {
    00214         return size_;
    00215     }
    00216
    00217     bool isValid( int i ) const
    00218     {
    00219         return i >= 0 && i < size_;
    00220     }
    00221
    00222 };
    00223
    00224 class CellArray
    00225 : public ConstCellArray
    00226 {
    00227   public:
    00228
    00229     struct Proxy
    00230     : public ConstCellArray::Proxy
    00231     {
    00232         Proxy(mxArray * matPointer, int index)
    00233         : ConstCellArray::Proxy(matPointer, index)
    00234         {}
    00235
    00236         void operator=(mxArray * v)
    00237         {
    00238             mxDestroyArray(mxGetCell(matPointer_, index_));
    00239             mxSetCell(matPointer_, index_, v);
    00240         }
    00241     };
    00242
    00243     CellArray(const mxArray * matPointer)
    00244     : ConstCellArray(matPointer)
    00245     {}
    00246
    00247     Proxy operator[](int i)
    00248     {
    00249         if(!isValid(i))
    00250             mexErrMsgTxt("CellArray::operator[]: Index out of range.");
    00251         return Proxy(matPointer_, i);
    00252     }
    00253
    00254     ConstCellArray::Proxy operator[](int i) const
    00255     {
    00256         if(!isValid(i))
    00257             mexErrMsgTxt("CellArray::operator[]: Index out of range.");
    00258         return ConstCellArray::Proxy(matPointer_, i);
    00259     }
    00260 };
    00261
    00262
    00263
    00264
    00265
    00266 template <class T, unsigned int SIZE>
    00267 TinyVectorView<T, SIZE>
    00268 getTinyVector(mxArray const * t)
    00269 {
    00270     if(!ValueType<T>::check(t))
    00271     {
    00272         std::string msg = std::string("Input array must have type ") +
    00273                           ValueType<T>::typeName() + ".";
    00274         mexErrMsgTxt(msg.c_str());
    00275     }
    00276     if(SIZE != mxGetNumberOfElements(t))
    00277     {
    00278         mexErrMsgTxt("getTinyVector(): Input array has wrong number of elements.");
    00279     }
    00280
    00281     return TinyVectorView<T, SIZE>((T *)mxGetData(t));
    00282 }
    00283
    00284 template <unsigned int SIZE>
    00285 typename MultiArrayShape<SIZE>::type
    00286 getShape(mxArray const * t)
    00287 {
    00288     if(!ValueType<Int32>::check(t))
    00289     {
    00290         std::string msg = std::string("Input array must have type 'int32'.");
    00291         mexErrMsgTxt(msg.c_str());
    00292     }
    00293     if(SIZE != mxGetNumberOfElements(t))
    00294     {
    00295         mexErrMsgTxt("getShape(): Input array has wrong number of elements.");
    00296     }
    00297     TinyVectorView<Int32, SIZE> res((MultiArrayIndex *)mxGetData(t));
    00298     return typename MultiArrayShape<SIZE>::type(res);
    00299 }
    00300
    00301 template <int DIM, class T>
    00302 MultiArrayView<DIM, T>
    00303 getMultiArray(mxArray const * t)
    00304 {
    00305     typedef typename MultiArrayView<DIM, T>::difference_type Shape;
    00306
    00307     if(!ValueType<T>::check(t))
    00308     {
    00309         std::string msg = std::string("getMultiArray(): Input array must have type ") +
    00310                           ValueType<T>::typeName() + ".";
    00311         mexErrMsgTxt(msg.c_str());
    00312     }
    00313
    00314     Shape shape;
    00315     if(DIM > 1)
    00316     {
    00317         int mdim = mxGetNumberOfDimensions(t);
    00318         if(DIM < mdim)
    00319         {
    00320             mexErrMsgTxt("getMultiArray(): Input array has too many dimensions.");
    00321         }
    00322         const mwSize * matlabShape = mxGetDimensions(t);
    00323         for(int k=0; k<mdim; ++k)
    00324         {
    00325             shape[k] = static_cast<typename Shape::value_type>(matlabShape[k]);
    00326         }
    00327         for(int k=mdim; k<DIM; ++k)
    00328         {
    00329             shape[k] = 1;
    00330         }
    00331     }
    00332     else
    00333     {
    00334         shape[0] = static_cast<typename Shape::value_type>(mxGetNumberOfElements(t));
    00335     }
    00336     return MultiArrayView<DIM, T>(shape, (T *)mxGetData(t));
    00337 }
    00338
    00339 template <int DIM, class T>
    00340 MultiArrayView<DIM, T>
    00341 createMultiArray(typename MultiArrayShape<DIM>::type const & shape, mxArray * & t)
    00342 {
    00343     mwSize matlabShape[DIM];
    00344     for(int k=0; k<DIM; ++k)
    00345         matlabShape[k] = static_cast<mwSize>(shape[k]);
    00346     t = mxCreateNumericArray(DIM, matlabShape, ValueType<T>::classID, mxREAL);
    00347
    00348     return MultiArrayView<DIM, T>(shape, (T *)mxGetData(t));
    00349 }
    00350
    00351 template <int DIM, class T>
    00352 MultiArrayView<DIM, T>
    00353 createMultiArray(typename MultiArrayShape<DIM>::type const & shape, CellArray::Proxy t)
    00354 {
    00355     mwSize matlabShape[DIM];
    00356     for(int k=0; k<DIM; ++k)
    00357         matlabShape[k] = static_cast<mwSize>(shape[k]);
    00358     t = mxCreateNumericArray(DIM, matlabShape, ValueType<T>::classID, mxREAL);
    00359
    00360     return MultiArrayView<DIM, T>(shape, (T *)mxGetData(t));
    00361 }
    00362
    00363 template <class T>
    00364 inline MultiArrayView<1, T>
    00365 getArray(mxArray const * t)
    00366 {
    00367     return getMultiArray<1, T>(t);
    00368 }
    00369
    00370 template <class T>
    00371 inline MultiArrayView<1, T>
    00372 createArray(MultiArrayIndex size, mxArray * & t)
    00373 {
    00374     return createMultiArray<1, T>(MultiArrayShape<1>::type(size), t);
    00375 }
    00376
    00377 template <class T>
    00378 inline MultiArrayView<1, T>
    00379 createArray(MultiArrayIndex size, CellArray::Proxy t)
    00380 {
    00381     return createMultiArray<1, T>(MultiArrayShape<1>::type(size), t);
    00382 }
    00383
    00384 template <class T>
    00385 MultiArrayView<2, T>
    00386 getMatrix(mxArray const * t)
    00387 {
    00388     typedef typename MultiArrayView<2, T>::difference_type Shape;
    00389
    00390     if(!ValueType<T>::check(t))
    00391     {
    00392         std::string msg = std::string("getMatrix(): Input matrix must have type ") +
    00393                           ValueType<T>::typeName() + ".";
    00394         mexErrMsgTxt(msg.c_str());
    00395     }
    00396
    00397     if(2 != mxGetNumberOfDimensions(t))
    00398         mexErrMsgTxt("getMatrix(): Input matrix must have 2 dimensions.");
    00399
    00400     const mwSize * matlabShape = mxGetDimensions(t);
    00401     Shape shape(static_cast<MultiArrayIndex>(matlabShape[0]),
    00402                 static_cast<MultiArrayIndex>(matlabShape[1]));
    00403
    00404     return MultiArrayView<2, T>(shape, (T *)mxGetData(t));
    00405 }
    00406
    00407 template <class T>
    00408 MultiArrayView<2, T>
    00409 createMatrix(mwSize rowCount, mwSize columnCount, mxArray * & t)
    00410 {
    00411     typedef typename MultiArrayView<2, T>::difference_type Shape;
    00412
    00413     Shape shape(rowCount, columnCount);
    00414     t = mxCreateNumericMatrix(rowCount, columnCount, ValueType<T>::classID, mxREAL);
    00415
    00416     return MultiArrayView<2, T>(shape, (T *)mxGetData(t));
    00417 }
    00418
    00419 template <class T>
    00420 MultiArrayView<2, T>
    00421 createMatrix(mwSize rowCount, mwSize columnCount, CellArray::Proxy t)
    00422 {
    00423     typedef typename MultiArrayView<2, T>::difference_type Shape;
    00424
    00425     Shape shape(rowCount, columnCount);
    00426     t = mxCreateNumericMatrix(rowCount, columnCount, ValueType<T>::classID, mxREAL);
    00427
    00428     return MultiArrayView<2, T>(shape, (T *)mxGetData(t));
    00429 }
    00430
    00431 template <class T>
    00432 BasicImageView<T>
    00433 getImage(mxArray const * t)
    00434 {
    00435     if(!ValueType<T>::check(t))
    00436     {
    00437         std::string msg = std::string("getImage(): Input matrix must have type ") +
    00438                           ValueType<T>::typeName() + ".";
    00439         mexErrMsgTxt(msg.c_str());
    00440     }
    00441
    00442     if(2 != mxGetNumberOfDimensions(t))
    00443         mexErrMsgTxt("getImage(): Input matrix must have 2 dimensions.");
    00444
    00445     const mwSize * matlabShape = mxGetDimensions(t);
    00446     return BasicImageView<T>((T *)mxGetData(t), static_cast<int>(matlabShape[0]),
    00447                                                 static_cast<int>(matlabShape[1]));
    00448 }
    00449
    00450 template <class T>
    00451 BasicImageView<T>
    00452 createImage(mwSize width, mwSize height, mxArray * & t)
    00453 {
    00454     t = mxCreateNumericMatrix(width, height, ValueType<T>::classID, mxREAL);
    00455
    00456     return BasicImageView<T>((T *)mxGetData(t), width, height);
    00457 }
    00458
    00459 template <class T>
    00460 BasicImageView<T>
    00461 createImage(mwSize width, mwSize height, CellArray::Proxy t)
    00462 {
    00463     t = mxCreateNumericMatrix(width, height, ValueType<T>::classID, mxREAL);
    00464
    00465     return BasicImageView<T>((T *)mxGetData(t), width, height);
    00466 }
    00467
    00468 inline ConstCellArray
    00469 getCellArray(mxArray const * t)
    00470 {
    00471     return ConstCellArray(t);
    00472 }
    00473
    00474 inline CellArray
    00475 createCellArray(mwSize size, mxArray * & t)
    00476 {
    00477     mwSize matSize[] = { size };
    00478     t = mxCreateCellArray(1, matSize);
    00479
    00480     return CellArray(t);
    00481 }
    00482
    00483 inline CellArray
    00484 createCellArray(mwSize size, CellArray::Proxy t)
    00485 {
    00486     mwSize matSize[] = { size };
    00487     t = mxCreateCellArray(1, matSize);
    00488
    00489     return CellArray(t);
    00490 }
    00491
    00492 inline ConstStructArray
    00493 getStructArray(mxArray const * t)
    00494 {
    00495     return ConstStructArray(t);
    00496 }
    00497
    00498 template<class T>
    00499 T
    00500 getScalar(mxArray const * t)
    00501 {
    00502     if(mxIsEmpty(t))
    00503         mexErrMsgTxt("getScalar() on empty input.");
    00504     if(!mxIsNumeric(t) && !mxIsLogical(t))
    00505         mexErrMsgTxt("getScalar(): argument is not numeric.");
    00506     return static_cast<T>(mxGetScalar(t));
    00507 }
    00508
    00509 template<class T>
    00510 mxArray *
    00511 createScalar(T v)
    00512 {
    00513     mxArray * m;
    00514     createMatrix<double>(1, 1, m)(0,0) = static_cast<double>(v);
    00515     return m;
    00516 }
    00517
    00518 inline std::string
    00519 getString(mxArray const * t)
    00520 {
    00521     if(mxIsEmpty(t))
    00522         mexErrMsgTxt("getString() on empty input.");
    00523     if(!mxIsChar(t))
    00524         mexErrMsgTxt("getString(): argument is not a string.");
    00525     int size = mxGetNumberOfElements(t) + 1;
    00526     ArrayVector<char> buf(size);
    00527     mxGetString(t, buf.begin(), size);
    00528     return std::string(buf.begin());
    00529 }
    00530
    00531
    00532
    00533 class CompileTimeError;
    00534
    00535 namespace detail {
    00536
    00537 class Required
    00538 {
    00539   public:
    00540     void argumentWasProvided() const { /* empty because required arguments are always provided */ }
    00541 };
    00542
    00543
    00544 template<class T>
    00545 class DefaultImpl
    00546 {
    00547   public:
    00548
    00549     T defaultValue_;
    00550     mutable bool * argumentWasProvided_;
    00551
    00552     DefaultImpl(T v, bool * argFlag = 0)
    00553     : defaultValue_(v),
    00554       argumentWasProvided_(argFlag)
    00555     {
    00556         if(argumentWasProvided_ != 0)
    00557             *argumentWasProvided_ = false;
    00558     }
    00559
    00560     void argumentWasProvided() const
    00561     {
    00562         if(argumentWasProvided_ != 0)
    00563             *argumentWasProvided_ = true;
    00564     }
    00565 };
    00566
    00567 class OptionalImpl
    00568 {
    00569   public:
    00570     mutable bool * argumentWasProvided_;
    00571
    00572     OptionalImpl(bool * argFlag = 0)
    00573     : argumentWasProvided_(argFlag)
    00574     {
    00575         if(argumentWasProvided_ != 0)
    00576             *argumentWasProvided_ = false;
    00577     }
    00578
    00579     void argumentWasProvided() const
    00580     {
    00581         if(argumentWasProvided_ != 0)
    00582             *argumentWasProvided_ = true;
    00583     }
    00584 };
    00585
    00586 } // namespace detail
    00587
    00588 inline detail::Required v_required()
    00589 {
    00590     return detail::Required();
    00591 }
    00592
    00593 template<class T>
    00594 inline detail::DefaultImpl<T> v_default(T in)
    00595 {
    00596     return detail::DefaultImpl<T>(in);
    00597 }
    00598
    00599 template<class T>
    00600 inline detail::DefaultImpl<T> v_default(T in, bool & argFlag)
    00601 {
    00602     return detail::DefaultImpl<T>(in, &argFlag);
    00603 }
    00604
    00605 inline detail::OptionalImpl v_optional()
    00606 {
    00607     return detail::OptionalImpl();
    00608 }
    00609
    00610 inline detail::OptionalImpl v_optional(bool& argFlag)
    00611 {
    00612     return detail::OptionalImpl(&argFlag);
    00613 }
    00614
    00615 // TODO:
    00616 //    * handle rgb images
    00617 //    * handle complex matrices
    00618 //    * handle sparse matrices
    00619
    00620 class InputArray
    00621 {
    00622     int size_;
    00623     const mxArray ** data_;
    00624
    00625     std::string createErrMsg(std::string name)
    00626     {
    00627         std::string s1;
    00628         s1 =  "Required input '" + name + "' not found in option struct!";
    00629         return s1;
    00630     }
    00631     std::string createErrMsg(int pos)
    00632     {
    00633         char tmp[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    00634         std::string oi(1, tmp[pos%10]);
    00635         std::string s1  = "Required input in signature of function at position: '"+ oi+"' has not been supplied";
    00636         return s1;
    00637     }
    00638
    00639
    00640   public:
    00641     ConstStructArray options_;
    00642
    00643     /* Local Typedefs */
    00644     typedef const mxArray * value_type;
    00645     typedef value_type & reference;
    00646     typedef value_type const & const_reference;
    00647     typedef value_type * pointer;
    00648     typedef value_type const * const_pointer;
    00649     typedef int size_type;
    00650     typedef int difference_type;
    00651
    00652     /*Constructor*/
    00653     InputArray(size_type size, pointer data)
    00654     : size_(size),
    00655       data_(data),
    00656       options_(isValid(size-1) && mxIsStruct(data_[size-1])
    00657                  ? data_[size-1]
    00658                  : 0)
    00659     {}
    00660
    00661     /*Operators*/
    00662     const_reference operator[]( difference_type i ) const
    00663     {
    00664         if(!isValid(i))
    00665             mexErrMsgTxt("Too few input arguments.");
    00666         return data_[i];
    00667     }
    00668
    00669     value_type operator[]( std::string name) const
    00670     {
    00671         std::string errMsg = "Not Found " + name +" in OptionStruct or OptionStruct not set";
    00672         if(!isValid(name))
    00673             mexErrMsgTxt(errMsg.c_str());
    00674         return options_[name];
    00675     }
    00676
    00677
    00678     /*Some More Helper Func*/
    00679     size_type size() const
    00680     {
    00681         return size_;
    00682     }
    00683
    00684     bool isValid( difference_type i ) const
    00685     {
    00686         return i >= 0 && i < size_;
    00687     }
    00688
    00689     bool isValid(std::string name) const
    00690     {
    00691         return options_.isValid(name);
    00692     }
    00693
    00694     bool isEmpty(difference_type i) const
    00695     {
    00696         return mxIsEmpty(data_[i]);
    00697     }
    00698
    00699     bool isEmpty(std::string name) const
    00700     {
    00701         return mxIsEmpty(options_[name]);
    00702     }
    00703
    00704     bool hasData(difference_type i) const
    00705     {
    00706         return isValid(i) && !isEmpty(i);
    00707     }
    00708
    00709     bool hasData(std::string name) const
    00710     {
    00711         return isValid(name) && !isEmpty(name);
    00712     }
    00713
    00714     template<class Place>
    00715     mxClassID typeOf(Place posOrName)
    00716     {
    00717         return mxGetClassID((*this)[posOrName]);
    00718     }
    00719
    00720     /*Action to take if value not set*/
    00721     template <class T, class U, class Place>
    00722     T errorOrDefault(detail::DefaultImpl<U> const & o, Place posOrName)
    00723     {
    00724         return o.defaultValue_;
    00725     }
    00726
    00727     template <class T, class Place>
    00728     T errorOrDefault(detail::OptionalImpl, Place posOrName)
    00729     {
    00730         return T();
    00731     }
    00732
    00733     template <class T, class Place>
    00734     T errorOrDefault(detail::Required r, Place posOrName)
    00735     {
    00736         std::string a = createErrMsg(posOrName);
    00737         mexErrMsgTxt( a.c_str());
    00738         return T();
    00739     }
    00740
    00741     /*getter Func*/
    00742     template <class Place, class ReqType>
    00743     int getEnum(Place posOrName, ReqType req, std::map<std::string, int> const & converter)
    00744     {
    00745         if(!hasData(posOrName))
    00746         {
    00747             return errorOrDefault<int>(req, posOrName);
    00748         }
    00749         std::string enumAsString = matlab::getString((*this)[posOrName]);
    00750         typename std::map<std::string, int>::const_iterator m = converter.find(enumAsString);
    00751         if(m == converter.end())
    00752         {
    00753             std::string msg = std::string("Unknown option: ") + enumAsString + ".";
    00754             mexErrMsgTxt(msg.c_str());
    00755         }
    00756
    00757         req.argumentWasProvided();
    00758         return (*m).second;
    00759     }
    00760
    00761
    00762     /*String Type*/
    00763     template <class Place, class ReqType>
    00764     std::string getString(Place posOrName, ReqType req)
    00765     {
    00766         if(!hasData(posOrName))
    00767         {
    00768             return errorOrDefault<std::string>(req, posOrName);
    00769         }
    00770         else
    00771         {
    00772             req.argumentWasProvided();
    00773             return matlab::getString((*this)[posOrName]);
    00774         }
    00775     }
    00776
    00777     /*Scalar Type*/
    00778     template <class T,class Place, class ReqType>
    00779     T getScalar(Place posOrName, ReqType req)
    00780     {
    00781         if(!hasData(posOrName))
    00782         {
    00783             return errorOrDefault<T>(req, posOrName);
    00784         }
    00785         else
    00786         {
    00787             req.argumentWasProvided();
    00788             return matlab::getScalar<T>((*this)[posOrName]);
    00789         }
    00790     }
    00791
    00792
    00793     template <class T, class Place, class ReqType, class minClass, class maxClass>
    00794     T getScalarMinMax(Place posOrName, ReqType req, minClass min_, maxClass max_)
    00795     {
    00796         T temp = this->getScalar<T>(posOrName, req);
    00797         if (!is_in_range(temp, min_, max_))
    00798             mexErrMsgTxt("Value out of bounds.");
    00799         return temp;
    00800     }
    00801
    00802     template <class T, class Place, class ReqType, class iteratorType>
    00803     T getScalarVals(Place posOrName, ReqType req, iteratorType begin_, iteratorType end_)
    00804     {
    00805         T temp = this->getScalar<T>(posOrName, req);
    00806         for(iteratorType iter = begin_; iter != end_; ++iter)
    00807         {
    00808             if((*iter) == temp) return temp;
    00809         }
    00810         mexErrMsgTxt("Value not allowed");
    00811     }
    00812
    00813
    00814
    00815     template <class T, class Place, class ReqType, class iteratorType>
    00816     T getScalarVals2D3D(Place posOrName, ReqType req, iteratorType begin2D_, iteratorType end2D_,
    00817                                                      iteratorType begin3D_, iteratorType end3D_,
    00818                                                      int dimVar)
    00819     {
    00820         T temp = this->getScalar<T>(posOrName, req);
    00821         switch(dimVar)
    00822         {
    00823             case 2:
    00824                 for(iteratorType iter = begin2D_; iter != end2D_; ++iter)
    00825                 {
    00826                     if((*iter) == temp) return temp;
    00827                 }
    00828                 break;
    00829             case 3:
    00830                 for(iteratorType iter = begin3D_; iter != end3D_; ++iter)
    00831                 {
    00832                     if((*iter) == temp) return temp;
    00833                 }
    00834                 break;
    00835             default:
    00836                 mexErrMsgTxt("dimVar specified must be 2 or 3");
    00837         }
    00838         mexErrMsgTxt("Value not allowed");
    00839     }
    00840
    00841     template <class Place, class ReqType>
    00842     bool getBool(Place posOrName, ReqType req)
    00843     {
    00844         return this->getScalarMinMax<int>(posOrName, req, 0, 1) != 0;
    00845     }
    00846
    00847     /*Array Type*/
    00848     template <unsigned int N, class T, class Place, class ReqType>
    00849     MultiArrayView<N,T> getMultiArray(Place posOrName, ReqType req)
    00850     {
    00851         if(!hasData(posOrName))
    00852         {
    00853             return errorOrDefault< MultiArrayView<N,T> >(req, posOrName);
    00854         }
    00855         else
    00856         {
    00857             req.argumentWasProvided();
    00858             value_type temp = (*this)[posOrName];
    00859             return matlab::getMultiArray<N,T>(temp);
    00860         }
    00861     }
    00862
    00863     template < class T, class Place, class ReqType>
    00864     BasicImageView<T> getImage(Place posOrName, ReqType req)
    00865     {
    00866         if(!hasData(posOrName))
    00867         {
    00868             return errorOrDefault<BasicImageView<T> >(req, posOrName);
    00869         }
    00870         else
    00871         {
    00872             req.argumentWasProvided();
    00873             value_type temp = (*this)[posOrName];
    00874             return matlab::getImage<T>(temp);
    00875         }
    00876     }
    00877
    00878     template<class T,unsigned int sze, class Place, class ReqType>
    00879     TinyVectorView< T, sze> getTinyVector(Place posOrName, ReqType req)
    00880     {
    00881         if(!hasData(posOrName))
    00882         {
    00883             return errorOrDefault<TinyVectorView< T, sze> >(req, posOrName);
    00884         }
    00885         else
    00886         {
    00887             req.argumentWasProvided();
    00888             value_type temp = (*this)[posOrName];
    00889             return matlab::getTinyVector< T, sze>(temp);
    00890         }
    00891     }
    00892
    00893     template< unsigned int sze, class Place, class ReqType>
    00894     TinyVectorView<MultiArrayIndex, sze> getShape(Place posOrName, ReqType req)
    00895     {
    00896         if(!hasData(posOrName))
    00897         {
    00898             return errorOrDefault<TinyVectorView<MultiArrayIndex, sze> >(req, posOrName);
    00899         }
    00900         else
    00901         {
    00902             req.argumentWasProvided();
    00903             value_type temp = (*this)[posOrName];
    00904             return matlab::getShape<sze>(temp);
    00905         }
    00906     }
    00907
    00908
    00909     template< class Place, class ReqType>
    00910     int getDimOfInput(Place posOrName, ReqType req)
    00911     {
    00912         if(!hasData(posOrName))
    00913         {
    00914             return errorOrDefault<int>(req, posOrName);
    00915         }
    00916         else
    00917         {
    00918             req.argumentWasProvided();
    00919             return mxGetNumberOfDimensions((*this)[posOrName]);
    00920         }
    00921     }
    00922
    00923     template<class ReqType>
    00924     ConstCellArray getCellArray(int posOrName, ReqType req)
    00925     {
    00926         if(!hasData(posOrName))
    00927         {
    00928             return errorOrDefault<ConstCellArray>(req, posOrName);
    00929         }
    00930         else
    00931         {
    00932             req.argumentWasProvided();
    00933             value_type temp = (*this)[posOrName];
    00934             return matlab::getCellArray(temp);
    00935         }
    00936     }
    00937
    00938     template<class ReqType>
    00939     ConstCellArray getCellArray(std::string posOrName, ReqType req)
    00940     {
    00941         CompileTimeError ERROR__Const_Cell_Array_May_Not_Be_In_Option_Struct;
    00942         return ConstCellArray(); //avoid compiler warningg
    00943     }
    00944
    00945 };
    00946
    00947 class OutputArray
    00948 {
    00949     int size_;
    00950     mxArray ** data_;
    00951     std::string createErrMsgOut(int pos)
    00952     {
    00953         char tmp[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    00954         std::string oi(1, tmp[pos%10]);
    00955         std::string s1 =  "Required Output at position: '" + oi + "' has not been supplied";
    00956         return s1;
    00957     }
    00958   public:
    00959
    00960     typedef mxArray * value_type;
    00961     typedef value_type & reference;
    00962     typedef value_type const & const_reference;
    00963     typedef value_type * pointer;
    00964     typedef value_type const * const_pointer;
    00965     typedef int size_type;
    00966     typedef int difference_type;
    00967
    00968     OutputArray(size_type size, pointer data)
    00969     : size_(size),
    00970       data_(data)
    00971     {}
    00972
    00973     reference operator[]( difference_type i )
    00974     {
    00975         if(!isValid(i))
    00976             mexErrMsgTxt("Too few output arguments.");
    00977         return data_[i];
    00978     }
    00979
    00980     const_reference operator[]( difference_type i ) const
    00981     {
    00982         if(!isValid(i))
    00983             mexErrMsgTxt("Too few output arguments.");
    00984         return data_[i];
    00985     }
    00986
    00987     size_type size() const
    00988     {
    00989         return size_;
    00990     }
    00991
    00992     bool isValid( difference_type i ) const
    00993     {
    00994         return i >= 0 && i < size_;
    00995     }
    00996
    00997     bool isEmpty(difference_type i){
    00998         return mxIsEmpty(data_[i]);
    00999     }
    01000
    01001     template <class T>
    01002     T errorOrDefault(detail::OptionalImpl const & o, int Pos)
    01003     {
    01004         return T();
    01005     }
    01006
    01007     template <class T>
    01008     T errorOrDefault(detail::Required r, int Pos)
    01009     {
    01010         mexErrMsgTxt(createErrMsgOut(Pos).c_str());
    01011         return T();
    01012     }
    01013
    01014     /* creating func */
    01015     template <unsigned int DIM, class T, class ReqType>
    01016     MultiArrayView<DIM, T> createMultiArray(int pos,ReqType req,
    01017                                             const TinyVector<int, DIM>  & shape)
    01018     {
    01019         if(!isValid(pos))
    01020             return errorOrDefault<MultiArrayView<DIM, T> >(req, pos);
    01021         req.argumentWasProvided();
    01022         return matlab::createMultiArray<DIM, T>(shape, (*this)[pos]);
    01023     }
    01024
    01025     template <class T, class ReqType>
    01026     BasicImageView<T> createImage(int pos, ReqType req,
    01027                                     mwSize width, mwSize height)
    01028     {
    01029         if(!isValid(pos))
    01030             return errorOrDefault<BasicImageView<T> >(req, pos);
    01031         req.argumentWasProvided();
    01032         return matlab::createImage<T>(width, height, (*this)[pos]);
    01033     }
    01034
    01035     template <class T, class ReqType>
    01036     BasicImageView<T> createImage(  int pos, ReqType req,
    01037                                     typename MultiArrayShape<2>::type const & shape)
    01038     {
    01039         return createImage<T>(pos, req, shape[1], shape[0]);
    01040     }
    01041
    01042     template <class T, class ReqType>
    01043     T* createScalar(int pos, ReqType req)
    01044     {
    01045         if(!isValid(pos))
    01046             return errorOrDefault<T*>(req, pos);
    01047         req.argumentWasProvided();
    01048         BasicImageView<T> temp = matlab::createImage<T>(1, 1, (*this)[pos]);
    01049         return &temp(0,0);
    01050     }
    01051
    01052     template <class T, class ReqType>
    01053     void createScalar(int pos, ReqType req, T val)
    01054     {
    01055         if(!isValid(pos))
    01056         {
    01057             errorOrDefault<T>(req, pos);
    01058             return;
    01059         }
    01060         req.argumentWasProvided();
    01061         BasicImageView<T> temp = matlab::createImage<T>(1, 1, (*this)[pos]);
    01062         temp(0,0) = val;
    01063     }
    01064
    01065     template <class ReqType>
    01066     ConstCellArray createCellArray(int pos, ReqType req, mwSize sze)
    01067     {
    01068         if(!isValid(pos))
    01069             return errorOrDefault<ConstCellArray>(req, pos);
    01070         return matlab::createCellArray(sze, (*this)[pos]);
    01071     }
    01072 };
    01073
    01074
    01075
    01076 /***********************************
    01077 Rahuls code starts here
    01078 ************************************/
    01079 using namespace vigra;
    01080
    01081
    01082 /*++++++++++++++++++++++++++HELPERFUNC+++++++++++++++++++++++++++++++*
    01083  * This is used for better readibility of the test cases            .
    01084  * Nothing to be done here.
    01085  *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    01086 int cantorPair(int x, int y){
    01087         return (int)(((x+y)*(x+y+1))/2+y);
    01088 }
    01089
    01090 int cantorPair(int x, int y, int z){
    01091         return cantorPair(cantorPair(x,y),z);
    01092 }
    01093
    01094 template <int x, int y>
    01095 struct cP{
    01096     enum { value = (int)(((x+y)*(x+y+1))/2+y)};
    01097 };
    01098
    01099 template <int x, int y, int z>
    01100 struct cP3{
    01101     enum { value = cP<cP<x, y>::value, z>::value};
    01102 };
    01103
    01104 template <class T>
    01105 inline bool is_in_range(T in, T min, T max)
    01106 {
    01107     return (in >= min && in <= max);
    01108 }
    01109 template<class T>
    01110 inline bool is_in_range(T in, std::string min, T max)
    01111 {
    01112     return(in <= max);
    01113 }
    01114
    01115 template<class T>
    01116 inline bool is_in_range(T in, T min, std::string max)
    01117 {
    01118     return (in >= min);
    01119 }
    01120
    01121
    01122
    01123 //Wrapper classes to STL-Map for use as a sparse array.
    01124
    01125 //This is used for the ordering of the map. Lexicographical ordering of the index pairs.
    01126 struct ShapeCmp {
    01127   bool operator()( TinyVector<int,2> s1, TinyVector<int,2>  s2 ) const {
    01128     if(s1[0] != s2[0]){
    01129         return (s1[0] < s2[0]);
    01130     } else {
    01131         return s1[1] < s2[1];
    01132     }
    01133   }
    01134 };
    01135
    01136 template<class T>
    01137 class SparseArray
    01138 {
    01139
    01140     std::map<TinyVector<int,2>, T,ShapeCmp> data;
    01141     int width, length;
    01142
    01143     public:
    01144     void assign(int i = 1, int j = 1){
    01145         width = j;
    01146         length = i;
    01147     }
    01148     SparseArray(int i = 1 , int j = 1){
    01149         width = j;
    01150         length = i;
    01151     }
    01152
    01153     //Any better idea? i would like to unify the get and operator() functions.
    01154     // Problem is that  operator() always passes a reference or creates one.
    01155     template<class indexType>
    01156     T& operator()(indexType i_, indexType j_){
    01157         Int32 i = static_cast<Int32>(i_);
    01158         Int32 j = static_cast<Int32>(j_);
    01159         TinyVector<int,2> newShapew(i, j);
    01160         typename std::map<TinyVector<int,2>, T, ShapeCmp>::iterator iter;
    01161         TinyVector<int,2> newShape;
    01162         return data[newShapew];
    01163     }
    01164
    01165     template<class indexType>
    01166     const T get(indexType i_, indexType j_){
    01167         Int32 i = static_cast<Int32>(i_);
    01168         Int32 j = static_cast<Int32>(j_);
    01169         TinyVector<int,2> newShape(i, j);
    01170         if(data.find(newShape) == data.end()) return 0;
    01171         else return data.find(newShape)->second;
    01172     }
    01173
    01174     //see dokumentation of mxCreateSparse and the mxGet functions to understand this.
    01175     void mapToMxArray(mxArray * & in){
    01176
    01177         int len = data.size();
    01178         in = mxCreateSparse(width, length, len, mxREAL);
    01179         int* jc = mxGetJc(in);
    01180         int* ir = mxGetIr(in);
    01181         double* pr = mxGetPr(in);
    01182         if(len == 0){
    01183             jc[0] = 1;
    01184             return;
    01185         }
    01186         typename std::map<TinyVector<int,2>, T, ShapeCmp>::iterator iter;
    01187         TinyVector<int,2> newShape;
    01188         int ii = 0;
    01189         int jj = 0;
    01190         int curjc = -1;
    01191         for( iter = data.begin(); iter != data.end(); ++iter ) {
    01192             newShape = iter->first;
    01193             ir[ii] = newShape[1];
    01194             pr[ii] = iter->second;
    01195             if(newShape[0]  != curjc){
    01196                 curjc = newShape[0] ;
    01197                 jc[jj] = ii;
    01198                 jj++;
    01199             }
    01200
    01201             ii++;
    01202         }
    01203         jc[jj] = len;
    01204     }
    01205
    01206 };
    01207
    01208 enum DataDimension {IMAGE = 2, VOLUME = 3};
    01209
    01210 } // namespace matlab
    01211
    01212 } // namespace vigra
    01213
    01214 void vigraMexFunction(vigra::matlab::OutputArray, vigra::matlab::InputArray);
    01215
    01216 #ifndef VIGRA_CUSTOM_MEXFUNCTION
    01217
    01218 /*
    01219     DO NOT Comment out this function. If you are using a
    01220     custom mexfunction just #define VIGRA_CUSTOM_MEXFUNCTION
    01221     before #including matlab.hxx.
    01222 */
    01223 void mexFunction(int nlhs, mxArray *plhs[],
    01224                  int nrhs, const mxArray *prhs[])
    01225 {
    01226   try
    01227   {
    01228     vigra::matlab::InputArray inputs(nrhs, prhs);
    01229     vigra::matlab::OutputArray outputs(nlhs, plhs);
    01230
    01231     vigraMexFunction(outputs, inputs);
    01232   }
    01233   catch(std::exception & e)
    01234   {
    01235     mexErrMsgTxt(e.what());
    01236   }
    01237 }
    01238
    01239 #endif /*CUSTOM_MEXFUNCTION*/
    01240
    01241
    01242 #define VIGRA_CREATE_ENUM_AND_STD_MAP2(mapName, item1, item2) \
    01243     const int item1 = 1;\
    01244     const int item2 = 2;\
    01245     std::map<std::string,int>  mapName;\
    01246     mapName[#item1] = (int)item1;\
    01247     mapName[#item2] = (int)item2;\
    01248
    01249
    01250 #define VIGRA_CREATE_ENUM_AND_STD_MAP3(mapName, item1, item2, item3) \
    01251     const int item1 = 1;\
    01252     const int item2 = 2;\
    01253     const int item3 = 3;\
    01254     std::map<std::string,int>  mapName;\
    01255     mapName[#item1] = (int)item1;\
    01256     mapName[#item2] = (int)item2;\
    01257     mapName[#item3] = (int)item3;\
    01258
    01259
    01260 #define VIGRA_CREATE_ENUM_AND_STD_MAP4(mapName, item1, item2, item3, item4) \
    01261     const int item1 = 1;\
    01262     const int item2 = 2;\
    01263     const int item3 = 3;\
    01264     const int item4 = 4;\
    01265     std::map<std::string,int>  mapName;\
    01266     mapName[#item1] = (int)item1;\
    01267     mapName[#item2] = (int)item2;\
    01268     mapName[#item3] = (int)item3;\
    01269     mapName[#item4] = (int)item4;\
    01270
    01271 #define VIGRA_CREATE_ENUM_AND_STD_MAP5(mapName, item1, item2, item3, item4, item5) \
    01272     const int item1 = 1;\
    01273     const int item2 = 2;\
    01274     const int item3 = 3;\
    01275     const int item4 = 4;\
    01276     const int item5 = 5;\
    01277     std::map<std::string, int>  mapName;\
    01278     mapName[#item1] = (int)item1;\
    01279     mapName[#item2] = (int)item2;\
    01280     mapName[#item3] = (int)item3;\
    01281     mapName[#item4] = (int)item4;\
    01282     mapName[#item5] = (int)item5;\
    01283
    01284 #define VIGRA_CREATE_ENUM_AND_STD_MAP6(mapName, item1, item2, item3, item4, item5, item6) \
    01285     const int item1 = 1;\
    01286     const int item2 = 2;\
    01287     const int item3 = 3;\
    01288     const int item4 = 4;\
    01289     const int item5 = 5;\
    01290     const int item6 = 6;\
    01291     std::map<std::string,int>  mapName;\
    01292     mapName[#item1] = (int)item1;\
    01293     mapName[#item2] = (int)item2;\
    01294     mapName[#item3] = (int)item3;\
    01295     mapName[#item4] = (int)item4;\
    01296     mapName[#item5] = (int)item5;\
    01297     mapName[#item6] = (int)item6;\
    01298
    01299 #endif // VIGRA_MATLAB_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.7.1 (3 Dec 2010)