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