Xmipp  v3.23.11-Nereus
xmipp_image_generic.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Authors: Joaquin Oton (joton@cnb.csic.es)
3  *
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
26 #include "xmipp_image.h"
27 #include "xmipp_image_generic.h"
28 #include "xmipp_image_extension.h"
29 #include "xmipp_error.h"
30 #include "xmipp_fftw.h"
31 #include "xmipp_types.h"
32 #include "xvsmooth.h"
33 #include "metadata_static.h"
34 #include "metadata_base.h"
35 
36 void ImageGeneric::initGeometry(const size_t n)
37 {
38  MDL::emptifyHeader(*(image->MD[n]));
39 }
40 
42 {
43  init();
44  setDatatype(_datatype);
45 }
46 
48 {
49  init();
50  read(filename);
51 }
52 
54 {
55  init();
56  copy(img);
57 }
58 
60 {
61  delete image;
62  delete data;
63 }
64 
66 {
67  image = NULL;
68  data = NULL;
70 }
71 
73 {
74  if (image != NULL)
75  {
76  image->clear();
77  delete image;
78  delete data;
79  init();
80  }
81 }
82 
84 {
85  if (img.datatype != DT_Unknown)
86  {
87  setDatatype(img.datatype);
88 #define COPY(type) (*(Image<type>*)image) = (*(Image<type>*)img.image);
89 
91 #undef COPY
92 
93  }
94 
95 }
96 
97 void ImageGeneric::getDimensions(size_t & xdim, size_t & ydim, size_t & Zdim) const
98 {
99  size_t Ndim;
100  image->getDimensions(xdim, ydim, Zdim, Ndim);
101 }
102 
103 void ImageGeneric::getDimensions(size_t & xdim, size_t & ydim, size_t & Zdim, size_t & Ndim) const
104 {
105  image->getDimensions(xdim, ydim, Zdim, Ndim);
106 }
107 
109 {
110  image->getDimensions(aDim);
111 }
112 
113 void ImageGeneric::getInfo(ImageInfo &imgInfo) const
114 {
115  image->getInfo(imgInfo);
116 }
117 
119 {
120  if (imgType == datatype)
121  return;
122 
123  clear();
124  datatype = imgType;
125  switch (datatype)
126  {
127  case DT_Float:
128  {
129  Image<float> *imT = new Image<float>;
130  image = imT;
132  }
133  break;
134  case DT_Double:
135  {
136  Image<double> *imT = new Image<double>;
137  image = imT;
139  }
140  break;
141  case DT_UInt:
142  {
144  image = imT;
146  }
147  break;
148  case DT_Int:
149  {
150  Image<int> *imT = new Image<int>;
151  image = imT;
153  }
154  break;
155  case DT_UShort:
156  {
158  image = imT;
160  }
161  break;
162  case DT_Short:
163  {
164  Image<short> *imT = new Image<short>;
165  image = imT;
167  }
168  break;
169  case DT_UHalfByte:
170  case DT_UChar:
171  {
173  image = imT;
175  }
176  break;
177  case DT_SChar:
178  {
179  Image<char> *imT = new Image<char>;
180  image = imT;
182  }
183  break;
184  case DT_ULong:
185  {
187  image = imT;
189  }
190  break;
191  case DT_Long:
192  {
193  Image<long> *imT = new Image<long>;
194  image = imT;
196  }
197  break;
198  case DT_HalfFloat:
199  {
201  image = imT;
203  }
204  break;
205  case DT_Unknown:
206  REPORT_ERROR(ERR_IMG_UNKNOWN,"Datatype of the image file is unknown.");
207  break;
208  default:
209  REPORT_ERROR(ERR_NOT_IMPLEMENTED, "Datatype not implemented.");
210  break;
211  }
212 }
213 
214 void ImageGeneric::setDatatype(const FileName &name, ImageInfo &imgInf)
215 {
216  getImageInfo(name, imgInf);
217  checkImageFileSize(name, imgInf, true);
218  setDatatype(imgInf.datatype);
219 
220 }
221 
222 #define SET_DATATYPE(name) ImageInfo imgInf; setDatatype(name, imgInf);
223 
225 {
226  SET_DATATYPE(name);
227 }
228 
229 int ImageGeneric::read(const FileName &name, DataMode datamode, size_t select_img,
230  bool mapData)
231 {
232  SET_DATATYPE(name);
233  return image->read(name, datamode, select_img, mapData && !imgInf.swap);
234 }
235 
236 int ImageGeneric::readMapped(const FileName &name, size_t select_img, int mode)
237 {
238  SET_DATATYPE(name);
239  return image->read(name, DATA, select_img, !imgInf.swap, mode);
240 }
241 
242 int ImageGeneric::readOrReadMapped(const FileName &name, size_t select_img, int mode)
243 {
244  try
245  {
246  return read(name, DATA, select_img, false);
247  }
248  catch (XmippError &xe)
249  {
250  if (xe.__errno == ERR_MEM_NOTENOUGH)
251  {
252  reportWarning("ImageBase::readOrReadMapped: Not enough memory to allocate. \n"
253  " Proceeding to map image from file.");
254  return readMapped(name, select_img, mode);
255  }
256  else
257  throw xe;
258  }
259 }
260 
261 double getScale(ImageInfo imgInf, size_t &xdim, size_t &ydim)
262 {
263  double scale = 0;
264  // If only xdim is passed, it is the higher allowable size, for any dimension
265  if (ydim == 0 && imgInf.adim.xdim < imgInf.adim.ydim)
266  {
267  ydim = xdim;
268  scale = ((double) ydim)/((double) imgInf.adim.ydim);
269  xdim = (int)(scale*imgInf.adim.xdim);
270  }
271  else
272  {
273  scale = ((double) xdim)/((double) imgInf.adim.xdim);
274  if (ydim == 0)
275  ydim = (int)(scale*imgInf.adim.ydim);
276  }
277  return scale;
278 }
279 
280 int ImageGeneric::readPreview(const FileName &name, size_t xdim, size_t ydim, int select_slice, size_t select_img)
281 {
282  SET_DATATYPE(name);
283  double scale = getScale(imgInf, xdim, ydim);
284  //std::cerr << "DEBUG_JM: readPreview, scale: " << scale << std::endl;
285 
286  if (scale < 0.1)
287  return readPreviewSmooth(name, xdim, ydim, select_slice, select_img);
288  return image->readPreview(name, xdim, ydim, select_slice, select_img);
289 }
290 
291 int ImageGeneric::readOrReadPreview(const FileName &name, size_t xdim, size_t ydim, int select_slice, size_t select_img,
292  bool mapData, bool wrap)
293 {
294  SET_DATATYPE(name);
295  double scale = getScale(imgInf, xdim, ydim);
296  //std::cerr << "DEBUG_JM: readOrReadPreview, scale: " << scale << std::endl;
297 
298  if (scale < 0.1)
299  return readPreviewSmooth(name, xdim, ydim, select_slice, select_img);
300  return image->readOrReadPreview(name, xdim, ydim, select_slice, select_img, !imgInf.swap && mapData);
301 }
302 
303 void ImageGeneric::getPreview(ImageGeneric &imgOut, int xdim, int ydim, int select_slice, size_t select_img)
304 {
305  imgOut.setDatatype(getDatatype());
306  image->getPreview(imgOut.image, xdim, ydim, select_slice, select_img);
307 }
308 
309 
310 int ImageGeneric::readPreviewFourier(const FileName &name, size_t xdim, size_t ydim, int select_slice, size_t select_img)
311 {
312  ImageGeneric ig;
313  int result = ig.read(name, DATA, select_img);
314  ImageInfo ii;
315  ig.getInfo(ii);
316  setDatatype(ii.datatype);
317  switch (select_slice)
318  {
319  case CENTRAL_SLICE:
320  case ALL_SLICES:
321  select_slice = (int)((float)ii.adim.zdim / 2.0);
322  break;
323  default:
324  select_slice--;
325  break;
326  }
327 
328  getScale(ii, xdim, ydim);
329 
330  ig().getSlice(select_slice, data);
331 
332 
333  data->setXmippOrigin();
334  selfScaleToSizeFourier((int)ydim, (int)xdim, *data, 1);
335  return result;
336 }
337 
338 int ImageGeneric::readPreviewSmooth(const FileName &name, size_t xdim, size_t ydim, int select_slice, size_t select_img)
339 {
340  //std::cerr << "DEBUG_JM: readPreviewSmooth" << std::endl;
341  ImageGeneric ig;
342  int result = ig.read(name, DATA, select_img);
344  ImageInfo ii;
345  ig.getInfo(ii);
346 
347  getScale(ii, xdim, ydim);
348 
350  resize(xdim, ydim, 1, 1, false);
351 
352  byte *inputArray = (byte*) MULTIDIM_ARRAY_GENERIC(ig).getArrayPointer();
353  byte *outputArray = (byte*) MULTIDIM_ARRAY_GENERIC(*this).getArrayPointer();
354 
355  SmoothResize(inputArray, outputArray, ii.adim.xdim, ii.adim.ydim, xdim, ydim);
356  return result;
357 }
358 
359 
360 void ImageGeneric::mapFile2Write(int xdim, int ydim, int Zdim, const FileName &_filename,
361  bool createTempFile, size_t select_img, bool isStack,int mode, int swapWrite)
362 {
363  image->setDataMode(HEADER); // Use this to ask rw* which datatype to use
364  if (swapWrite > 0)
365  image->swapOnWrite();
366  image->mapFile2Write(xdim,ydim,Zdim,_filename,createTempFile, select_img, isStack, mode);
367 
368  DataType writeDT = image->datatype();
369 
370  if ( writeDT != datatype)
371  {
372  setDatatype(writeDT);
373 
374  image->mapFile2Write(xdim,ydim,Zdim,_filename,createTempFile, select_img, isStack, mode);
375  }
376 }
377 
378 int ImageGeneric::readApplyGeo(const FileName &name, const MDRow &row,
379  const ApplyGeoParams &params)
380 {
381  setDatatype(name);
382  return image->readApplyGeo(name, row, params);
383 }
384 
385 int ImageGeneric::readApplyGeo(const FileName &name, const MetaData &md, size_t objId,
386  const ApplyGeoParams &params)
387 {
388  setDatatype(name);
389  return image->readApplyGeo(name, md, objId, params);
390 }
391 
393 {
394  return image->mirrorY();
395 }
397 int ImageGeneric::readApplyGeo(const MetaData &md, size_t objId,
398  const ApplyGeoParams &params)
399 {
400  FileName name;
401  md.getValue(MDL_IMAGE, name, objId/*md.firstObject()*/);
402  setDatatype(name);
403  return image->readApplyGeo(name, md, objId, params);
404 }
405 
407 void ImageGeneric::applyGeo(const MetaData &md, size_t objId,
408  const ApplyGeoParams &params)
409 {
410  image->applyGeo(md, objId, params);
411 }
412 
413 
415 {
416  if (_datatype == datatype || _datatype == DT_Unknown)
417  return;
418 
419  ArrayDim aDim;
420  data->getDimensions(aDim);
421 
422  ImageBase * newImage;
423  MultidimArrayGeneric * newMAG;
424 
425 #define CONVERTTYPE(type) Image<type> *imT = new Image<type>; \
426  newImage = imT;\
427  newMAG = new MultidimArrayGeneric((MultidimArrayBase*) &(imT->data), _datatype);\
428  MultidimArray<type>* pMAG;\
429  newMAG->getMultidimArrayPointer(pMAG);\
430  if (castMode == CW_CAST)\
431  data->getImage(*pMAG);\
432  else\
433  {\
434  pMAG->resize(aDim);\
435  double min, max;\
436  data->computeDoubleMinMax(min, max);\
437  ((Image<double>*) image)->getCastConvertPageFromT(0, (char*)pMAG->data, _datatype, aDim.nzyxdim, min, max, castMode);\
438  }\
439 
440  SWITCHDATATYPE(_datatype, CONVERTTYPE)
441 
442 #undef CONVERTTYPE
443 
444  /* aDimFile must be set in order to movePointerTo can be used.
445  * If movePointerTo has been used before convert2Datatype, then
446  * only the pointed image/slice is converted, and the images/slices left
447  * are lost. This is why we set the new dimensions to the new ImageGeneric Object*/
448  newImage->setADimFile(aDim);
449 
450  clear();
451  datatype = _datatype;
452  image = newImage;
453  data = newMAG;
454 }
455 
456 
458 {
459  ArrayDim aDim, aDimOut;
460  data->getDimensions(aDim);
461 
462  char axis;
463  bool reverse;
464 
465  aDimOut = aDim;
466 
467  if (face == VIEW_Y_NEG || face == VIEW_Y_POS)
468  {
469  axis = 'Y';
470  aDimOut.ydim = aDim.zdim;
471  aDimOut.zdim = aDim.ydim;
472  reverse = (face == VIEW_Y_NEG);
473  }
474  else if (face == VIEW_X_NEG || face == VIEW_X_POS)
475  {
476  axis = 'X';
477  aDimOut.xdim = aDim.zdim;
478  aDimOut.zdim = aDim.xdim;
479  reverse = (face == VIEW_X_NEG);
480  }
481  else
482  REPORT_ERROR(ERR_VALUE_INCORRECT, formatString("reslice: not supported view %d", (int)face));
483 
484  DataType dtype = getDatatype();
485  imgOut.setDatatype(dtype);
486  imgOut().resize(aDimOut, false);
487  imgOut.image->setADimFile(aDimOut);
488 
489  MultidimArrayGeneric imTemp;
490 
491  int index;
492 
493  for (size_t k = 0; k < aDimOut.zdim; k++)
494  {
495  imTemp.aliasSlice(MULTIDIM_ARRAY_GENERIC(imgOut), k);
496  index = k + (aDimOut.zdim - 1 - 2*k) * (int)reverse;
497  MULTIDIM_ARRAY_GENERIC(*this).getSlice(index, &imTemp, axis, !reverse);
498  }
499 
500 }
501 
503 {
504  ImageGeneric imgOut;
505  reslice(face, imgOut);
506  clear();
507  datatype = imgOut.getDatatype();
508  image = imgOut.image;
509  data = imgOut.data;
510  imgOut.image = NULL;
511  imgOut.data = NULL;
512 }
513 
514 
516 {
517  copy(img);
518  return *this;
519 }
520 
522 {
523  return(*(this->data) == *(i1.data));
524 }
525 
527 {
528  String s;
529  toString(s);
530  std::cout << s <<std::endl;
531 }
532 
534 {
535  std::stringstream ss;
536  if (image == NULL)
537  ss << "Xmipp::ImageGeneric: Uninitialized image";
538  else
539  ss << *image;
540  s = ss.str();
541 }
542 
544 {
545  if (datatype != img.datatype)
546  REPORT_ERROR(ERR_TYPE_INCORRECT, "Images have different datatypes");
547 
548 #define ADD(type) MultidimArray<type> & kk = *((MultidimArray<type>*) data->im);\
549  MultidimArray<type> & pp = *((MultidimArray<type>*) img.data->im);\
550  kk += pp;
551 
553 #undef ADD
554 
555 }
556 
558 {
559  if (datatype != img.datatype)
560  REPORT_ERROR(ERR_TYPE_INCORRECT, "Images have different datatypes");
561 
562 #define MINUS(type) MultidimArray<type> & kk = *((MultidimArray<type>*) data->im);\
563  MultidimArray<type> & pp = *((MultidimArray<type>*) img.data->im);\
564  kk -= pp;
565 
567 #undef MINUS
568 
569 }
570 
572 {
573 
574 #define MULTIPLYIMG(type) MultidimArray<type> & kk = *((MultidimArray<type>*) data->im);\
575  MultidimArray<type> & pp = *((MultidimArray<type>*) img.data->im);\
576  kk *= pp;
577 
579 #undef MULTIPLYIMG
580 
581 }
582 
583 void ImageGeneric::multiply(const double value)
584 {
585 
586 #define MULTIPLY(type) MultidimArray<type> & kk = *((MultidimArray<type>*) data->im);\
587  kk *= value;
588 
590 #undef MULTIPLY
591 
592 }
593 
595 {
596 
597 #define DIVIDEIMG(type) MultidimArray<type> & kk = *((MultidimArray<type>*) data->im);\
598  MultidimArray<type> & pp = *((MultidimArray<type>*) img.data->im);\
599  kk /= pp;
600 
602 #undef DIVIDEIMG
603 
604 }
605 
606 void ImageGeneric::divide(const double value)
607 {
608 
609 #define DIVIDE(type) MultidimArray<type> & kk = *((MultidimArray<type>*) data->im);\
610  kk /= value;
611 
613 #undef DIVIDE
614 
615 }
616 
617 void createEmptyFile(const FileName &filename, int xdim, int ydim, int Zdim,
618  size_t select_img, bool isStack, int mode, int _swapWrite, const MDRowVec *md)
619 {
621  size_t found = filename.find_first_of("%");
622  String strType = "";
623 
624  if (found == String::npos)
625  image.setDatatype(DT_Float);
626  else
627  {
628  strType = filename.substr(found+1).c_str();
629  image.setDatatype(str2Datatype(strType));
630  }
631 
632  // Use given metadata if present
633  if (md)
634  image.image->MDMainHeader = *md;
635 
636  image.mapFile2Write(xdim, ydim, Zdim, filename, false, select_img, isStack, mode, _swapWrite);
637 }
bool operator==(const ImageGeneric &i1) const
void applyGeo(const MetaData &md, size_t objId, const ApplyGeoParams &params=DefaultApplyGeoParams)
int readPreviewFourier(const FileName &name, size_t Xdim, size_t Ydim=0, int select_slice=CENTRAL_SLICE, size_t select_img=FIRST_IMAGE)
void resize(int Xdim, int Ydim, int Zdim, size_t Ndim, bool copy=true)
#define ADD(type)
Case or algorithm not implemented yet.
Definition: xmipp_error.h:177
size_t xdim
void reportWarning(const String &what)
void toString(String &s) const
void aliasSlice(MultidimArrayGeneric &mdim, int select_slice)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void add(const ImageGeneric &img)
void copy(const ImageGeneric &img)
int readPreviewSmooth(const FileName &name, size_t Xdim, size_t Ydim=0, int select_slice=CENTRAL_SLICE, size_t select_img=FIRST_IMAGE)
There is not enough memory for allocation.
Definition: xmipp_error.h:166
std::vector< std::unique_ptr< MDRow > > MD
static void emptifyHeader(MDRow &)
void multiply(const double value)
Unknown image type.
Definition: xmipp_error.h:130
virtual int readPreview(const FileName &name, size_t Xdim, size_t Ydim=0, int select_slice=CENTRAL_SLICE, size_t select_img=FIRST_IMAGE)=0
void SmoothResize(byte *picSrc8, byte *destpic8, size_t swide, size_t shigh, size_t dwide, size_t dhigh)
Definition: xvsmooth.cpp:93
#define MULTIPLY(type)
#define MULTIPLYIMG(type)
virtual bool getValue(MDObject &mdValueOut, size_t id) const =0
void initGeometry(const size_t n=0)
int readApplyGeo(const FileName &name, const MDRow &row, const ApplyGeoParams &params=DefaultApplyGeoParams)
DataMode
#define SET_DATATYPE(name)
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
DataType getDatatype() const
MultidimArray< T > data
Definition: xmipp_image.h:55
virtual void mirrorY()=0
void getImageInfo(const MetaData &md, size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim, DataType &datatype, MDLabel image_label)
AxisView
Definition: axis_view.h:32
#define DIVIDEIMG(type)
void setADimFile(ArrayDim aDim)
char axis
void getInfo(ImageInfo &imgInfo) const
size_t zdim
void getDimensions(size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim) const
viol index
void swapOnWrite()
void getPreview(ImageGeneric &imgOut, int Xdim, int Ydim=-1, int select_slice=CENTRAL_SLICE, size_t select_img=FIRST_IMAGE)
void divide(const ImageGeneric &img)
int readOrReadPreview(const FileName &name, size_t Xdim, size_t Ydim, int select_slice=CENTRAL_SLICE, size_t select_img=FIRST_IMAGE, bool mapData=false)
void getInfo(ImageInfo &imgInfo) const
#define MINUS(type)
double getScale(ImageInfo imgInf, size_t &xdim, size_t &ydim)
void mapFile2Write(int Xdim, int Ydim, int Zdim, const FileName &_filename, bool createTempFile=false, size_t select_img=APPEND_IMAGE, bool isStack=false, int mode=WRITE_OVERWRITE, int _swapWrite=0)
void selfScaleToSizeFourier(int Zdim, int Ydim, int Xdim, MultidimArray< double > &mda, int nThreads)
Definition: xmipp_fftw.cpp:723
ImageGeneric & operator=(const ImageGeneric &img)
void applyGeo(const MetaData &md, size_t objId, const ApplyGeoParams &params=DefaultApplyGeoParams)
DataType
int readOrReadPreview(const FileName &name, size_t Xdim, size_t Ydim=0, int select_slice=CENTRAL_SLICE, size_t select_img=FIRST_IMAGE, bool mapData=false, bool wrap=true)
void createEmptyFile(const FileName &filename, int xdim, int ydim, int Zdim, size_t select_img, bool isStack, int mode, int _swapWrite, const MDRowVec *md)
ArrayDim adim
void mode
Image base class.
void setDataMode(DataMode mode)
virtual void clear()=0
ImageBase * image
void reslice(AxisView view)
#define CENTRAL_SLICE
void convert2Datatype(DataType datatype, CastWriteMode castMode=CW_CONVERT)
#define MULTIDIM_ARRAY_GENERIC(v)
MDRowVec MDMainHeader
#define DIVIDE(type)
DataType str2Datatype(const std::string &str)
void setDatatype(DataType _datatype)
#define COPY(type)
unsigned char byte
Definition: xvsmooth.cpp:73
DataType datatype() const
int readApplyGeo(const FileName &name, const MDRow &row, const ApplyGeoParams &params=DefaultApplyGeoParams)
std::string String
Definition: xmipp_strings.h:34
int readOrReadMapped(const FileName &name, size_t select_img=ALL_IMAGES, int mode=WRITE_READONLY)
String formatString(const char *format,...)
#define CONVERTTYPE(type)
size_t ydim
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
ErrorType __errno
Definition: xmipp_error.h:227
int readPreview(const FileName &name, size_t Xdim, size_t Ydim=0, int select_slice=CENTRAL_SLICE, size_t select_img=FIRST_IMAGE)
DataType datatype
CastWriteMode
void getDimensions(size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim) const
Incorrect type received.
Definition: xmipp_error.h:190
virtual void getPreview(ImageBase *imgOut, size_t Xdim, size_t Ydim=0, int select_slice=CENTRAL_SLICE, size_t select_img=FIRST_IMAGE)=0
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false)
Incorrect value received.
Definition: xmipp_error.h:195
MultidimArrayGeneric * data
#define ALL_SLICES
void mapFile2Write(size_t Xdim, size_t Ydim, size_t Zdim, const FileName &_filename, bool createTempFile=false, size_t select_img=APPEND_IMAGE, bool isStack=false, int mode=WRITE_OVERWRITE)
int readMapped(const FileName &name, size_t select_img=ALL_IMAGES, int mode=WRITE_READONLY)
int * n
Name of an image (std::string)
void subtract(const ImageGeneric &img)
bool checkImageFileSize(const FileName &name, const ImageInfo &imgInfo, bool error)
#define SWITCHDATATYPE(datatype, OP)
void getDimensions(size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim) const