1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImageReader2.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkImageReader2.h"
16 
17 #include "vtkByteSwap.h"
18 #include "vtkDataArray.h"
19 #include "vtkImageData.h"
20 #include "vtkInformation.h"
21 #include "vtkInformationVector.h"
22 #include "vtkObjectFactory.h"
23 #include "vtkPointData.h"
24 #include "vtkErrorCode.h"
25 #include "vtkStreamingDemandDrivenPipeline.h"
26 #include "vtkStringArray.h"
27 
28 #include "vtksys/SystemTools.hxx"
29 
30 vtkStandardNewMacro(vtkImageReader2);
31 
32 #ifdef read
33 #undef read
34 #endif
35 
36 #ifdef close
37 #undef close
38 #endif
39 
40 //----------------------------------------------------------------------------
vtkImageReader2()41 vtkImageReader2::vtkImageReader2()
42 {
43   this->FilePrefix = nullptr;
44   this->FilePattern = new char[strlen("%s.%d") + 1];
45   strcpy (this->FilePattern, "%s.%d");
46   this->File = nullptr;
47 
48   this->DataScalarType = VTK_SHORT;
49   this->NumberOfScalarComponents = 1;
50 
51   this->DataOrigin[0] = this->DataOrigin[1] = this->DataOrigin[2] = 0.0;
52 
53   this->DataSpacing[0] = this->DataSpacing[1] = this->DataSpacing[2] = 1.0;
54 
55   this->DataExtent[0] = this->DataExtent[2] = this->DataExtent[4] = 0;
56   this->DataExtent[1] = this->DataExtent[3] = this->DataExtent[5] = 0;
57 
58   this->DataIncrements[0] = this->DataIncrements[1] =
59   this->DataIncrements[2] = this->DataIncrements[3] = 1;
60 
61   this->FileNames = nullptr;
62 
63   this->FileName = nullptr;
64   this->InternalFileName = nullptr;
65 
66   this->MemoryBuffer = nullptr;
67   this->MemoryBufferLength = 0;
68 
69   this->HeaderSize = 0;
70   this->ManualHeaderSize = 0;
71 
72   this->FileNameSliceOffset = 0;
73   this->FileNameSliceSpacing = 1;
74 
75   // Left over from short reader
76   this->SwapBytes = 0;
77   this->FileLowerLeft = 0;
78   this->FileDimensionality = 2;
79   this->SetNumberOfInputPorts(0);
80 }
81 
82 //----------------------------------------------------------------------------
~vtkImageReader2()83 vtkImageReader2::~vtkImageReader2()
84 {
85   if (this->File)
86   {
87     this->File->close();
88     delete this->File;
89     this->File = nullptr;
90   }
91 
92   if (this->FileNames)
93   {
94     this->FileNames->Delete();
95     this->FileNames = nullptr;
96   }
97   delete [] this->FileName;
98   this->FileName = nullptr;
99   delete [] this->FilePrefix;
100   this->FilePrefix = nullptr;
101   delete [] this->FilePattern;
102   this->FilePattern = nullptr;
103   delete [] this->InternalFileName;
104   this->InternalFileName = nullptr;
105 }
106 
107 //----------------------------------------------------------------------------
108 // This function sets the name of the file.
ComputeInternalFileName(int slice)109 void vtkImageReader2::ComputeInternalFileName(int slice)
110 {
111   // delete any old filename
112   delete [] this->InternalFileName;
113   this->InternalFileName = nullptr;
114 
115   if (!this->FileName && !this->FilePattern && !this->FileNames)
116   {
117     vtkErrorMacro(<<"Either a FileName, FileNames, or FilePattern"
118                   <<" must be specified.");
119     return;
120   }
121 
122   // make sure we figure out a filename to open
123   if (this->FileNames)
124   {
125     const char *filename = this->FileNames->GetValue(slice);
126     size_t size = strlen(filename) + 10;
127     this->InternalFileName = new char [size];
128     snprintf(this->InternalFileName,size,"%s",filename);
129   }
130   else if (this->FileName)
131   {
132     size_t size = strlen(this->FileName) + 10;
133     this->InternalFileName = new char [size];
134     snprintf(this->InternalFileName,size,"%s",this->FileName);
135   }
136   else
137   {
138     int slicenum =
139       slice * this->FileNameSliceSpacing
140       + this->FileNameSliceOffset;
141     if (this->FilePrefix && this->FilePattern)
142     {
143       size_t size = strlen(this->FilePrefix) + strlen(this->FilePattern) + 10;
144       this->InternalFileName = new char [size];
145       snprintf (this->InternalFileName, size, this->FilePattern,
146                 this->FilePrefix, slicenum);
147     }
148     else if (this->FilePattern)
149     {
150       size_t size = strlen(this->FilePattern) + 10;
151       this->InternalFileName = new char [size];
152       int len = static_cast<int>(strlen(this->FilePattern));
153       int hasPercentS = 0;
154       for(int i =0; i < len-1; ++i)
155       {
156         if(this->FilePattern[i] == '%' && this->FilePattern[i+1] == 's')
157         {
158           hasPercentS = 1;
159           break;
160         }
161       }
162       if(hasPercentS)
163       {
164         snprintf (this->InternalFileName, size, this->FilePattern, "", slicenum);
165       }
166       else
167       {
168         snprintf (this->InternalFileName, size, this->FilePattern, slicenum);
169       }
170     }
171     else
172     {
173       delete [] this->InternalFileName;
174       this->InternalFileName = nullptr;
175     }
176   }
177 }
178 
179 
180 //----------------------------------------------------------------------------
181 // This function sets the name of the file.
SetFileName(const char * name)182 void vtkImageReader2::SetFileName(const char *name)
183 {
184   if ( this->FileName && name && (!strcmp(this->FileName,name)))
185   {
186     return;
187   }
188   if (!name && !this->FileName)
189   {
190     return;
191   }
192   delete [] this->FileName;
193   this->FileName = nullptr;
194   if (name)
195   {
196     this->FileName = new char[strlen(name) + 1];
197     strcpy(this->FileName, name);
198 
199     delete [] this->FilePrefix;
200     this->FilePrefix = nullptr;
201     if (this->FileNames)
202     {
203       this->FileNames->Delete();
204       this->FileNames = nullptr;
205     }
206   }
207 
208   this->Modified();
209 }
210 
211 //----------------------------------------------------------------------------
212 // This function sets an array containing file names
SetFileNames(vtkStringArray * filenames)213 void vtkImageReader2::SetFileNames(vtkStringArray *filenames)
214 {
215   if (filenames == this->FileNames)
216   {
217     return;
218   }
219   if (this->FileNames)
220   {
221     this->FileNames->Delete();
222     this->FileNames = nullptr;
223   }
224   if (filenames)
225   {
226     this->FileNames = filenames;
227     this->FileNames->Register(this);
228     if (this->FileNames->GetNumberOfValues() > 0)
229     {
230       this->DataExtent[4] = 0;
231       this->DataExtent[5] = this->FileNames->GetNumberOfValues() - 1;
232     }
233     delete [] this->FilePrefix;
234     this->FilePrefix = nullptr;
235     delete [] this->FileName;
236     this->FileName = nullptr;
237   }
238 
239   this->Modified();
240 }
241 
242 //----------------------------------------------------------------------------
243 // This function sets the prefix of the file name. "image" would be the
244 // name of a series: image.1, image.2 ...
SetFilePrefix(const char * prefix)245 void vtkImageReader2::SetFilePrefix(const char *prefix)
246 {
247   if ( this->FilePrefix && prefix && (!strcmp(this->FilePrefix,prefix)))
248   {
249     return;
250   }
251   if (!prefix && !this->FilePrefix)
252   {
253     return;
254   }
255   delete [] this->FilePrefix;
256   this->FilePrefix = nullptr;
257   if (prefix)
258   {
259     this->FilePrefix = new char[strlen(prefix) + 1];
260     strcpy(this->FilePrefix, prefix);
261 
262     delete [] this->FileName;
263     this->FileName = nullptr;
264     if (this->FileNames)
265     {
266       this->FileNames->Delete();
267       this->FileNames = nullptr;
268     }
269   }
270 
271   this->Modified();
272 }
273 
274 //----------------------------------------------------------------------------
275 // This function sets the pattern of the file name which turn a prefix
276 // into a file name. "%s.%03d" would be the
277 // pattern of a series: image.001, image.002 ...
SetFilePattern(const char * pattern)278 void vtkImageReader2::SetFilePattern(const char *pattern)
279 {
280   if ( this->FilePattern && pattern &&
281        (!strcmp(this->FilePattern,pattern)))
282   {
283     return;
284   }
285   if (!pattern && !this->FilePattern)
286   {
287     return;
288   }
289   delete [] this->FilePattern;
290   this->FilePattern = nullptr;
291   if (pattern)
292   {
293     this->FilePattern = new char[strlen(pattern) + 1];
294     strcpy(this->FilePattern, pattern);
295 
296     delete [] this->FileName;
297     this->FileName = nullptr;
298     if (this->FileNames)
299     {
300       this->FileNames->Delete();
301       this->FileNames = nullptr;
302     }
303   }
304 
305   this->Modified();
306 }
307 
308 //----------------------------------------------------------------------------
SetDataByteOrderToBigEndian()309 void vtkImageReader2::SetDataByteOrderToBigEndian()
310 {
311 #ifndef VTK_WORDS_BIGENDIAN
312   this->SwapBytesOn();
313 #else
314   this->SwapBytesOff();
315 #endif
316 }
317 
318 //----------------------------------------------------------------------------
SetDataByteOrderToLittleEndian()319 void vtkImageReader2::SetDataByteOrderToLittleEndian()
320 {
321 #ifdef VTK_WORDS_BIGENDIAN
322   this->SwapBytesOn();
323 #else
324   this->SwapBytesOff();
325 #endif
326 }
327 
328 //----------------------------------------------------------------------------
SetDataByteOrder(int byteOrder)329 void vtkImageReader2::SetDataByteOrder(int byteOrder)
330 {
331   if ( byteOrder == VTK_FILE_BYTE_ORDER_BIG_ENDIAN )
332   {
333     this->SetDataByteOrderToBigEndian();
334   }
335   else
336   {
337     this->SetDataByteOrderToLittleEndian();
338   }
339 }
340 
341 //----------------------------------------------------------------------------
GetDataByteOrder()342 int vtkImageReader2::GetDataByteOrder()
343 {
344 #ifdef VTK_WORDS_BIGENDIAN
345   if ( this->SwapBytes )
346   {
347     return VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN;
348   }
349   else
350   {
351     return VTK_FILE_BYTE_ORDER_BIG_ENDIAN;
352   }
353 #else
354   if ( this->SwapBytes )
355   {
356     return VTK_FILE_BYTE_ORDER_BIG_ENDIAN;
357   }
358   else
359   {
360     return VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN;
361   }
362 #endif
363 }
364 
365 //----------------------------------------------------------------------------
GetDataByteOrderAsString()366 const char *vtkImageReader2::GetDataByteOrderAsString()
367 {
368 #ifdef VTK_WORDS_BIGENDIAN
369   if ( this->SwapBytes )
370   {
371     return "LittleEndian";
372   }
373   else
374   {
375     return "BigEndian";
376   }
377 #else
378   if ( this->SwapBytes )
379   {
380     return "BigEndian";
381   }
382   else
383   {
384     return "LittleEndian";
385   }
386 #endif
387 }
388 
389 
390 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)391 void vtkImageReader2::PrintSelf(ostream& os, vtkIndent indent)
392 {
393   int idx;
394 
395   this->Superclass::PrintSelf(os,indent);
396 
397   // this->File, this->Colors need not be printed
398   os << indent << "FileName: " <<
399     (this->FileName ? this->FileName : "(none)") << "\n";
400   os << indent << "FileNames: " << this->FileNames << "\n";
401   os << indent << "FilePrefix: " <<
402     (this->FilePrefix ? this->FilePrefix : "(none)") << "\n";
403   os << indent << "FilePattern: " <<
404     (this->FilePattern ? this->FilePattern : "(none)") << "\n";
405 
406   os << indent << "FileNameSliceOffset: "
407      << this->FileNameSliceOffset << "\n";
408   os << indent << "FileNameSliceSpacing: "
409      << this->FileNameSliceSpacing << "\n";
410 
411   os << indent << "DataScalarType: "
412      << vtkImageScalarTypeNameMacro(this->DataScalarType) << "\n";
413   os << indent << "NumberOfScalarComponents: "
414      << this->NumberOfScalarComponents << "\n";
415 
416   os << indent << "File Dimensionality: " << this->FileDimensionality << "\n";
417 
418   os << indent << "File Lower Left: " <<
419     (this->FileLowerLeft ? "On\n" : "Off\n");
420 
421   os << indent << "Swap Bytes: " << (this->SwapBytes ? "On\n" : "Off\n");
422 
423   os << indent << "DataIncrements: (" << this->DataIncrements[0];
424   for (idx = 1; idx < 2; ++idx)
425   {
426     os << ", " << this->DataIncrements[idx];
427   }
428   os << ")\n";
429 
430   os << indent << "DataExtent: (" << this->DataExtent[0];
431   for (idx = 1; idx < 6; ++idx)
432   {
433     os << ", " << this->DataExtent[idx];
434   }
435   os << ")\n";
436 
437   os << indent << "DataSpacing: (" << this->DataSpacing[0];
438   for (idx = 1; idx < 3; ++idx)
439   {
440     os << ", " << this->DataSpacing[idx];
441   }
442   os << ")\n";
443 
444   os << indent << "DataOrigin: (" << this->DataOrigin[0];
445   for (idx = 1; idx < 3; ++idx)
446   {
447     os << ", " << this->DataOrigin[idx];
448   }
449   os << ")\n";
450 
451   os << indent << "HeaderSize: " << this->HeaderSize << "\n";
452 
453   if ( this->InternalFileName )
454   {
455     os << indent << "Internal File Name: " << this->InternalFileName << "\n";
456   }
457   else
458   {
459     os << indent << "Internal File Name: (none)\n";
460   }
461 }
462 
463 //----------------------------------------------------------------------------
ExecuteInformation()464 void vtkImageReader2::ExecuteInformation()
465 {
466   // this is empty, the idea is that converted filters should implement
467   // RequestInformation. But to help out old filters we will call
468   // ExecuteInformation and hope that the subclasses correctly set the ivars
469   // and not the output.
470 }
471 
472 //----------------------------------------------------------------------------
473 // This method returns the largest data that can be generated.
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)474 int vtkImageReader2::RequestInformation (
475   vtkInformation       * vtkNotUsed( request ),
476   vtkInformationVector** vtkNotUsed( inputVector ),
477   vtkInformationVector * outputVector)
478 {
479   this->SetErrorCode( vtkErrorCode::NoError );
480   // call for backwards compatibility
481   this->ExecuteInformation();
482   // Check for any error set by downstream filter (IO in most case)
483   if ( this->GetErrorCode() )
484   {
485     return 0;
486   }
487 
488   // get the info objects
489   vtkInformation* outInfo = outputVector->GetInformationObject(0);
490 
491   // if a list of file names is supplied, set slice extent
492   if (this->FileNames && this->FileNames->GetNumberOfValues() > 0)
493   {
494     this->DataExtent[4] = 0;
495     this->DataExtent[5] = this->FileNames->GetNumberOfValues()-1;
496   }
497 
498   outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
499                this->DataExtent, 6);
500   outInfo->Set(vtkDataObject::SPACING(), this->DataSpacing, 3);
501   outInfo->Set(vtkDataObject::ORIGIN(),  this->DataOrigin, 3);
502 
503   vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->DataScalarType,
504     this->NumberOfScalarComponents);
505 
506   outInfo->Set(CAN_PRODUCE_SUB_EXTENT(), 1);
507 
508   return 1;
509 }
510 
511 //----------------------------------------------------------------------------
512 // Manual initialization.
SetHeaderSize(unsigned long size)513 void vtkImageReader2::SetHeaderSize(unsigned long size)
514 {
515   if (size != this->HeaderSize)
516   {
517     this->HeaderSize = size;
518     this->Modified();
519   }
520   this->ManualHeaderSize = 1;
521 }
522 
523 
524 //----------------------------------------------------------------------------
525 template <class T>
vtkImageReader2GetSize(T *)526 unsigned long vtkImageReader2GetSize(T*)
527 {
528   return sizeof(T);
529 }
530 
531 //----------------------------------------------------------------------------
532 // This function opens a file to determine the file size, and to
533 // automatically determine the header size.
ComputeDataIncrements()534 void vtkImageReader2::ComputeDataIncrements()
535 {
536   int idx;
537   unsigned long fileDataLength;
538 
539   // Determine the expected length of the data ...
540   switch (this->DataScalarType)
541   {
542     vtkTemplateMacro(
543       fileDataLength = vtkImageReader2GetSize(static_cast<VTK_TT*>(nullptr))
544       );
545     default:
546       vtkErrorMacro(<< "Unknown DataScalarType");
547       return;
548   }
549 
550   fileDataLength *= this->NumberOfScalarComponents;
551 
552   // compute the fileDataLength (in units of bytes)
553   for (idx = 0; idx < 3; ++idx)
554   {
555     this->DataIncrements[idx] = fileDataLength;
556     fileDataLength = fileDataLength *
557       (this->DataExtent[idx*2+1] - this->DataExtent[idx*2] + 1);
558   }
559   this->DataIncrements[3] = fileDataLength;
560 }
561 
562 
563 //----------------------------------------------------------------------------
OpenFile()564 int vtkImageReader2::OpenFile()
565 {
566   if (!this->FileName && !this->FilePattern && !this->FileNames)
567   {
568     vtkErrorMacro(<<"Either a FileName, FileNames, or FilePattern"
569                   << " must be specified.");
570     return 0;
571   }
572 
573   // Close file from any previous image
574   if (this->File)
575   {
576     this->File->close();
577     delete this->File;
578     this->File = nullptr;
579   }
580 
581   // Open the new file
582   vtkDebugMacro(<< "Initialize: opening file " << this->InternalFileName);
583   vtksys::SystemTools::Stat_t fs;
584   if ( !vtksys::SystemTools::Stat( this->InternalFileName, &fs) )
585   {
586 #ifdef _WIN32
587     this->File = new ifstream(this->InternalFileName, ios::in | ios::binary);
588 #else
589     this->File = new ifstream(this->InternalFileName, ios::in);
590 #endif
591   }
592   if (! this->File || this->File->fail())
593   {
594     vtkErrorMacro(<< "Initialize: Could not open file "
595                   << this->InternalFileName);
596     return 0;
597   }
598   return 1;
599 }
600 
601 
602 //----------------------------------------------------------------------------
GetHeaderSize()603 unsigned long vtkImageReader2::GetHeaderSize()
604 {
605   unsigned long firstIdx;
606 
607   if (this->FileNames)
608   {
609     // if FileNames is used, indexing always starts at zero
610     firstIdx = 0;
611   }
612   else
613   {
614     // FilePrefix uses the DataExtent to figure out the first slice index
615     firstIdx = this->DataExtent[4];
616   }
617 
618   return this->GetHeaderSize(firstIdx);
619 }
620 
621 //----------------------------------------------------------------------------
GetHeaderSize(unsigned long idx)622 unsigned long vtkImageReader2::GetHeaderSize(unsigned long idx)
623 {
624   if (!this->FileName && !this->FilePattern)
625   {
626     vtkErrorMacro(<<"Either a FileName or FilePattern must be specified.");
627     return 0;
628   }
629   if ( ! this->ManualHeaderSize)
630   {
631     this->ComputeDataIncrements();
632 
633     // make sure we figure out a filename to open
634     this->ComputeInternalFileName(idx);
635 
636     vtksys::SystemTools::Stat_t statbuf;
637     if (!vtksys::SystemTools::Stat(this->InternalFileName, &statbuf))
638     {
639       return (int)(statbuf.st_size -
640                    (long)this->DataIncrements[this->GetFileDimensionality()]);
641     }
642   }
643 
644   return this->HeaderSize;
645 }
646 
647 //----------------------------------------------------------------------------
SeekFile(int i,int j,int k)648 void vtkImageReader2::SeekFile(int i, int j, int k)
649 {
650   unsigned long streamStart;
651 
652   // convert data extent into constants that can be used to seek.
653   streamStart =
654     (i - this->DataExtent[0]) * this->DataIncrements[0];
655 
656   if (this->FileLowerLeft)
657   {
658     streamStart = streamStart +
659       (j - this->DataExtent[2]) * this->DataIncrements[1];
660   }
661   else
662   {
663     streamStart = streamStart +
664       (this->DataExtent[3] - this->DataExtent[2] - j) *
665       this->DataIncrements[1];
666   }
667 
668   // handle three and four dimensional files
669   if (this->GetFileDimensionality() >= 3)
670   {
671     streamStart = streamStart +
672       (k - this->DataExtent[4]) * this->DataIncrements[2];
673   }
674 
675   streamStart += this->GetHeaderSize(k);
676 
677   // error checking
678   if (!this->File)
679   {
680     vtkWarningMacro(<<"File must be specified.");
681     return;
682   }
683 
684   this->File->seekg((long)streamStart, ios::beg);
685   if (this->File->fail())
686   {
687     vtkWarningMacro("File operation failed.");
688     return;
689   }
690 }
691 
692 //----------------------------------------------------------------------------
693 // This function reads in one data of data.
694 // templated to handle different data types.
695 template <class OT>
vtkImageReader2Update(vtkImageReader2 * self,vtkImageData * data,OT * outPtr)696 void vtkImageReader2Update(vtkImageReader2 *self, vtkImageData *data, OT *outPtr)
697 {
698   vtkIdType outIncr[3];
699   OT *outPtr1, *outPtr2;
700   long streamRead;
701   int idx1, idx2, nComponents;
702   int outExtent[6];
703   unsigned long count = 0;
704   unsigned long target;
705 
706   // Get the requested extents and increments
707   data->GetExtent(outExtent);
708   data->GetIncrements(outIncr);
709   nComponents = data->GetNumberOfScalarComponents();
710 
711   // length of a row, num pixels read at a time
712   int pixelRead = outExtent[1] - outExtent[0] + 1;
713   streamRead = (long)(pixelRead*nComponents*sizeof(OT));
714 
715   // create a buffer to hold a row of the data
716   target = (unsigned long)((outExtent[5]-outExtent[4]+1)*
717                            (outExtent[3]-outExtent[2]+1)/50.0);
718   target++;
719 
720   // read the data row by row
721   if (self->GetFileDimensionality() == 3)
722   {
723     self->ComputeInternalFileName(0);
724     if ( !self->OpenFile() )
725     {
726       return;
727     }
728   }
729   outPtr2 = outPtr;
730   for (idx2 = outExtent[4]; idx2 <= outExtent[5]; ++idx2)
731   {
732     if (self->GetFileDimensionality() == 2)
733     {
734       self->ComputeInternalFileName(idx2);
735       if ( !self->OpenFile() )
736       {
737         return;
738       }
739     }
740     outPtr1 = outPtr2;
741     for (idx1 = outExtent[2];
742          !self->AbortExecute && idx1 <= outExtent[3]; ++idx1)
743     {
744       if (!(count%target))
745       {
746         self->UpdateProgress(count/(50.0*target));
747       }
748       count++;
749 
750       // seek to the correct row
751       self->SeekFile(outExtent[0],idx1,idx2);
752       // read the row.
753       if ( !self->GetFile()->read((char *)outPtr1, streamRead))
754       {
755         vtkGenericWarningMacro("File operation failed. row = " << idx1
756                                << ", Read = " << streamRead
757                                << ", FilePos = " << static_cast<vtkIdType>(self->GetFile()->tellg()));
758         return;
759       }
760       // handle swapping
761       if (self->GetSwapBytes() && sizeof(OT) > 1)
762       {
763         vtkByteSwap::SwapVoidRange(outPtr1, pixelRead*nComponents, sizeof(OT));
764       }
765       outPtr1 += outIncr[1];
766     }
767     // move to the next image in the file and data
768     outPtr2 += outIncr[2];
769   }
770 }
771 
772 //----------------------------------------------------------------------------
773 // This function reads a data from a file.  The datas extent/axes
774 // are assumed to be the same as the file extent/order.
ExecuteDataWithInformation(vtkDataObject * output,vtkInformation * outInfo)775 void vtkImageReader2::ExecuteDataWithInformation(vtkDataObject *output,
776                                                  vtkInformation *outInfo)
777 {
778   vtkImageData *data = this->AllocateOutputData(output, outInfo);
779 
780   void *ptr;
781 
782   if (!this->FileName && !this->FilePattern)
783   {
784     vtkErrorMacro("Either a valid FileName or FilePattern must be specified.");
785     return;
786   }
787 
788   data->GetPointData()->GetScalars()->SetName("ImageFile");
789 
790 #ifndef NDEBUG
791   int *ext = data->GetExtent();
792 #endif
793 
794   vtkDebugMacro("Reading extent: " << ext[0] << ", " << ext[1] << ", "
795         << ext[2] << ", " << ext[3] << ", " << ext[4] << ", " << ext[5]);
796 
797   this->ComputeDataIncrements();
798 
799   // Call the correct templated function for the output
800   ptr = data->GetScalarPointer();
801   switch (this->GetDataScalarType())
802   {
803     vtkTemplateMacro(vtkImageReader2Update(this, data, (VTK_TT *)(ptr)));
804     default:
805       vtkErrorMacro(<< "UpdateFromFile: Unknown data type");
806   }
807 }
808 
809 //----------------------------------------------------------------------------
SetMemoryBuffer(void * membuf)810 void vtkImageReader2::SetMemoryBuffer(void *membuf)
811 {
812   if (this->MemoryBuffer != membuf)
813   {
814     this->MemoryBuffer = membuf;
815     this->Modified();
816   }
817 }
818 
819 //----------------------------------------------------------------------------
SetMemoryBufferLength(vtkIdType buflen)820 void vtkImageReader2::SetMemoryBufferLength(vtkIdType buflen)
821 {
822   if (this->MemoryBufferLength != buflen)
823   {
824     this->MemoryBufferLength = buflen;
825     this->Modified();
826   }
827 }
828 
829 //----------------------------------------------------------------------------
830 // Set the data type of pixels in the file.
831 // If you want the output scalar type to have a different value, set it
832 // after this method is called.
SetDataScalarType(int type)833 void vtkImageReader2::SetDataScalarType(int type)
834 {
835   if (type == this->DataScalarType)
836   {
837     return;
838   }
839 
840   this->Modified();
841   this->DataScalarType = type;
842   // Set the default output scalar type
843   vtkImageData::SetScalarType(this->DataScalarType,
844                               this->GetOutputInformation(0));
845 }
846