Switch to side-by-side view

--- a
+++ b/Thoracic Organs Segmentation code/OpticalFlow3D/cimgmatlab.h
@@ -0,0 +1,387 @@
+/*************************************************************************
+ * cimgmatlab.h
+ * -------------
+ *
+ * cimgmatlab.h  is a "plugin" for the CImg library that allows to convert
+ * CImg<T> images from/to MATLAB arrays, so that CImg can be used to write
+ * MATLAB mex files.  It also swaps the "x" and "y" coordinates when going
+ * from / to MATLAB array, i.e. the usual image-processing annoying MATLAB
+ * behaviour of considering images as matrices.
+ *
+ * Added to the CImg<T> class are:
+ *
+ *  - a constructor : CImg(const mxArray *matlabArray, bool vdata = false)
+ *    the vdata  serves  to  decide  whether a 3D matlab array should give
+ *    rise to a 3D CImg object or a "2D vectorial" one.
+ *
+ *  - a assignment operator : CImg & operator=(const mxArray *matlabArray)
+ *    (I use myself extremely seldom and might remove it in the future).
+ *
+ *  - a routine converting a CImg image to a matlab array:
+ *    mxArray *toMatlab(mxClassID classID = mxDOUBLE_CLASS,
+ *                      bool squeeze = false) const
+ *    the squeeze argument serves the opposite purpose than the vdata from
+ *    the constructor.
+ *
+ * For a  bit  more documentation, the manual is this header, see the more
+ * detailed comments in the source code (i.e. RTFM)
+ *
+ *
+ * Its usage should be straightforward:
+ *
+ * - file cimgmatlab.h must be in a directory that the compiler can locate.
+ * - prior to include CImg.h, mex.h  must  be  included first, else it will
+ *   result in a compiler error.
+ * - after the inclusion of mex.h, one must define the macro cimg_plugin as
+ *   "cimgmatlab.h"  or  <cimgmatlab.h> or  <CImg/plugins/cimgmatlab.h>  or
+ *   a variation that  matches your  local installation of CImg package and
+ *   plugins probably via the appropriate specification of the include path
+ *   "-Ipath/to/cimg/and/plugins" at mex cmdline.
+ *
+ * You would probably have this kind of declaration:
+ *
+ * // The begining of my fantastic mex file code...
+ * #include <mex.h>
+ * ...
+ * #define cimg_plugin  <cimgmatlab.h>
+ * #include <CImg.h>
+ * ...
+ * // and now I can implement my new killer MATLAB function!
+ * ....
+ *
+ *
+ * Copyright (c) 2004-2008 Francois Lauze
+ * Licence: the Gnu Lesser General Public License
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * MATLAB is copyright of The MathWorks, Inc, http://www.mathworks.com
+ *
+ * Any comments, improvements and potential bug corrections are welcome, so
+ * write to  me at francois@diku.dk, or use CImg forums, I promise I'll try
+ * to read them once in a while. BTW who modified the cpMatlabData with the
+ * cimg::type<t>::is_float() test (good idea!)
+ *
+ ***************************************************************************/
+
+#define CIMGMATLAB_VER 0102
+#ifndef mex_h
+#error the file mex.h must be included prior to inclusion of cimgmatlab.h
+#endif
+#ifndef cimg_version
+#error cimgmatlab.h requires that CImg.h is included!
+#endif
+
+/**********************************************************
+ * introduction of mwSize and mwIndex types in relatively *
+ * recent versions of matlab, 7.3.0 from what I gathered. *
+ * here is hopefully a needed fix for older versions      *
+ **********************************************************/
+#if !defined(MX_API_VER) ||  MX_API_VER < 0x7030000
+typedef int mwSize;
+#endif
+
+/*********************************************************
+ * begin of included methods                             *
+ * They are just added as member functions / constructor *
+ * for the CImg<T> class.                                *
+ *********************************************************/
+
+private:
+    /**********************************************************************
+     * internally used to transfer MATLAB array values to CImg<> objects,
+     * check wether the array type is a "numerical" one (including logical)
+     */
+    static int isNumericalClassID(mxClassID id)
+    {
+        // all these constants are defined in matrix.h included by mex.h
+        switch (id) {
+        case mxLOGICAL_CLASS:
+        case mxDOUBLE_CLASS:
+        case mxSINGLE_CLASS:
+        case mxINT8_CLASS:
+        case mxUINT8_CLASS:
+        case mxINT16_CLASS:
+        case mxUINT16_CLASS:
+        case mxINT32_CLASS:
+        case mxUINT32_CLASS:
+        case mxINT64_CLASS:
+        case mxUINT64_CLASS:
+            return 1;
+        default:
+            return 0;
+        }
+    }
+
+    /***************************************************
+     * driving routine that will copy the content of
+     * a MATLAB array to this->data
+     * The type names used are defined in matlab c/c++
+     * header file tmwtypes.h
+     */
+    void makeImageFromMatlabData(const mxArray *matlabArray, mxClassID classID)
+    {
+        if (classID == mxLOGICAL_CLASS)
+        {
+            // logical type works a bit differently than the numerical types
+            mxLogical *mdata = mxGetLogicals(matlabArray);
+            cpMatlabData((const mxLogical *)mdata);
+        }
+        else
+        {
+            void *mdata = (void *)mxGetPr(matlabArray);
+
+            switch (classID) {
+            case mxDOUBLE_CLASS:
+                cpMatlabData((const real64_T *)mdata);
+                break;
+            case mxSINGLE_CLASS:
+                cpMatlabData((const real32_T *)mdata);
+                break;
+            case mxINT8_CLASS:
+                cpMatlabData((const int8_T *)mdata);
+                break;
+            case mxUINT8_CLASS:
+                cpMatlabData((const uint8_T *)mdata);
+                break;
+            case mxINT16_CLASS:
+                cpMatlabData((const int16_T *)mdata);
+                break;
+            case mxUINT16_CLASS:
+                cpMatlabData((const uint16_T *)mdata);
+                break;
+            case mxINT32_CLASS:
+                cpMatlabData((const int32_T *)mdata);
+                break;
+            case mxUINT32_CLASS:
+                cpMatlabData((const uint32_T *)mdata);
+                break;
+            case mxINT64_CLASS:
+                cpMatlabData((const int64_T *)mdata);
+                break;
+            case mxUINT64_CLASS:
+                cpMatlabData((const uint64_T *)mdata);
+                break;
+            }
+        }
+    }
+
+    /***********************************************************
+     * the actual memory copy and base type conversion is then
+     * performed by this routine that handles the annoying x-y
+     * problem of MATLAB when dealing with images: we switch
+     * line and column storage: the MATLAB A(x,y) becomes the
+     * CImg img(y,x)
+     */
+    template <typename t> void cpMatlabData(const t* mdata)
+    {
+        if (cimg::type<t>::is_float())
+        {
+            cimg_forXYZV(*this, x, y, z, v)
+            {
+                (*this)(x, y, z, v) = (T)(mdata[((v*depth + z)*width+x)*height+y]);
+            }
+        }
+        else
+        {
+            cimg_forXYZV(*this, x, y, z, v)
+            {
+                (*this)(x, y, z, v) = (T)(int)(mdata[((v*depth + z)*width+x)*height+y]);
+            }
+        }
+    }
+
+public:
+
+    /******************************************************************
+     * Consruct a CImg<T> object from a MATLAB mxArray.
+     * The MATLAB array must be AT MOST 4-dimensional. The boolean
+     * argument vdata is employed in the case the the input mxArray
+     * has dimension 3, say M x N x K. In that case, if vdata is true,
+     * the last dimension is assumed to be "vectorial" and the
+     * resulting CImg<T> object has dimension N x M x 1 x K. Otherwise,
+     * the resulting object has dimension N x M x K x 1.
+     * When MATLAB array has dimension 2 or 4, vdata has no effects.
+     * No shared memory mechanisms are used, it would be the easiest
+     * to crash Matlab (from my own experience...)
+     */
+    CImg(const mxArray *matlabArray, bool vdata = false)
+    : is_shared(false)
+    {
+        mwSize nbdims = mxGetNumberOfDimensions(matlabArray);
+        mxClassID classID = mxGetClassID(matlabArray);
+        if (nbdims > 4 || !isNumericalClassID(classID))
+        {
+            data=NULL;
+            width=height=depth=dim=0;
+#if cimg_debug>1
+            cimg::warn("MATLAB array is more than 4D or/and "
+                       "not numerical, returning null image.");
+#endif
+        }
+        else
+        {
+            const mwSize *dims = mxGetDimensions(matlabArray);
+            depth = dim = 1;
+            width =  (unsigned)dims[1];
+            height = (unsigned)dims[0];
+            if (nbdims == 4)
+            {
+                depth = (unsigned)dims[2];
+                dim =   (unsigned)dims[3];
+            }
+            else if (nbdims == 3)
+            {
+                if (vdata)
+                {
+                    dim = (unsigned)dims[2];
+                }
+                else
+                {
+                    depth = (unsigned)dims[2];
+                }
+            }
+
+            data = new T[size()];
+            makeImageFromMatlabData(matlabArray, classID);
+        }
+    }
+
+    /*******************************************************************
+     * operator=(). Copy  mxMarray data mArray into the current image
+     * Works as the previous constructor, but without the vdata stuff.
+     * don't know if it is of any use...
+     */
+    CImg & operator=(const mxArray *matlabArray)
+    {
+        int nbdims = (int)mxGetNumberOfDimensions(matlabArray);
+        int classID = mxGetClassID(matlabArray);
+        if (nbdims > 4 || !isNumericalClassID(classID))
+        {
+            delete [] data;
+            data = NULL;
+            width=height=depth=dim=0;
+#if cimg_debug>1
+            cimg::warn("MATLAB array is more than 4D or/and "
+                       "not numerical, returning null image.");
+#endif
+        }
+        else
+        {
+            const mwSize *dims = mxGetDimensions(matlabArray);
+            depth = dim = 1;
+            width =  (unsigned)dims[1];
+            height = (unsigned)dims[0];
+            if (nbdims > 2)
+            {
+                depth = (unsigned)dims[2];
+            }
+            if (nbdims > 3)
+            {
+                dim = (unsigned)dims[3];
+            }
+
+            delete [] data;
+            data = new T[size()];
+
+            makeImageFromMatlabData(matlabArray, classID);
+        }
+    }
+
+private:
+    /*****************************************************************
+     * private routines used for transfering a CImg<T> to a mxArray
+     * here also, we have to exchange the x and y dims so we get the
+     * expected MATLAB array.
+     */
+    template <typename c> void populate_maltlab_array(c *mdata) const
+    {
+        cimg_forXYZV(*this, x, y, z, v)
+        {
+            mdata[((v*depth + z)*width+x)*height+y] = (c)(*this)(x, y, z, v);
+        }
+    }
+
+    /*************************************************
+     * the specialized version for "logical" entries
+     */
+    void populate_maltlab_array(mxLogical *mdata) const
+    {
+        cimg_forXYZV(*this, x, y, z, v)
+        {
+            mdata[((v*depth + z)*width+x)*height+y] = (mxLogical)((*this)(x, y, z, v)!=0);
+        }
+    }
+
+public:
+    /******************************************
+     * export a CImg image to a MATLAB array.
+     **/
+    mxArray *toMatlab(mxClassID classID = mxDOUBLE_CLASS, bool squeeze = false) const
+    {
+        if (!isNumericalClassID(classID))
+        {
+#if cimg_debug>1
+            cimg::warn("Invalid MATLAB Class Id Specified.");
+#endif
+            return NULL;
+        }
+
+        mwSize dims[4];
+        dims[0] = (mwSize)height;
+        dims[1] = (mwSize)width;
+        dims[2] = (mwSize)depth;
+        dims[3] = (mwSize)dim;
+
+        if (squeeze && depth == 1)
+        {
+            dims[2] = (mwSize)dim;
+            dims[3] = (mwSize)1;
+        }
+
+        mxArray *matlabArray = mxCreateNumericArray((mwSize)4, dims, classID, mxREAL);
+
+        if (classID == mxLOGICAL_CLASS)
+        {
+            mxLogical *mdata = mxGetLogicals(matlabArray);
+            populate_maltlab_array(mdata);
+        }
+        else
+        {
+            void *mdata = mxGetPr(matlabArray);
+            switch (classID) {
+            case mxDOUBLE_CLASS:
+                populate_maltlab_array((real64_T *)mdata);
+                break;
+            case mxSINGLE_CLASS:
+                populate_maltlab_array((real32_T *)mdata);
+                break;
+            case mxINT8_CLASS:
+                populate_maltlab_array((int8_T *)mdata);
+                break;
+            case mxUINT8_CLASS:
+                populate_maltlab_array((uint8_T *)mdata);
+                break;
+            case mxINT16_CLASS:
+                populate_maltlab_array((int16_T *)mdata);
+                break;
+            case mxUINT16_CLASS:
+                populate_maltlab_array((uint16_T *)mdata);
+                break;
+            case mxINT32_CLASS:
+                populate_maltlab_array((int32_T *)mdata);
+                break;
+            case mxUINT32_CLASS:
+                populate_maltlab_array((uint32_T *)mdata);
+                break;
+            case mxINT64_CLASS:
+                populate_maltlab_array((int64_T *)mdata);
+                break;
+            case mxUINT64_CLASS:
+                populate_maltlab_array((uint64_T *)mdata);
+                break;
+            }
+        }
+        return matlabArray;
+    }
+
+// end of cimgmatlab.h