Xmipp  v3.23.11-Nereus
rwTIFF.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 <cstdint>
27 #include "xmipp_image_base.h"
28 #include "xmipp_error.h"
29 #include <tiffio.h>
30 #include "multidim_array_base.h"
31 #include "metadata_static.h"
32 
39  size_t offset ,
40  char* tif_buf,
41  unsigned int x, unsigned int y,
42  unsigned int imageWidth, unsigned int imageLength,
43  unsigned int tileWidth, unsigned int tileLength,
44  unsigned short samplesPerPixel,
45  DataType datatype)
46 {
47  int typeSize = gettypesize(datatype);
48  unsigned int i, j;
49  unsigned int x_max = x + tileWidth,
50  y_max = y + tileLength;
51 
52  if (x_max > imageWidth)
53  x_max = imageWidth;
54  if (y_max > imageLength)
55  y_max = imageLength;
56 
57 
58  for (j = y; j < y_max; j++)
59  for (i = x; i < x_max; i++)
60  setPage2T(offset+(j*imageWidth + i), (char*) tif_buf+((j-y)*samplesPerPixel*typeSize*tileWidth+(i-x)*samplesPerPixel*typeSize), datatype, (size_t) 1);
61 }
62 
68  size_t offset,
69  char* tif_buf,
70  unsigned int y,
71  unsigned int imageWidth, unsigned int imageLength,
72  unsigned short samplesPerPixel,
74 {
75  unsigned int x;
76  int typeSize = gettypesize(datatype);
77 
78  for (x = 0; x < imageWidth; x++)
79  setPage2T(offset+(y*imageWidth + x), (char*) tif_buf+(samplesPerPixel*typeSize * x), datatype, (size_t) 1);
80 }
81 
86 {
88 
89  switch (dHead.bitsPerSample)
90  {
91  case 8:
92  if (dHead.imageSampleFormat == SAMPLEFORMAT_INT)
93  datatype = DT_SChar;
94  else
95  datatype = DT_UChar;
96  break;
97  case 16:
98  if (dHead.imageSampleFormat == SAMPLEFORMAT_INT)
99  datatype = DT_Short;
100  else
101  datatype = DT_UShort;
102 
103  // else if (dHead.imageSampleFormat == SAMPLEFORMAT_UINT ||
104  // dHead.imageSampleFormat == SAMPLEFORMAT_IEEEFP ) //Don't know why
105  // datatype = DT_UShort;
106  // // else if (dHead.imageSampleFormat == 0 ||
107  // // dHead.imageSampleFormat == 32767 ) // Format 0 and 32767 are not declared in TIFF 6.0 specifications
108  // else
109  // datatype = DT_UShort;
110  break;
111  case 32:
112  if (dHead.imageSampleFormat == SAMPLEFORMAT_INT)
113  datatype = DT_Int;
114  else if (dHead.imageSampleFormat == SAMPLEFORMAT_UINT )
115  datatype = DT_UInt;
116  else if (dHead.imageSampleFormat == SAMPLEFORMAT_IEEEFP )
117  datatype = DT_Float;
118  else
119  //datatype = DT_Unknown;
120  datatype = DT_Float; // Eman2 does not write the datatype
121  break;
122  default:
123  datatype = DT_Unknown;
124  (void)datatype; // to suppress dead assignment warning
125  // REPORT_ERROR(ERR_TYPE_INCORRECT,"rwTIFF: Unsupported TIFF sample format.");
126  break;
127  }
128  return datatype;
129 }
130 
134 int ImageBase::readTIFF(size_t select_img, bool isStack)
135 {
136 #undef DEBUG
137  //#define DEBUG
138 #ifdef DEBUG
139  printf("DEBUG readTIFF: Reading TIFF file\n");
140 #endif
141 
142  // TIFFSetWarningHandler(NULL); // Switch off warning messages
143 
144  char* tif_buf = NULL;
145  std::vector<TIFFDirHead> dirHead;
146  TIFFDirHead dhRef;
147 
148  /* Get TIFF image properties */
149  do
150  {
151  dhRef.imageSampleFormat = SAMPLEFORMAT_VOID;
152  if (TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &dhRef.bitsPerSample) == 0)
153  REPORT_ERROR(ERR_IO_NOREAD,"rwTIFF: Error reading TIFFTAG_BITSPERSAMPLE");
154  if (TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL,&dhRef.samplesPerPixel) == 0)
155  dhRef.samplesPerPixel = 1;
156 
157  if (TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &dhRef.imageWidth) == 0)
158  REPORT_ERROR(ERR_IO_NOREAD,"rwTIFF: Error reading TIFFTAG_IMAGEWIDTH");
159  if (TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &dhRef.imageLength) == 0)
160  REPORT_ERROR(ERR_IO_NOREAD,"rwTIFF: Error reading TIFFTAG_IMAGELENGTH");
161  if (TIFFGetField(tif, TIFFTAG_SUBFILETYPE, &dhRef.subFileType) == 0)
162  dhRef.subFileType = 0; // Some scanners does not provide this label. So, we set this to zero
163  // REPORT_ERROR(ERR_IO_NOREAD,"rwTIFF: Error reading TIFFTAG_SUBFILETYPE");
164  TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &dhRef.imageSampleFormat);
165  TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &dhRef.resUnit);
166  TIFFGetField(tif, TIFFTAG_XRESOLUTION, &dhRef.xTiffRes);
167  TIFFGetField(tif, TIFFTAG_YRESOLUTION, &dhRef.yTiffRes);
168  TIFFGetField(tif, TIFFTAG_PAGENUMBER, &dhRef.pNumber, &dhRef.pTotal);
169 
170  if ((dhRef.subFileType & 0x00000001) != 0x00000001) //add image if not a thumbnail
171  dirHead.push_back(dhRef);
172  }
173  while(TIFFReadDirectory(tif));
174 
175  swap = TIFFIsByteSwapped(tif);
176 
177  //Check select_img is lower than stack size
178  if (select_img > dirHead.size())
179  REPORT_ERROR(ERR_INDEX_OUTOFBOUNDS, formatString("readTIFF (%s): Image number %lu exceeds stack size %lu", filename.c_str(), select_img, dirHead.size()));
180  else if (select_img == ALL_IMAGES)// Check images dimensions. Need to be the same
181  {
182  for (size_t i = 1; i < dirHead.size(); i++)
183  {
184  if (dirHead[0].imageLength != dirHead[i].imageLength || \
185  dirHead[0].imageWidth != dirHead[i].imageWidth)
186  dirHead.resize(i);
187  /*REPORT_ERROR(ERR_IMG_NOREAD, formatString("readTIFF: %s file contains %lu images with, at least,"\
188  " two of them with different dimensions. Try to read them individually.",filename.c_str(), dirHead.size()));*/
189  }
190  }
191 
192  // Calculate x,y space dimension resolution
193  double xRes=1.0, yRes=1.0;
194 
195  if (dirHead[0].xTiffRes>0 && dirHead[0].yTiffRes>0)
196  {
197  switch (dirHead[0].resUnit)
198  {
199  case RESUNIT_NONE:
200  {
201  xRes = yRes = -1;
202  break;
203  }
204  case RESUNIT_INCH:
205  {
206  xRes = 2.54e8/dirHead[0].xTiffRes;
207  yRes = 2.54e8/dirHead[0].yTiffRes;
208  break;
209  }
210  case RESUNIT_CENTIMETER:
211  {
212  xRes = 1e8/dirHead[0].xTiffRes;
213  yRes = 1e8/dirHead[0].yTiffRes;
214  break;
215  }
216  }
217  }
218 
219  // cast image data to image class datatypes
220  ArrayDim aDim;
221 
222  size_t imgStart = IMG_INDEX(select_img);
223 
224  aDim.xdim = (int) dirHead[imgStart].imageWidth;
225  aDim.ydim = (int) dirHead[imgStart].imageLength;
226  aDim.zdim = 1;
227  aDim.ndim = replaceNsize = (select_img == ALL_IMAGES)? dirHead.size() : 1;
228  setDimensions(aDim);
229 
230  size_t imgEnd = (select_img != ALL_IMAGES) ? imgStart + 1 : aDim.ndim;
231 
232  DataType datatype = datatypeTIFF(dirHead[0]);
233 
234  //Set main header
239 
240  //Read header only
241  if( dataMode < DATA ||( dataMode == _HEADER_ALL && aDim.ndim > 1) )
242  return 0;
243 
244  /* As we cannot mmap a TIFF File, when this option is passed we are going to mmap
245  * the multidimarray of Image
246  */
247  if (mmapOnRead)
248  {
249  mmapOnRead = false;
250  if (aDim.nzyxdim*gettypesize(datatype) > tiff_map_min_size)
251  mdaBase->setMmap(true);
252  }
253 
254  // Allocate memory for image data (Assume xdim, ydim, zdim and ndim are already set
255  //if memory already allocated use it (no resize allowed)
257 
258  size_t pad = aDim.yxdim;
259  int imReaded = 0;
260 
261  MD.clear();
262  for (size_t i = 0; i < aDim.ndim; i++)
263  MD.push_back(std::unique_ptr<MDRowVec>(new MDRowVec(MDL::emptyHeaderVec())));
264 
265  uint32_t rowsperstrip;
266  tsize_t scanline;
267 
268  unsigned int x, y;
269  // Dimensions of tiles
270  unsigned int tileWidth, tileLength;
271  tileWidth = tileLength = 0;
272 
273  for (size_t i = imgStart; i < imgEnd; ++i)
274  {
275  TIFFSetDirectory(tif,(tdir_t) i);
276 
277  // If samplesPerPixel is higher than 3 it means there are extra samples, as associated alpha data
278  // Greyscale images are usually samplesPerPixel=1
279  // RGB images are usually samplesPerPixel=3 (this is only implemented for untiled 8-bit tiffs)
280  if (dirHead[i].samplesPerPixel > 3)
281  dirHead[i].samplesPerPixel = 1;
282 
283  if (TIFFIsTiled(tif))
284  {
285  TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tileWidth);
286  TIFFGetField(tif, TIFFTAG_TILELENGTH,&tileLength);
287  tif_buf = (char*)_TIFFmalloc(TIFFTileSize(tif));
288  }
289  else
290  {
291  TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
292  scanline = TIFFScanlineSize(tif);
293  tif_buf = (char*)_TIFFmalloc(scanline);
294  }
295  if (tif_buf == 0)
296  {
297  TIFFError(TIFFFileName(tif), "No space for strip buffer");
298  exit(-1);
299  }
300 
301  /* Start to convert the TIFF image to type T */
302 
303  datatype = datatypeTIFF(dirHead[i]);
304 
305  if (TIFFIsTiled(tif))
306  {
307  for (y = 0; y < dirHead[0].imageLength; y += tileLength)
308  for (x = 0; x < dirHead[0].imageWidth; x += tileWidth)
309  {
310  TIFFReadTile(tif, tif_buf, x, y, 0, 0);
311  if (swap)
312  swapPage((char*)tif_buf, TIFFTileSize(tif)*sizeof(unsigned char), datatype);
313 
314  castTiffTile2T((pad*imReaded), tif_buf, x, y,
315  dirHead[i].imageWidth, dirHead[i].imageLength,
316  tileWidth, tileLength,
317  dirHead[i].samplesPerPixel,
318  datatype);
319  }
320  }
321  else
322  {
323  for (y = 0; y < dirHead[i].imageLength; y++)
324  {
325  TIFFReadScanline(tif, tif_buf, y);
326  castTiffLine2T((pad*imReaded), tif_buf, y,
327  dirHead[i].imageWidth, dirHead[i].imageLength,
328  dirHead[i].samplesPerPixel,
329  datatype);
330  }
331  }
332 
333  ++imReaded;
334  _TIFFfree(tif_buf);
335  }
336  return 0;
337 }
338 
342 int ImageBase::writeTIFF(size_t select_img, bool isStack, int mode, String bitDepth, CastWriteMode castMode)
343 {
344 #undef DEBUG
345 
346  if (isComplexT())
347  {
348  REPORT_ERROR(ERR_TYPE_INCORRECT,"rwTIFF: Complex images are not supported by TIFF format.");
349  return 0;
350  }
351 
352  ArrayDim aDim;
353  mdaBase->getDimensions(aDim);
354 
355  // Volumes are not supported
356  if (aDim.zdim > 1)
357  REPORT_ERROR(ERR_MULTIDIM_DIM, "writeTIFF does not support volumes.");
358  // TIFF cannot open a file to read/write at the same time, so the file must be overwritten
359  // if (mode != WRITE_OVERWRITE)
360  // REPORT_ERROR(ERR_VALUE_INCORRECT, "writeTIFF: LIBTIFF cannot modify an existing file, only overwrite it.");
361 
362  TIFFDirHead dhMain; // Main header
363 
364  //Selection of output datatype
365 
366  DataType wDType,myTypeID = myT();
367 
368  if (bitDepth == "")
369  {
370  castMode = CW_CAST;
371  switch(myTypeID)
372  {
373  case DT_Double:
374  case DT_Float:
375  wDType = DT_Float;
376  dhMain.imageSampleFormat = SAMPLEFORMAT_IEEEFP;
377  break;
378  case DT_Int:
379  castMode = CW_CONVERT;
380  case DT_UInt:
381  wDType = DT_UInt;
382  dhMain.imageSampleFormat = SAMPLEFORMAT_UINT;
383  break;
384  case DT_Short:
385  castMode = CW_CONVERT;
386  case DT_UShort:
387  wDType = DT_UShort;
388  dhMain.imageSampleFormat = SAMPLEFORMAT_UINT;
389  break;
390  case DT_SChar:
391  castMode = CW_CONVERT;
392  case DT_UChar:
393  wDType = DT_UChar;
394  dhMain.imageSampleFormat = SAMPLEFORMAT_UINT;
395  break;
396  default:
397  wDType = DT_Unknown;
398  (void)wDType; // to suppress dead assignment warning
399  REPORT_ERROR(ERR_TYPE_INCORRECT,formatString("rwTIFF: cannot write TIFF format from %s\
400  datatype.",datatype2Str(myTypeID).c_str()));
401  }
402  }
403  else
404  {
405  // Default Value
406  wDType = (bitDepth == "default") ? DT_UChar : datatypeRAW(bitDepth);
407 
408  switch(wDType)
409  {
410  case DT_Float:
411  dhMain.imageSampleFormat = SAMPLEFORMAT_IEEEFP;
412  break;
413  case DT_UInt:
414  case DT_UShort:
415  case DT_UChar:
416  dhMain.imageSampleFormat = SAMPLEFORMAT_UINT;
417  break;
418  default:
419  wDType = DT_Unknown;
420  (void)wDType; // to suppress dead assignment warning
421  REPORT_ERROR(ERR_TYPE_INCORRECT,formatString("rwTIFF: TIFF format does not support %s " \
422  "datatype.",datatype2Str(myTypeID).c_str()));
423  }
424  }
425 
426  if (mmapOnWrite)
427  {
428  /* As we cannot mmap a TIFF File, when this option is passed we are going to mmap
429  * the multidimarray of Image
430  */
431  mmapOnWrite = false;
432  dataMode = DATA;
433  MDMainHeader.setValue(MDL_DATATYPE,(int) myTypeID);
434 
435  if (mdaBase->nzyxdim*gettypesize(myTypeID) > tiff_map_min_size)
436  mdaBase->setMmap(true);
437 
438  // Allocate memory for image data (Assume xdim, ydim, zdim and ndim are already set
439  //if memory already allocated use it (no resize allowed)
440 
442 
443  return 0;
444  }
445 
446  int nBytes = gettypesize(wDType);
447 
448  /* Set TIFF image properties */
449  dhMain.bitsPerSample = (unsigned short int) nBytes*8;
450  dhMain.samplesPerPixel = 1;
451  dhMain.imageWidth = aDim.xdim;
452  dhMain.imageLength = aDim.ydim;
453  dhMain.resUnit = RESUNIT_CENTIMETER;
454 
455  double aux=1.0;
456 
457  if (!MDMainHeader.empty())
458  {
459  dhMain.xTiffRes = (MDMainHeader.getValue(MDL_SAMPLINGRATE_X, aux)) ? (float) 1e8/aux : 0. ;
460  dhMain.yTiffRes = (MDMainHeader.getValue(MDL_SAMPLINGRATE_X, aux)) ? (float) 1e8/aux : 0. ;
461  }
462  else
463  {
464  dhMain.xTiffRes = 1.0;
465  dhMain.yTiffRes = 1.0;
466  }
467 
468  size_t imgStart = (mode == WRITE_APPEND)? replaceNsize : IMG_INDEX(select_img);
469 
470  size_t bufferSize, datasize_n;
471  bufferSize = aDim.xdim*nBytes;
472  datasize_n = aDim.zyxdim;
473 
474  char* tif_buf;
475 
476  if ((tif_buf = (char*)_TIFFmalloc(bufferSize)) == 0)
477  {
478  TIFFError(TIFFFileName(tif), "No space for strip buffer");
479  exit(-1);
480  }
481 
482  //Write each image in a directory
483  for (size_t i = 0; i < aDim.ndim; i++ )
484  {
485  TIFFSetDirectory(tif,(tdir_t) i + imgStart);
486 
487  // Image header
488  TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, dhMain.bitsPerSample);
489  TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL,dhMain.samplesPerPixel);
490  TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, dhMain.imageSampleFormat);
491  TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, dhMain.imageWidth);
492  TIFFSetField(tif, TIFFTAG_IMAGELENGTH, dhMain.imageLength);
493  TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, dhMain.resUnit);
494  TIFFSetField(tif, TIFFTAG_XRESOLUTION, dhMain.xTiffRes);
495  TIFFSetField(tif, TIFFTAG_YRESOLUTION, dhMain.yTiffRes);
496  TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
497  TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
498  TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, dhMain.imageLength);
499  TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
500  TIFFSetField(tif, TIFFTAG_SOFTWARE, "Xmipp 3.0");
501 
502  if (aDim.ndim == 1 && isStack == false)
503  {
504  TIFFSetField(tif, TIFFTAG_SUBFILETYPE, (unsigned int) 0x0);
505  TIFFSetField(tif, TIFFTAG_PAGENUMBER, (uint16_t) 0, (uint16_t) 0);
506  }
507  else
508  {
509  TIFFSetField(tif, TIFFTAG_SUBFILETYPE, (unsigned int) 0x2);
510  TIFFSetField(tif, TIFFTAG_PAGENUMBER, (uint16_t) i, (uint16_t) aDim.ndim);
511  }
512 
513  // Only write images when needed
514  if (dataMode >= DATA)
515  {
516  double min0, max0;
517 
518  if (castMode != CW_CAST)
519  mdaBase->computeDoubleMinMaxRange(min0, max0, i*datasize_n, datasize_n);
520 
521  for (uint32_t y = 0; y < aDim.ydim; y++)
522  {
523  if (castMode == CW_CAST)
524  getPageFromT(i*datasize_n + y*aDim.xdim, (char *)tif_buf, wDType, (size_t) aDim.xdim);
525  else
526  getCastConvertPageFromT(i*datasize_n + y*aDim.xdim,
527  (char *)tif_buf, wDType, (size_t) aDim.xdim, min0, max0, castMode);
528 
529  TIFFWriteScanline(tif, tif_buf,y,0);
530  }
531  }
532 
533  TIFFWriteDirectory(tif);
534  }
535 
536  _TIFFfree(tif_buf);
537  return(0);
538 }
std::string datatype2Str(DataType datatype)
Index out of bounds.
Definition: xmipp_error.h:132
sampling rate in A/pixel (double)
size_t xdim
sampling rate in A/pixel (double)
DataMode dataMode
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
virtual void setPage2T(size_t offset, char *page, DataType datatype, size_t pageSize)=0
virtual void coreAllocateReuse()=0
static double * y
void setValue(const MDObject &object) override
void swapPage(char *page, size_t pageNrElements, DataType datatype, int swap=1)
std::vector< std::unique_ptr< MDRow > > MD
void castTiffTile2T(size_t offset, char *tif_buf, unsigned int x, unsigned int y, unsigned int imageWidth, unsigned int imageLength, unsigned int tileWidth, unsigned int tileLength, unsigned short samplesPerPixel, DataType datatype)
Definition: rwTIFF.cpp:38
if read from file original image datatype, this is an struct defined in image
void castTiffLine2T(size_t offset, char *tif_buf, unsigned int y, unsigned int imageWidth, unsigned int imageLength, unsigned short samplesPerPixel, DataType datatype)
Definition: rwTIFF.cpp:67
unsigned short samplesPerPixel
doublereal * x
#define i
int writeTIFF(size_t select_img, bool isStack=false, int mode=WRITE_OVERWRITE, String bitDepth="", CastWriteMode castMode=CW_CAST)
Definition: rwTIFF.cpp:342
T & getValue(MDLabel label)
virtual void computeDoubleMinMaxRange(double &minval, double &maxval, size_t offset, size_t size) const =0
#define x0
size_t nzyxdim
size_t zdim
unsigned short bitsPerSample
const size_t tiff_map_min_size
virtual void getPageFromT(size_t offset, char *page, DataType datatype, size_t pageSize)=0
void setMmap(bool mmap)
size_t zyxdim
virtual void setDimensions(int Xdim, int Ydim, int Zdim, size_t Ndim)=0
size_t yxdim
DataType datatypeTIFF(TIFFDirHead dHead)
Definition: rwTIFF.cpp:85
virtual bool isComplexT() const =0
Couldn&#39;t read from file.
Definition: xmipp_error.h:139
static MDRowVec emptyHeaderVec()
DataType
void mode
#define j
int readTIFF(size_t select_img, bool isStack=false)
Definition: rwTIFF.cpp:134
MDRowVec MDMainHeader
size_t ndim
DataType datatype() const
std::string String
Definition: xmipp_strings.h:34
#define ALL_IMAGES
virtual void getCastConvertPageFromT(size_t offset, char *page, DataType datatype, size_t pageSize, double min0, double max0, CastWriteMode castMode=CW_CONVERT) const =0
String formatString(const char *format,...)
bool empty() const override
#define IMG_INDEX(select_img)
size_t ydim
Incorrect MultidimArray dimensions.
Definition: xmipp_error.h:173
FileName filename
CastWriteMode
virtual DataType myT() const =0
Incorrect type received.
Definition: xmipp_error.h:190
void clear() override
size_t replaceNsize
MultidimArrayBase * mdaBase
DataType datatypeRAW(String strDT)
Definition: rwRAW.cpp:31
size_t gettypesize(DataType type)
Returns memory size of datatype.
void getDimensions(size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim) const