1 /*============================================================================
2   MetaIO
3   Copyright 2000-2010 Insight Software Consortium
4 
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7 
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the License for more information.
11 ============================================================================*/
12 #include "metaImage.h"
13 
14 #include <stdio.h>
15 #include <ctype.h>
16 #include <string>
17 #include <string.h> // for memcpy
18 #include <stdlib.h> // for atoi
19 #include <math.h>
20 
21 #if defined (__BORLANDC__) && (__BORLANDC__ >= 0x0580)
22 #include <mem.h>
23 #endif
24 
25 #if defined(_WIN32)
26 # include <io.h>
27 #endif
28 
29 // support for access
30 #ifndef _WIN32
31 #include <limits.h>
32 #include <sys/param.h>
33 #include <sys/wait.h>
34 #include <sys/ioctl.h>
35 #include <unistd.h>
36 #include <pwd.h>
37 #include <termios.h>
38 #include <signal.h>    /* sigprocmask */
39 #endif
40 
41 namespace {
42 
openReadStream(METAIO_STREAM::ifstream & inputStream,const char * fname)43 void openReadStream(METAIO_STREAM::ifstream & inputStream, const char * fname)
44 {
45 #ifdef __sgi
46   inputStream.open( fname, METAIO_STREAM::ios::in );
47 #else
48   inputStream.open( fname, METAIO_STREAM::ios::in |
49                            METAIO_STREAM::ios::binary );
50 #endif
51 }
52 
openWriteStream(METAIO_STREAM::ofstream & outputStream,const char * fname,bool append)53 void openWriteStream(METAIO_STREAM::ofstream & outputStream, const char * fname, bool append)
54 {
55 // Some older sgi compilers have a error in the ofstream constructor
56 // that requires a file to exist for output
57 #ifdef __sgi
58   {
59   METAIO_STREAM::ofstream tFile(fname, METAIO_STREAM::ios::out);
60   tFile.close();
61   }
62 #endif
63 
64   if(!append)
65     {
66 #ifdef __sgi
67     outputStream.open(fname, METAIO_STREAM::ios::out);
68 #else
69     outputStream.open(fname, METAIO_STREAM::ios::binary |
70                              METAIO_STREAM::ios::out);
71 #endif
72     }
73   else
74     {
75 #ifdef __sgi
76     outputStream.open(fname, METAIO_STREAM::ios::app |
77                              METAIO_STREAM::ios::out);
78 #else
79     outputStream.open(fname, METAIO_STREAM::ios::binary |
80                              METAIO_STREAM::ios::app |
81                              METAIO_STREAM::ios::out);
82 #endif
83     }
84 }
85 
86 const unsigned int MAXPATHLENGHT = 2048;
87 
88 } // end anonymous namespace
89 
90 #if (METAIO_USE_NAMESPACE)
91 namespace METAIO_NAMESPACE {
92 #endif
93 
94 // 1 Gigabyte is the maximum chunk to read/write in on function call
95 static const METAIO_STL::streamoff MaxIOChunk = 1024*1024*1024;
96 
97 //
98 // MetaImage Constructors
99 //
100 MetaImage::
MetaImage()101 MetaImage()
102 :MetaObject()
103   {
104   if(META_DEBUG)
105     {
106     METAIO_STREAM::cout << "MetaImage()" << METAIO_STREAM::endl;
107     }
108 
109   m_CompressionTable = new MET_CompressionTableType;
110   m_CompressionTable->compressedStream = NULL;
111   m_CompressionTable->buffer = NULL;
112   Clear();
113   }
114 
115 //
116 MetaImage::
MetaImage(const char * _headerName)117 MetaImage(const char *_headerName)
118 :MetaObject()
119   {
120   if(META_DEBUG)
121     {
122     METAIO_STREAM::cout << "MetaImage()" << METAIO_STREAM::endl;
123     }
124 
125   m_CompressionTable = new MET_CompressionTableType;
126   m_CompressionTable->compressedStream = NULL;
127   m_CompressionTable->buffer = NULL;
128   Clear();
129 
130   Read(_headerName);
131   }
132 
133 //
134 MetaImage::
MetaImage(MetaImage * _im)135 MetaImage(MetaImage *_im)
136 :MetaObject()
137   {
138   if(META_DEBUG)
139     {
140     METAIO_STREAM::cout << "MetaImage()" << METAIO_STREAM::endl;
141     }
142 
143   m_CompressionTable = new MET_CompressionTableType;
144   m_CompressionTable->compressedStream = NULL;
145   m_CompressionTable->buffer = NULL;
146   Clear();
147 
148   InitializeEssential(_im->NDims(),
149                       _im->DimSize(),
150                       _im->ElementSpacing(),
151                       _im->ElementType(),
152                       _im->ElementNumberOfChannels(),
153                       _im->ElementData(),
154                       false);
155   CopyInfo(_im);
156   }
157 
158 //
159 MetaImage::
MetaImage(int _nDims,const int * _dimSize,const float * _elementSpacing,MET_ValueEnumType _elementType,int _elementNumberOfChannels,void * _elementData)160 MetaImage(int _nDims,
161           const int * _dimSize,
162           const float * _elementSpacing,
163           MET_ValueEnumType _elementType,
164           int _elementNumberOfChannels,
165           void *_elementData)
166 :MetaObject()
167   {
168   if(META_DEBUG)
169     {
170     METAIO_STREAM::cout << "MetaImage()" << METAIO_STREAM::endl;
171     }
172 
173   m_CompressionTable = new MET_CompressionTableType;
174   m_CompressionTable->buffer = NULL;
175   m_CompressionTable->compressedStream = NULL;
176   Clear();
177 
178   if(_elementData == NULL)
179     {
180     InitializeEssential(_nDims,
181                         _dimSize,
182                         _elementSpacing,
183                         _elementType,
184                         _elementNumberOfChannels,
185                         NULL, true);
186     }
187   else
188     {
189     InitializeEssential(_nDims,
190                         _dimSize,
191                         _elementSpacing,
192                         _elementType,
193                         _elementNumberOfChannels,
194                         _elementData, false);
195     }
196 
197   }
198 
199 //
200 MetaImage::
MetaImage(int _x,int _y,float _elementSpacingX,float _elementSpacingY,MET_ValueEnumType _elementType,int _elementNumberOfChannels,void * _elementData)201 MetaImage(int _x, int _y,
202           float _elementSpacingX, float _elementSpacingY,
203           MET_ValueEnumType _elementType,
204           int _elementNumberOfChannels, void *_elementData)
205 :MetaObject()
206   {
207   if(META_DEBUG)
208     {
209     METAIO_STREAM::cout << "MetaImage()" << METAIO_STREAM::endl;
210     }
211 
212   m_CompressionTable = new MET_CompressionTableType;
213   m_CompressionTable->compressedStream = NULL;
214   m_CompressionTable->buffer = NULL;
215   Clear();
216 
217   int ds[2];
218   ds[0] = _x;
219   ds[1] = _y;
220 
221   float es[2];
222   es[0] = _elementSpacingX;
223   es[1] = _elementSpacingY;
224 
225   if(_elementData == NULL)
226     {
227     InitializeEssential(2,
228                         ds,
229                         es,
230                         _elementType,
231                         _elementNumberOfChannels,
232                         NULL,
233                         true);
234     }
235   else
236     {
237     InitializeEssential(2,
238                         ds,
239                         es,
240                         _elementType,
241                         _elementNumberOfChannels,
242                         _elementData,
243                         false);
244     }
245   }
246 
247 //
248 MetaImage::
MetaImage(int _x,int _y,int _z,float _elementSpacingX,float _elementSpacingY,float _elementSpacingZ,MET_ValueEnumType _elementType,int _elementNumberOfChannels,void * _elementData)249 MetaImage(int _x, int _y, int _z,
250           float _elementSpacingX,
251           float _elementSpacingY,
252           float _elementSpacingZ,
253           MET_ValueEnumType _elementType,
254           int _elementNumberOfChannels,
255           void *_elementData)
256 :MetaObject()
257   {
258   if(META_DEBUG)
259     {
260     METAIO_STREAM::cout << "MetaImage()" << METAIO_STREAM::endl;
261     }
262 
263   m_CompressionTable = new MET_CompressionTableType;
264   m_CompressionTable->compressedStream = NULL;
265   m_CompressionTable->buffer = NULL;
266   Clear();
267 
268   int ds[3];
269   ds[0] = _x;
270   ds[1] = _y;
271   ds[2] = _z;
272 
273   float es[3];
274   es[0] = _elementSpacingX;
275   es[1] = _elementSpacingY;
276   es[2] = _elementSpacingZ;
277 
278   if(_elementData == NULL)
279     {
280     InitializeEssential(3,
281                         ds,
282                         es,
283                         _elementType,
284                         _elementNumberOfChannels,
285                         NULL,
286                         true);
287     }
288   else
289     {
290     InitializeEssential(3,
291                         ds,
292                         es,
293                         _elementType,
294                         _elementNumberOfChannels,
295                         _elementData,
296                         false);
297     }
298   }
299 
300 //
301 MetaImage::
~MetaImage()302 ~MetaImage()
303   {
304   M_Destroy();
305   }
306 
307 //
308 void MetaImage::
PrintInfo() const309 PrintInfo() const
310   {
311   int i;
312 
313   MetaObject::PrintInfo();
314 
315   char s[MAXPATHLENGHT];
316   MET_ImageModalityToString(m_Modality, s);
317   METAIO_STREAM::cout << "Modality = " << s << METAIO_STREAM::endl;
318 
319   METAIO_STREAM::cout << "DimSize = ";
320   for(i=0; i<m_NDims; i++)
321     {
322     METAIO_STREAM::cout << m_DimSize[i] << " ";
323     }
324   METAIO_STREAM::cout << METAIO_STREAM::endl;
325   METAIO_STREAM::cout << "SubQuantity = ";
326   for(i=0; i<m_NDims; i++)
327     {
328     METAIO_STREAM::cout << m_SubQuantity[i] << " ";
329     }
330   METAIO_STREAM::cout << METAIO_STREAM::endl;
331 
332   METAIO_STREAM::cout << "Quantity = " << m_Quantity << METAIO_STREAM::endl;
333 
334 
335   METAIO_STREAM::cout << "HeaderSize = " << m_HeaderSize << METAIO_STREAM::endl;
336 
337   METAIO_STREAM::cout << "SequenceID = ";
338   for(i=0; i<m_NDims; i++)
339     {
340     METAIO_STREAM::cout << m_SequenceID[i] << " ";
341     }
342   METAIO_STREAM::cout << METAIO_STREAM::endl;
343 
344   METAIO_STREAM::cout << "ElementSizeValid = " << (int)m_ElementSizeValid
345             << METAIO_STREAM::endl;
346   METAIO_STREAM::cout << "ElementSize = ";
347   for(i=0; i<m_NDims; i++)
348     {
349     METAIO_STREAM::cout << m_ElementSize[i] << " ";
350     }
351   METAIO_STREAM::cout << METAIO_STREAM::endl;
352 
353   char str[MAXPATHLENGHT];
354   MET_TypeToString(m_ElementType, str);
355   METAIO_STREAM::cout << "ElementType = " << str << METAIO_STREAM::endl;
356 
357   METAIO_STREAM::cout << "ElementNumberOfChannels = "
358                       << m_ElementNumberOfChannels << METAIO_STREAM::endl;
359 
360   if(m_ElementMinMaxValid)
361     {
362     METAIO_STREAM::cout << "Min and Max are valid" << METAIO_STREAM::endl;
363     METAIO_STREAM::cout << "   Min = " << m_ElementMin << METAIO_STREAM::endl;
364     METAIO_STREAM::cout << "   Max = " << m_ElementMax << METAIO_STREAM::endl;
365     }
366   else
367     {
368     METAIO_STREAM::cout << "Min and Max are not valid" << METAIO_STREAM::endl;
369     }
370 
371   METAIO_STREAM::cout << "ElementToIntensityFunctionSlope = "
372                       << m_ElementToIntensityFunctionSlope
373                       << METAIO_STREAM::endl;
374   METAIO_STREAM::cout << "ElementToIntensityFunctionOffset = "
375                       << m_ElementToIntensityFunctionOffset
376                       << METAIO_STREAM::endl;
377 
378 
379   METAIO_STREAM::cout << "AutoFreeElementData = "
380                       << ((m_AutoFreeElementData)?"True":"False")
381                       << METAIO_STREAM::endl;
382 
383   METAIO_STREAM::cout << "ElementData = "
384                       << ((m_ElementData==NULL)?"NULL":"Valid")
385                       << METAIO_STREAM::endl;
386 
387   METAIO_STREAM::cout << "ElementDataFileName = "
388                       << m_ElementDataFileName << METAIO_STREAM::endl;
389 
390   }
391 
392 void MetaImage::
CopyInfo(const MetaObject * _object)393 CopyInfo(const MetaObject * _object)
394   {
395   MetaObject::CopyInfo(_object);
396 
397   if(_object)
398     {
399     const MetaImage * im;
400     try
401       {
402       im = (const MetaImage *)(_object);
403       }
404     catch( ... )
405       {
406       return;
407       }
408 
409     if( im )
410       {
411       Modality(im->Modality());
412 
413       HeaderSize(im->HeaderSize());
414 
415       SequenceID(im->SequenceID());
416 
417       ElementSizeValid(im->ElementSizeValid());
418       if(im->ElementSizeValid())
419         {
420         ElementSize(im->ElementSize());
421         }
422 
423       ElementMinMaxValid(im->ElementMinMaxValid());
424       if(im->ElementMinMaxValid())
425         {
426         ElementMin(im->ElementMin());
427         ElementMax(im->ElementMax());
428         }
429 
430       ElementToIntensityFunctionSlope(im->ElementToIntensityFunctionSlope());
431       ElementToIntensityFunctionOffset(im->ElementToIntensityFunctionOffset());
432       }
433     }
434   }
435 
436 /** Clear function */
Clear(void)437 void MetaImage::Clear(void)
438 {
439   if(META_DEBUG)
440     {
441     METAIO_STREAM::cout << "MetaImage: Clear" << METAIO_STREAM::endl;
442     }
443 
444   m_Modality = MET_MOD_UNKNOWN;
445 
446   m_DimSize[0] = 0;
447   m_SubQuantity[0] = 0;
448   m_Quantity = 0;
449 
450   m_HeaderSize = 0;
451 
452   memset(m_SequenceID, 0, 4*sizeof(float));
453 
454   m_ElementSizeValid = false;
455   memset(m_ElementSize, 0, 10*sizeof(float));
456 
457   m_ElementType = MET_NONE;
458 
459   m_ElementNumberOfChannels = 1;
460 
461   m_ElementMinMaxValid = false;
462   m_ElementMin = 0;
463   m_ElementMax = 0;
464 
465   m_ElementToIntensityFunctionSlope = 1;
466   m_ElementToIntensityFunctionOffset = 0;
467 
468   m_AutoFreeElementData = true;
469 
470   m_ElementData = NULL;
471 
472   strcpy(m_ElementDataFileName, "");
473 
474   MetaObject::Clear();
475 
476   // Change the default for this object
477   m_BinaryData = true;
478 
479   if(m_CompressionTable)
480     {
481     if(m_CompressionTable->compressedStream)
482       {
483       inflateEnd(m_CompressionTable->compressedStream);
484       delete m_CompressionTable->compressedStream;
485       delete [] m_CompressionTable->buffer;
486       m_CompressionTable->buffer = NULL;
487       }
488     m_CompressionTable->compressedStream = NULL;
489     m_CompressionTable->offsetList.clear();
490     }
491   else
492     {
493     m_CompressionTable = new MET_CompressionTableType;
494     m_CompressionTable->compressedStream = NULL;
495     }
496 
497 }
498 
499 bool MetaImage::
InitializeEssential(int _nDims,const int * _dimSize,const float * _elementSpacing,MET_ValueEnumType _elementType,int _elementNumberOfChannels,void * _elementData,bool _allocElementMemory)500 InitializeEssential(int _nDims,
501                     const int * _dimSize,
502                     const float * _elementSpacing,
503                     MET_ValueEnumType _elementType,
504                     int _elementNumberOfChannels,
505                     void * _elementData,
506                     bool _allocElementMemory)
507   {
508   if(META_DEBUG)
509     {
510     METAIO_STREAM::cout << "MetaImage: Initialize" << METAIO_STREAM::endl;
511     }
512 
513   MetaObject::InitializeEssential(_nDims);
514 
515   int i;
516   if(!m_CompressionTable)
517     {
518     m_CompressionTable = new MET_CompressionTableType;
519     m_CompressionTable->buffer = NULL;
520     m_CompressionTable->compressedStream = NULL;
521     }
522   m_SubQuantity[0] = 1;
523   m_Quantity = 1;
524   m_ElementSizeValid = false;
525   for(i=0; i<m_NDims; i++)
526     {
527     m_DimSize[i] = _dimSize[i];
528     m_Quantity *= _dimSize[i];
529     if(i>0)
530       {
531       m_SubQuantity[i] = m_SubQuantity[i-1]*m_DimSize[i-1];
532       }
533     m_ElementSpacing[i] = _elementSpacing[i];
534     if(m_ElementSize[i] == 0)
535       {
536       m_ElementSize[i] = m_ElementSpacing[i];
537       }
538     else
539       {
540       m_ElementSizeValid = true;
541       }
542     }
543 
544   m_ElementType = _elementType;
545 
546   m_ElementNumberOfChannels = _elementNumberOfChannels;
547 
548   if(_elementData != NULL)
549     {
550     m_AutoFreeElementData = false;
551     m_ElementData = (void *)_elementData;
552     }
553   else if(_allocElementMemory)
554     {
555     m_AutoFreeElementData = true;
556     MET_SizeOfType(m_ElementType, &i);
557     m_ElementData = new char[m_Quantity*m_ElementNumberOfChannels*i];
558     if(m_ElementData == NULL)
559       {
560       METAIO_STREAM::cerr << "MetaImage:: M_Allocate:: Insufficient memory"
561                           << METAIO_STREAM::endl;
562       return false;
563       }
564     }
565   else
566     {
567     m_AutoFreeElementData = true;
568     m_ElementData = NULL;
569     }
570 
571   return true;
572   }
573 
574 
575 //
576 //
577 //
578 int MetaImage::
HeaderSize(void) const579 HeaderSize(void) const
580   {
581   return m_HeaderSize;
582   }
583 
584 void MetaImage::
HeaderSize(int _headerSize)585 HeaderSize(int _headerSize)
586   {
587   m_HeaderSize = _headerSize;
588   }
589 
590 //
591 //
592 //
593 MET_ImageModalityEnumType MetaImage::
Modality(void) const594 Modality(void) const
595   {
596   return m_Modality;
597   }
598 
599 void MetaImage::
Modality(MET_ImageModalityEnumType _modality)600 Modality(MET_ImageModalityEnumType _modality)
601   {
602   m_Modality = _modality;
603   }
604 
605 //
606 //
607 //
608 const int * MetaImage::
DimSize(void) const609 DimSize(void) const
610   {
611   return m_DimSize;
612   }
613 
614 int MetaImage::
DimSize(int _i) const615 DimSize(int _i) const
616   {
617   return m_DimSize[_i];
618   }
619 
620 //
621 //
622 //
623 METAIO_STL::streamoff MetaImage::
Quantity(void) const624 Quantity(void) const
625   {
626   return m_Quantity;
627   }
628 
629 //
630 //
631 //
632 const METAIO_STL::streamoff * MetaImage::
SubQuantity(void) const633 SubQuantity(void) const
634   {
635   return m_SubQuantity;
636   }
637 
638 METAIO_STL::streamoff MetaImage::
SubQuantity(int _i) const639 SubQuantity(int _i) const
640   {
641   return m_SubQuantity[_i];
642   }
643 
644 //
645 //
646 //
647 const float * MetaImage::
SequenceID(void) const648 SequenceID(void) const
649   {
650   return m_SequenceID;
651   }
652 
653 float MetaImage::
SequenceID(int _i) const654 SequenceID(int _i) const
655   {
656   return m_SequenceID[_i];
657   }
658 
659 void MetaImage::
SequenceID(const float * _sequenceID)660 SequenceID(const float *_sequenceID)
661   {
662   memcpy(m_SequenceID, _sequenceID, m_NDims*sizeof(float));
663   }
664 
665 void MetaImage::
SequenceID(int _i,float _value)666 SequenceID(int _i, float _value)
667   {
668   m_SequenceID[_i] = _value;
669   }
670 
671 //
672 //
673 //
674 bool MetaImage::
ElementSizeValid(void) const675 ElementSizeValid(void) const
676   {
677   return m_ElementSizeValid;
678   }
679 
680 void MetaImage::
ElementSizeValid(bool _elementSizeValid)681 ElementSizeValid(bool _elementSizeValid)
682   {
683   m_ElementSizeValid = _elementSizeValid;
684   }
685 
686 const float * MetaImage::
ElementSize(void) const687 ElementSize(void) const
688   {
689   return m_ElementSize;
690   }
691 
692 float MetaImage::
ElementSize(int _i) const693 ElementSize(int _i) const
694   {
695   return m_ElementSize[_i];
696   }
697 
698 void MetaImage::
ElementSize(const float * _elementSize)699 ElementSize(const float *_elementSize)
700   {
701   memcpy(m_ElementSize, _elementSize, m_NDims*sizeof(float));
702   m_ElementSizeValid = true;
703   }
704 
705 void MetaImage::
ElementSize(int _i,float _value)706 ElementSize(int _i, float _value)
707   {
708   m_ElementSize[_i] = _value;
709   m_ElementSizeValid = true;
710   }
711 
712 //
713 //
714 //
715 MET_ValueEnumType MetaImage::
ElementType(void) const716 ElementType(void) const
717   {
718   return m_ElementType;
719   }
720 
721 void MetaImage::
ElementType(MET_ValueEnumType _elementType)722 ElementType(MET_ValueEnumType _elementType)
723   {
724   m_ElementType = _elementType;
725   }
726 
727 //
728 //
729 //
730 int MetaImage::
ElementNumberOfChannels(void) const731 ElementNumberOfChannels(void) const
732   {
733   return m_ElementNumberOfChannels;
734   }
735 
736 void MetaImage::
ElementNumberOfChannels(int _elementNumberOfChannels)737 ElementNumberOfChannels(int _elementNumberOfChannels)
738   {
739   m_ElementNumberOfChannels = _elementNumberOfChannels;
740   }
741 
742 //
743 //
744 //
745 void MetaImage::
ElementByteOrderSwap(METAIO_STL::streamoff _quantity)746 ElementByteOrderSwap(METAIO_STL::streamoff _quantity)
747   {
748 
749   // use the user provided value if provided or the internal ivar
750   METAIO_STL::streamoff quantity = _quantity ? _quantity : m_Quantity;
751 
752   if(META_DEBUG)
753     {
754     METAIO_STREAM::cout << "MetaImage: ElementByteOrderSwap"
755                         << METAIO_STREAM::endl;
756     }
757 
758   int eSize;
759   MET_SizeOfType(m_ElementType, &eSize);
760   switch(eSize)
761     {
762     default:
763     case 0:
764     case 1:
765       {
766       break;
767       }
768     case 2:
769       {
770       int i;
771       for(i=0; i<quantity*m_ElementNumberOfChannels; i++)
772         {
773         ((MET_USHORT_TYPE *)m_ElementData)[i] =
774               MET_ByteOrderSwapShort(((MET_USHORT_TYPE *)m_ElementData)[i]);
775         }
776       break;
777       }
778     case 4:
779       {
780       int i;
781       for(i=0; i<quantity*m_ElementNumberOfChannels; i++)
782         {
783         ((MET_UINT_TYPE *)m_ElementData)[i] =
784               MET_ByteOrderSwapLong(((MET_UINT_TYPE *)m_ElementData)[i]);
785         }
786       break;
787       }
788     case 8:
789       {
790       int i;
791       char* data = (char*)m_ElementData;
792       for(i=0; i<quantity*m_ElementNumberOfChannels; i++)
793         {
794         MET_ByteOrderSwap8(data);
795         data += 8;
796         }
797       break;
798       }
799     }
800   m_BinaryDataByteOrderMSB = !m_BinaryDataByteOrderMSB;
801   }
802 
803 bool MetaImage::
ElementByteOrderFix(METAIO_STL::streamoff _quantity)804 ElementByteOrderFix(METAIO_STL::streamoff _quantity)
805   {
806   if(m_BinaryDataByteOrderMSB != MET_SystemByteOrderMSB())
807     {
808     ElementByteOrderSwap(_quantity);
809     return true;
810     }
811   return true;
812   }
813 
814 //
815 //
816 //
817 bool MetaImage::
ElementMinMaxValid(void) const818 ElementMinMaxValid(void) const
819   {
820   return m_ElementMinMaxValid;
821   }
822 
823 void MetaImage::
ElementMinMaxValid(bool _elementMinMaxValid)824 ElementMinMaxValid(bool _elementMinMaxValid)
825   {
826   m_ElementMinMaxValid = _elementMinMaxValid;
827   }
828 
829 void MetaImage::
ElementMinMaxRecalc(void)830 ElementMinMaxRecalc(void)
831   {
832   int i;
833   double tf;
834 
835   if(m_ElementData == NULL)
836     return;
837 
838   ElementByteOrderFix();
839 
840   MET_ValueToDouble(m_ElementType, m_ElementData, 0, &tf);
841   m_ElementMin = tf;
842   m_ElementMax = tf;
843   for(i=1; i<m_Quantity*m_ElementNumberOfChannels; i++)
844     {
845     MET_ValueToDouble(m_ElementType, m_ElementData, i, &tf);
846     if(tf<m_ElementMin)
847       {
848       m_ElementMin = tf;
849       }
850     else if(tf>m_ElementMax)
851       {
852       m_ElementMax = tf;
853       }
854     }
855 
856   m_ElementMinMaxValid = true;
857   }
858 
859 double MetaImage::
ElementMin(void) const860 ElementMin(void) const
861   {
862   return m_ElementMin;
863   }
864 
865 void MetaImage::
ElementMin(double _elementMin)866 ElementMin(double _elementMin)
867   {
868   m_ElementMin = _elementMin;
869   }
870 
871 double MetaImage::
ElementMax(void) const872 ElementMax(void) const
873   {
874   return m_ElementMax;
875   }
876 
877 void MetaImage::
ElementMax(double _elementMax)878 ElementMax(double _elementMax)
879   {
880   m_ElementMax = _elementMax;
881   }
882 
883 //
884 //
885 //
886 double MetaImage::
ElementToIntensityFunctionSlope(void) const887 ElementToIntensityFunctionSlope(void) const
888   {
889   return m_ElementToIntensityFunctionSlope;
890   }
891 
892 void MetaImage::
ElementToIntensityFunctionSlope(double _elementToIntensityFunctionSlope)893 ElementToIntensityFunctionSlope(double _elementToIntensityFunctionSlope)
894   {
895   m_ElementToIntensityFunctionSlope = _elementToIntensityFunctionSlope;
896   }
897 
898 double MetaImage::
ElementToIntensityFunctionOffset(void) const899 ElementToIntensityFunctionOffset(void) const
900   {
901   return m_ElementToIntensityFunctionOffset;
902   }
903 
904 void MetaImage::
ElementToIntensityFunctionOffset(double _elementOffset)905 ElementToIntensityFunctionOffset(double _elementOffset)
906   {
907   m_ElementToIntensityFunctionOffset = _elementOffset;
908   }
909 
910 //
911 //
912 //
913 bool MetaImage::
AutoFreeElementData(void) const914 AutoFreeElementData(void) const
915   {
916   return m_AutoFreeElementData;
917   }
918 
919 void MetaImage::
AutoFreeElementData(bool _autoFreeElementData)920 AutoFreeElementData(bool _autoFreeElementData)
921   {
922   m_AutoFreeElementData = _autoFreeElementData;
923   }
924 
925 //
926 //
927 //
928 const char * MetaImage::
ElementDataFileName(void) const929 ElementDataFileName(void) const
930   {
931   return m_ElementDataFileName;
932   }
933 
934 void MetaImage::
ElementDataFileName(const char * _elementDataFileName)935 ElementDataFileName(const char * _elementDataFileName)
936   {
937   strcpy(m_ElementDataFileName, _elementDataFileName);
938   }
939 
940 //
941 //
942 //
943 void * MetaImage::
ElementData(void)944 ElementData(void)
945   {
946   return m_ElementData;
947   }
948 
949 double MetaImage::
ElementData(METAIO_STL::streamoff _i) const950 ElementData(METAIO_STL::streamoff _i) const
951   {
952   double tf = 0;
953   MET_ValueToDouble(m_ElementType, m_ElementData, _i, &tf);
954 
955   return tf;
956   }
957 
958 bool MetaImage::
ElementData(METAIO_STL::streamoff _i,double _v)959 ElementData(METAIO_STL::streamoff _i, double _v)
960   {
961   if(_i<m_Quantity)
962     {
963     MET_DoubleToValue(_v, m_ElementType, m_ElementData, _i);
964     return true;
965     }
966   return false;
967   }
968 
969 void MetaImage::
ElementData(void * _elementData,bool _autoFreeElementData)970 ElementData(void * _elementData, bool _autoFreeElementData)
971   {
972   if(m_AutoFreeElementData)
973     {
974     delete [] (char *)m_ElementData;
975     }
976   m_ElementData = _elementData;
977   m_AutoFreeElementData = _autoFreeElementData;
978   }
979 
980 //
981 //
982 //
983 bool MetaImage::
ConvertElementDataTo(MET_ValueEnumType _elementType,double _toMin,double _toMax)984 ConvertElementDataTo(MET_ValueEnumType _elementType,
985                      double _toMin, double _toMax)
986   {
987   int eSize;
988   MET_SizeOfType(_elementType, &eSize);
989   void * newElementData = new char[m_Quantity*m_ElementNumberOfChannels*eSize];
990 
991   ElementByteOrderFix();
992   if(!ElementMinMaxValid())
993     {
994     ElementMinMaxRecalc();
995     }
996 
997   int i;
998   for(i=0; i<m_Quantity*m_ElementNumberOfChannels; i++)
999     {
1000     MET_ValueToValue(m_ElementType, m_ElementData, i, _elementType,
1001                      newElementData, m_ElementMin, m_ElementMax,
1002                      _toMin, _toMax);
1003     }
1004 
1005   if(m_AutoFreeElementData)
1006     {
1007     delete [] (char *)m_ElementData;
1008     }
1009   m_ElementData = newElementData;
1010   m_ElementType = _elementType;
1011   m_ElementMinMaxValid = true;
1012   m_ElementMin = _toMin;
1013   m_ElementMax = _toMax;
1014   m_AutoFreeElementData = true;
1015 
1016   return true;
1017   }
1018 
1019 bool MetaImage::
ConvertElementDataToIntensityData(MET_ValueEnumType _elementType)1020 ConvertElementDataToIntensityData(MET_ValueEnumType _elementType)
1021   {
1022   ElementByteOrderFix();
1023   if(!ElementMinMaxValid())
1024     {
1025     ElementMinMaxRecalc();
1026     }
1027 
1028   double toMin = m_ElementMin + m_ElementToIntensityFunctionOffset;
1029   double toMax = (m_ElementMax-m_ElementMin)
1030                    * m_ElementToIntensityFunctionSlope
1031                    + m_ElementMin;
1032 
1033   return ConvertElementDataTo(_elementType, toMin, toMax);
1034   }
1035 
1036 bool MetaImage::
ConvertIntensityDataToElementData(MET_ValueEnumType _elementType)1037 ConvertIntensityDataToElementData(MET_ValueEnumType _elementType)
1038   {
1039   ElementByteOrderFix();
1040   if(!ElementMinMaxValid())
1041     {
1042     ElementMinMaxRecalc();
1043     }
1044 
1045   double toMin = m_ElementMin - m_ElementToIntensityFunctionOffset;
1046   double toMax = (m_ElementMax - m_ElementMin)
1047                    / m_ElementToIntensityFunctionSlope
1048                    + toMin;
1049 
1050   return ConvertElementDataTo(_elementType, toMin, toMax);
1051   }
1052 
1053 // return true if the file exists
M_FileExists(const char * filename) const1054 bool MetaImage::M_FileExists(const char* filename) const
1055 {
1056 #ifdef _MSC_VER
1057 # define access _access
1058 #endif
1059 #ifndef R_OK
1060 # define R_OK 04
1061 #endif
1062   if ( access(filename, R_OK) != 0 )
1063     {
1064     return false;
1065     }
1066   else
1067     {
1068     return true;
1069     }
1070 }
1071 
FileIsFullPath(const char * in_name) const1072 bool MetaImage::FileIsFullPath(const char* in_name) const
1073 {
1074 #if defined(_WIN32) || defined(__CYGWIN__)
1075   // On Windows, the name must be at least two characters long.
1076   if(strlen(in_name) < 2)
1077     {
1078     return false;
1079     }
1080   if(in_name[1] == ':')
1081     {
1082     return true;
1083     }
1084   if(in_name[0] == '\\')
1085     {
1086     return true;
1087     }
1088 #else
1089   // On UNIX, the name must be at least one character long.
1090   if(strlen(in_name) < 1)
1091     {
1092     return false;
1093     }
1094 #endif
1095 #if !defined(_WIN32)
1096   if(in_name[0] == '~')
1097     {
1098     return true;
1099     }
1100 #endif
1101   // On UNIX, the name must begin in a '/'.
1102   // On Windows, if the name begins in a '/', then it is a full
1103   // network path.
1104   if(in_name[0] == '/')
1105     {
1106     return true;
1107     }
1108   return false;
1109 }
1110 
1111 // Return the value of a tag
1112 METAIO_STL::string
1113 MetaImage::
M_GetTagValue(const METAIO_STL::string & buffer,const char * tag) const1114 M_GetTagValue(const METAIO_STL::string & buffer, const char* tag) const
1115 {
1116   size_t stringPos = buffer.find(tag);
1117   if( stringPos == METAIO_STL::string::npos )
1118     {
1119     return "";
1120     }
1121 
1122   size_t pos2 = buffer.find("=",stringPos);
1123   if(pos2 == METAIO_STL::string::npos )
1124     {
1125     pos2 = buffer.find(":",stringPos);
1126     }
1127 
1128   if(pos2 == METAIO_STL::string::npos )
1129     {
1130     return "";
1131     }
1132 
1133   size_t posend = buffer.find('\r',pos2);
1134   if(posend == METAIO_STL::string::npos )
1135     {
1136     posend = buffer.find('\n',pos2);
1137     }
1138 
1139   // Get the element data filename
1140   METAIO_STL::string value = "";
1141   bool firstspace = true;
1142   size_t index = pos2+1;
1143   while(index<buffer.size()
1144         && buffer[index] != '\r'
1145         && buffer[index] != '\n'
1146         )
1147     {
1148     if(buffer[index] != ' ')
1149       {
1150       firstspace = false;
1151       }
1152     if(!firstspace)
1153       {
1154       value += buffer[index];
1155       }
1156     index++;
1157     }
1158 
1159   return value;
1160 }
1161 
1162 //
1163 //
1164 //
1165 bool MetaImage::
CanRead(const char * _headerName) const1166 CanRead(const char *_headerName) const
1167   {
1168   // First check the extension
1169   METAIO_STL::string fname = _headerName;
1170   if(  fname == "" )
1171     {
1172     return false;
1173     }
1174 
1175   bool extensionFound = false;
1176 
1177   METAIO_STL::string::size_type stringPos = fname.rfind(".mhd");
1178   if ((stringPos != METAIO_STL::string::npos)
1179       && (stringPos == fname.length() - 4))
1180     {
1181     extensionFound = true;
1182     }
1183 
1184   stringPos = fname.rfind(".mha");
1185   if ((stringPos != METAIO_STL::string::npos)
1186       && (stringPos == fname.length() - 4))
1187     {
1188     extensionFound = true;
1189     }
1190 
1191   if( !extensionFound )
1192     {
1193     return false;
1194     }
1195 
1196   // Now check the file content
1197   METAIO_STREAM::ifstream inputStream;
1198 
1199   openReadStream(inputStream, fname.c_str());
1200 
1201   if( inputStream.fail() )
1202     {
1203     return false;
1204     }
1205 
1206   char* buf = new char[8001];
1207   inputStream.read(buf,8000);
1208   unsigned long fileSize = inputStream.gcount();
1209   buf[fileSize] = 0;
1210   METAIO_STL::string header(buf);
1211   header.resize(fileSize);
1212   delete [] buf;
1213   inputStream.close();
1214 
1215   stringPos = header.find("NDims");
1216   if( stringPos == METAIO_STL::string::npos )
1217     {
1218     return false;
1219     }
1220 
1221   METAIO_STL::string elementDataFileName = M_GetTagValue(header,"ElementDataFile");
1222 
1223   return true;
1224   }
1225 
1226 bool MetaImage::
Read(const char * _headerName,bool _readElements,void * _buffer)1227 Read(const char *_headerName, bool _readElements, void * _buffer)
1228   {
1229   M_Destroy();
1230 
1231   Clear();
1232 
1233   M_SetupReadFields();
1234 
1235   if(_headerName != NULL)
1236     {
1237     strcpy(m_FileName, _headerName);
1238     }
1239 
1240   M_PrepareNewReadStream();
1241 
1242   METAIO_STREAM::ifstream * tmpReadStream = new METAIO_STREAM::ifstream;
1243 
1244   openReadStream(*tmpReadStream, m_FileName);
1245 
1246   if(!tmpReadStream->is_open())
1247     {
1248     delete tmpReadStream;
1249     return false;
1250     }
1251 
1252   if( !this->ReadStream(0, tmpReadStream, _readElements, _buffer) )
1253     {
1254     tmpReadStream->close();
1255     delete tmpReadStream;
1256     return false;
1257     }
1258 
1259   tmpReadStream->close();
1260 
1261   delete tmpReadStream;
1262 
1263   return true;
1264   }
1265 
1266 bool MetaImage::
CanReadStream(METAIO_STREAM::ifstream * _stream) const1267 CanReadStream(METAIO_STREAM::ifstream * _stream) const
1268   {
1269   if(!strncmp(MET_ReadType(*_stream).c_str(), "Image", 5))
1270     {
1271     return true;
1272     }
1273   return false;
1274   }
1275 
1276 
1277 bool MetaImage::
ReadStream(int _nDims,METAIO_STREAM::ifstream * _stream,bool _readElements,void * _buffer)1278 ReadStream(int _nDims,
1279            METAIO_STREAM::ifstream * _stream,
1280            bool _readElements,
1281            void * _buffer)
1282   {
1283   if(!MetaObject::ReadStream(_nDims, _stream))
1284     {
1285     METAIO_STREAM::cerr << "MetaImage: Read: Cannot parse file"
1286                         << METAIO_STREAM::endl;
1287     return false;
1288     }
1289 
1290   if(_readElements)
1291     {
1292     if(_buffer == NULL)
1293       {
1294       InitializeEssential(m_NDims,
1295                           m_DimSize,
1296                           m_ElementSpacing,
1297                           m_ElementType,
1298                           m_ElementNumberOfChannels,
1299                           NULL, true);
1300       }
1301     else
1302       {
1303       InitializeEssential(m_NDims,
1304                           m_DimSize,
1305                           m_ElementSpacing,
1306                           m_ElementType,
1307                           m_ElementNumberOfChannels,
1308                           _buffer, false);
1309       }
1310 
1311     int i;
1312     size_t j;
1313     bool usePath;
1314     char pathName[MAXPATHLENGHT];
1315     char fName[MAXPATHLENGHT];
1316     usePath = MET_GetFilePath(m_FileName, pathName);
1317 
1318     if(!strcmp("Local", m_ElementDataFileName) ||
1319        !strcmp("LOCAL", m_ElementDataFileName) ||
1320        !strcmp("local", m_ElementDataFileName))
1321       {
1322       M_ReadElements(_stream, m_ElementData, m_Quantity);
1323       }
1324     else if(!strncmp("LIST", m_ElementDataFileName,4))
1325       {
1326       int fileImageDim = m_NDims - 1;
1327       int nWrds;
1328       char **wrds;
1329       MET_StringToWordArray(m_ElementDataFileName, &nWrds, &wrds);
1330       if(nWrds > 1)
1331         {
1332         fileImageDim = (int)atof(wrds[1]);
1333         }
1334       for(i=0; i<nWrds; i++)
1335         {
1336         delete [] wrds[i];
1337         }
1338       delete [] wrds;
1339       if ( (fileImageDim == 0) || (fileImageDim > m_NDims) )
1340         {
1341         // if optional file dimension size is not given or is larger than
1342         // overall dimension then default to a size of m_NDims - 1.
1343         fileImageDim = m_NDims-1;
1344         }
1345       char s[1024];
1346       METAIO_STREAM::ifstream* readStreamTemp = new METAIO_STREAM::ifstream;
1347       int elementSize;
1348       MET_SizeOfType(m_ElementType, &elementSize);
1349       elementSize *= m_ElementNumberOfChannels;
1350       int totalFiles = 1;
1351       for (i = m_NDims; i > fileImageDim; i--)
1352         {
1353         totalFiles *= m_DimSize[i-1];
1354         }
1355       for(i=0; i< totalFiles && !_stream->eof(); i++)
1356         {
1357         _stream->getline(s, 1024);
1358         if(!_stream->eof())
1359           {
1360           j = strlen(s)-1;
1361           while(j>0 && (isspace(s[j]) || !isprint(s[j])))
1362             {
1363             s[j--] = '\0';
1364             }
1365           if(usePath && !FileIsFullPath(s))
1366             {
1367             sprintf(fName, "%s%s", pathName, s);
1368             }
1369           else
1370             {
1371             strcpy(fName, s);
1372             }
1373 
1374           openReadStream(*readStreamTemp, fName);
1375           if(!readStreamTemp->is_open())
1376             {
1377             METAIO_STREAM::cerr << "MetaImage: Read: cannot open slice"
1378                                 << METAIO_STREAM::endl;
1379             continue;
1380             }
1381           M_ReadElements(readStreamTemp,
1382                        &(((char *)m_ElementData)[i*m_SubQuantity[fileImageDim]*
1383                                                  elementSize]),
1384                        m_SubQuantity[fileImageDim]);
1385           readStreamTemp->close();
1386           }
1387         }
1388       delete readStreamTemp;
1389       }
1390     else if(strstr(m_ElementDataFileName, "%"))
1391       {
1392       int elementSize;
1393       MET_SizeOfType(m_ElementType, &elementSize);
1394       elementSize *= m_ElementNumberOfChannels;
1395 
1396       int nWrds;
1397       char **wrds;
1398       int minV = 1;
1399       int maxV = m_DimSize[m_NDims-1];
1400       int stepV = 1;
1401       char s[MAXPATHLENGHT];
1402       METAIO_STREAM::ifstream* readStreamTemp = new METAIO_STREAM::ifstream;
1403       MET_StringToWordArray(m_ElementDataFileName, &nWrds, &wrds);
1404       if(nWrds >= 2)
1405         {
1406         minV = (int)atof(wrds[1]);
1407         maxV = minV + m_DimSize[m_NDims-1] - 1;
1408         }
1409       if(nWrds >= 3)
1410         {
1411         maxV = (int)atof(wrds[2]);
1412         stepV = (maxV-minV)/(m_DimSize[m_NDims-1]);
1413         }
1414       if(nWrds >= 4)
1415         {
1416         stepV = (int)atof(wrds[3]);
1417         }
1418       if(nWrds >= 5 )
1419       {
1420         // In this case, the filename must have had spaces in the
1421         // name.  The filename was parsed into multiple pieces by the
1422         // MET_StringToWordArray, which parses based on spaces.
1423         // Thus, we need to reconstruct the filename in this case.
1424         // The last three wrds must be numbers.  If they are not, we give an error.
1425         for( i = nWrds-3; i < nWrds; i++ )
1426         {
1427           for( j = 0; j < strlen(wrds[i]); j++ )
1428           {
1429             if( !isdigit(wrds[i][j]) )
1430             {
1431               METAIO_STREAM::cerr << "MetaImage: Read: Last three arguments must be numbers!"
1432                   << METAIO_STREAM::endl;
1433               continue;
1434             }
1435           }
1436         }
1437         stepV = (int)atof(wrds[nWrds-1]);
1438         maxV =  (int)atof(wrds[nWrds-2]);
1439         minV =  (int)atof(wrds[nWrds-3]);
1440         for( i = 1; i < nWrds-3; i++ )
1441         {
1442           strcat(wrds[0]," ");
1443           strcat(wrds[0],wrds[i]);
1444         }
1445       }
1446       // If the specified size of the third dimension is less than the size
1447       // specified by the regular expression, we should only read a volume with the specified
1448       // size.  Otherwise, the code will crash when trying to fill m_ElementData more than it can hold.
1449       // Therefore, we modify maxV to ensure that the images spanned by minV:stepV:maxV are less than or equal
1450       // to the size in the last dimension.
1451       int numberOfImages = 1 + (maxV - minV)/stepV;
1452       if( numberOfImages > m_DimSize[m_NDims-1] )
1453       {
1454         maxV = (m_DimSize[m_NDims-1]-1)*stepV + minV;
1455       }
1456       int cnt = 0;
1457       for(i=minV; i<=maxV; i += stepV)
1458         {
1459         sprintf(s, wrds[0], i);
1460         if(usePath && !FileIsFullPath(s))
1461           {
1462           sprintf(fName, "%s%s", pathName, s);
1463           }
1464         else
1465           {
1466           strcpy(fName, s);
1467           }
1468         openReadStream(*readStreamTemp,fName);
1469         if(!readStreamTemp->is_open())
1470           {
1471           METAIO_STREAM::cerr << "MetaImage: Read: cannot construct file"
1472                               << METAIO_STREAM::endl;
1473           continue;
1474           }
1475 
1476         M_ReadElements(readStreamTemp,
1477                        &(((char *)m_ElementData)[cnt*m_SubQuantity[m_NDims-1]*
1478                                                  elementSize]),
1479                        m_SubQuantity[m_NDims-1]);
1480         cnt++;
1481 
1482         readStreamTemp->close();
1483         }
1484       delete readStreamTemp;
1485       for(i=0; i<nWrds; i++)
1486         {
1487         delete [] wrds[i];
1488         }
1489       delete [] wrds;
1490       }
1491     else
1492       {
1493       if(usePath && !FileIsFullPath(m_ElementDataFileName))
1494         {
1495         sprintf(fName, "%s%s", pathName, m_ElementDataFileName);
1496         }
1497       else
1498         {
1499         strcpy(fName, m_ElementDataFileName);
1500         }
1501 
1502       METAIO_STREAM::ifstream* readStreamTemp = new METAIO_STREAM::ifstream;
1503 
1504       const char *extensions[] = { "", ".gz", ".Z", 0 };
1505       for(unsigned ii = 0; extensions[ii] != 0; ii++)
1506         {
1507         METAIO_STL::string tempFName(fName);
1508         tempFName += extensions[ii];
1509         openReadStream(*readStreamTemp,tempFName.c_str());
1510         if(readStreamTemp->is_open())
1511           {
1512           if(ii > 0)
1513             {
1514             this->CompressedData(true);
1515             this->BinaryData(true);
1516             }
1517           break;
1518           }
1519         }
1520 
1521       if(!readStreamTemp->is_open())
1522         {
1523         METAIO_STREAM::cerr << "MetaImage: Read: Cannot open data file"
1524                             << METAIO_STREAM::endl;
1525         if(m_ReadStream)
1526           {
1527           m_ReadStream->close();
1528           }
1529         return false;
1530         }
1531       M_ReadElements(readStreamTemp, m_ElementData, m_Quantity);
1532 
1533       readStreamTemp->close();
1534       delete readStreamTemp;
1535       }
1536     }
1537 
1538   return true;
1539   }
1540 
1541 
1542 //
1543 //
1544 //
1545 bool MetaImage::
Write(const char * _headName,const char * _dataName,bool _writeElements,const void * _constElementData,bool _append)1546 Write(const char *_headName,
1547       const char *_dataName,
1548       bool _writeElements,
1549       const void * _constElementData,
1550       bool _append)
1551   {
1552   if(_headName != NULL)
1553     {
1554     FileName(_headName);
1555     }
1556 
1557   bool userDataFileName = true;
1558   if(_dataName == NULL && strlen(m_ElementDataFileName) == 0)
1559     {
1560     userDataFileName = false;
1561     int sPtr = 0;
1562     MET_GetFileSuffixPtr(m_FileName, &sPtr);
1563     if(!strcmp(&m_FileName[sPtr], "mha"))
1564       {
1565       ElementDataFileName("LOCAL");
1566       }
1567     else
1568       {
1569       if(!_append)
1570         {
1571         MET_SetFileSuffix(m_FileName, "mhd");
1572         }
1573       strcpy(m_ElementDataFileName, m_FileName);
1574       if(m_CompressedData)
1575         {
1576         MET_SetFileSuffix(m_ElementDataFileName, "zraw");
1577         }
1578       else
1579         {
1580         MET_SetFileSuffix(m_ElementDataFileName, "raw");
1581         }
1582       }
1583     }
1584   else if(_dataName != NULL)
1585     {
1586     userDataFileName = false;
1587     ElementDataFileName(_dataName);
1588     }
1589 
1590   // make sure suffix is valid
1591   if(!_append)
1592     {
1593     if(!strcmp(m_ElementDataFileName, "LOCAL"))
1594       {
1595       MET_SetFileSuffix(m_FileName, "mha");
1596       }
1597      else
1598       {
1599       MET_SetFileSuffix(m_FileName, "mhd");
1600       }
1601     }
1602 
1603   char pathName[MAXPATHLENGHT];
1604   bool usePath = MET_GetFilePath(m_FileName, pathName);
1605   if(usePath)
1606     {
1607     char elementPathName[MAXPATHLENGHT];
1608     MET_GetFilePath(m_ElementDataFileName, elementPathName);
1609     if(!strcmp(pathName, elementPathName))
1610       {
1611       strcpy(elementPathName, &m_ElementDataFileName[strlen(pathName)]);
1612       strcpy(m_ElementDataFileName, elementPathName);
1613       }
1614     }
1615 
1616   METAIO_STREAM::ofstream * tmpWriteStream = new METAIO_STREAM::ofstream;
1617 
1618   openWriteStream(*tmpWriteStream, m_FileName, _append);
1619 
1620   if(!tmpWriteStream->is_open())
1621     {
1622     if(!userDataFileName)
1623       {
1624       ElementDataFileName("");
1625       }
1626 
1627     delete tmpWriteStream;
1628 
1629     return false;
1630     }
1631 
1632   bool result = MetaImage::WriteStream(tmpWriteStream,
1633                                        _writeElements,
1634                                        _constElementData);
1635 
1636   if(!userDataFileName)
1637     {
1638     ElementDataFileName("");
1639     }
1640 
1641   tmpWriteStream->close();
1642   delete tmpWriteStream;
1643 
1644   return result;
1645   }
1646 
1647 bool MetaImage::
WriteStream(METAIO_STREAM::ofstream * _stream,bool _writeElements,const void * _constElementData)1648 WriteStream(METAIO_STREAM::ofstream * _stream,
1649             bool _writeElements,
1650             const void * _constElementData)
1651   {
1652   if(m_WriteStream != NULL)
1653     {
1654     METAIO_STREAM::cerr << "MetaArray: WriteStream: two files open?"
1655                         << METAIO_STREAM::endl;
1656     delete m_WriteStream;
1657     }
1658 
1659   m_WriteStream = _stream;
1660 
1661   unsigned char * compressedElementData = NULL;
1662   if(m_BinaryData && m_CompressedData && !strstr(m_ElementDataFileName, "%"))
1663     // compressed & !slice/file
1664     {
1665     int elementSize;
1666     MET_SizeOfType(m_ElementType, &elementSize);
1667     int elementNumberOfBytes = elementSize*m_ElementNumberOfChannels;
1668 
1669     if(_constElementData == NULL)
1670       {
1671       compressedElementData = MET_PerformCompression(
1672                                   (const unsigned char *)m_ElementData,
1673                                   m_Quantity * elementNumberOfBytes,
1674                                   & m_CompressedDataSize );
1675       }
1676     else
1677       {
1678       compressedElementData = MET_PerformCompression(
1679                                   (const unsigned char *)_constElementData,
1680                                   m_Quantity * elementNumberOfBytes,
1681                                   & m_CompressedDataSize );
1682       }
1683     }
1684 
1685   M_SetupWriteFields();
1686 
1687   M_Write();
1688 
1689   if(_writeElements)
1690     {
1691     if(m_BinaryData && m_CompressedData && !strstr(m_ElementDataFileName, "%"))
1692       // compressed & !slice/file
1693       {
1694       M_WriteElements(m_WriteStream,
1695                       compressedElementData,
1696                       m_CompressedDataSize);
1697 
1698       delete [] compressedElementData;
1699       m_CompressedDataSize = 0;
1700       }
1701     else
1702       {
1703       if(_constElementData == NULL)
1704         {
1705         M_WriteElements(m_WriteStream,
1706                         m_ElementData,
1707                         m_Quantity);
1708         }
1709       else
1710         {
1711         M_WriteElements(m_WriteStream,
1712                         _constElementData,
1713                         m_Quantity);
1714         }
1715       }
1716     }
1717 
1718   m_WriteStream = NULL;
1719 
1720   return true;
1721   }
1722 
1723 
1724 /** Write a portion of an image */
WriteROI(int * _indexMin,int * _indexMax,const char * _headName,const char * _dataName,bool _writeElements,const void * _constElementData,bool _append)1725 bool MetaImage::WriteROI( int * _indexMin, int * _indexMax,
1726                           const char *_headName,
1727                           const char *_dataName,
1728                           bool _writeElements,
1729                           const void * _constElementData,
1730                           bool _append
1731                           )
1732 {
1733   if( _headName != NULL )
1734     {
1735     FileName( _headName );
1736     }
1737 
1738   if( !_writeElements )
1739     {
1740     return false;
1741     }
1742 
1743   // Check if the file exists
1744   if( M_FileExists(_headName) )
1745     {
1746     char* elementData = const_cast<char*>(
1747                             static_cast<const char*>(_constElementData) );
1748     if( elementData == NULL )
1749       {
1750       elementData = (char*)m_ElementData;
1751       }
1752     if( elementData == NULL )
1753       {
1754       METAIO_STREAM::cerr << "Element data is NULL" << METAIO_STREAM::endl;
1755       return false;
1756       }
1757 
1758     // Find the start of the data
1759     METAIO_STREAM::ifstream * readStream = new METAIO_STREAM::ifstream;
1760     readStream->open( m_FileName, METAIO_STREAM::ios::binary |
1761                                   METAIO_STREAM::ios::in);
1762 
1763     // File must be readable
1764     if( !MetaObject::ReadStream( m_NDims, readStream ) )
1765       {
1766       METAIO_STREAM::cerr << "MetaImage: Read: Cannot parse file"
1767                           << METAIO_STREAM::endl;
1768       delete readStream;
1769       return false;
1770       }
1771 
1772     // File must not be compressed
1773     if(m_CompressedData)
1774       {
1775       METAIO_STREAM::cerr
1776                << "MetaImage cannot insert ROI into a compressed file."
1777                << METAIO_STREAM::endl;
1778       readStream->close();
1779       delete readStream;
1780       return false;
1781       }
1782 
1783     InitializeEssential( m_NDims,
1784                          m_DimSize,
1785                          m_ElementSpacing,
1786                          m_ElementType,
1787                          m_ElementNumberOfChannels,
1788                          NULL, false ); // no memory allocation
1789 
1790     METAIO_STL::string  filename = ElementDataFileName();
1791     METAIO_STL::streampos dataPos = 0;
1792 
1793     // local file
1794     if( filename == "LOCAL" )
1795       {
1796       filename = m_FileName;
1797       dataPos = readStream->tellg();
1798       }
1799     else if( filename == "LIST"
1800              || strstr(filename.c_str(), "%") )
1801       {
1802       METAIO_STREAM::cerr
1803                << "MetaImage cannot insert ROI into a list of files."
1804                << METAIO_STREAM::endl;
1805       readStream->close();
1806       delete readStream;
1807       return false;
1808       }
1809 
1810     readStream->close();
1811     delete readStream;
1812 
1813     // Write the region
1814     if( !M_FileExists(filename.c_str()) )
1815       {
1816       char pathName[MAXPATHLENGHT];
1817       MET_GetFilePath(_headName, pathName);
1818       filename = pathName+filename;
1819       }
1820 
1821     METAIO_STREAM::ofstream * tmpWriteStream = new METAIO_STREAM::ofstream;
1822     tmpWriteStream->open( filename.c_str(),
1823                           METAIO_STREAM::ios::binary |
1824                           METAIO_STREAM::ios::in |
1825                           METAIO_STREAM::ios::out );
1826 
1827     if( !tmpWriteStream->is_open() )
1828       {
1829       METAIO_STREAM::cerr << "Cannot open ROI file: "
1830                           << filename.c_str()
1831                           << METAIO_STREAM::endl;
1832       delete tmpWriteStream;
1833       return false;
1834       }
1835 
1836     int elementSize;
1837     MET_SizeOfType( m_ElementType, &elementSize );
1838     int elementNumberOfBytes = elementSize*m_ElementNumberOfChannels;
1839 
1840     // seek to the end and write one byte to allocate the entire file size
1841     METAIO_STL::streamoff seekoff = m_Quantity*elementNumberOfBytes;
1842     tmpWriteStream->seekp(0, METAIO_STREAM::ios::end);
1843     if (tmpWriteStream->tellp() != (dataPos+seekoff))
1844       {
1845       seekoff = seekoff - 1;
1846       tmpWriteStream->seekp(dataPos+seekoff, METAIO_STREAM::ios::beg);
1847       const char zerobyte = 0;
1848       tmpWriteStream->write(&zerobyte, 1);
1849       }
1850 
1851     if( !elementData )
1852       {
1853       METAIO_STREAM::cerr << "Element data is NULL" << METAIO_STREAM::endl;
1854       delete tmpWriteStream;
1855       return false;
1856       }
1857 
1858     M_WriteElementsROI(tmpWriteStream, elementData, dataPos,
1859                        _indexMin, _indexMax);
1860 
1861     tmpWriteStream->close();
1862     delete tmpWriteStream;
1863     }
1864   else // the file doesn't exist
1865     {
1866     if(m_CompressedData)
1867       {
1868       METAIO_STREAM::cerr
1869                << "MetaImage cannot write an ROI using compression."
1870                << METAIO_STREAM::endl;
1871       return false;
1872       }
1873 
1874     // Get the data filename right...
1875     bool userDataFileName = true;
1876     if( _dataName == NULL && strlen(m_ElementDataFileName) == 0 )
1877       {
1878       userDataFileName = false;
1879       int sPtr = 0;
1880       MET_GetFileSuffixPtr(m_FileName, &sPtr);
1881       if( !strcmp(&m_FileName[sPtr], "mha") )
1882         {
1883         ElementDataFileName( "LOCAL" );
1884         }
1885       else
1886         {
1887         if(!_append)
1888           {
1889           MET_SetFileSuffix(m_FileName, "mhd");
1890           }
1891         strcpy(m_ElementDataFileName, m_FileName);
1892         if(m_CompressedData)
1893           {
1894           MET_SetFileSuffix(m_ElementDataFileName, "zraw");
1895           }
1896         else
1897           {
1898           MET_SetFileSuffix(m_ElementDataFileName, "raw");
1899           }
1900         }
1901       }
1902     else if(_dataName != NULL)
1903       {
1904       userDataFileName = false;
1905       ElementDataFileName(_dataName);
1906       }
1907 
1908     if( !strcmp(m_ElementDataFileName, "LIST")
1909         || strstr(m_ElementDataFileName, "%") )
1910       {
1911       METAIO_STREAM::cerr
1912                << "MetaImage cannot insert ROI into a list of files."
1913                << METAIO_STREAM::endl;
1914       return false;
1915       }
1916 
1917     // make sure the header suffix is valid, unless forcing to match an
1918     // existing file via the append bool argument.
1919     if(!_append)
1920       {
1921       if(!strcmp(m_ElementDataFileName, "LOCAL"))
1922         {
1923         MET_SetFileSuffix(m_FileName, "mha");
1924         }
1925        else
1926         {
1927         MET_SetFileSuffix(m_FileName, "mhd");
1928         }
1929       }
1930 
1931     char pathName[MAXPATHLENGHT];
1932     bool usePath = MET_GetFilePath(m_FileName, pathName);
1933     if(usePath)
1934       {
1935       char elementPathName[MAXPATHLENGHT];
1936       MET_GetFilePath(m_ElementDataFileName, elementPathName);
1937       if(!strcmp(pathName, elementPathName))
1938         {
1939         strcpy(elementPathName, &m_ElementDataFileName[strlen(pathName)]);
1940         strcpy(m_ElementDataFileName, elementPathName);
1941         }
1942       }
1943 
1944     METAIO_STREAM::ofstream * tmpWriteStream = new METAIO_STREAM::ofstream;
1945 
1946     openWriteStream(*tmpWriteStream, m_FileName, _append);
1947 
1948     if(!tmpWriteStream->is_open())
1949       {
1950       if(!userDataFileName)
1951         {
1952         ElementDataFileName("");
1953         }
1954       delete tmpWriteStream;
1955       return false;
1956       }
1957 
1958     // Write the ROI header file
1959     char* elementData = const_cast<char*>(
1960                           static_cast<const char*>(_constElementData) );
1961     if(elementData == NULL)
1962       {
1963       elementData = (char*)m_ElementData;
1964       }
1965 
1966     m_WriteStream = tmpWriteStream;
1967     M_SetupWriteFields();
1968     M_Write();
1969 
1970     METAIO_STL::streampos dataPos = m_WriteStream->tellp();
1971 
1972     // If data is in a separate file, set dataPos and point to that file.
1973     //   ( we've already verified the name isn't LIST and doesn't
1974     //     contain % )
1975     if( strcmp( m_ElementDataFileName, "LOCAL" ) )
1976       {
1977       m_WriteStream = NULL;
1978       tmpWriteStream->close();
1979 
1980       dataPos = 0;
1981 
1982       char dataFileName[MAXPATHLENGHT];
1983       if(usePath&& !FileIsFullPath(m_ElementDataFileName))
1984         {
1985         sprintf(dataFileName, "%s%s", pathName, m_ElementDataFileName);
1986         }
1987       else
1988         {
1989         strcpy(dataFileName, m_ElementDataFileName);
1990         }
1991 
1992       openWriteStream(*tmpWriteStream, dataFileName, _append);
1993       m_WriteStream = tmpWriteStream;
1994       }
1995 
1996     int elementSize;
1997     MET_SizeOfType( m_ElementType, &elementSize );
1998     int elementNumberOfBytes = elementSize*m_ElementNumberOfChannels;
1999 
2000     // write the last byte in the file to allocate it
2001     METAIO_STL::streamoff seekoff = m_Quantity * elementNumberOfBytes;
2002     seekoff -= 1;
2003     m_WriteStream->seekp(seekoff, METAIO_STREAM::ios::cur);
2004     const char zerobyte = 0;
2005     m_WriteStream->write(&zerobyte, 1);
2006 
2007     M_WriteElementsROI(m_WriteStream, elementData, dataPos,
2008                        _indexMin, _indexMax);
2009 
2010     m_WriteStream = NULL;
2011 
2012     if(!userDataFileName)
2013       {
2014       ElementDataFileName("");
2015       }
2016 
2017     tmpWriteStream->close();
2018     delete tmpWriteStream;
2019     }
2020 
2021   return true;
2022 }
2023 
2024 bool  MetaImage::
M_WriteElementsROI(METAIO_STREAM::ofstream * _fstream,const void * _data,METAIO_STL::streampos _dataPos,int * _indexMin,int * _indexMax)2025 M_WriteElementsROI(METAIO_STREAM::ofstream * _fstream,
2026                    const void * _data,
2027                    METAIO_STL::streampos _dataPos,
2028                    int * _indexMin,
2029                    int* _indexMax )
2030 {
2031   const char* data = static_cast<const char*>(_data);
2032 
2033   int elementSize;
2034   MET_SizeOfType(m_ElementType, &elementSize);
2035   const int elementNumberOfBytes = elementSize*m_ElementNumberOfChannels;
2036 
2037   // Write the IO region line by line
2038   int * currentIndex = new int[m_NDims];
2039   for(int i=0; i<m_NDims; i++)
2040     {
2041     currentIndex[i] = _indexMin[i];
2042     }
2043 
2044   // Optimize the size of the buffer to written depending on the
2045   // region shape
2046   // This calculate the number of continuous bytes in the file
2047   // which can be written
2048   METAIO_STL::streamoff elementsToWrite = 1;
2049   int movingDirection = 0;
2050   do
2051     {
2052     elementsToWrite *= _indexMax[movingDirection] - _indexMin[movingDirection] + 1;
2053     ++movingDirection;
2054     }
2055   while(movingDirection < m_NDims
2056         && _indexMin[movingDirection-1] == 0
2057         && _indexMax[movingDirection-1] == m_DimSize[movingDirection-1]-1);
2058 
2059   // write line by line
2060   bool done = false;
2061   while(!done)
2062     {
2063     // Seek to the right position
2064     METAIO_STL::streamoff seekoff = _dataPos;
2065     for(int i=0; i<m_NDims; i++)
2066       {
2067       seekoff += m_SubQuantity[i] * currentIndex[i] * elementNumberOfBytes;
2068       }
2069     _fstream->seekp( seekoff, METAIO_STREAM::ios::beg );
2070 
2071     M_WriteElementData( _fstream, data, elementsToWrite );
2072     data += elementsToWrite * elementNumberOfBytes;
2073 
2074     // check if there is only one write needed
2075     if( movingDirection >= m_NDims )
2076       {
2077       break;
2078       }
2079 
2080     ++currentIndex[movingDirection];
2081 
2082     // Check if we are still in the region
2083     for( int j=movingDirection; j<m_NDims; j++ )
2084       {
2085       if( currentIndex[j] > _indexMax[j] )
2086         {
2087         if( j == m_NDims-1 )
2088           {
2089           done = true;
2090           break;
2091           }
2092         else
2093           {
2094           currentIndex[j] = _indexMin[j];
2095           currentIndex[j+1]++;
2096           }
2097         }
2098       }
2099     } // end writing  loop
2100 
2101   delete [] currentIndex;
2102 
2103   return true;
2104 }
2105 
2106 bool MetaImage::
Append(const char * _headName)2107 Append(const char *_headName)
2108   {
2109   if(META_DEBUG)
2110    {
2111    METAIO_STREAM::cout << "MetaImage: Append" << METAIO_STREAM::endl;
2112    }
2113 
2114   return this->Write(_headName, NULL, true, NULL, true);
2115   }
2116 
2117 void MetaImage::
M_Destroy(void)2118 M_Destroy(void)
2119   {
2120   if(m_AutoFreeElementData && m_ElementData != NULL)
2121     {
2122     delete [] (char *)m_ElementData;
2123     }
2124 
2125   m_ElementData = NULL;
2126 
2127   if(m_CompressionTable && m_CompressionTable->compressedStream)
2128     {
2129     inflateEnd(m_CompressionTable->compressedStream);
2130     delete m_CompressionTable->compressedStream;
2131     delete [] m_CompressionTable->buffer;
2132     m_CompressionTable->buffer = NULL;
2133     }
2134   delete m_CompressionTable;
2135   m_CompressionTable = NULL;
2136 
2137   MetaObject::M_Destroy();
2138   }
2139 
2140 void MetaImage::
M_SetupReadFields(void)2141 M_SetupReadFields(void)
2142   {
2143   if(META_DEBUG)
2144     {
2145     METAIO_STREAM::cout << "MetaImage: M_SetupReadFields"
2146                         << METAIO_STREAM::endl;
2147     }
2148 
2149   MetaObject::M_SetupReadFields();
2150 
2151   MET_FieldRecordType * mF;
2152 
2153   int nDimsRecNum = MET_GetFieldRecordNumber("NDims", &m_Fields);
2154 
2155   mF = new MET_FieldRecordType;
2156   MET_InitReadField(mF, "DimSize", MET_INT_ARRAY, true, nDimsRecNum);
2157   mF->required = true;
2158   m_Fields.push_back(mF);
2159 
2160   mF = new MET_FieldRecordType;
2161   MET_InitReadField(mF, "HeaderSize", MET_INT, false);
2162   m_Fields.push_back(mF);
2163 
2164   mF = new MET_FieldRecordType;
2165   MET_InitReadField(mF, "Modality", MET_STRING, false);
2166   m_Fields.push_back(mF);
2167 
2168   mF = new MET_FieldRecordType;
2169   MET_InitReadField(mF, "ImagePosition", MET_FLOAT_ARRAY, false, nDimsRecNum);
2170   m_Fields.push_back(mF);
2171 
2172   mF = new MET_FieldRecordType;
2173   MET_InitReadField(mF, "SequenceID", MET_INT_ARRAY, false, nDimsRecNum);
2174   m_Fields.push_back(mF);
2175 
2176   mF = new MET_FieldRecordType;
2177   MET_InitReadField(mF, "ElementMin", MET_FLOAT, false);
2178   m_Fields.push_back(mF);
2179 
2180   mF = new MET_FieldRecordType;
2181   MET_InitReadField(mF, "ElementMax", MET_FLOAT, false);
2182   m_Fields.push_back(mF);
2183 
2184   mF = new MET_FieldRecordType;
2185   MET_InitReadField(mF, "ElementNumberOfChannels", MET_INT, false);
2186   m_Fields.push_back(mF);
2187 
2188   mF = new MET_FieldRecordType;
2189   MET_InitReadField(mF, "ElementSize", MET_FLOAT_ARRAY, false, nDimsRecNum);
2190   m_Fields.push_back(mF);
2191 
2192   mF = new MET_FieldRecordType;  // Set but not used...
2193   MET_InitReadField(mF, "ElementNBits", MET_INT, false);
2194   m_Fields.push_back(mF);
2195 
2196   mF = new MET_FieldRecordType;  // Used by ConvertElementToIntensity funcs
2197   MET_InitReadField(mF, "ElementToIntensityFunctionSlope", MET_FLOAT, false);
2198   m_Fields.push_back(mF);
2199 
2200   mF = new MET_FieldRecordType;  // Used by ConvertElementToIntensity funcs
2201   MET_InitReadField(mF, "ElementToIntensityFunctionOffset", MET_FLOAT, false);
2202   m_Fields.push_back(mF);
2203 
2204   mF = new MET_FieldRecordType;
2205   MET_InitReadField(mF, "ElementType", MET_STRING, true);
2206   mF->required = true;
2207   m_Fields.push_back(mF);
2208 
2209   mF = new MET_FieldRecordType;
2210   MET_InitReadField(mF, "ElementDataFile", MET_STRING, true);
2211   mF->required = true;
2212   mF->terminateRead = true;
2213   m_Fields.push_back(mF);
2214   }
2215 
2216 void MetaImage::
M_SetupWriteFields(void)2217 M_SetupWriteFields(void)
2218   {
2219   strcpy(m_ObjectTypeName,"Image");
2220   MetaObject::M_SetupWriteFields();
2221 
2222   MET_FieldRecordType * mF;
2223 
2224   mF = new MET_FieldRecordType;
2225   MET_InitWriteField(mF, "DimSize", MET_INT_ARRAY, m_NDims, m_DimSize);
2226   m_Fields.push_back(mF);
2227 
2228   char s[MAXPATHLENGHT];
2229   if(m_HeaderSize > 0 || m_HeaderSize == -1)
2230     {
2231     mF = new MET_FieldRecordType;
2232     MET_InitWriteField(mF, "HeaderSize", MET_INT);
2233     m_Fields.push_back(mF);
2234     }
2235 
2236   int i;
2237   if(m_Modality != MET_MOD_UNKNOWN)
2238     {
2239     mF = new MET_FieldRecordType;
2240     strcpy(s, MET_ValueTypeName[m_Modality]);
2241     MET_InitWriteField(mF, "Modality", MET_STRING, strlen(s), s);
2242     m_Fields.push_back(mF);
2243     }
2244 
2245   i = MET_GetFieldRecordNumber("AnatomicalOrientation", &m_Fields);
2246   if(i < 0)
2247     {
2248     const char * str = AnatomicalOrientationAcronym();
2249     mF = new MET_FieldRecordType;
2250     MET_InitWriteField(mF, "AnatomicalOrientation",
2251                        MET_STRING, strlen(str), str);
2252     m_Fields.push_back(mF);
2253     }
2254 
2255   bool valid = false;
2256   for(i=0; i<4; i++)
2257     {
2258     if(m_SequenceID[i] != 0)
2259       {
2260       valid = true;
2261       break;
2262       }
2263     }
2264   if(valid)
2265     {
2266     mF = new MET_FieldRecordType;
2267     MET_InitWriteField(mF, "SequenceID", MET_FLOAT_ARRAY, m_NDims,
2268                        m_SequenceID);
2269     m_Fields.push_back(mF);
2270     }
2271 
2272   if(m_ElementMinMaxValid)
2273     {
2274     mF = new MET_FieldRecordType;
2275     MET_InitWriteField(mF, "ElementMin", MET_FLOAT, m_ElementMin);
2276     m_Fields.push_back(mF);
2277 
2278     mF = new MET_FieldRecordType;
2279     MET_InitWriteField(mF, "ElementMax", MET_FLOAT, m_ElementMax);
2280     m_Fields.push_back(mF);
2281     }
2282 
2283   if(m_ElementNumberOfChannels>1)
2284     {
2285     mF = new MET_FieldRecordType;
2286     MET_InitWriteField(mF, "ElementNumberOfChannels", MET_INT,
2287                        m_ElementNumberOfChannels);
2288     m_Fields.push_back(mF);
2289     }
2290 
2291   if(m_ElementSizeValid)
2292     {
2293     mF = new MET_FieldRecordType;
2294     MET_InitWriteField(mF, "ElementSize", MET_FLOAT_ARRAY, m_NDims,
2295                        m_ElementSize);
2296     m_Fields.push_back(mF);
2297     }
2298 
2299   if(m_ElementToIntensityFunctionSlope != 1 ||
2300      m_ElementToIntensityFunctionOffset != 0)
2301     {
2302     mF = new MET_FieldRecordType;
2303     MET_InitWriteField(mF, "ElementToIntensityFunctionSlope",
2304                        MET_FLOAT, m_ElementToIntensityFunctionSlope);
2305     m_Fields.push_back(mF);
2306     mF = new MET_FieldRecordType;
2307     MET_InitWriteField(mF, "ElementToIntensityFunctionOffset",
2308                        MET_FLOAT, m_ElementToIntensityFunctionOffset);
2309     m_Fields.push_back(mF);
2310     }
2311 
2312   mF = new MET_FieldRecordType;
2313   MET_TypeToString(m_ElementType, s);
2314   MET_InitWriteField(mF, "ElementType", MET_STRING, strlen(s), s);
2315   m_Fields.push_back(mF);
2316 
2317   mF = new MET_FieldRecordType;
2318   MET_InitWriteField(mF, "ElementDataFile", MET_STRING,
2319                      strlen(m_ElementDataFileName),
2320                      m_ElementDataFileName);
2321   mF->terminateRead = true;
2322   m_Fields.push_back(mF);
2323   }
2324 
2325 //
2326 //
2327 //
2328 bool MetaImage::
M_Read(void)2329 M_Read(void)
2330   {
2331   if(META_DEBUG)
2332     {
2333     METAIO_STREAM::cout << "MetaImage: M_Read: Loading Header"
2334                         << METAIO_STREAM::endl;
2335     }
2336   if(!MetaObject::M_Read())
2337     {
2338     METAIO_STREAM::cerr << "MetaImage: M_Read: Error parsing file"
2339                         << METAIO_STREAM::endl;
2340     return false;
2341     }
2342 
2343   if(META_DEBUG)
2344     {
2345     METAIO_STREAM::cout << "MetaImage: M_Read: Parsing Header"
2346                         << METAIO_STREAM::endl;
2347     }
2348   MET_FieldRecordType * mF;
2349 
2350   if(META_DEBUG)
2351     {
2352     METAIO_STREAM::cout << "metaImage: M_Read: elementSpacing[" << 0 << "] = "
2353                         << m_ElementSpacing[0] << METAIO_STREAM::endl;
2354     }
2355   mF = MET_GetFieldRecord("DimSize", &m_Fields);
2356   if(mF && mF->defined)
2357     {
2358     int i;
2359     for(i=0; i<m_NDims; i++)
2360       {
2361       m_DimSize[i] = (int)mF->value[i];
2362       }
2363     }
2364 
2365   mF = MET_GetFieldRecord("HeaderSize", &m_Fields);
2366   if(mF && mF->defined)
2367     {
2368     m_HeaderSize = (int)mF->value[0];
2369     }
2370 
2371   mF = MET_GetFieldRecord("Modality", &m_Fields);
2372   if(mF && mF->defined)
2373     {
2374     MET_StringToImageModality((char *)mF->value, &m_Modality);
2375     }
2376 
2377   mF = MET_GetFieldRecord("SequenceID", &m_Fields);
2378   if(mF && mF->defined)
2379     {
2380     int i;
2381     for(i=0; i<m_NDims; i++)
2382       {
2383       m_SequenceID[i] = (float)(mF->value[i]);
2384       }
2385     }
2386 
2387   mF = MET_GetFieldRecord("ImagePosition", &m_Fields);
2388   if(mF && mF->defined)
2389     {
2390     int i;
2391     for(i=0; i<m_NDims; i++)
2392       {
2393       m_Offset[i] = static_cast<double>(mF->value[i]);
2394       }
2395     }
2396 
2397   mF = MET_GetFieldRecord("ElementMin", &m_Fields);
2398   if(mF && mF->defined)
2399     {
2400     m_ElementMin = mF->value[0];
2401     }
2402 
2403   mF = MET_GetFieldRecord("ElementMax", &m_Fields);
2404   if(mF && mF->defined)
2405     {
2406     m_ElementMax = mF->value[0];
2407     }
2408 
2409   mF = MET_GetFieldRecord("ElementNumberOfChannels", &m_Fields);
2410   if(mF && mF->defined)
2411     {
2412     m_ElementNumberOfChannels = (int)mF->value[0];
2413     }
2414 
2415 
2416   mF = MET_GetFieldRecord("ElementSize", &m_Fields);
2417   if(mF && mF->defined)
2418     {
2419     m_ElementSizeValid = true;
2420     int i;
2421     for(i=0; i<m_NDims; i++)
2422       {
2423       m_ElementSize[i] = (float)(mF->value[i]);
2424       }
2425     mF = MET_GetFieldRecord("ElementSpacing", &m_Fields);
2426     if(mF && !mF->defined)
2427       {
2428       for(i=0; i<m_NDims; i++)
2429         {
2430         m_ElementSpacing[i] = m_ElementSize[i];
2431         }
2432       }
2433     }
2434   else
2435     {
2436     int i;
2437     m_ElementSizeValid = false;
2438     for(i=0; i<m_NDims; i++)
2439       {
2440       m_ElementSize[i] = m_ElementSpacing[i];
2441       }
2442     }
2443 
2444   m_ElementToIntensityFunctionSlope = 1;
2445   m_ElementToIntensityFunctionOffset = 0;
2446   mF = MET_GetFieldRecord("ElementToIntensityFunctionSlope", &m_Fields);
2447   if(mF && mF->defined)
2448     {
2449     m_ElementToIntensityFunctionSlope = mF->value[0];
2450     }
2451   mF = MET_GetFieldRecord("ElementToIntensityFunctionOffset", &m_Fields);
2452   if(mF && mF->defined)
2453     {
2454     m_ElementToIntensityFunctionOffset = mF->value[0];
2455     }
2456 
2457   mF = MET_GetFieldRecord("ElementType", &m_Fields);
2458   if(mF && mF->defined)
2459     {
2460     MET_StringToType((char *)(mF->value), &m_ElementType);
2461     }
2462 
2463   mF = MET_GetFieldRecord("ElementDataFile", &m_Fields);
2464   if(mF && mF->defined)
2465     {
2466     strcpy(m_ElementDataFileName, (char *)(mF->value));
2467     }
2468 
2469   return true;
2470   }
2471 
2472 //
2473 //
2474 //
2475 bool MetaImage::
M_ReadElements(METAIO_STREAM::ifstream * _fstream,void * _data,METAIO_STL::streamoff _dataQuantity)2476 M_ReadElements(METAIO_STREAM::ifstream * _fstream, void * _data,
2477                METAIO_STL::streamoff _dataQuantity)
2478   {
2479   if(META_DEBUG)
2480     {
2481     METAIO_STREAM::cout << "MetaImage: M_ReadElements" << METAIO_STREAM::endl;
2482     }
2483 
2484   if(m_HeaderSize>(int)0)
2485     {
2486     _fstream->seekg(m_HeaderSize, METAIO_STREAM::ios::beg);
2487     if(!_fstream->good())
2488       {
2489       METAIO_STREAM::cerr << "MetaImage: Read: header not read correctly"
2490                           << METAIO_STREAM::endl;
2491       return false;
2492       }
2493     }
2494 
2495   int elementSize;
2496   MET_SizeOfType(m_ElementType, &elementSize);
2497   METAIO_STL::streamoff readSize = _dataQuantity*m_ElementNumberOfChannels*elementSize;
2498   if(META_DEBUG)
2499     {
2500     METAIO_STREAM::cout << "MetaImage: M_ReadElements: ReadSize = "
2501                         << readSize << METAIO_STREAM::endl;
2502     }
2503 
2504   if(m_HeaderSize == -1)
2505     {
2506     if(META_DEBUG)
2507       {
2508       METAIO_STREAM::cout << "MetaImage: M_ReadElements: Skipping header"
2509                           << METAIO_STREAM::endl;
2510       }
2511     _fstream->seekg(-readSize, METAIO_STREAM::ios::end);
2512     }
2513 
2514   // If compressed we inflate
2515   if(m_BinaryData && m_CompressedData)
2516     {
2517     // if m_CompressedDataSize is not defined we assume the size of the
2518     // file is the size of the compressed data
2519     bool compressedDataDeterminedFromFile = false;
2520     if(m_CompressedDataSize==0)
2521       {
2522       compressedDataDeterminedFromFile = true;
2523       _fstream->seekg(0, METAIO_STREAM::ios::end);
2524       m_CompressedDataSize = _fstream->tellg();
2525       _fstream->seekg(0, METAIO_STREAM::ios::beg);
2526       }
2527 
2528     unsigned char* compr = new unsigned char[m_CompressedDataSize];
2529 
2530     M_ReadElementData( _fstream, compr, m_CompressedDataSize );
2531 
2532     MET_PerformUncompression(compr, m_CompressedDataSize,
2533                              (unsigned char *)_data, readSize);
2534 
2535     if (compressedDataDeterminedFromFile)
2536       {
2537       m_CompressedDataSize = 0;
2538       }
2539 
2540     delete [] compr;
2541     }
2542   else // if not compressed
2543     {
2544     if(!m_BinaryData)
2545       {
2546 
2547       M_ReadElementData( _fstream, _data, _dataQuantity );
2548 
2549       }
2550     else
2551       {
2552 
2553       if ( !M_ReadElementData( _fstream, _data, _dataQuantity ) )
2554         return false;
2555 
2556       }
2557     }
2558 
2559   return true;
2560   }
2561 
2562 bool MetaImage::
M_WriteElements(METAIO_STREAM::ofstream * _fstream,const void * _data,METAIO_STL::streamoff _dataQuantity)2563 M_WriteElements(METAIO_STREAM::ofstream * _fstream,
2564                 const void * _data,
2565                 METAIO_STL::streamoff _dataQuantity)
2566   {
2567 
2568   if(!strcmp(m_ElementDataFileName, "LOCAL"))
2569     {
2570     MetaImage::M_WriteElementData(_fstream, _data, _dataQuantity);
2571     }
2572   else // write the data in a separate file
2573     {
2574     char dataFileName[MAXPATHLENGHT];
2575     char pathName[MAXPATHLENGHT];
2576     bool usePath = MET_GetFilePath(m_FileName, pathName);
2577     if(usePath&& !FileIsFullPath(m_ElementDataFileName))
2578       {
2579       sprintf(dataFileName, "%s%s", pathName, m_ElementDataFileName);
2580       }
2581     else
2582       {
2583       strcpy(dataFileName, m_ElementDataFileName);
2584       }
2585 
2586     if(strstr(dataFileName, "%")) // write slice by slice
2587       {
2588       int i;
2589       char fName[MAXPATHLENGHT];
2590       int elementSize;
2591       MET_SizeOfType(m_ElementType, &elementSize);
2592       METAIO_STL::streamoff elementNumberOfBytes = elementSize*m_ElementNumberOfChannels;
2593       METAIO_STL::streamoff sliceNumberOfBytes = m_SubQuantity[m_NDims-1]*elementNumberOfBytes;
2594 
2595       METAIO_STREAM::ofstream* writeStreamTemp = new METAIO_STREAM::ofstream;
2596       for(i=1; i<=m_DimSize[m_NDims-1]; i++)
2597         {
2598         sprintf(fName, dataFileName, i);
2599 
2600         openWriteStream(*writeStreamTemp, fName, false);
2601 
2602         if(!m_CompressedData)
2603           {
2604           // BUG? This looks wrong to me as the third parameter should
2605           // contain the number of elements/quantity, not number of bytes -BCL
2606           MetaImage::M_WriteElementData(writeStreamTemp,
2607                              &(((const char *)_data)[(i-1)*sliceNumberOfBytes]),
2608                              sliceNumberOfBytes);
2609           }
2610         else
2611           {
2612           unsigned char * compressedData = NULL;
2613           METAIO_STL::streamoff compressedDataSize = 0;
2614 
2615           // Compress the data slice by slice
2616           compressedData = MET_PerformCompression(
2617                   &(((const unsigned char *)_data)[(i-1)*sliceNumberOfBytes]),
2618                   sliceNumberOfBytes,
2619                   & compressedDataSize );
2620 
2621           // Write the compressed data
2622           MetaImage::M_WriteElementData( writeStreamTemp,
2623                               compressedData,
2624                               compressedDataSize );
2625 
2626           delete [] compressedData;
2627           }
2628 
2629         writeStreamTemp->close();
2630         }
2631 
2632       delete writeStreamTemp;
2633       }
2634     else // write the image in one unique other file
2635       {
2636       METAIO_STREAM::ofstream* writeStreamTemp = new METAIO_STREAM::ofstream;
2637       openWriteStream(*writeStreamTemp, dataFileName, false);
2638 
2639       MetaImage::M_WriteElementData(writeStreamTemp, _data, _dataQuantity);
2640 
2641       writeStreamTemp->close();
2642       delete writeStreamTemp;
2643       }
2644     }
2645 
2646   return true;
2647   }
2648 
2649 
2650 bool MetaImage::
M_WriteElementData(METAIO_STREAM::ofstream * _fstream,const void * _data,METAIO_STL::streamoff _dataQuantity)2651 M_WriteElementData(METAIO_STREAM::ofstream * _fstream,
2652                    const void * _data,
2653                    METAIO_STL::streamoff _dataQuantity)
2654   {
2655   if(!m_BinaryData)
2656     {
2657 
2658     double tf;
2659     for(METAIO_STL::streamoff i=0; i<_dataQuantity; i++)
2660       {
2661       MET_ValueToDouble(m_ElementType, _data, i, &tf);
2662       if((i+1)/10 == (double)(i+1.0)/10.0)
2663         {
2664         (*_fstream) << tf << METAIO_STREAM::endl;
2665         }
2666       else
2667         {
2668         (*_fstream) << tf << " ";
2669         }
2670       }
2671     }
2672   else
2673     {
2674     if(m_CompressedData)
2675       {
2676       // the data is writen in writes no bigger then MaxIOChunk
2677       METAIO_STL::streamoff bytesRemaining = _dataQuantity;
2678       while ( bytesRemaining )
2679         {
2680         METAIO_STL::streamoff chunkToWrite = bytesRemaining > MaxIOChunk ? MaxIOChunk : bytesRemaining;
2681         _fstream->write( (const char *)_data, (size_t)chunkToWrite );
2682         _data = (const char *)(_data) + chunkToWrite; // <- Note: data is changed
2683         bytesRemaining -= chunkToWrite;
2684         }
2685       }
2686     else
2687       {
2688       int elementSize;
2689       MET_SizeOfType(m_ElementType, &elementSize);
2690       METAIO_STL::streamoff elementNumberOfBytes = elementSize*m_ElementNumberOfChannels;
2691 
2692       // the data is writen in writes no bigger then MaxIOChunk
2693       METAIO_STL::streamoff bytesRemaining = _dataQuantity * elementNumberOfBytes;
2694       while ( bytesRemaining )
2695         {
2696         METAIO_STL::streamoff chunkToWrite = bytesRemaining > MaxIOChunk ? MaxIOChunk : bytesRemaining;
2697         _fstream->write( (const char *)_data, (size_t)chunkToWrite );
2698         _data = (const char *)(_data) + chunkToWrite; // <- Note: _data is changed
2699         bytesRemaining -= chunkToWrite;
2700         }
2701       }
2702     }
2703 
2704   // check the the io stream did not fail in the process of writing
2705   if ( _fstream->fail() )
2706     {
2707     METAIO_STREAM::cerr
2708       << "MetaImage: M_WriteElementsData: file stream is fail after write"
2709       << METAIO_STREAM::endl;
2710     return false;
2711     }
2712 
2713   return true;
2714   }
2715 
2716 /** Streaming related functions */
2717 bool MetaImage::
ReadROI(int * _indexMin,int * _indexMax,const char * _headerName,bool _readElements,void * _buffer,unsigned int subSamplingFactor)2718 ReadROI(int * _indexMin, int * _indexMax,
2719         const char *_headerName,
2720         bool _readElements,
2721         void * _buffer,
2722         unsigned int subSamplingFactor)
2723 {
2724   M_Destroy();
2725 
2726   Clear();
2727 
2728   M_SetupReadFields();
2729 
2730   if(_headerName != NULL)
2731     {
2732     strcpy(m_FileName, _headerName);
2733     }
2734 
2735   M_PrepareNewReadStream();
2736 
2737   METAIO_STREAM::ifstream * tmpReadStream = new METAIO_STREAM::ifstream;
2738 
2739   openReadStream(*tmpReadStream, m_FileName);
2740 
2741   if(!tmpReadStream->is_open())
2742     {
2743     delete tmpReadStream;
2744     return false;
2745     }
2746 
2747   if( !this->ReadROIStream(_indexMin, _indexMax,
2748                            0, tmpReadStream, _readElements, _buffer,subSamplingFactor) )
2749     {
2750     tmpReadStream->close();
2751     delete tmpReadStream;
2752     return false;
2753     }
2754 
2755   tmpReadStream->close();
2756 
2757   delete tmpReadStream;
2758 
2759   return true;
2760 }
2761 
2762 /** Read the ROI Stream */
ReadROIStream(int * _indexMin,int * _indexMax,int _nDims,METAIO_STREAM::ifstream * _stream,bool _readElements,void * _buffer,unsigned int subSamplingFactor)2763 bool MetaImage::ReadROIStream(int * _indexMin, int * _indexMax,
2764                               int _nDims,
2765                               METAIO_STREAM::ifstream * _stream,
2766                               bool _readElements,
2767                               void * _buffer,
2768                               unsigned int subSamplingFactor)
2769 {
2770   if(!MetaObject::ReadStream(_nDims, _stream))
2771     {
2772     METAIO_STREAM::cerr << "MetaImage: Read: Cannot parse file"
2773                         << METAIO_STREAM::endl;
2774     return false;
2775     }
2776 
2777   if(_readElements)
2778     {
2779     if(_buffer == NULL)
2780       {
2781       InitializeEssential(m_NDims,
2782                           m_DimSize,
2783                           m_ElementSpacing,
2784                           m_ElementType,
2785                           m_ElementNumberOfChannels,
2786                           NULL, true);
2787       }
2788     else
2789       {
2790       InitializeEssential(m_NDims,
2791                           m_DimSize,
2792                           m_ElementSpacing,
2793                           m_ElementType,
2794                           m_ElementNumberOfChannels,
2795                           _buffer, false);
2796       }
2797 
2798     // Streaming related. We need to update some of the fields
2799     METAIO_STL::streamoff quantity = 1;
2800     int i;
2801     size_t j;
2802     for(i=0; i<m_NDims; i++)
2803       {
2804       quantity *= (_indexMax[i] - _indexMin[i] + 1);
2805       }
2806 
2807     bool usePath;
2808     char pathName[MAXPATHLENGHT];
2809     char fName[MAXPATHLENGHT];
2810     usePath = MET_GetFilePath(m_FileName, pathName);
2811 
2812     if(!strcmp("Local", m_ElementDataFileName) ||
2813        !strcmp("LOCAL", m_ElementDataFileName) ||
2814        !strcmp("local", m_ElementDataFileName))
2815       {
2816       M_ReadElementsROI(_stream, m_ElementData, quantity,
2817                         _indexMin, _indexMax, subSamplingFactor,
2818                         m_Quantity);
2819       }
2820     else if(!strncmp("LIST", m_ElementDataFileName,4))
2821       {
2822       int fileImageDim = m_NDims - 1;
2823       int nWrds;
2824       char **wrds;
2825       MET_StringToWordArray(m_ElementDataFileName, &nWrds, &wrds);
2826       if(nWrds > 1)
2827         {
2828         fileImageDim = (int)atof(wrds[1]);
2829         }
2830       for(i=0; i<nWrds; i++)
2831         {
2832         delete [] wrds[i];
2833         }
2834       delete [] wrds;
2835       if ( (fileImageDim == 0) || (fileImageDim > m_NDims) )
2836         {
2837         // if optional file dimension size is not given or is larger than
2838         // overall dimension then default to a size of m_NDims - 1.
2839         fileImageDim = m_NDims-1;
2840         }
2841       char s[1024];
2842       METAIO_STREAM::ifstream* readStreamTemp = new METAIO_STREAM::ifstream;
2843       int elementSize;
2844       MET_SizeOfType(m_ElementType, &elementSize);
2845       elementSize *= m_ElementNumberOfChannels;
2846 
2847       int minV = _indexMin[m_NDims-1];
2848       int maxV = minV + (_indexMax[m_NDims-1]-_indexMin[m_NDims-1]);
2849 
2850       int cnt=0;
2851 
2852       // Read the previous lines
2853       for(i=0;i<minV;i++)
2854         {
2855         _stream->getline(s, 1024);
2856         }
2857 
2858       for(i=minV; i<=maxV; i+=1)
2859         {
2860         _stream->getline(s, 1024);
2861         if(!_stream->eof())
2862           {
2863           j = strlen(s)-1;
2864           while(j>0 && (isspace(s[j]) || !isprint(s[j])))
2865             {
2866             s[j--] = '\0';
2867             }
2868           if(usePath && !FileIsFullPath(s))
2869             {
2870             sprintf(fName, "%s%s", pathName, s);
2871             }
2872           else
2873             {
2874             strcpy(fName, s);
2875             }
2876 
2877           openReadStream(*readStreamTemp, fName);
2878           if(!readStreamTemp->is_open())
2879             {
2880             METAIO_STREAM::cerr << "MetaImage: Read: cannot open slice"
2881                                 << METAIO_STREAM::endl;
2882             continue;
2883             }
2884 
2885           // read only one slice
2886           int * indexMin = new int[m_NDims];
2887           int * indexMax = new int[m_NDims];
2888           quantity = 1;
2889           for(int k = 0;k<m_NDims-1;k++)
2890             {
2891             quantity *= _indexMax[k]-_indexMin[k]+1;
2892             indexMin[k]= _indexMin[k];
2893             indexMax[k]= _indexMax[k];
2894             }
2895           indexMin[m_NDims-1]=0;
2896           indexMax[m_NDims-1]=0;
2897 
2898           M_ReadElementsROI(readStreamTemp,
2899                              &(((char *)m_ElementData)[cnt*quantity*
2900                                                      elementSize]),
2901                              quantity, indexMin, indexMax,
2902                              subSamplingFactor,
2903                              m_SubQuantity[m_NDims-1]);
2904 
2905           cnt++;
2906           readStreamTemp->close();
2907           }
2908         }
2909       delete readStreamTemp;
2910       }
2911     else if(strstr(m_ElementDataFileName, "%"))
2912       {
2913       int elementSize;
2914       MET_SizeOfType(m_ElementType, &elementSize);
2915       elementSize *= m_ElementNumberOfChannels;
2916 
2917       int nWrds;
2918       char **wrds;
2919       int minV = 1;
2920       int maxV = m_DimSize[m_NDims-1];
2921       int stepV = 1;
2922       char s[MAXPATHLENGHT];
2923       METAIO_STREAM::ifstream* readStreamTemp = new METAIO_STREAM::ifstream;
2924       MET_StringToWordArray(m_ElementDataFileName, &nWrds, &wrds);
2925       if(nWrds >= 2)
2926         {
2927         minV = (int)atof(wrds[1]);
2928         maxV = minV + m_DimSize[m_NDims-1] - 1;
2929         }
2930       if(nWrds >= 3)
2931         {
2932         maxV = (int)atof(wrds[2]);
2933         stepV = (maxV-minV)/(m_DimSize[m_NDims-1]);
2934         }
2935       if(nWrds >= 4)
2936         {
2937         stepV = (int)atof(wrds[3]);
2938         }
2939       if(nWrds >= 5 )
2940       {
2941         // In this case, the filename must have had spaces in the
2942         // name.  The filename was parsed into multiple pieces by the
2943         // MET_StringToWordArray, which parses based on spaces.
2944         // Thus, we need to reconstruct the filename in this case.
2945         // The last three wrds must be numbers.  If they are not, we give an error.
2946         for( i = nWrds-3; i < nWrds; i++ )
2947         {
2948           for( j = 0; j < strlen(wrds[i]); j++ )
2949           {
2950             if( !isdigit(wrds[i][j]) )
2951             {
2952               METAIO_STREAM::cerr << "MetaImage: Read: Last three arguments must be numbers!"
2953                   << METAIO_STREAM::endl;
2954               continue;
2955             }
2956           }
2957         }
2958         stepV = (int)atof(wrds[nWrds-1]);
2959         maxV =  (int)atof(wrds[nWrds-2]);
2960         minV =  (int)atof(wrds[nWrds-3]);
2961         for( i = 1; i < nWrds-3; i++ )
2962         {
2963           strcat(wrds[0]," ");
2964           strcat(wrds[0],wrds[i]);
2965         }
2966       }
2967       // If the specified size of the third dimension is less than the size
2968       // specified by the regular expression, we should only read a volume with the specified
2969       // size.  Otherwise, the code will crash when trying to fill m_ElementData more than it can hold.
2970       // Therefore, we modify maxV to ensure that the images spanned by minV:stepV:maxV are less than or equal
2971       // to the size in the last dimension.
2972       int numberOfImages = 1 + (maxV - minV)/stepV;
2973       if( numberOfImages > m_DimSize[m_NDims-1] )
2974       {
2975         maxV = (m_DimSize[m_NDims-1]-1)*stepV + minV;
2976       }
2977 
2978       int cnt = 0;
2979 
2980       // Uses the _indexMin and _indexMax
2981       minV += _indexMin[m_NDims-1];
2982       maxV = minV + (_indexMax[m_NDims-1]-_indexMin[m_NDims-1])*stepV;
2983 
2984       for(i=minV; i<=maxV; i += stepV)
2985         {
2986         sprintf(s, wrds[0], i);
2987         if(usePath && !FileIsFullPath(s))
2988           {
2989           sprintf(fName, "%s%s", pathName, s);
2990           }
2991         else
2992           {
2993           strcpy(fName, s);
2994           }
2995 
2996 
2997         openReadStream(*readStreamTemp, fName);
2998         if(!readStreamTemp->is_open())
2999           {
3000           METAIO_STREAM::cerr << "MetaImage: Read: cannot construct file"
3001                               << METAIO_STREAM::endl;
3002           continue;
3003           }
3004 
3005         // read only one slice
3006         int * indexMin = new int[m_NDims];
3007         int * indexMax = new int[m_NDims];
3008         quantity = 1;
3009         for(int k = 0;k<m_NDims-1;k++)
3010           {
3011           quantity *= _indexMax[k]-_indexMin[k]+1;
3012           indexMin[k]= _indexMin[k];
3013           indexMax[k]= _indexMax[k];
3014           }
3015         indexMin[m_NDims-1]=0;
3016         indexMax[m_NDims-1]=0;
3017 
3018         M_ReadElementsROI(readStreamTemp,
3019                        &(((char *)m_ElementData)[cnt*quantity*
3020                                                  elementSize]),
3021                        quantity, indexMin, indexMax,
3022                        subSamplingFactor,
3023                        m_SubQuantity[m_NDims-1]);
3024 
3025         cnt++;
3026 
3027         delete [] indexMin;
3028         delete [] indexMax;
3029 
3030         readStreamTemp->close();
3031         }
3032 
3033       for(i=0; i<nWrds; i++)
3034         {
3035         delete [] wrds[i];
3036         }
3037       delete [] wrds;
3038 
3039       delete readStreamTemp;
3040       }
3041     else
3042       {
3043       if(usePath && !FileIsFullPath(m_ElementDataFileName))
3044         {
3045         sprintf(fName, "%s%s", pathName, m_ElementDataFileName);
3046         }
3047       else
3048         {
3049         strcpy(fName, m_ElementDataFileName);
3050         }
3051 
3052       METAIO_STREAM::ifstream* readStreamTemp = new METAIO_STREAM::ifstream;
3053 
3054       const char *extensions[] = { "", ".gz", ".Z", 0 };
3055       for(unsigned ii = 0; extensions[ii] != 0; ii++)
3056         {
3057         METAIO_STL::string tempFName(fName);
3058         tempFName += extensions[ii];
3059         openReadStream(*readStreamTemp,tempFName.c_str());
3060         if(readStreamTemp->is_open())
3061           {
3062           if(ii > 0)
3063             {
3064             this->CompressedData(true);
3065             this->BinaryData(true);
3066             }
3067           break;
3068           }
3069         }
3070 
3071       if(!readStreamTemp->is_open())
3072         {
3073         METAIO_STREAM::cerr << "MetaImage: ReadROI: Cannot open data file"
3074                             << METAIO_STREAM::endl;
3075         if(m_ReadStream)
3076           {
3077           m_ReadStream->close();
3078           }
3079         delete readStreamTemp;
3080         return false;
3081         }
3082 
3083       M_ReadElementsROI(readStreamTemp, m_ElementData, quantity,
3084                         _indexMin, _indexMax, subSamplingFactor,
3085                         m_Quantity);
3086 
3087       readStreamTemp->close();
3088       delete readStreamTemp;
3089       }
3090     }
3091   return true;
3092 }
3093 
3094 /** Read an ROI */
3095 bool MetaImage::
M_ReadElementsROI(METAIO_STREAM::ifstream * _fstream,void * _data,METAIO_STL::streamoff _dataQuantity,int * _indexMin,int * _indexMax,unsigned int subSamplingFactor,METAIO_STL::streamoff _totalDataQuantity)3096 M_ReadElementsROI(METAIO_STREAM::ifstream * _fstream, void * _data,
3097                   METAIO_STL::streamoff _dataQuantity,
3098                   int* _indexMin, int* _indexMax,unsigned int subSamplingFactor,
3099                   METAIO_STL::streamoff _totalDataQuantity)
3100 {
3101   if(_totalDataQuantity ==0)
3102     {
3103     _totalDataQuantity = _dataQuantity;
3104     }
3105 
3106   for(int dim=0;dim<m_NDims;dim++)
3107     {
3108     _indexMin[dim] *= subSamplingFactor;
3109     _indexMax[dim] *= subSamplingFactor;
3110     }
3111 
3112 
3113   if(META_DEBUG)
3114     {
3115     METAIO_STREAM::cout << "MetaImage: M_ReadElementsROI" << METAIO_STREAM::endl;
3116     }
3117 
3118   if(m_HeaderSize>(int)0)
3119     {
3120     _fstream->seekg(m_HeaderSize, METAIO_STREAM::ios::beg);
3121     if(!_fstream->good())
3122       {
3123       METAIO_STREAM::cerr << "MetaImage: M_ReadElementsROI: header not read correctly"
3124                           << METAIO_STREAM::endl;
3125       return false;
3126       }
3127     }
3128 
3129   int elementSize;
3130   MET_SizeOfType(m_ElementType, &elementSize);
3131   METAIO_STL::streamoff readSize = _dataQuantity*m_ElementNumberOfChannels*elementSize;
3132   int elementNumberOfBytes = elementSize*m_ElementNumberOfChannels;
3133 
3134   if(META_DEBUG)
3135     {
3136     METAIO_STREAM::cout << "MetaImage: M_ReadElementsROI: ReadSize = "
3137                         << readSize << METAIO_STREAM::endl;
3138     }
3139 
3140   if(m_HeaderSize == -1)
3141     {
3142     if(META_DEBUG)
3143       {
3144       METAIO_STREAM::cout << "MetaImage: M_ReadElementsROI: Skipping header"
3145                           << METAIO_STREAM::endl;
3146       }
3147     METAIO_STL::streamoff headSize = _totalDataQuantity*m_ElementNumberOfChannels*elementSize;
3148     _fstream->seekg(-headSize, METAIO_STREAM::ios::end);
3149     }
3150 
3151   METAIO_STL::streampos dataPos = _fstream->tellg();
3152   METAIO_STL::streamoff i;
3153 
3154   // If compressed we inflate
3155   if(m_BinaryData && m_CompressedData)
3156     {
3157     // if m_CompressedDataSize is not defined we assume the size of the
3158     // file is the size of the compressed data
3159     if(m_CompressedDataSize==0)
3160       {
3161       _fstream->seekg(0, METAIO_STREAM::ios::end);
3162       m_CompressedDataSize = _fstream->tellg();
3163       _fstream->seekg(0, METAIO_STREAM::ios::beg);
3164       }
3165 
3166       unsigned char* data = static_cast<unsigned char*>(_data);
3167       // Initialize the index
3168       int* currentIndex = new int[m_NDims];
3169       for(i=0;i<m_NDims;i++)
3170         {
3171         currentIndex[i] = _indexMin[i];
3172         }
3173 
3174       // Optimize the size of the buffer to read depending on the
3175       // region shape
3176       // This calculate the number of continuous bytes in the file
3177       // which can be read
3178       METAIO_STL::streamoff elementsToRead = 1;
3179       int movingDirection = 0;
3180       do
3181         {
3182         elementsToRead *= _indexMax[movingDirection] - _indexMin[movingDirection] + 1;
3183         ++movingDirection;
3184         }
3185       while(subSamplingFactor == 1
3186             && movingDirection < m_NDims
3187             && _indexMin[movingDirection-1] == 0
3188             && _indexMax[movingDirection-1] == m_DimSize[movingDirection-1]-1);
3189 
3190       METAIO_STL::streamoff bytesToRead = elementsToRead*elementNumberOfBytes;
3191       METAIO_STL::streamoff gc = 0;
3192 
3193       bool done = false;
3194       while(!done)
3195         {
3196         // Seek to the right position
3197         METAIO_STL::streamoff seekoff = 0;
3198         for(i=0; i<m_NDims; i++)
3199           {
3200           seekoff += m_SubQuantity[i]*elementNumberOfBytes*currentIndex[i];
3201           }
3202 
3203 
3204         if(subSamplingFactor > 1)
3205           {
3206           unsigned char* subdata = new unsigned char[bytesToRead];
3207           METAIO_STL::streamoff rOff =
3208             MET_UncompressStream(_fstream, seekoff, subdata,
3209                                  bytesToRead, m_CompressedDataSize,
3210                                  m_CompressionTable);
3211           // if there was a read error
3212           if(rOff == -1)
3213             {
3214             delete [] currentIndex;
3215             return false;
3216             }
3217 
3218           for(METAIO_STL::streamoff p=0;
3219               p<bytesToRead;
3220               p+=(subSamplingFactor*m_ElementNumberOfChannels*elementSize))
3221             {
3222             for(int s=0; s<m_ElementNumberOfChannels*elementSize; s++)
3223               {
3224               *data = subdata[p+s];
3225               gc++;
3226               data++;
3227               }
3228             }
3229           delete [] subdata;
3230           }
3231         else
3232           {
3233           METAIO_STL::streamoff rOff =
3234             MET_UncompressStream(_fstream, seekoff, data,
3235                                  bytesToRead, m_CompressedDataSize,
3236                                  m_CompressionTable);
3237           if(rOff == -1)
3238             {
3239             delete [] currentIndex;
3240             return false;
3241             }
3242           data += bytesToRead;
3243           gc += rOff;
3244           }
3245 
3246         if(gc == readSize)
3247           {
3248           break;
3249           }
3250 
3251         // Go forward
3252         if(m_NDims == 1)
3253           {
3254           break;
3255           }
3256 
3257         currentIndex[movingDirection] += subSamplingFactor;
3258 
3259         // Check if we are still in the region
3260         for(i=1;i<m_NDims;i++)
3261           {
3262           if(currentIndex[i]>_indexMax[i])
3263             {
3264             if(i==m_NDims-1)
3265               {
3266               done = true;
3267               break;
3268               }
3269             else
3270               {
3271               currentIndex[i] = _indexMin[i];
3272               currentIndex[i+1] += subSamplingFactor;
3273               }
3274             }
3275           }
3276         }
3277 
3278       if(gc != readSize)
3279         {
3280         METAIO_STREAM::cerr
3281                   << "MetaImage: M_ReadElementsROI: data not read completely"
3282                   << METAIO_STREAM::endl;
3283         METAIO_STREAM::cerr << "   ideal = " << readSize << " : actual = " << gc
3284                   << METAIO_STREAM::endl;
3285         delete [] currentIndex;
3286         return false;
3287         }
3288 
3289       delete [] currentIndex;
3290     }
3291   else // if not compressed
3292     {
3293     double tf;
3294     MET_SizeOfType(m_ElementType, &elementSize);
3295 
3296     char* data = static_cast<char*>(_data);
3297     // Initialize the index
3298     int* currentIndex = new int[m_NDims];
3299     for(i=0;i<m_NDims;i++)
3300       {
3301       currentIndex[i] = _indexMin[i];
3302       }
3303 
3304     // Optimize the size of the buffer to read depending on the
3305     // region shape
3306     // This calculate the number of continuous bytes in the file
3307     // which can be read
3308     METAIO_STL::streamoff elementsToRead = 1;
3309     int movingDirection = 0;
3310     do
3311       {
3312       elementsToRead *= _indexMax[movingDirection] - _indexMin[movingDirection] + 1;
3313       ++movingDirection;
3314       }
3315     while(subSamplingFactor == 1
3316           && movingDirection < m_NDims
3317           && _indexMin[movingDirection-1] == 0
3318           && _indexMax[movingDirection-1] == m_DimSize[movingDirection-1]-1);
3319 
3320     //readLine *= m_ElementNumberOfChannels*elementSize;
3321     METAIO_STL::streamoff gc = 0;
3322 
3323     bool done = false;
3324     while(!done)
3325       {
3326       // Seek to the right position
3327       METAIO_STL::streamoff seekoff = 0;
3328       for(i=0;i<m_NDims;i++)
3329         {
3330         seekoff += m_SubQuantity[i]*m_ElementNumberOfChannels*elementSize*currentIndex[i];
3331         }
3332 
3333       _fstream->seekg(dataPos+seekoff, METAIO_STREAM::ios::beg);
3334 
3335       // Read a line
3336       if(subSamplingFactor > 1)
3337         {
3338         if(!m_BinaryData) // Not binary data
3339           {
3340           for(i=0; i<elementsToRead; i+=subSamplingFactor)
3341             {
3342             *_fstream >> tf;
3343             MET_DoubleToValue(tf, m_ElementType, _data, i);
3344 
3345             for(unsigned int j=0;j<subSamplingFactor;j++)
3346               {
3347               _fstream->get();
3348               }
3349             }
3350           }
3351         else // Binary data
3352           {
3353           char* subdata = new char[elementsToRead*elementNumberOfBytes];
3354 
3355           _fstream->read(subdata, size_t(elementsToRead*elementNumberOfBytes));
3356 
3357           for(METAIO_STL::streamoff p=0;
3358               p<elementsToRead*elementNumberOfBytes;
3359               p+=(subSamplingFactor*elementNumberOfBytes))
3360             {
3361             for(int s=0;s<elementNumberOfBytes;s++)
3362               {
3363               *data = subdata[p+s];
3364               gc++;
3365               data++;
3366               }
3367             }
3368           delete [] subdata;
3369           }
3370         }
3371       else
3372         {
3373         if(!m_BinaryData) // Not binary data
3374           {
3375           // anyone using ROI reading of ASCII??
3376           // does this work? what about incrementing data?
3377           // what about data sizes and random access of file?
3378           METAIO_STL::streamoff blockSize = elementsToRead*m_ElementNumberOfChannels*elementSize;
3379           M_ReadElementData(  _fstream, data, (size_t)blockSize  );
3380           gc += blockSize;
3381 
3382           }
3383         else // binary data
3384           {
3385 
3386           M_ReadElementData(  _fstream, data, elementsToRead );
3387           gc += elementsToRead*elementNumberOfBytes;
3388           data += elementsToRead*elementNumberOfBytes;
3389           }
3390         }
3391 
3392       // I don't think this check is really needed -BCL
3393       if(gc == readSize)
3394         {
3395         break;
3396         }
3397 
3398       // check if there is only one read needed
3399       if ( movingDirection >= m_NDims )
3400         {
3401         break;
3402         }
3403 
3404       // Go forward
3405       currentIndex[movingDirection] += subSamplingFactor;
3406 
3407       // Check if we are still in the region
3408       for(i=movingDirection;i<m_NDims;i++)
3409         {
3410         if(currentIndex[i]>_indexMax[i])
3411           {
3412           if(i==m_NDims-1)
3413             {
3414             done = true;
3415             break;
3416             }
3417           else
3418             {
3419             currentIndex[i] = _indexMin[i];
3420             currentIndex[i+1] += subSamplingFactor;
3421             }
3422           }
3423         }
3424       }
3425 
3426     delete [] currentIndex;
3427 
3428     if(gc != readSize)
3429       {
3430       METAIO_STREAM::cerr
3431                 << "MetaImage: M_ReadElementsROI: data not read completely"
3432                 << METAIO_STREAM::endl;
3433       METAIO_STREAM::cerr << "   ideal = " << readSize << " : actual = " << gc
3434                 << METAIO_STREAM::endl;
3435       return false;
3436       }
3437     }
3438 
3439   return true;
3440 }
3441 
3442 
3443 bool MetaImage::
M_ReadElementData(METAIO_STREAM::ifstream * _fstream,void * _data,METAIO_STL::streamoff _dataQuantity)3444 M_ReadElementData(METAIO_STREAM::ifstream * _fstream,
3445                   void * _data,
3446                   METAIO_STL::streamoff _dataQuantity)
3447 {
3448   // NOTE: this method is different from WriteElementData
3449   METAIO_STL::streamoff gc = 0;
3450 
3451   if(!m_BinaryData)
3452     {
3453     double tf;
3454 
3455     for(int i=0; i<_dataQuantity; i++)
3456       {
3457       *_fstream >> tf;
3458       MET_DoubleToValue(tf, m_ElementType, _data, i);
3459       _fstream->get();
3460       ++gc;
3461       }
3462     }
3463   else
3464     {
3465     if(m_CompressedData)
3466       {
3467 
3468       // the data is read with calls no bigger then MaxIOChunk
3469       METAIO_STL::streamoff bytesRemaining = _dataQuantity;
3470       while ( bytesRemaining )
3471         {
3472         METAIO_STL::streamoff chunkToRead = bytesRemaining > MaxIOChunk ? MaxIOChunk : bytesRemaining;
3473         _fstream->read( (char *)_data, (size_t)chunkToRead );
3474         _data = (char *)(_data) + chunkToRead;
3475         bytesRemaining -= chunkToRead;
3476         METAIO_STL::streamsize numberOfBytesRead = _fstream->gcount();
3477         gc += numberOfBytesRead;
3478         }
3479 
3480       }
3481     else
3482       {
3483       int elementSize;
3484       MET_SizeOfType(m_ElementType, &elementSize);
3485       METAIO_STL::streamoff elementNumberOfBytes = elementSize*m_ElementNumberOfChannels;
3486 
3487       // the data is read with calls no bigger than MaxIOChunk
3488       METAIO_STL::streamoff bytesRemaining = _dataQuantity * elementNumberOfBytes;
3489       while ( bytesRemaining )
3490         {
3491         METAIO_STL::streamoff chunkToRead = bytesRemaining > MaxIOChunk ? MaxIOChunk : bytesRemaining;
3492         _fstream->read( (char *)_data, (size_t)chunkToRead );
3493         _data = (char *)(_data) + chunkToRead;
3494         bytesRemaining -= chunkToRead;
3495         METAIO_STL::streamsize numberOfBytesRead = _fstream->gcount();
3496         gc += numberOfBytesRead;
3497         }
3498       // convert to number of bytes so that it'll match gc's units
3499       _dataQuantity *= elementNumberOfBytes;
3500       }
3501     }
3502 
3503   // check that we actually read the correct number of bytes
3504   if( gc != _dataQuantity )
3505     {
3506     METAIO_STREAM::cerr
3507       << "MetaImage: M_ReadElementsData: data not read completely"
3508       << METAIO_STREAM::endl;
3509     METAIO_STREAM::cerr << "   ideal = " << _dataQuantity << " : actual = " << gc
3510                         << METAIO_STREAM::endl;
3511     return false;
3512     }
3513 
3514   // check the the io stream did not fail in the process of reading
3515   if ( _fstream->fail() )
3516     {
3517     METAIO_STREAM::cerr
3518       << "MetaImage: M_ReadElementsData: file stream is fail after read"
3519       << METAIO_STREAM::endl;
3520     return false;
3521     }
3522 
3523   return true;
3524   }
3525 
3526 
3527 #if (METAIO_USE_NAMESPACE)
3528 }
3529 #endif
3530