00001 /*!@file Matlab/mexConverts.C conversions from and to MEX arrays 00002 */ 00003 00004 // //////////////////////////////////////////////////////////////////// // 00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00006 // University of Southern California (USC) and the iLab at USC. // 00007 // See http://iLab.usc.edu for information about this project. // 00008 // //////////////////////////////////////////////////////////////////// // 00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00011 // in Visual Environments, and Applications'' by Christof Koch and // 00012 // Laurent Itti, California Institute of Technology, 2001 (patent // 00013 // pending; application number 09/912,225 filed July 23, 2001; see // 00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00015 // //////////////////////////////////////////////////////////////////// // 00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00017 // // 00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00019 // redistribute it and/or modify it under the terms of the GNU General // 00020 // Public License as published by the Free Software Foundation; either // 00021 // version 2 of the License, or (at your option) any later version. // 00022 // // 00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00026 // PURPOSE. See the GNU General Public License for more details. // 00027 // // 00028 // You should have received a copy of the GNU General Public License // 00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00031 // Boston, MA 02111-1307 USA. // 00032 // //////////////////////////////////////////////////////////////////// // 00033 // 00034 // Primary maintainer for this file: Dirk Walther <walther@caltech.edu> 00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Matlab/mexConverts.C $ 00036 // $Id: mexConverts.C 9412 2008-03-10 23:10:15Z farhan $ 00037 // 00038 00039 #include "Matlab/mexConverts.H" 00040 00041 #include "Image/Image.H" 00042 #include "Image/Pixels.H" 00043 #include "Matlab/mexLog.H" 00044 #include "Util/sformat.H" 00045 #include "rutz/shared_ptr.h" 00046 00047 // ###################################################################### 00048 template <class T> 00049 Image<T> mexArray2Image(const mxArray* arrptr) 00050 { 00051 const int* intptr = mxGetDimensions(arrptr); 00052 const int num_dim = mxGetNumberOfDimensions(arrptr); 00053 const int height = *intptr++; 00054 const int width = *intptr++; 00055 00056 // check whether we actually have a 2D array 00057 if (num_dim != 2) 00058 mexFatal(sformat("Wrong number of dimensions for gray scale image: %i " 00059 "- should be 2.",num_dim)); 00060 00061 // convert UINT8 or double array into an Image object 00062 Image<T> img(width, height, NO_INIT); 00063 00064 if (mxIsUint8(arrptr)) 00065 { 00066 const byte *src_ptr, *src_ptr2; 00067 src_ptr = (byte*)mxGetPr(arrptr); 00068 typename Image<T>::iterator tgt_ptr = img.beginw(); 00069 for (int y = 0; y < height; y++) 00070 { 00071 src_ptr2 = src_ptr; 00072 for (int x = 0; x < width; x++) 00073 { 00074 conv(src_ptr2,&*(tgt_ptr++)); 00075 src_ptr2 += height; 00076 } 00077 src_ptr++; 00078 } 00079 } 00080 else if (mxIsDouble(arrptr)) 00081 { 00082 const double *src_ptr, *src_ptr2; 00083 src_ptr = (double*)mxGetPr(arrptr); 00084 typename Image<T>::iterator tgt_ptr = img.beginw(); 00085 for (int y = 0; y < height; y++) 00086 { 00087 src_ptr2 = src_ptr; 00088 for (int x = 0; x < width; x++) 00089 { 00090 conv(src_ptr2,&*(tgt_ptr++)); 00091 src_ptr2 += height; 00092 } 00093 src_ptr++; 00094 } 00095 } 00096 else mexFatal("Image data type must be uint8 or double."); 00097 00098 return img; 00099 } 00100 00101 00102 // ###################################################################### 00103 template <class T> 00104 Image< PixRGB<T> > mexArray2RGBImage(const mxArray* arrptr) 00105 { 00106 const int* intptr = mxGetDimensions(arrptr); 00107 const int num_dim = mxGetNumberOfDimensions(arrptr); 00108 const int height = *intptr++; 00109 const int width = *intptr++; 00110 const int size = width * height; 00111 int RGBcount = 0; 00112 00113 // check whether we have RGB or grayscale image 00114 if (num_dim > 2) 00115 { 00116 if (*intptr == 3) RGBcount = size; 00117 else if (*intptr != 1) 00118 mexFatal(sformat("Wrong number of dimensions for image: %d " 00119 "- should be 2 for grayscale or 3 for RGB",num_dim)); 00120 } 00121 int RGBcount2 = RGBcount + RGBcount; 00122 00123 // convert UINT8 or double array into an Image object 00124 Image< PixRGB<T> > img(width, height, NO_INIT); 00125 if (mxIsUint8(arrptr)) 00126 { 00127 const byte *src_ptr, *src_ptr2; 00128 src_ptr = (byte*)mxGetPr(arrptr); 00129 T dummy; 00130 typename Image<PixRGB<T> >::iterator tgt_ptr = img.beginw(); 00131 for (int y = 0; y < height; y++) 00132 { 00133 src_ptr2 = src_ptr; 00134 for (int x = 0; x < width; x++) 00135 { 00136 tgt_ptr->setRed (conv(src_ptr2, &dummy)); 00137 tgt_ptr->setGreen(conv(src_ptr2 + RGBcount, &dummy)); 00138 tgt_ptr->setBlue (conv(src_ptr2 + RGBcount2, &dummy)); 00139 tgt_ptr++; 00140 src_ptr2 += height; 00141 } 00142 src_ptr++; 00143 } 00144 } 00145 else if (mxIsDouble(arrptr)) 00146 { 00147 const double *src_ptr, *src_ptr2; 00148 src_ptr = (double*)mxGetPr(arrptr); 00149 T dummy; 00150 typename Image<PixRGB<T> >::iterator tgt_ptr = img.beginw(); 00151 for (int y = 0; y < height; y++) 00152 { 00153 src_ptr2 = src_ptr; 00154 for (int x = 0; x < width; x++) 00155 { 00156 tgt_ptr->setRed (conv(src_ptr2, &dummy)); 00157 tgt_ptr->setGreen(conv(src_ptr2 + RGBcount, &dummy)); 00158 tgt_ptr->setBlue (conv(src_ptr2 + RGBcount2, &dummy)); 00159 tgt_ptr++; 00160 src_ptr2 += height; 00161 } 00162 src_ptr++; 00163 } 00164 } 00165 else mexFatal("Image data type must be uint8 or double."); 00166 00167 return img; 00168 } 00169 00170 // ###################################################################### 00171 template <class T> 00172 mxArray* Image2mexArray(const Image<T>& img) 00173 { 00174 if (img.getSize() == 0) return mxCreateScalarDouble(0); 00175 double *tgt_ptr, *tgt_ptr2; 00176 int height = img.getHeight(), width = img.getWidth(); 00177 mxArray* arrptr = mxCreateDoubleMatrix(height, width, mxREAL); 00178 tgt_ptr = (double*)mxGetPr(arrptr); 00179 typename Image<T>::const_iterator src_ptr = img.begin(); 00180 for (int y = 0; y < height; y++) 00181 { 00182 tgt_ptr2 = tgt_ptr; 00183 for (int x = 0; x < width; x++) 00184 { 00185 conv(&*(src_ptr++),tgt_ptr2); 00186 tgt_ptr2 += height; 00187 } 00188 tgt_ptr++; 00189 } 00190 return arrptr; 00191 } 00192 00193 // ###################################################################### 00194 mxArray* Image2mexArrayUint8(const Image<byte>* img) 00195 { 00196 const int height = img->getHeight(); 00197 const int width = img->getWidth(); 00198 mxArray* arrptr = 00199 mxCreateNumericMatrix(height, width, mxUINT8_CLASS, mxREAL); 00200 byte* tgt_ptr = reinterpret_cast<byte*>(mxGetPr(arrptr)); 00201 Image<byte>::const_iterator src_ptr = img->begin(); 00202 for (int y = 0; y < height; ++y) 00203 { 00204 byte* tgt_ptr2 = tgt_ptr; 00205 for (int x = 0; x < width; ++x) 00206 { 00207 *tgt_ptr2 = *src_ptr++; 00208 tgt_ptr2 += height; 00209 } 00210 ++tgt_ptr; 00211 } 00212 return arrptr; 00213 } 00214 00215 // ###################################################################### 00216 template <class T> 00217 mxArray* RGBImage2mexArray(const Image< PixRGB<T> >& img) 00218 { 00219 if (img.getSize() == 0) return mxCreateScalarDouble(0); 00220 double *tgt_ptr, *tgt_ptr2; 00221 T r, g, b; 00222 int dims[3]; 00223 dims[0] = img.getHeight(); 00224 dims[1] = img.getWidth(); 00225 dims[2] = 3; 00226 int size = dims[0] * dims[1], size2 = size + size; 00227 mxArray* arrptr = mxCreateNumericArray(3, dims, mxDOUBLE_CLASS, mxREAL); 00228 tgt_ptr = (double*)mxGetPr(arrptr); 00229 typename Image<PixRGB<T> >::const_iterator src_ptr = img.begin(); 00230 for (int y = 0; y < dims[0]; y++) 00231 { 00232 tgt_ptr2 = tgt_ptr; 00233 for (int x = 0; x < dims[1]; x++) 00234 { 00235 r = src_ptr->red(); g = src_ptr->green(); b = src_ptr->blue(); 00236 conv(&r,tgt_ptr2); conv(&g,tgt_ptr2 + size); conv(&b, tgt_ptr2 + size2); 00237 src_ptr++; 00238 tgt_ptr2 += dims[0]; 00239 } 00240 tgt_ptr++; 00241 } 00242 return arrptr; 00243 } 00244 00245 // ###################################################################### 00246 mxArray* RGBImage2mexArrayUint8(const Image< PixRGB<byte> >* img) 00247 { 00248 const int dims[3] = 00249 { 00250 img->getHeight(), 00251 img->getWidth(), 00252 3 00253 }; 00254 const int size = dims[0] * dims[1]; 00255 const int size2 = size + size; 00256 mxArray* arrptr = 00257 mxCreateNumericArray(3, dims, mxUINT8_CLASS, mxREAL); 00258 byte* tgt_ptr = reinterpret_cast<byte*>(mxGetPr(arrptr)); 00259 Image<PixRGB<byte> >::const_iterator src_ptr = img->begin(); 00260 00261 for (int y = 0; y < dims[0]; ++y) 00262 { 00263 byte* tgt_ptr2 = tgt_ptr; 00264 for (int x = 0; x < dims[1]; ++x) 00265 { 00266 tgt_ptr2[0] = src_ptr->red(); 00267 tgt_ptr2[size] = src_ptr->green(); 00268 tgt_ptr2[size2] = src_ptr->blue(); 00269 ++src_ptr; 00270 tgt_ptr2 += dims[0]; 00271 } 00272 ++tgt_ptr; 00273 } 00274 00275 return arrptr; 00276 } 00277 00278 // ###################################################################### 00279 template <class T> 00280 std::vector<T> mexArr2Vector(const mxArray* vecptr, uint num_elements) 00281 { 00282 if (!mxIsDouble(vecptr)) 00283 mexErrMsgTxt("Can only convert vectors of type double."); 00284 if((uint)mxGetNumberOfElements(vecptr) < num_elements) 00285 mexErrMsgTxt("Not enough data to convert to vector."); 00286 00287 double* src_ptr = (double*)mxGetPr(vecptr); 00288 std::vector<T> result; 00289 for (uint i = 0; i < num_elements; i++) 00290 result.push_back((T)(*src_ptr++)); 00291 00292 return result; 00293 } 00294 00295 // ###################################################################### 00296 template <class T> 00297 std::vector<T> mexArr2Vector(const mxArray* vecptr) 00298 { 00299 return mexArr2Vector<T>(vecptr, (uint)mxGetNumberOfElements(vecptr)); 00300 } 00301 00302 // ###################################################################### 00303 template <class T> 00304 mxArray* Vector2mexArr(const std::vector<T>& vect, uint num_elements) 00305 { 00306 if (vect.size() < num_elements) 00307 mexFatal(sformat("std::vector too small to convert to mxArray: " 00308 "%"ZU", but should be %d.",vect.size(),num_elements)); 00309 00310 if (vect.empty()) return mxCreateScalarDouble(0); 00311 00312 mxArray* result = mxCreateDoubleMatrix(1, num_elements, mxREAL); 00313 double* tgt_ptr = (double*)mxGetPr(result); 00314 for (uint i = 0; i < num_elements; i++) 00315 *tgt_ptr++ = (double)vect[i]; 00316 return result; 00317 } 00318 00319 // ###################################################################### 00320 template <class T> 00321 mxArray* Vector2mexArr(const std::vector<T>& vect) 00322 { 00323 return Vector2mexArr(vect, vect.size()); 00324 } 00325 00326 // ###################################################################### 00327 std::vector<Point2D<int> > mexArr2Point2DVec(const mxArray* arrptr) 00328 { 00329 if (!mxIsDouble(arrptr)) 00330 mexFatal("Can only convert vectors of type double."); 00331 if (mxGetNumberOfDimensions(arrptr) != 2) 00332 mexFatal("mxArray must be 2D to be converted to vector<Point2D<int> >."); 00333 if (mxGetM(arrptr) != 2) 00334 mexFatal("mxArray must be of dimensions 2 x N to be converted " 00335 "to vector<Point2D<int> >"); 00336 int n = mxGetN(arrptr); 00337 const double* src_ptr = (double*) mxGetPr(arrptr); 00338 std::vector<Point2D<int> > result; 00339 00340 for (int i = 0; i < n; i++) 00341 { 00342 result.push_back(Point2D<int>((int)src_ptr[0], (int)src_ptr[1])); 00343 src_ptr += 2; 00344 } 00345 return result; 00346 } 00347 00348 // ###################################################################### 00349 mxArray* Point2DVec2mexArr(const std::vector<Point2D<int> >& vect) 00350 { 00351 if (vect.empty()) return mxCreateScalarDouble(0); 00352 mxArray* result = mxCreateDoubleMatrix(2, vect.size(), mxREAL); 00353 double* tgt_ptr = (double*)mxGetPr(result); 00354 for (uint i = 0; i < vect.size(); i++) 00355 { 00356 *tgt_ptr++ = (double)vect[i].i; 00357 *tgt_ptr++ = (double)vect[i].j; 00358 } 00359 return result; 00360 } 00361 00362 // ###################################################################### 00363 template <class T> 00364 mxArray* ImgVec2mexArr(const ImageSet<T>& vect) 00365 { 00366 if (vect.isEmpty()) return mxCreateScalarDouble(0); 00367 00368 int dims[3]; 00369 dims[0] = vect.size(); 00370 dims[1] = vect[0].getHeight(); 00371 dims[2] = vect[0].getWidth(); 00372 int inc = dims[0] * dims[1]; 00373 mxArray* result = mxCreateNumericArray(3, dims, mxDOUBLE_CLASS, mxREAL); 00374 double *tgt, *tgt2, *tgt3; 00375 tgt = (double*)mxGetPr(result); 00376 00377 for (int i = 0; i < dims[0]; i++) 00378 { 00379 tgt2 = tgt; 00380 if (!vect[i].isSameSize(vect[0])) 00381 mexFatal("All images in an ImageSet must have the same dimensions."); 00382 typename Image<T>::const_iterator src = vect[i].begin(); 00383 for (int y = 0; y < dims[1]; y++) 00384 { 00385 tgt3 = tgt2; 00386 for (int x = 0; x < dims[2]; x++) 00387 { 00388 conv(&*(src++),tgt3); 00389 tgt3 += inc; 00390 } 00391 tgt2 += dims[0]; 00392 } 00393 tgt++; 00394 } 00395 return result; 00396 } 00397 00398 // ###################################################################### 00399 template <class T> 00400 ImageSet<T> mexArr2ImgVec(const mxArray* arrptr) 00401 { 00402 const int num_dim = mxGetNumberOfDimensions(arrptr); 00403 const int* dims = mxGetDimensions(arrptr); 00404 int num_img=0, height=0, width=0; 00405 00406 switch(num_dim) 00407 { 00408 case 2: // just a single image -> create just one element of the vector 00409 { 00410 num_img = 1; 00411 height = dims[0]; 00412 width = dims[1]; 00413 break; 00414 } 00415 00416 case 3: // multiple images -> how many and how big? 00417 { 00418 num_img = dims[0]; 00419 height = dims[1]; 00420 width = dims[2]; 00421 break; 00422 } 00423 00424 default: 00425 { 00426 mexFatal(sformat("Array must have 2 or 3 dimensions to be converted to " 00427 "a grayscale image vector, but not %d.",num_dim)); 00428 break; 00429 } 00430 } 00431 const int inc = num_img * height; 00432 ImageSet<T> result(num_img, Dims(dims[2], dims[1]), NO_INIT); 00433 00434 if (mxIsUint8(arrptr)) 00435 { 00436 const byte *src, *src2, *src3; 00437 src = (byte*)mxGetPr(arrptr); 00438 for (int img_no = 0; img_no < num_img; ++img_no) 00439 { 00440 src2 = src; 00441 typename Image<T>::iterator tgt = result[img_no].beginw(); 00442 for (int y = 0; y < height; ++y) 00443 { 00444 src3 = src2; 00445 for (int x = 0; x < width; ++x) 00446 { 00447 conv(src3,&*(tgt++)); 00448 src3 += inc; 00449 } 00450 src2 += num_img; 00451 } 00452 src++; 00453 } 00454 } 00455 else if (mxIsDouble(arrptr)) 00456 { 00457 const double *src, *src2, *src3; 00458 src = (double*)mxGetPr(arrptr); 00459 for (int img_no = 0; img_no < num_img; ++img_no) 00460 { 00461 src2 = src; 00462 typename Image<T>::iterator tgt = result[img_no].beginw(); 00463 for (int y = 0; y < height; ++y) 00464 { 00465 src3 = src2; 00466 for (int x = 0; x < width; ++x) 00467 { 00468 conv(src3,&*(tgt++)); 00469 src3 += inc; 00470 } 00471 src2 += num_img; 00472 } 00473 src++; 00474 } 00475 } 00476 else mexFatal("Image data type must be uint8 or double."); 00477 00478 return result; 00479 } 00480 00481 // ###################################################################### 00482 template <class T> 00483 mxArray* ImageSet2cellArr(const ImageSet<T>& imset) 00484 { 00485 int num = imset.size(); 00486 mxArray *result = mxCreateCellArray(1,&num); 00487 00488 for (int i = 0; i < num; ++i) 00489 mxSetCell(result,i,Image2mexArray(imset[i])); 00490 00491 return result; 00492 } 00493 00494 // ###################################################################### 00495 template <class T> 00496 ImageSet<T> cellArr2ImageSet(const mxArray* arrptr) 00497 { 00498 if (!mxIsCell(arrptr)) mexFatal("cellArr2ImageSet: expected cell array"); 00499 00500 int num = mxGetNumberOfElements(arrptr); 00501 ImageSet<T> result(num); 00502 00503 for (int i = 0; i < num; ++i) 00504 result[i] = mexArray2Image<T>(mxGetCell(arrptr,i)); 00505 00506 return result; 00507 } 00508 00509 // ###################################################################### 00510 template <class T> 00511 mxArray* ImageSetVec2cellArr(const std::vector< ImageSet<T> >& vec) 00512 { 00513 int dims[2],idx[2]; 00514 dims[0] = vec.size(); 00515 dims[1] = vec.size(); 00516 00517 mxArray *result = mxCreateCellArray(2,dims); 00518 00519 for (idx[0] = 0; idx[0] < dims[0]; ++idx[0]) 00520 for (idx[1] = 0; idx[1] < dims[1]; ++idx[1]) 00521 { 00522 int sub = mxCalcSingleSubscript(result,2,idx); 00523 mxSetCell(result,sub,Image2mexArray(vec[idx[0]][idx[1]])); 00524 } 00525 return result; 00526 } 00527 00528 // ###################################################################### 00529 template <class T> 00530 std::vector< ImageSet<T> > cellArr2ImageSetVec(const mxArray* arrptr) 00531 { 00532 if (!mxIsCell(arrptr)) mexFatal("arrPtr needs to be a 2D cell array."); 00533 00534 if (mxGetNumberOfDimensions(arrptr) == 1) 00535 { 00536 std::vector< ImageSet<T> > result(1); 00537 result[0] = cellArr2ImageSet<T>(arrptr); 00538 return result; 00539 } 00540 else if (mxGetNumberOfDimensions(arrptr) != 2) 00541 mexFatal("arrPtr needs to be a 2D cell array."); 00542 00543 int numSets = mxGetM(arrptr); 00544 int numImgs = mxGetN(arrptr); 00545 int idx[2]; 00546 00547 std::vector< ImageSet<T> > result(numSets,ImageSet<T>(uint(numImgs))); 00548 00549 for (idx[0] = 0; idx[0] < numSets; ++idx[0]) 00550 for (idx[1] = 0; idx[1] < numImgs; ++idx[1]) 00551 { 00552 int sub = mxCalcSingleSubscript(arrptr,2,idx); 00553 result[idx[0]][idx[1]] = mexArray2Image<T>(mxGetCell(arrptr,sub)); 00554 } 00555 return result; 00556 } 00557 00558 // ###################################################################### 00559 // ###### member functions for class MexReturn 00560 // ###################################################################### 00561 MexReturn::MexReturn(int nlhs, mxArray **plhs) 00562 : itsNlhs(nlhs), 00563 itsPlhs(plhs) 00564 {} 00565 00566 // ###################################################################### 00567 MexReturn::~MexReturn() 00568 { 00569 bool okay = true; 00570 for(int i = 0; i < itsNlhs; ++i) 00571 if (!itsPlhs[i]) 00572 { 00573 mexError(sformat("Return argument %i is not assigned.",i+1)); 00574 okay = false; 00575 } 00576 00577 if (!okay) mexFatal("There were unassigned return arguments."); 00578 } 00579 00580 // ###################################################################### 00581 int MexReturn::numArgs() 00582 { return itsNlhs; } 00583 00584 // ###################################################################### 00585 bool MexReturn::isNumOK(int num) 00586 { return ((num >= 0) && (num < numArgs())); } 00587 00588 // ###################################################################### 00589 bool MexReturn::store(int num, mxArray *val) 00590 { 00591 if (!isNumOK(num)) return false; 00592 itsPlhs[num] = val; 00593 return true; 00594 } 00595 00596 // ###################################################################### 00597 bool MexReturn::store(int num, double val) 00598 { return store(num,mxCreateScalarDouble(val)); } 00599 00600 // ###################################################################### 00601 template <class T> 00602 bool MexReturn::store(int num, const std::vector<T>& val) 00603 { 00604 if (!isNumOK(num)) return false; 00605 return store(num,Vector2mexArr(val)); 00606 } 00607 00608 // ###################################################################### 00609 template <class T> 00610 bool MexReturn::store(int num, const Image<T>& val) 00611 { 00612 if (!isNumOK(num)) return false; 00613 return store(num,Image2mexArray(val)); 00614 } 00615 00616 // ###################################################################### 00617 template <class T> 00618 bool MexReturn::store(int num, const Image< PixRGB<T> >& val) 00619 { 00620 if (!isNumOK(num)) return false; 00621 return store(num,RGBImage2mexArray(val)); 00622 } 00623 00624 // ###################################################################### 00625 00626 00627 #define INSTANTIATE(T) \ 00628 template Image<T> mexArray2Image(const mxArray* arrptr); \ 00629 template Image< PixRGB<T> > mexArray2RGBImage(const mxArray* arrptr); \ 00630 template mxArray* Image2mexArray(const Image<T>& img); \ 00631 template mxArray* RGBImage2mexArray(const Image< PixRGB<T> >& img); \ 00632 template mxArray* ImgVec2mexArr(const ImageSet<T>& vect); \ 00633 template ImageSet<T> mexArr2ImgVec(const mxArray* arrptr); \ 00634 template mxArray* ImageSet2cellArr(const ImageSet<T>& imset); \ 00635 template ImageSet<T> cellArr2ImageSet(const mxArray* arrptr); \ 00636 template mxArray* ImageSetVec2cellArr(const std::vector< ImageSet<T> >& vec); \ 00637 template std::vector< ImageSet<T> > cellArr2ImageSetVec(const mxArray* arrptr); \ 00638 template bool MexReturn::store(int num, const Image<T>& val); \ 00639 template bool MexReturn::store(int num, const Image< PixRGB<T> >& val); \ 00640 00641 00642 INSTANTIATE(byte); 00643 INSTANTIATE(float); 00644 00645 // Also instantiate these for doubles: 00646 template mxArray* Image2mexArray(const Image<double>& img); 00647 00648 #define INSTANTIATE2(T) \ 00649 template std::vector<T> mexArr2Vector(const mxArray* vecptr, uint num_elements); \ 00650 template std::vector<T> mexArr2Vector(const mxArray* vecptr); \ 00651 template mxArray* Vector2mexArr(const std::vector<T>& vect, uint num_elements); \ 00652 template mxArray* Vector2mexArr(const std::vector<T>& vect); \ 00653 template bool MexReturn::store(int num, const std::vector<T>& val); \ 00654 00655 INSTANTIATE2(byte); 00656 INSTANTIATE2(float); 00657 INSTANTIATE2(int); 00658 INSTANTIATE2(double); 00659 00660 00661 // ###################################################################### 00662 /* So things look consistent in everyone's emacs... */ 00663 /* Local Variables: */ 00664 /* indent-tabs-mode: nil */ 00665 /* End: */