Orfeo Toolbox  3.16
itkMINC2ImageIO.cxx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkMINC2ImageIO.cxx,v $
5  Language: C++
6  Date: $Date: 2008-12-28 09:07:20 $
7  Version: $Revision: 1.18 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 #include "itkMINC2ImageIO.h"
18 #include <stdio.h>
19 #include <vnl/vnl_vector.h>
20 
21 namespace itk
22 {
23 #define MINC2_MAXDIM 15
24 #define MINC2_MAXUSE 5
25 
26 bool MINC2ImageIO::CanReadFile(const char* file)
27 {
28  if( *file == 0)
29  {
30  itkDebugMacro(<<"No filename specified.");
31  return false;
32  }
33 
34  mihandle_t volume;
35 
36  if (miopen_volume(file,MI2_OPEN_READ,&volume)< 0)
37  {
38  itkDebugMacro(<<" Can not open File:" << file << "\n");
39  return false;
40  }
41  if (miclose_volume(volume) < 0)
42  {
43  itkDebugMacro(<<" Can not close File:" << file << "\n");
44  return false;
45  }
46  return true;
47 }
48 
49 
50 void MINC2ImageIO::Read(void* buffer)
51 {
52 
53  mihandle_t volume;
54  // call to minc2.0 function to open the file
55  if (miopen_volume(m_FileName.c_str(),MI2_OPEN_READ,&volume)< 0)
56  {
57  // Error opening the volume
58  itkDebugMacro("Could not open file \"" << m_FileName.c_str() << "\".");
59  return;
60  }
61  mitype_t volume_data_type;
62  if(miget_data_type(volume,&volume_data_type) < 0)
63  {
64  itkDebugMacro(" Can not get volume data type!!\n");
65  }
66  int slice_scaling_flag;
67  // find out whether the data has slice scaling
68  if (miget_slice_scaling_flag(volume, &slice_scaling_flag) < 0)
69  {
70  itkDebugMacro(" Can not get slice scaling flag!!\n");
71  }
72  double valid_max, valid_min;
73  // find the data valid range
74  if(miget_volume_valid_range(volume,&valid_max,&valid_min) <0)
75  {
76  itkDebugMacro(" Can not get valid max or min!!\n");
77  }
78 
79  miclass_t volume_data_class;
80  if(miget_data_class(volume,&volume_data_class) < 0)
81  {
82  itkDebugMacro(" Can not get volume data class!!\n");
83  }
84 
85  unsigned long start[MINC2_MAXDIM+1];
86  unsigned long count[MINC2_MAXDIM+1];
87 
88  // figure out how many dimensions out of the total NDims
89  // are used by this class
90  unsigned int usefulDimensions = 0;
91  unsigned int i;
92  for (i=0; i < MINC2_MAXUSE; i++)
93  {
94  if (this->m_DimensionIndices[i] != -1 )
95  {
96  usefulDimensions++;
97  }
98  }
99 
100  // fill out the array of dimension handles,"regularly sampled"
101  // the dimensions will be retrieved in file order
102  midimhandle_t *hdims = new midimhandle_t[usefulDimensions];
103  if(miget_volume_dimensions(volume,MI_DIMCLASS_ANY, MI_DIMATTR_REGULARLY_SAMPLED,MI_DIMORDER_FILE, this->m_NDims, hdims) < 0)
104  {
105  itkDebugMacro(" Can not get dimension handles!!\n");
106  return;
107  }
108 
109  midimhandle_t *apparent_order = new midimhandle_t[usefulDimensions];
110  // order of dim_indices x,y,z,t,vector-dimension
111  // apparent order vector-dimension,t,z,y,x
112  unsigned int j=0;
113  for( i = 0; i < 5; i++ )
114  {
115  if (this->m_DimensionIndices[i] != -1 )
116  {
117  apparent_order[j] = hdims[this->m_DimensionIndices[i]];
118  j++;
119  }
120  }
121 
122  //check to see if app order same as file order
123  for( i = 0; i < usefulDimensions; i++ )
124  {
125  if (this->m_DimensionIndices[i] != static_cast<int>(i) )
126  {
127  // set apparent order of dimensions so data can be accesed in that order
128  if(miset_apparent_dimension_order(volume,usefulDimensions ,apparent_order) < 0)
129  {
130  itkDebugMacro(" Can not get apparent dimension order!!\n");
131  }
132  break;
133  }
134  }
135  // clean dynamic space allocated for dimension handles
136  delete [] hdims;
137  delete [] apparent_order;
138  //set the unused dimension to start 0 and offset 1 if ANY
139  i=0;
140  for( i = 0; i < (this->m_NDims-usefulDimensions); i++ )
141  {
142  start[i] = 0;
143  count[i] = 1;
144  }
145 
146  start[i] = 0;
147  count[i] = this->GetDimensions(2);
148  i++;
149  start[i] = 0;
150  count[i] = this->GetDimensions(1);
151  i++;
152  start[i] = 0;
153  count[i] = this->GetDimensions(0);
154  i++;
155 
156  //now take care of vector or time dimension
157  // z,y,x, t, vector_dimension
158  if( usefulDimensions == 5 )
159  {
160  start[i] = 0;
161  unsigned int icount = count[i];
162  if( miget_dimension_size(apparent_order[3], &icount) < 0 )
163  {
164  itkDebugMacro(" Can not get dimension size \n");
165  }
166  count[i] = icount;
167  i++;
168  start[i] = 0;
169  icount = count[i];
170  if (miget_dimension_size(apparent_order[4], &icount) < 0)
171  {
172  itkDebugMacro(" Can not get dimension size \n");
173  }
174  count[i] = icount;
175  }
176  if (usefulDimensions == 4)
177  {
178  start[i] = 0;
179  unsigned int icount = count[i];
180  if (miget_dimension_size(apparent_order[3], &icount) < 0)
181  {
182  itkDebugMacro(" Can not get dimension size \n");
183  }
184  count[i] = icount;
185  }
186 
187  // set the data class for the file
188  switch (volume_data_class)
189  {
190  case MI_CLASS_REAL:
191  case MI_CLASS_COMPLEX:
192  case MI_CLASS_INT:
193  if( slice_scaling_flag )
194  {
195 
196  if( miget_real_value_hyperslab(volume, volume_data_type, start, count,buffer) < 0 )
197  {
198  itkDebugMacro(" Can not get real value hyperslab!!\n");
199  }
200  }
201  else
202  {
203  if( miget_voxel_value_hyperslab(volume, volume_data_type, start, count,buffer) < 0 )
204  {
205  itkDebugMacro(" Can not get voxel value hyperslabs!!\n");
206  }
207  }
208  break;
209  case MI_CLASS_LABEL:
210  if( miget_voxel_value_hyperslab(volume, volume_data_type, start, count,buffer) < 0 )
211  {
212  itkDebugMacro(" Can not get voxel value hyperslabs!!\n");
213  }
214  break;
215  case MI_CLASS_UNIFORM_RECORD:
216  {
217  itkDebugMacro(" Leave this until minc2.0 support it complete!!\n");
218  }
219  default:
220  return;
221  }
222 
223  if( miclose_volume(volume)< 0 )
224  {
225  itkDebugMacro(" Can not close volume!\n");
226  }
227 }
228 
229 
231 {
232  this->m_NDims = 0;
233  this->m_DimensionName = new char *[ MINC2_MAXDIM + 1];
234  this->m_DimensionSize = new unsigned int[MINC2_MAXDIM+1];
235  this->m_DimensionStart = new double[MINC2_MAXDIM+1];
236  this->m_DimensionStep = new double[MINC2_MAXDIM+1];
237  this->m_DimensionIndices = new int[MINC2_MAXDIM+1];
238 
239  for (int i = 0; i <= MINC2_MAXDIM; i++)
240  {
241  this->m_DimensionName[i] = 0;
242  this->m_DimensionSize[i] = 0;
243  this->m_DimensionStart[i] = 0.0;
244  this->m_DimensionStep[i] = 0.0;
245  this->m_DimensionIndices[i] = -1;
246  }
247  m_DimensionOrder = 0;
248 
249  m_Shift = 0.0;
250  m_Scale = 1.0;
251  m_OriginalStart[0] = 0;
252  m_OriginalStart[1] = 0;
253  m_OriginalStart[2] = 0;
254  m_Complex = 0;
255 }
256 
258 {
259  delete [] this->m_DimensionName;
260  delete [] this->m_DimensionSize;
261  delete [] this->m_DimensionStart;
262  delete [] this->m_DimensionStep;
263  delete [] this->m_DimensionIndices;
264 }
265 
266 void MINC2ImageIO::PrintSelf(std::ostream& os, Indent indent) const
267 {
268  Superclass::PrintSelf(os, indent);
269 
270  os << indent << "NDims: " << m_NDims << std::endl;
271  os << indent << "Dimension Order: " << m_DimensionOrder << std::endl;
272 }
273 
275 {
276  mihandle_t volume;
277 
278  // call to minc2.0 function to open the file
279  if (miopen_volume(m_FileName.c_str(),MI2_OPEN_READ,&volume)< 0)
280  {
281  // Error opening the volume
282  itkDebugMacro("Could not open file \"" << m_FileName.c_str() << "\".");
283  return;
284  }
285 
286  // find out how many dimensions are there regularly sampled
287  // dimensions only
288  int numberOfDimensions;
289  if(miget_volume_dimension_count(volume, MI_DIMCLASS_ANY, MI_DIMATTR_REGULARLY_SAMPLED, &numberOfDimensions) < 0)
290  {
291  itkDebugMacro("Could not get the number of dimensions in the volume!");
292  return;
293  }
294  m_NDims = static_cast<unsigned int>( numberOfDimensions );
296  if (m_NDims > MINC2_MAXDIM)
297  {
298  // Error TOO MANY dimensions
299  itkDebugMacro("Number of dimensions exceeds expectation!");
300  }
301 
302  // get dimension handles in FILE ORDER (i.e, the order as they are
303  // submitted to file)
304  midimhandle_t *hdims = new midimhandle_t[m_NDims];
305  if(miget_volume_dimensions(volume,MI_DIMCLASS_ANY, MI_DIMATTR_REGULARLY_SAMPLED,MI_DIMORDER_FILE, m_NDims, hdims) < 0)
306  {
307  itkDebugMacro("Could not get dimension handles!");
308  return;
309  }
310 
311  // fill the DimensionOrder (string containing the first letter of all dimensions
312  // in FILE_ORDER) and DimensionName
313  m_DimensionOrder = new char[ m_NDims + 1];
314  unsigned int i;
315  for (i=0; i < m_NDims; i++)
316  {
317  char *name;
318  if (miget_dimension_name(hdims[i],&name) < 0 )
319  {
320  // Error getting dimension name
321  itkDebugMacro("Could not get dimension name!");
322  return;
323  }
324 
325  this->m_DimensionName[i] = name;
326  this->m_DimensionOrder[i] = name[0];
327  }
328  this->m_DimensionOrder[i]='\0';
329 
330  // fill the DimensionSize by calling the following MINC2.0 function
331  unsigned int *sizes = new unsigned int[m_NDims];
332  if (miget_dimension_sizes(hdims, m_NDims, sizes) < 0 )
333  {
334  // Error getting dimension sizes
335  itkDebugMacro("Could not get dimension sizes!");
336  return;
337  }
338 
339  // correct this part first
340  for ( i=0; i < m_NDims; i++)
341  {
342  this->m_DimensionSize[i] = sizes[i];
343  }
344  unsigned int numberOfComponents = 1;
345  this->XYZFromDirectionCosines(hdims, this->m_DimensionIndices, &numberOfComponents);
346 
347  double separations[MINC2_MAXDIM+1];
348  if(miget_dimension_separations(hdims, MI_ORDER_FILE, m_NDims, separations) < 0)
349  {
350  itkDebugMacro(" Could not dimension sizes");
351  return;
352  }
353  double starts[MINC2_MAXDIM+1];
354  if(miget_dimension_starts(hdims, MI_ORDER_FILE, this->m_NDims, starts) < 0)
355  {
356  itkDebugMacro(" Could not dimension sizes");
357  return;
358  }
359  //fill out dimension size, step and start
360  // note : rotate origin as itk will *NOT* do it
361  // ITK ADPOTED DICOM conversions which do *NOT* rotate origin
362  int j=this->m_NDims - 1;
363  for (i=0; i < this->m_NDims; i++)
364  {
365  this->SetDimensions(i,this->m_DimensionSize[this->m_DimensionIndices[j]]);
366  this->SetSpacing(i,separations[this->m_DimensionIndices[j]]);
367  this->SetOrigin(i,starts[this->m_DimensionIndices[j]]);
368  //keep this for writing before rotating it
369  m_OriginalStart[i] = starts[this->m_DimensionIndices[j]];
370  j--;
371  }
372  // pass direction cosines to ITK
373  vnl_vector<double> row(3),column(3), slice(3);
374 
375  row[0] = m_DirectionCosines[0][0];
376  row[1] = m_DirectionCosines[1][0];
377  row[2] = m_DirectionCosines[2][0];
378  this->SetDirection(0,row);
379  column[0] = m_DirectionCosines[0][1];
380  column[1] = m_DirectionCosines[1][1];
381  column[2] = m_DirectionCosines[2][1];
382  this->SetDirection(1,column);
383 
384  if ( this->m_NDims > 2 )
385  {
386  slice[0] = m_DirectionCosines[0][2];
387  slice[1] = m_DirectionCosines[1][2];
388  slice[2] = m_DirectionCosines[2][2];
389  this->SetDirection(2,slice);
390  }
391 
392  mitype_t volume_data_type;
393  if(miget_data_type(volume,&volume_data_type) < 0)
394  {
395  itkDebugMacro(" Can not get volume data type!!\n");
396  }
397  // set the file data type
398  switch (volume_data_type)
399  {
400  case MI_TYPE_BYTE:
401  this->SetComponentType(CHAR);
402  break;
403  case MI_TYPE_UBYTE:
404  this->SetComponentType(UCHAR);
405  break;
406  case MI_TYPE_SHORT:
407  this->SetComponentType(SHORT);
408  break;
409  case MI_TYPE_USHORT:
410  this->SetComponentType(USHORT);
411  break;
412  case MI_TYPE_INT:
413  this->SetComponentType(INT);
414  break;
415  case MI_TYPE_UINT:
416  this->SetComponentType(UINT);
417  break;
418  case MI_TYPE_FLOAT:
419  this->SetComponentType(FLOAT);
420  break;
421  case MI_TYPE_DOUBLE:
422  this->SetComponentType(DOUBLE);
423  break;
424  case MI_TYPE_SCOMPLEX:
425  this->SetComponentType(SHORT);
426  break;
427  case MI_TYPE_ICOMPLEX:
428  this->SetComponentType(INT);
429  break;
430  case MI_TYPE_FCOMPLEX:
431  this->SetComponentType(FLOAT);
432  break;
433  case MI_TYPE_DCOMPLEX:
434  this->SetComponentType(DOUBLE);
435  break;
436  default:
437  itkDebugMacro("Bad data type ");
438  return;
439  } //end of switch
440 
441  this->ComputeStrides();
442 
443  // find out whether the data has slice scaling
444  int slice_scaling_flag;
445  if (miget_slice_scaling_flag(volume, &slice_scaling_flag) < 0)
446  {
447  itkDebugMacro(" Can not get slice scaling flag!!\n");
448  }
449  miclass_t volume_data_class;
450 
451  if(miget_data_class(volume,&volume_data_class) < 0)
452  {
453  itkDebugMacro(" Could not get data class");
454  return;
455  }
456  switch (volume_data_class)
457  {
458  case MI_CLASS_REAL:
459  this->SetPixelType(SCALAR);
460  if( !(volume_data_type == MI_TYPE_FLOAT || volume_data_type == MI_TYPE_DOUBLE) )
461  {
462  if(slice_scaling_flag)
463  {
464  this->SetSliceScalingFromLocalScaling(volume);
465  }
466  else
467  {
468  this->SetSliceScalingFromGlobalScaling(volume);
469  }
470  }
471  break;
472  case MI_CLASS_INT:
473  this->SetPixelType(SCALAR);
474  if( slice_scaling_flag )
475  {
476  this->SetSliceScalingFromLocalScaling(volume);
477  }
478  else
479  {
480  this->SetSliceScalingFromGlobalScaling(volume);
481  }
482  break;
483  case MI_CLASS_LABEL:
484  // create an array of label names and values
485  // not sure how to pass this to itk yet!
486  break;
487  case MI_CLASS_COMPLEX:
488  m_Complex = 1;
489  this->SetPixelType(COMPLEX);
490  numberOfComponents *= 2;
491  break;
492  default:
493  itkDebugMacro("Bad data class ");
494  return;
495  } //end of switch
496 
497 
498  this->SetNumberOfComponents(numberOfComponents);
499 
500  if (miclose_volume(volume)< 0)
501  {
502  // Error closing the volume
503  itkDebugMacro("Could not close file \"" << m_FileName.c_str() << "\".");
504  return;
505  }
506 
507  //clean dynamic allocation
508  delete [] sizes;
509  delete [] hdims;
510 }
511 
512 void MINC2ImageIO::SetDimensionName(unsigned int i,char *name)
513 {
514  if (name)
515  {
516  this->Modified();
517  this->m_DimensionName[i] = name;
518  }
519  else
520  {
521  return;
522  }
523 }
524 
525 bool MINC2ImageIO::CanWriteFile( const char * name )
526 {
527  std::string filename = name;
528 
529  // transform filename to lower case to make checks case-insensitive
530  std::transform( filename.begin(), filename.end(), filename.begin(), (int(*)(int)) std::tolower );
531 
532  if( filename == "" )
533  {
534  itkDebugMacro(<<"No filename specified.");
535  return false;
536  }
537 
538  std::string::size_type mncPos = filename.rfind(".mnc");
539  if ( (mncPos != std::string::npos)
540  && (mncPos > 0)
541  && (mncPos == filename.length() - 4) )
542  {
543  return true;
544  }
545 
546  mncPos = filename.rfind(".mnc2");
547  if ( (mncPos != std::string::npos)
548  && (mncPos > 0)
549  && (mncPos == filename.length() - 5) )
550  {
551  return true;
552  }
553 
554  return false;
555 }
556 
557 /*
558  * fill out the appropriate header information
559 */
561 {
562  std::cout << "WriteImageInformation" << std::endl;
563  // FIXME: implement this!
564 }
565 
566 template <class TBuffer>
567 void MINCComputeScalarRange(int itkNotUsed(Strides)[3], int Sizes[3], int nComponents, double& maxval,double& minval,TBuffer *buffer)
568 {
569 // This differs with ITK Journal version in that
570 // no longer skipping ahead by strides, but just plodding through
571 // buffer one point at a time.
572 
573 // FIXME: this difference is probably something that should be thought
574 // through more clearly.
575 // Rupert Brooks, August 23, 2007
576  double tmpminval = 1000.0;
577  double tmpmaxval = 0.0;
578  int idX, idY, idZ;
579 
580  for( idZ = 0; idZ < Sizes[2]; idZ++ )
581  {
582  for( idY = 0; idY < Sizes[1]; idY++ )
583  {
584  for( idX = 0; idX < Sizes[0]*nComponents; idX++ )
585  {
586  TBuffer val = *buffer++;//Strides[0];
587  if (val > tmpmaxval)
588  {
589  tmpmaxval = val;
590  }
591  if (val < tmpminval)
592  {
593  tmpminval = val;
594  }
595  }
596  //buffer += Strides[1];
597  }
598  //buffer += Strides[2];
599  }
600  maxval = tmpmaxval;
601  minval = tmpminval;
602 
603 }
604 
605 //void MINC2ImageIO::
606 template<class TBuffer>
607 void MINCWriteHyperSlab(mihandle_t volume,
608  unsigned long ndims,
609  mitype_t minctype,
610  const unsigned long start[],
611  const unsigned long count[],
612  TBuffer *buffer)
613 {
614  unsigned long i, j;
615 
616  unsigned long tmpstart[MINC2_MAXDIM+1];
617  unsigned long tmpcount[MINC2_MAXDIM+1];
618  // calculate the number of voxels per slice
619  unsigned long size = 1;
620 
621  for (i = 1; i < ndims; i++)
622  {
623  tmpstart[i] = start[i];
624 
625  tmpcount[i] = count[i];
626 
627  size = size*count[i];
628  }
629 
630  // allocate memory for a slice
631  TBuffer *tmpbuffer = new TBuffer[size];
632  for (i = 0; i < count[0]; i++)
633  {
634  // set start to the current slice
635  tmpstart[0] = i;
636  tmpcount[0] = 1;
637 
638  // copy the slice
639  for (j = 0; j < size; j++)
640  {
641  tmpbuffer[j] = buffer[j];
642  }
643 
644  // write the slice
645  miset_voxel_value_hyperslab(volume, minctype,
646  tmpstart, tmpcount, tmpbuffer);
647 
648  // move on to next slice
649  buffer += size;
650  }
651 
652  delete [] tmpbuffer;
653 }
654 
655 void MINC2ImageIO::Write(const void* buffer)
656 {
657  int i,j;
658  int ncomp;
659 
660 // in general we cannot assume that m_original start or m_DirectionCosines exist
661  // have to recompute them
662 
663  // FIXME: i use a vnl_matrix here, because i know how to invert it, and the itk::Matrix
664  // used for the m_DirectionCosines I dont know how. However, maybe this matrix
665  // should be a different type anyway, so its variable size.
666  // This inelegant solution is Rupert being too lazy to RTFM, not for any good reason
667  vnl_matrix<double> dircosmatrix(3,3);
668  for( i = 0; i < 3; i++ )
669  {
670  for( j = 0; j < 3; j++ )
671  {
672  m_DirectionCosines[i][j]=this->m_Direction[j][i];
673  dircosmatrix[i][j]=m_DirectionCosines[i][j];
674  }
675  }
676  vnl_matrix<double> inverseDirectionCosines=vnl_matrix_inverse<double>(dircosmatrix);
677  /*
678  for( i = 0; i < 3; i++ )
679  {
680  m_OriginalStart[i]=0;
681  for( j = 0; j < 3; j++ )
682  {
683  m_OriginalStart[i] += inverseDirectionCosines[i][j] * this->GetOrigin(j);
684  }
685  }
686  */
687  for( i = 0; i < 3; i++ )
688  {
689  m_OriginalStart[i] = this->GetOrigin(i);
690  }
691  ncomp = this->GetNumberOfComponents();
692 
693  // ensure that the type is valid
694  if( m_Complex )
695  {
696  if (this->GetComponentType() == CHAR || this->GetComponentType() == UCHAR)
697  {
698  itkDebugMacro("MINC does not support 8-bit complex types");
699  return;
700  }
701  else if (this->GetComponentType() == USHORT || this->GetComponentType() == UINT)
702  {
703  itkDebugMacro("MINC does not support unsigned complex types");
704  return;
705  }
706  }
707 
708  // get the dimension order set by the user (copy it because
709  // CheckDimensionOrder will modify it)
710  char userdimorder[MINC2_MAXDIM+1];
711  if (this->GetDimensionOrder() != 0)
712  {
713  strncpy(userdimorder,this->GetDimensionOrder(),MINC2_MAXDIM);
714  userdimorder[MINC2_MAXDIM] = '\0';
715  }
716  else
717  {
718  strncpy(userdimorder,"zyx",MINC2_MAXDIM);
719  }
720 
721  // check the dimension order, add any dimensions that
722  // the users have set sizes for but which aren't in DimensionOrder
723  if (this->CheckDimensionOrder(userdimorder) == 0)
724  {
725  return;
726  }
727 
728  // three dimensions (x,y,z) are always present
729  int ndims = 3;
730  int vsize = 0; // vector_dimension size
731  int usize = 0; // produce of all user defined dimensions
732  int tsize = 0; // time dimension size
733  int xsize = this->GetDimensions(0);
734  int ysize = this->GetDimensions(1);
735  int zsize = this->GetDimensions(2);
736 
737  const char *vname = "vector_dimension";
738  const char *tname = "tspace";
739  const char *xname = "xspace";
740  const char *yname = "yspace";
741  const char *zname = "zspace";
742 
743  // update the names of dimensions if the user has specified
744  // e.g. xfrequency instead of xspace, and also get the sizes
745  // for all non-spatial dimensions
746  for( i = 0; i <= MINC2_MAXDIM; i++ )
747  {
748  if( this->m_DimensionName[i] )
749  {
750  // the first char in the name
751  int dimchar = this->m_DimensionName[i][0];
752 
753  if (dimchar == 'v')
754  { // add v dimension
755  vsize = this->m_DimensionSize[i];
756  vname = this->m_DimensionName[i];
757  if (vsize > 0)
758  {
759  ndims++;
760  }
761  }
762  else if (dimchar == 't')
763  { // add t dimension
764  tsize = this->m_DimensionSize[i];
765  tname = this->m_DimensionName[i];
766  if (tsize > 0)
767  {
768  ndims++;
769  }
770  }
771  else if (dimchar == 'x')
772  {
773  // xsize is calculated from extent
774  xname = this->m_DimensionName[i];
775  }
776  else if (dimchar == 'y')
777  {
778  // ysize is calculated from extent
779  yname = this->m_DimensionName[i];
780  }
781  else if (dimchar == 'z')
782  {
783  // zsize is calculated from extent
784  zname = this->m_DimensionName[i];
785  }
786  else
787  { // add other dimensions as vector dimensions
788  if( this->m_DimensionSize[i] > 0 )
789  {
790  if( usize == 0 )
791  {
792  usize = this->m_DimensionSize[i];
793  }
794  else
795  {
796  usize *= this->m_DimensionSize[i];
797  }
798  ndims++;
799  }
800  }
801  }
802  }
803 
804  // csize depends on whether the data is complex
805  int csize = (m_Complex ? 2 : 1);
806  // check the number of components: the product of the sizes of
807  // the complex, vector, and time dimensions should equal the
808  // number of scalar components in the vtkImageData
809  if ((tsize == 0 ? 1 : tsize)*(vsize == 0 ? 1 : vsize)*
810  (usize == 0 ? 1 : usize)*csize != ncomp)
811  {
812  // the number of components does not match extra dimension sizes,
813  // so try to make a vector dimension to account for this.
814 
815  // calculate the product of the dimension sizes except for vsize
816  int dimprod = (usize == 0 ? 1 : usize)*(tsize == 0 ? 1 : tsize)*csize;
817 
818  if (ncomp % dimprod != 0)
819  {
820  itkDebugMacro("Write: Product of non-spatial dimension sizes does not match number of scalar components: " << tsize << "*" << usize*csize << "!=" << ncomp);
821  return;
822  }
823 
824  // add the vector dimension if it was missing
825  if (vsize == 0)
826  {
827  ndims++;
828  // add to userdimorder unless it was already there
829  char *cp;
830  for (cp = userdimorder; *cp != '\0'; cp++)
831  {
832  if (*cp == 'v')
833  {
834  break;
835  }
836  }
837  if (*cp == '\0') // if didn't find 'v'
838  {
839  *cp++ = 'v';
840  *cp++ = '\0';
841  }
842  }
843 
844  // calcuate the proper size of the vector dimension
845  vsize = ncomp/dimprod;
846  }
847 
848  // remove any unused dimensions from userdimorder
849  i = 0;
850  char *cp;
851  for (cp = userdimorder; *cp != '\0'; cp++)
852  {
853  int dimchar = *cp;
854  if (dimchar == xname[0] || dimchar == yname[0] || dimchar == zname[0])
855  {
856  userdimorder[i++] = dimchar;
857  }
858  else if ((dimchar == tname[0] && tsize != 0) ||
859  (dimchar == vname[0] && vsize != 0))
860  {
861  userdimorder[i++] = dimchar;
862  }
863  else
864  {
865  for (j = 0; j <= MINC2_MAXDIM; j++)
866  {
867  if (this->m_DimensionName[j] && this->m_DimensionName[j][0] == dimchar)
868  {
869  userdimorder[i++] = dimchar;
870  break;
871  }
872  }
873  }
874  }
875 
876  if (i != ndims)
877  {
878  itkDebugMacro("Failed sanity check: i != ndims (" <<
879  i << "!=" << ndims << ")");
880  return;
881  }
882 
883  userdimorder[i++] = '\0'; // terminate the string
884 
885 
886  int result = 0;
887  mihandle_t volume;
888  midimhandle_t dim[MINC2_MAXDIM+1];
889  unsigned long offsets[MINC2_MAXDIM+1];
890  unsigned long counts[MINC2_MAXDIM+1];
891  // create the MINC dimensions in the file order given by userdimorder,
892  // remove any characters from userdimorder that don't match a used
893  // dimension.
894  for (i = 0; i < ndims; i++)
895  {
896  unsigned long dimsize = 0;
897  midimclass_t dimclass = MI_DIMCLASS_ANY;
898  const char *dimname = 0;
899  int dimchar = userdimorder[i];
900  double dimseparation = 1.0;
901  double dimstart = 0.0;
902 
903  if( dimchar == xname[0] || dimchar == yname[0] || dimchar == zname[0] )
904  { // spatial or spatial frequency
905  if( dimchar == xname[0] )
906  {
907  dimname = xname;
908  dimsize = xsize;
909  dimseparation = this->GetSpacing(0);
910  dimstart = m_OriginalStart[0];
911  }
912  else if (dimchar == yname[0])
913  {
914  dimname = yname;
915  dimsize = ysize;
916  dimseparation = this->GetSpacing(1);
917  dimstart = m_OriginalStart[1];
918  }
919  else /* if (dimchar == zname[0]) */
920  {
921  dimname = zname;
922  dimsize = zsize;
923  dimseparation = this->GetSpacing(2);
924  dimstart = m_OriginalStart[2];
925  }
926  dimclass = MI_DIMCLASS_SPATIAL;
927  if( strcmp(&dimname[1],"frequency") == 0 )
928  {
929  dimclass = MI_DIMCLASS_SFREQUENCY;
930  }
931  }
932  else if (dimchar == tname[0] && tsize != 0)
933  { // time or tfrequency
934  dimname = tname;
935  dimsize = tsize;
936  dimclass = MI_DIMCLASS_TIME;
937  if( strcmp(&dimname[1],"frequency") == 0 )
938  {
939  dimclass = MI_DIMCLASS_TFREQUENCY;
940  }
941  }
942  else if (dimchar == vname[0] && vsize != 0)
943  { // vector dimension
944  dimname = vname; // default is "vector_dimension"
945  dimsize = vsize; // default is all leftovers
946  dimclass = MI_DIMCLASS_RECORD; // unknown
947  }
948  else
949  { // other dimensions
950  // search through user-defined dimensions
951  for( j = 0; j <= MINC2_MAXDIM; j++ )
952  {
953  if (this->m_DimensionName[j] && this->m_DimensionName[j][0] == dimchar)
954  {
955  dimname = this->m_DimensionName[j];
956  dimsize = this->m_DimensionSize[j];
957  dimclass = MI_DIMCLASS_USER; // unknown
958  }
959  }
960  }
961 
962  //create MINC2.0 file
963  micreate_dimension(dimname, dimclass, MI_DIMATTR_REGULARLY_SAMPLED,dimsize, &dim[i]);
964 
965  // modify some parameters
966  if (dimclass == MI_DIMCLASS_SPATIAL || dimclass == MI_DIMCLASS_SFREQUENCY)
967  {
968  miset_dimension_units(dim[i], "mm");
969  miset_dimension_start(dim[i],/* MI_ORDER_APPARENT, */ dimstart);
970  miset_dimension_separation(dim[i],/* MI_ORDER_APPARENT,*/ dimseparation);
971 
972 
973  double dircos[3];
974  if( dimname[0] == 'x' )
975  {
976  dircos[0] = m_DirectionCosines[0][0];
977  dircos[1] = m_DirectionCosines[1][0];
978  dircos[2] = m_DirectionCosines[2][0];
979  }
980  else if ( dimname[0] == 'y' )
981  {
982  dircos[0] = m_DirectionCosines[0][1];
983  dircos[1] = m_DirectionCosines[1][1];
984  dircos[2] = m_DirectionCosines[2][1];
985  }
986  else if ( dimname[0] == 'z' )
987  {
988  dircos[0] = m_DirectionCosines[0][2];
989  dircos[1] = m_DirectionCosines[1][2];
990  dircos[2] = m_DirectionCosines[2][2];
991  }
992 
993  miset_dimension_cosines(dim[i], dircos);
994  }
995  else if (dimclass == MI_DIMCLASS_TIME || dimclass == MI_DIMCLASS_TFREQUENCY)
996  {
997  miset_dimension_units(dim[i], "s");
998  }
999  }
1000 
1001  // set the file data type
1002  mitype_t minctype;
1003  switch (this->GetComponentType())
1004  {
1005  case CHAR:
1006  minctype = MI_TYPE_BYTE;
1007  break;
1008  case UCHAR:
1009  minctype = MI_TYPE_UBYTE;
1010  break;
1011  case SHORT:
1012  minctype = MI_TYPE_SHORT;
1013  break;
1014  case USHORT:
1015  minctype = MI_TYPE_USHORT;
1016  break;
1017  case INT:
1018  minctype = MI_TYPE_INT;
1019  break;
1020  case UINT:
1021  minctype = MI_TYPE_UINT;
1022  break;
1023  case FLOAT:
1024  minctype = MI_TYPE_FLOAT;
1025  break;
1026  case DOUBLE:
1027  minctype = MI_TYPE_DOUBLE;
1028  break;
1029  default:
1030  itkDebugMacro("Bad data type ");
1031  return;
1032  } //end of switch
1033 
1034  // find the class
1035  miclass_t mincclass = MI_CLASS_REAL;
1036  if (m_Complex)
1037  {
1038  mincclass = MI_CLASS_COMPLEX;
1039  }
1040 
1041  result = micreate_volume(m_FileName.c_str(), ndims, dim, minctype , mincclass, NULL,&volume);
1042  if (result >= 0)
1043  {
1044  result = micreate_volume_image(volume);
1045  }
1046  // check for failed file open
1047  if (result < 0)
1048  {
1049  for (i = 0; i < ndims; i++)
1050  {
1051  mifree_dimension_handle(dim[i]);
1052  }
1053  itkDebugMacro("Couldn't open minc file " << m_FileName.c_str());
1054  return;
1055  }
1056  // set the apparent order before writing hyperslabs
1057  const char *dimnames[MINC2_MAXDIM+1];
1058  i = 0;
1059  dimnames[i] = zname; counts[i] = zsize; offsets[i++] = 0;
1060  dimnames[i] = yname; counts[i] = ysize; offsets[i++] = 0;
1061  dimnames[i] = xname; counts[i] = xsize; offsets[i++] = 0;
1062  if (tsize != 0)
1063  { // add time if it exists
1064  dimnames[i] = tname; counts[i] = tsize; offsets[i++] = 0;
1065  }
1066  // add other dimensions
1067  for (j = 0; j <= MINC2_MAXDIM; j++)
1068  {
1069  if (this->m_DimensionName[j] &&
1070  strcmp(this->m_DimensionName[j],zname) != 0 &&
1071  strcmp(this->m_DimensionName[j],yname) != 0 &&
1072  strcmp(this->m_DimensionName[j],xname) != 0 &&
1073  strcmp(this->m_DimensionName[j],tname) != 0 &&
1074  strcmp(this->m_DimensionName[j],vname) != 0)
1075  {
1076  dimnames[i] = this->m_DimensionName[j];
1077  counts[i] = this->m_DimensionSize[j];
1078  offsets[i++] = 0;
1079  }
1080  }
1081  // finally add a vector_dimension if we had to create one
1082  if (vsize != 0)
1083  {
1084  dimnames[i] = vname;
1085  counts[i] = vsize;
1086  offsets[i++] = 0;
1087  }
1088  // convert to string to compare to userdimorder
1089  char dimorder[MINC2_MAXDIM+1];
1090  for (i = 0; i < ndims; i++)
1091  {
1092  dimorder[i] = dimnames[i][0];
1093  }
1094  dimorder[ndims] = '\0';
1095 
1096  if (strcmp(dimorder, userdimorder) != 0)
1097  {
1098  miset_apparent_dimension_order_by_name(volume, ndims, (char **)dimnames);
1099  }
1100 
1101  // writing data in slice by slice
1102  switch (this->GetComponentType())
1103  {
1104  case CHAR:
1105  minctype = MI_TYPE_BYTE;
1106  MINCWriteHyperSlab(volume, ndims, minctype, offsets, counts,(char *)buffer);
1107  break;
1108  case UCHAR:
1109  minctype = MI_TYPE_UBYTE;
1110  MINCWriteHyperSlab(volume, ndims, minctype, offsets, counts,(unsigned char *)buffer);
1111  break;
1112  case SHORT:
1113  minctype = MI_TYPE_SHORT;
1114  MINCWriteHyperSlab(volume, ndims, minctype, offsets, counts,(short *)buffer);
1115  break;
1116  case USHORT:
1117  minctype = MI_TYPE_USHORT;
1118  MINCWriteHyperSlab(volume, ndims, minctype, offsets, counts,(unsigned short *)buffer);
1119  break;
1120  case INT:
1121  minctype = MI_TYPE_INT;
1122  MINCWriteHyperSlab(volume, ndims, minctype, offsets, counts,(int *)buffer);
1123  break;
1124  case UINT:
1125  minctype = MI_TYPE_UINT;
1126  MINCWriteHyperSlab(volume, ndims, minctype, offsets, counts,(unsigned int *)buffer);
1127  break;
1128  case FLOAT:
1129  minctype = MI_TYPE_FLOAT;
1130  MINCWriteHyperSlab(volume, ndims, minctype, offsets, counts,(float *)buffer);
1131  break;
1132  case DOUBLE:
1133  minctype = MI_TYPE_DOUBLE;
1134  MINCWriteHyperSlab(volume, ndims, minctype, offsets, counts,(double *)buffer);
1135  break;
1136  default:
1137  itkDebugMacro("Bad data type ");
1138  return;
1139  } //end of switch
1140 
1141  // set the min/max
1142  if (mincclass == MI_CLASS_REAL &&
1143  minctype != MI_TYPE_FLOAT && minctype != MI_TYPE_DOUBLE)
1144  {
1145  // need to calculate the min/max for the specified extent
1146  double minval, maxval;
1147  int Strides[3];
1148  Strides[0] = m_Strides[0];
1149  Strides[1] = m_Strides[1];
1150  Strides[2] = m_Strides[2];
1151  int Sizes[3];
1152  /* returns empty !??
1153  Sizes[0] = this->m_DimensionSize[0];
1154  Sizes[1] = this->m_DimensionSize[1];
1155  Sizes[2] = this->m_DimensionSize[2];*/
1156  Sizes[0] = this->GetDimensions(0);
1157  Sizes[1] = this->GetDimensions(1);
1158  Sizes[2] = this->GetDimensions(2);
1159  switch (minctype)
1160  {
1161  case MI_TYPE_BYTE:
1162  MINCComputeScalarRange(Strides,Sizes,this->GetNumberOfComponents(),maxval, minval,(char *)buffer);
1163  break;
1164  case MI_TYPE_UBYTE:
1165  MINCComputeScalarRange(Strides,Sizes,this->GetNumberOfComponents(),maxval, minval,(unsigned char *)buffer);
1166  break;
1167  case MI_TYPE_SHORT:
1168  MINCComputeScalarRange(Strides,Sizes,this->GetNumberOfComponents(),maxval, minval,(short *)buffer);
1169  break;
1170  case MI_TYPE_USHORT:
1171  MINCComputeScalarRange(Strides,Sizes,this->GetNumberOfComponents(),maxval, minval,(unsigned short *)buffer);
1172  break;
1173  case MI_TYPE_INT:
1174  MINCComputeScalarRange(Strides,Sizes,this->GetNumberOfComponents(),maxval, minval,(int *)buffer);
1175  break;
1176  case MI_TYPE_UINT:
1177  MINCComputeScalarRange(Strides,Sizes,this->GetNumberOfComponents(),maxval, minval,(unsigned int *)buffer);
1178  break;
1179  default:
1180  itkDebugMacro("Bad data type ");
1181  return;
1182  } //end of switch
1183  miset_volume_valid_range(volume, maxval, minval);
1184  miset_volume_range(volume, maxval*m_Scale+m_Shift,minval*m_Scale+m_Shift);
1185  }
1186  miclose_volume(volume);
1187  for (i = 0; i < ndims; i++)
1188  {
1189  mifree_dimension_handle(dim[i]);
1190  }
1191 }
1192 
1193 
1195 {
1196  //find out min of mins and max of maxs for slices
1197  unsigned int i;
1198  unsigned int j;
1199  unsigned long * coords=new(unsigned long[this->m_NDims]);
1200  double slice_max, slice_min;
1201  double max=-1e300, min=1e300;
1202  double valid_max, valid_min;
1203 
1204  if(miget_volume_valid_range(volume,&valid_max,&valid_min) <0)
1205  {
1206  itkDebugMacro("Could not get volume valid range ");
1207  return;
1208  }
1209 
1210  mitype_t volume_data_type;
1211 
1212  if(miget_data_type(volume,&volume_data_type) < 0)
1213  {
1214  itkDebugMacro(" Can not get volume data type!!\n");
1215  }
1216  // need coordinates in RAW dimension ordering
1217  // for miget_slice_range
1218  for(i = 0; i < this->m_NDims; i++)
1219  {
1220  coords[i] = 0;
1221  }
1222  // vector_dimension should not have slice scaling!!!
1223  // not sure how to deal with this yet
1224  // assume 4-dimensions without the vector now
1225  // go through slices in different dimensions
1226  for( i = 0; i < this->GetDimensions(this->m_NDims - 1); i++ )
1227  {
1228  coords[0] = i;
1229  if ( this->m_NDims > 3 )
1230  {
1231  for( j=0; j <this->GetDimensions(this->m_NDims - 2); j++ )
1232  {
1233  coords[1] = j;
1234  if (miget_slice_range(volume, coords, this->m_NDims, &slice_max, &slice_min) < 0)
1235  {
1236  itkDebugMacro("Could not get slice range");
1237  return;
1238  }
1239 
1240  if (slice_min < min)
1241  {
1242  min = slice_min;
1243  }
1244  if (slice_max > max)
1245  {
1246  max = slice_max;
1247  }
1248  }
1249  }
1250  else
1251  {
1252  if (miget_slice_range(volume, coords, this->m_NDims, &slice_max, &slice_min) < 0)
1253  {
1254  itkDebugMacro("Could not get slice range");
1255  return;
1256  }
1257  if (slice_min < min)
1258  {
1259  min = slice_min;
1260  }
1261  if (slice_max > max)
1262  {
1263  max = slice_max;
1264  }
1265  }
1266  }
1267  m_Scale = (max-min)/(valid_max - valid_min);
1268  m_Shift = min - (valid_min *m_Scale);
1269 
1270 }
1271 
1273 {
1274  double volume_max, volume_min;
1275  double valid_max, valid_min;
1276 
1277  if(miget_volume_valid_range(volume,&valid_max,&valid_min) <0)
1278  {
1279  itkDebugMacro("Could not get volume valid range ");
1280  return;
1281  }
1282  if(miget_volume_range(volume,&volume_max,&volume_min) < 0)
1283  {
1284  itkDebugMacro("Could not get volume range");
1285  return;
1286  }
1287 
1288  m_Scale = (volume_max-volume_min)/(valid_max-valid_min);
1289  m_Shift = volume_min - (valid_min * m_Scale);
1290 
1291 }
1292 
1293 void MINC2ImageIO::XYZFromDirectionCosines(midimhandle_t *hdims, int *dim_indices, unsigned int *numberOfComponents)
1294 {
1295 
1296  midimclass_t dim_class;
1297  double direction_cosines[3];
1298  double dircos[3][3] = { { 1, 0, 0},
1299  { 0, 1, 0},
1300  { 0, 0, 1}};
1301 
1302  // figure out present dimension in the order of either
1303  // xspace,yspace,zspace, time or xfrequency,yfrequency,zfrequency, tfrequency
1304  // --> x,y,z,t and vector-dimension
1305  unsigned int i=0;
1306  unsigned int counter=0;
1307  unsigned int counter2=5;
1308 
1309  for(i=0; i < this->m_NDims; i++)
1310  {
1311  if(miget_dimension_class(hdims[i],&dim_class) < 0)
1312  {
1313  // Error getting dimension class
1314  itkDebugMacro("Could not get dim class\"" << m_FileName.c_str() << "\".");
1315  return;
1316  }
1317 
1318  switch (dim_class)
1319  {
1320  case MI_DIMCLASS_SPATIAL:
1321  case MI_DIMCLASS_SFREQUENCY:
1322  // if none of xspace,yspace or zspace
1323  // use direction cosines to figure out which dimension is x,y,z
1324  if (miget_dimension_cosines(hdims[i],direction_cosines) < 0)
1325  {
1326  // Error getting dimension direction cosine
1327  itkDebugMacro("Could not getdirection cosines!");
1328  return;
1329  }
1330  // fill the dircos array for now, order x,y,z
1331  // figure out the order later
1332  dircos[0][counter] = direction_cosines[0];
1333  dircos[1][counter] = direction_cosines[1];
1334  dircos[2][counter] = direction_cosines[2];
1335  dim_indices[counter]=i;
1336  counter++;
1337  break;
1338  case MI_DIMCLASS_TIME:
1339  case MI_DIMCLASS_TFREQUENCY:
1340  dim_indices[3] = i;
1341  *numberOfComponents *= this->m_DimensionSize[i];
1342  break;
1343  // check for vector dimensions
1344  case MI_DIMCLASS_RECORD:
1345  dim_indices[4] = i;
1346  *numberOfComponents *= this->m_DimensionSize[i];
1347  break;
1348  case MI_DIMCLASS_ANY:
1349  case MI_DIMCLASS_USER:
1350  dim_indices[counter2] = i;
1351  counter2++;
1352  break;
1353  //default:
1354  // any other dimension is ignored!!
1355  //return;
1356 
1357  } // end of switch
1358  } //end of for
1359  // fill in the itk matrix for direction cosines
1360 
1361  m_DirectionCosines.Fill( 0.0 );
1363  //figure out from direction cosines which dimension is what
1364  // largest z component (3 dimensions) --> zspace
1365  // then largest y component (2 dimension) --> yspace
1366  // last remaining dimension xspace.
1367 
1368  int temp;
1369  if ( counter == 3 ) // three spatial dimensions
1370  {
1371  if((dircos[2][0] >= dircos[2][1]) && (dircos[2][0] >= dircos[2][2]))
1372  {
1373  // index 0 is the z dimension
1374  m_DirectionCosines[0][2] = dircos[0][0];
1375  m_DirectionCosines[1][2] = dircos[1][0];
1376  m_DirectionCosines[2][2] = dircos[2][0];
1377 
1378  if( dircos[1][1] >= dircos[1][2] )
1379  {
1380  m_DirectionCosines[0][1] = dircos[0][1];
1381  m_DirectionCosines[1][1] = dircos[1][1];
1382  m_DirectionCosines[2][1] = dircos[2][1];
1383  m_DirectionCosines[0][0] = dircos[0][2];
1384  m_DirectionCosines[1][0] = dircos[1][2];
1385  m_DirectionCosines[2][0] = dircos[2][2];
1386  }
1387  else
1388  {
1389  temp = dim_indices[1];
1390  dim_indices[1] = dim_indices[2];
1391  dim_indices[2] = temp;
1392  m_DirectionCosines[0][1] = dircos[0][2];
1393  m_DirectionCosines[1][1] = dircos[1][2];
1394  m_DirectionCosines[2][1] = dircos[2][2];
1395  m_DirectionCosines[0][0] = dircos[0][1];
1396  m_DirectionCosines[1][0] = dircos[1][1];
1397  m_DirectionCosines[2][0] = dircos[2][1];
1398  }
1399  }
1400  else if ((dircos[2][1] >= dircos[2][0]) && (dircos[2][1] >= dircos[2][2]))
1401  {
1402  m_DirectionCosines[0][2] = dircos[0][1];
1403  m_DirectionCosines[1][2] = dircos[1][1];
1404  m_DirectionCosines[2][2] = dircos[2][1];
1405  temp = dim_indices[0];
1406  dim_indices[0] = dim_indices[1];
1407  if( dircos[1][0] >= dircos[1][2] )
1408  {
1409  dim_indices[1] = temp;
1410  m_DirectionCosines[0][1] = dircos[0][0];
1411  m_DirectionCosines[1][1] = dircos[1][0];
1412  m_DirectionCosines[2][1] = dircos[2][0];
1413  m_DirectionCosines[0][0] = dircos[0][2];
1414  m_DirectionCosines[1][0] = dircos[1][2];
1415  m_DirectionCosines[2][0] = dircos[2][2];
1416  }
1417  else
1418  {
1419  dim_indices[1] = dim_indices[2];
1420  dim_indices[2] = temp;
1421  m_DirectionCosines[0][1] = dircos[0][2];
1422  m_DirectionCosines[1][1] = dircos[1][2];
1423  m_DirectionCosines[2][1] = dircos[2][2];
1424  m_DirectionCosines[0][0] = dircos[0][0];
1425  m_DirectionCosines[1][0] = dircos[1][0];
1426  m_DirectionCosines[2][0] = dircos[2][0];
1427  }
1428  }
1429  else
1430  {
1431  m_DirectionCosines[0][2] = dircos[0][2];
1432  m_DirectionCosines[1][2] = dircos[1][2];
1433  m_DirectionCosines[2][2] = dircos[2][2];
1434  temp = dim_indices[0];
1435  dim_indices[0] = dim_indices[2];
1436  if( dircos[1][0] >= dircos[1][1] )
1437  {
1438  dim_indices[2] = dim_indices[1];
1439  dim_indices[1] = temp;
1440  m_DirectionCosines[0][1] = dircos[0][0];
1441  m_DirectionCosines[1][1] = dircos[1][0];
1442  m_DirectionCosines[2][1] = dircos[2][0];
1443  m_DirectionCosines[0][0] = dircos[0][1];
1444  m_DirectionCosines[1][0] = dircos[1][1];
1445  m_DirectionCosines[2][0] = dircos[2][1];
1446  }
1447  else
1448  {
1449  dim_indices[2] = temp;
1450  m_DirectionCosines[0][0] = dircos[0][0];
1451  m_DirectionCosines[1][0] = dircos[1][0];
1452  m_DirectionCosines[2][0] = dircos[2][0];
1453  m_DirectionCosines[0][1] = dircos[0][1];
1454  m_DirectionCosines[1][1] = dircos[1][1];
1455  m_DirectionCosines[2][1] = dircos[2][1];
1456  }
1457  }
1458  }
1459 }
1460 
1462 {
1463  // This method will adjust the passed "userdimorder" parameter as necessary
1464  // to add extra dimensions for which sizes have been specified.
1465  //
1466  // A return value of 0 means a failed check, the reason for failure
1467  // will be printed via vtkErrorMacro
1468  //
1469  // Note that if you pass a userdimorder that is incomplete, e.g. "zx",
1470  // then temporal & spatial dimensions will be prepended, and other
1471  // dimensions will be appended. So "zx" becomes "yzx".
1472 
1473  int i, j;
1474 
1475  // check for repeats
1476  for(i = 0; userdimorder[i] && i <= MINC2_MAXDIM; i++)
1477  {
1478  for(j = 0; j < i; j++)
1479  {
1480  if (userdimorder[i] == userdimorder[j])
1481  {
1482  itkDebugMacro("Invalid DimensionOrder " << userdimorder);
1483  return 0;
1484  }
1485  }
1486  }
1487 
1488  // remove any characters which are not one of x, y or z and that
1489  // the user has not set a DimensionSize for.
1490  for (i = 0; userdimorder[i] && i <= MINC2_MAXDIM; i++)
1491  {
1492  int dimchar = userdimorder[i];
1493 
1494  if (dimchar != 'x' && dimchar != 'y' && dimchar != 'z')
1495  {
1496  for (j = 0; j <= MINC2_MAXDIM; j++)
1497  {
1498  if (this->m_DimensionName[j] && dimchar == this->m_DimensionName[j][0])
1499  {
1500  break;
1501  }
1502  }
1503  // if no dimension corresponds to the char in userdimorder, remove it
1504  if (j == MINC2_MAXDIM)
1505  {
1506  memmove(&userdimorder[i],&userdimorder[i+1],MINC2_MAXDIM-i-1);
1507  userdimorder[MINC2_MAXDIM-1] = '\0';
1508  i--; // backup by one char
1509  }
1510  }
1511  }
1512 
1513  // prepend any spatial dimension which isn't yet there
1514  static const char *spatial = "xyz";
1515  for (i = 0; i < 3; i++)
1516  {
1517  int dimchar = spatial[i];
1518  // is this dimension already in the dimension order?
1519  int found = 0;
1520  for (j = 0; userdimorder[j] && j <= MINC2_MAXDIM-1; j++)
1521  {
1522  if( userdimorder[j] == dimchar )
1523  {
1524  found = 1;
1525  }
1526  }
1527 
1528  if (!found)
1529  {
1530  memmove(&userdimorder[1],&userdimorder[0],MINC2_MAXDIM-1);
1531  userdimorder[0] = dimchar;
1532  }
1533  }
1534 
1535  // check the user-defined dimensions, expand "userdimorder" as necessary
1536  // to include any dimensions added via SetDimensionSize
1537  for (i = 0; i <= MINC2_MAXDIM; i++)
1538  {
1539  if (this->m_DimensionName[i])
1540  {
1541  // the first char in the name
1542  int dimchar = this->m_DimensionName[i][0];
1543 
1544  // is this dimension already in the dimension order?
1545  int found = 0;
1546  for (j = 0; userdimorder[j] && j <= MINC2_MAXDIM-1; j++)
1547  {
1548  if (userdimorder[j] == dimchar)
1549  {
1550  found = 1;
1551  }
1552  }
1553 
1554  if (!found)
1555  {
1556  if (dimchar == 't')
1557  { // add time to start of list
1558  memmove(&userdimorder[1],&userdimorder[0],MINC2_MAXDIM-1);
1559  userdimorder[0] = dimchar;
1560  }
1561  else
1562  { // add other dimension to end of list
1563  userdimorder[j] = dimchar;
1564  }
1565  }
1566  }
1567  }
1568 
1569  return 1;
1570 }
1571 
1572 } // end namespace itk

Generated at Sat May 18 2013 23:53:42 for Orfeo Toolbox with doxygen 1.8.3.1