PTdecode/CImg-1.3.0/plugins/cimgmatlab.h

changeset 5
1204ebf9340d
     1.1 diff -r 5edfbd3e7a46 -r 1204ebf9340d PTdecode/CImg-1.3.0/plugins/cimgmatlab.h
     1.2 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 +++ b/PTdecode/CImg-1.3.0/plugins/cimgmatlab.h	Mon Aug 03 14:09:20 2009 +0100
     1.4 @@ -0,0 +1,387 @@
     1.5 +/*************************************************************************
     1.6 + * cimgmatlab.h
     1.7 + * -------------
     1.8 + *
     1.9 + * cimgmatlab.h  is a "plugin" for the CImg library that allows to convert
    1.10 + * CImg<T> images from/to MATLAB arrays, so that CImg can be used to write
    1.11 + * MATLAB mex files.  It also swaps the "x" and "y" coordinates when going
    1.12 + * from / to MATLAB array, i.e. the usual image-processing annoying MATLAB
    1.13 + * behaviour of considering images as matrices.
    1.14 + *
    1.15 + * Added to the CImg<T> class are:
    1.16 + *
    1.17 + *  - a constructor : CImg(const mxArray *matlabArray, bool vdata = false)
    1.18 + *    the vdata  serves  to  decide  whether a 3D matlab array should give
    1.19 + *    rise to a 3D CImg object or a "2D vectorial" one.
    1.20 + *
    1.21 + *  - a assignment operator : CImg & operator=(const mxArray *matlabArray)
    1.22 + *    (I use myself extremely seldom and might remove it in the future).
    1.23 + *
    1.24 + *  - a routine converting a CImg image to a matlab array:
    1.25 + *    mxArray *toMatlab(mxClassID classID = mxDOUBLE_CLASS,
    1.26 + *                      bool squeeze = false) const
    1.27 + *    the squeeze argument serves the opposite purpose than the vdata from
    1.28 + *    the constructor.
    1.29 + *
    1.30 + * For a  bit  more documentation, the manual is this header, see the more
    1.31 + * detailed comments in the source code (i.e. RTFM)
    1.32 + *
    1.33 + *
    1.34 + * Its usage should be straightforward:
    1.35 + *
    1.36 + * - file cimgmatlab.h must be in a directory that the compiler can locate.
    1.37 + * - prior to include CImg.h, mex.h  must  be  included first, else it will
    1.38 + *   result in a compiler error.
    1.39 + * - after the inclusion of mex.h, one must define the macro cimg_plugin as
    1.40 + *   "cimgmatlab.h"  or  <cimgmatlab.h> or  <CImg/plugins/cimgmatlab.h>  or
    1.41 + *   a variation that  matches your  local installation of CImg package and
    1.42 + *   plugins probably via the appropriate specification of the include path
    1.43 + *   "-Ipath/to/cimg/and/plugins" at mex cmdline.
    1.44 + *
    1.45 + * You would probably have this kind of declaration:
    1.46 + *
    1.47 + * // The begining of my fantastic mex file code...
    1.48 + * #include <mex.h>
    1.49 + * ...
    1.50 + * #define cimg_plugin  <cimgmatlab.h>
    1.51 + * #include <CImg.h>
    1.52 + * ...
    1.53 + * // and now I can implement my new killer MATLAB function!
    1.54 + * ....
    1.55 + *
    1.56 + *
    1.57 + * Copyright (c) 2004-2008 Francois Lauze
    1.58 + * Licence: the Gnu Lesser General Public License
    1.59 + * http://www.gnu.org/licenses/lgpl.html
    1.60 + *
    1.61 + * MATLAB is copyright of The MathWorks, Inc, http://www.mathworks.com
    1.62 + *
    1.63 + * Any comments, improvements and potential bug corrections are welcome, so
    1.64 + * write to  me at francois@diku.dk, or use CImg forums, I promise I'll try
    1.65 + * to read them once in a while. BTW who modified the cpMatlabData with the
    1.66 + * cimg::type<t>::is_float() test (good idea!)
    1.67 + *
    1.68 + ***************************************************************************/
    1.69 +
    1.70 +#define CIMGMATLAB_VER 0102
    1.71 +#ifndef mex_h
    1.72 +#error the file mex.h must be included prior to inclusion of cimgmatlab.h
    1.73 +#endif
    1.74 +#ifndef cimg_version
    1.75 +#error cimgmatlab.h requires that CImg.h is included!
    1.76 +#endif
    1.77 +
    1.78 +/**********************************************************
    1.79 + * introduction of mwSize and mwIndex types in relatively *
    1.80 + * recent versions of matlab, 7.3.0 from what I gathered. *
    1.81 + * here is hopefully a needed fix for older versions      *
    1.82 + **********************************************************/
    1.83 +#if !defined(MX_API_VER) ||  MX_API_VER < 0x7030000
    1.84 +typedef int mwSize;
    1.85 +#endif
    1.86 +
    1.87 +/*********************************************************
    1.88 + * begin of included methods                             *
    1.89 + * They are just added as member functions / constructor *
    1.90 + * for the CImg<T> class.                                *
    1.91 + *********************************************************/
    1.92 +
    1.93 +private:
    1.94 +    /**********************************************************************
    1.95 +     * internally used to transfer MATLAB array values to CImg<> objects,
    1.96 +     * check wether the array type is a "numerical" one (including logical)
    1.97 +     */
    1.98 +    static int isNumericalClassID(mxClassID id)
    1.99 +    {
   1.100 +        // all these constants are defined in matrix.h included by mex.h
   1.101 +        switch (id) {
   1.102 +        case mxLOGICAL_CLASS:
   1.103 +        case mxDOUBLE_CLASS:
   1.104 +        case mxSINGLE_CLASS:
   1.105 +        case mxINT8_CLASS:
   1.106 +        case mxUINT8_CLASS:
   1.107 +        case mxINT16_CLASS:
   1.108 +        case mxUINT16_CLASS:
   1.109 +        case mxINT32_CLASS:
   1.110 +        case mxUINT32_CLASS:
   1.111 +        case mxINT64_CLASS:
   1.112 +        case mxUINT64_CLASS:
   1.113 +            return 1;
   1.114 +        default:
   1.115 +            return 0;
   1.116 +        }
   1.117 +    }
   1.118 +
   1.119 +    /***************************************************
   1.120 +     * driving routine that will copy the content of
   1.121 +     * a MATLAB array to this->data
   1.122 +     * The type names used are defined in matlab c/c++
   1.123 +     * header file tmwtypes.h
   1.124 +     */
   1.125 +    void makeImageFromMatlabData(const mxArray *matlabArray, mxClassID classID)
   1.126 +    {
   1.127 +        if (classID == mxLOGICAL_CLASS)
   1.128 +        {
   1.129 +            // logical type works a bit differently than the numerical types
   1.130 +            mxLogical *mdata = mxGetLogicals(matlabArray);
   1.131 +            cpMatlabData((const mxLogical *)mdata);
   1.132 +        }
   1.133 +        else
   1.134 +        {
   1.135 +            void *mdata = (void *)mxGetPr(matlabArray);
   1.136 +
   1.137 +            switch (classID) {
   1.138 +            case mxDOUBLE_CLASS:
   1.139 +                cpMatlabData((const real64_T *)mdata);
   1.140 +                break;
   1.141 +            case mxSINGLE_CLASS:
   1.142 +                cpMatlabData((const real32_T *)mdata);
   1.143 +                break;
   1.144 +            case mxINT8_CLASS:
   1.145 +                cpMatlabData((const int8_T *)mdata);
   1.146 +                break;
   1.147 +            case mxUINT8_CLASS:
   1.148 +                cpMatlabData((const uint8_T *)mdata);
   1.149 +                break;
   1.150 +            case mxINT16_CLASS:
   1.151 +                cpMatlabData((const int16_T *)mdata);
   1.152 +                break;
   1.153 +            case mxUINT16_CLASS:
   1.154 +                cpMatlabData((const uint16_T *)mdata);
   1.155 +                break;
   1.156 +            case mxINT32_CLASS:
   1.157 +                cpMatlabData((const int32_T *)mdata);
   1.158 +                break;
   1.159 +            case mxUINT32_CLASS:
   1.160 +                cpMatlabData((const uint32_T *)mdata);
   1.161 +                break;
   1.162 +            case mxINT64_CLASS:
   1.163 +                cpMatlabData((const int64_T *)mdata);
   1.164 +                break;
   1.165 +            case mxUINT64_CLASS:
   1.166 +                cpMatlabData((const uint64_T *)mdata);
   1.167 +                break;
   1.168 +            }
   1.169 +        }
   1.170 +    }
   1.171 +
   1.172 +    /***********************************************************
   1.173 +     * the actual memory copy and base type conversion is then
   1.174 +     * performed by this routine that handles the annoying x-y
   1.175 +     * problem of MATLAB when dealing with images: we switch
   1.176 +     * line and column storage: the MATLAB A(x,y) becomes the
   1.177 +     * CImg img(y,x)
   1.178 +     */
   1.179 +    template <typename t> void cpMatlabData(const t* mdata)
   1.180 +    {
   1.181 +        if (cimg::type<t>::is_float())
   1.182 +        {
   1.183 +            cimg_forXYZV(*this, x, y, z, v)
   1.184 +            {
   1.185 +                (*this)(x, y, z, v) = (T)(mdata[((v*depth + z)*width+x)*height+y]);
   1.186 +            }
   1.187 +        }
   1.188 +        else
   1.189 +        {
   1.190 +            cimg_forXYZV(*this, x, y, z, v)
   1.191 +            {
   1.192 +                (*this)(x, y, z, v) = (T)(int)(mdata[((v*depth + z)*width+x)*height+y]);
   1.193 +            }
   1.194 +        }
   1.195 +    }
   1.196 +
   1.197 +public:
   1.198 +
   1.199 +    /******************************************************************
   1.200 +     * Consruct a CImg<T> object from a MATLAB mxArray.
   1.201 +     * The MATLAB array must be AT MOST 4-dimensional. The boolean
   1.202 +     * argument vdata is employed in the case the the input mxArray
   1.203 +     * has dimension 3, say M x N x K. In that case, if vdata is true,
   1.204 +     * the last dimension is assumed to be "vectorial" and the
   1.205 +     * resulting CImg<T> object has dimension N x M x 1 x K. Otherwise,
   1.206 +     * the resulting object has dimension N x M x K x 1.
   1.207 +     * When MATLAB array has dimension 2 or 4, vdata has no effects.
   1.208 +     * No shared memory mechanisms are used, it would be the easiest
   1.209 +     * to crash Matlab (from my own experience...)
   1.210 +     */
   1.211 +    CImg(const mxArray *matlabArray, bool vdata = false)
   1.212 +    : is_shared(false)
   1.213 +    {
   1.214 +        mwSize nbdims = mxGetNumberOfDimensions(matlabArray);
   1.215 +        mxClassID classID = mxGetClassID(matlabArray);
   1.216 +        if (nbdims > 4 || !isNumericalClassID(classID))
   1.217 +        {
   1.218 +            data=NULL;
   1.219 +            width=height=depth=dim=0;
   1.220 +#if cimg_debug>1
   1.221 +            cimg::warn("MATLAB array is more than 4D or/and "
   1.222 +                       "not numerical, returning null image.");
   1.223 +#endif
   1.224 +        }
   1.225 +        else
   1.226 +        {
   1.227 +            const mwSize *dims = mxGetDimensions(matlabArray);
   1.228 +            depth = dim = 1;
   1.229 +            width =  (unsigned)dims[1];
   1.230 +            height = (unsigned)dims[0];
   1.231 +            if (nbdims == 4)
   1.232 +            {
   1.233 +                depth = (unsigned)dims[2];
   1.234 +                dim =   (unsigned)dims[3];
   1.235 +            }
   1.236 +            else if (nbdims == 3)
   1.237 +            {
   1.238 +                if (vdata)
   1.239 +                {
   1.240 +                    dim = (unsigned)dims[2];
   1.241 +                }
   1.242 +                else
   1.243 +                {
   1.244 +                    depth = (unsigned)dims[2];
   1.245 +                }
   1.246 +            }
   1.247 +
   1.248 +            data = new T[size()];
   1.249 +            makeImageFromMatlabData(matlabArray, classID);
   1.250 +        }
   1.251 +    }
   1.252 +
   1.253 +    /*******************************************************************
   1.254 +     * operator=(). Copy  mxMarray data mArray into the current image
   1.255 +     * Works as the previous constructor, but without the vdata stuff.
   1.256 +     * don't know if it is of any use...
   1.257 +     */
   1.258 +    CImg & operator=(const mxArray *matlabArray)
   1.259 +    {
   1.260 +        int nbdims = (int)mxGetNumberOfDimensions(matlabArray);
   1.261 +        int classID = mxGetClassID(matlabArray);
   1.262 +        if (nbdims > 4 || !isNumericalClassID(classID))
   1.263 +        {
   1.264 +            delete [] data;
   1.265 +            data = NULL;
   1.266 +            width=height=depth=dim=0;
   1.267 +#if cimg_debug>1
   1.268 +            cimg::warn("MATLAB array is more than 4D or/and "
   1.269 +                       "not numerical, returning null image.");
   1.270 +#endif
   1.271 +        }
   1.272 +        else
   1.273 +        {
   1.274 +            const mwSize *dims = mxGetDimensions(matlabArray);
   1.275 +            depth = dim = 1;
   1.276 +            width =  (unsigned)dims[1];
   1.277 +            height = (unsigned)dims[0];
   1.278 +            if (nbdims > 2)
   1.279 +            {
   1.280 +                depth = (unsigned)dims[2];
   1.281 +            }
   1.282 +            if (nbdims > 3)
   1.283 +            {
   1.284 +                dim = (unsigned)dims[3];
   1.285 +            }
   1.286 +
   1.287 +            delete [] data;
   1.288 +            data = new T[size()];
   1.289 +
   1.290 +            makeImageFromMatlabData(matlabArray, classID);
   1.291 +        }
   1.292 +    }
   1.293 +
   1.294 +private:
   1.295 +    /*****************************************************************
   1.296 +     * private routines used for transfering a CImg<T> to a mxArray
   1.297 +     * here also, we have to exchange the x and y dims so we get the
   1.298 +     * expected MATLAB array.
   1.299 +     */
   1.300 +    template <typename c> void populate_maltlab_array(c *mdata) const
   1.301 +    {
   1.302 +        cimg_forXYZV(*this, x, y, z, v)
   1.303 +        {
   1.304 +            mdata[((v*depth + z)*width+x)*height+y] = (c)(*this)(x, y, z, v);
   1.305 +        }
   1.306 +    }
   1.307 +
   1.308 +    /*************************************************
   1.309 +     * the specialized version for "logical" entries
   1.310 +     */
   1.311 +    void populate_maltlab_array(mxLogical *mdata) const
   1.312 +    {
   1.313 +        cimg_forXYZV(*this, x, y, z, v)
   1.314 +        {
   1.315 +            mdata[((v*depth + z)*width+x)*height+y] = (mxLogical)((*this)(x, y, z, v)!=0);
   1.316 +        }
   1.317 +    }
   1.318 +
   1.319 +public:
   1.320 +    /******************************************
   1.321 +     * export a CImg image to a MATLAB array.
   1.322 +     **/
   1.323 +    mxArray *toMatlab(mxClassID classID = mxDOUBLE_CLASS, bool squeeze = false) const
   1.324 +    {
   1.325 +        if (!isNumericalClassID(classID))
   1.326 +        {
   1.327 +#if cimg_debug>1
   1.328 +            cimg::warn("Invalid MATLAB Class Id Specified.");
   1.329 +#endif
   1.330 +            return NULL;
   1.331 +        }
   1.332 +
   1.333 +        mwSize dims[4];
   1.334 +        dims[0] = (mwSize)height;
   1.335 +        dims[1] = (mwSize)width;
   1.336 +        dims[2] = (mwSize)depth;
   1.337 +        dims[3] = (mwSize)dim;
   1.338 +
   1.339 +        if (squeeze && depth == 1)
   1.340 +        {
   1.341 +            dims[2] = (mwSize)dim;
   1.342 +            dims[3] = (mwSize)1;
   1.343 +        }
   1.344 +
   1.345 +        mxArray *matlabArray = mxCreateNumericArray((mwSize)4, dims, classID, mxREAL);
   1.346 +
   1.347 +        if (classID == mxLOGICAL_CLASS)
   1.348 +        {
   1.349 +            mxLogical *mdata = mxGetLogicals(matlabArray);
   1.350 +            populate_maltlab_array(mdata);
   1.351 +        }
   1.352 +        else
   1.353 +        {
   1.354 +            void *mdata = mxGetPr(matlabArray);
   1.355 +            switch (classID) {
   1.356 +            case mxDOUBLE_CLASS:
   1.357 +                populate_maltlab_array((real64_T *)mdata);
   1.358 +                break;
   1.359 +            case mxSINGLE_CLASS:
   1.360 +                populate_maltlab_array((real32_T *)mdata);
   1.361 +                break;
   1.362 +            case mxINT8_CLASS:
   1.363 +                populate_maltlab_array((int8_T *)mdata);
   1.364 +                break;
   1.365 +            case mxUINT8_CLASS:
   1.366 +                populate_maltlab_array((uint8_T *)mdata);
   1.367 +                break;
   1.368 +            case mxINT16_CLASS:
   1.369 +                populate_maltlab_array((int16_T *)mdata);
   1.370 +                break;
   1.371 +            case mxUINT16_CLASS:
   1.372 +                populate_maltlab_array((uint16_T *)mdata);
   1.373 +                break;
   1.374 +            case mxINT32_CLASS:
   1.375 +                populate_maltlab_array((int32_T *)mdata);
   1.376 +                break;
   1.377 +            case mxUINT32_CLASS:
   1.378 +                populate_maltlab_array((uint32_T *)mdata);
   1.379 +                break;
   1.380 +            case mxINT64_CLASS:
   1.381 +                populate_maltlab_array((int64_T *)mdata);
   1.382 +                break;
   1.383 +            case mxUINT64_CLASS:
   1.384 +                populate_maltlab_array((uint64_T *)mdata);
   1.385 +                break;
   1.386 +            }
   1.387 +        }
   1.388 +        return matlabArray;
   1.389 +    }
   1.390 +
   1.391 +// end of cimgmatlab.h