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