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