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