1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkImageIOBase_h
19 #define itkImageIOBase_h
20 #include "ITKIOImageBaseExport.h"
21 
22 #include "itkIOConfigure.h"
23 
24 #include "itkLightProcessObject.h"
25 #include "itkIndent.h"
26 #include "itkImageIORegion.h"
27 #include "itkRGBPixel.h"
28 #include "itkRGBAPixel.h"
29 #include "itkCovariantVector.h"
30 #include "itkSymmetricSecondRankTensor.h"
31 #include "itkDiffusionTensor3D.h"
32 #include "itkImageRegionSplitterBase.h"
33 
34 #include "vnl/vnl_vector.h"
35 #include "vcl_compiler.h"
36 
37 #include <fstream>
38 #include <string>
39 
40 namespace itk
41 {
42 // Forward reference for VariableLengthVector
43 template <typename TValue> class VariableLengthVector;
44 
45 /** \class ImageIOBase
46  * \brief Abstract superclass defines image IO interface.
47  *
48  * ImageIOBase is a class that reads and/or writes image data
49  * of a particular format (such as PNG or raw binary). The
50  * ImageIOBase encapsulates both the reading and writing of data. The
51  * ImageIOBase is used by the ImageFileReader class (to read data)
52  * and the ImageFileWriter (to write data) into a single file. The
53  * ImageSeriesReader and ImageSeriesWriter classes are used to read
54  * and write data (in conjunction with ImageIOBase) when the data is
55  * represented by a series of files. Normally the user does not directly
56  * manipulate this class other than to instantiate it, set the FileName,
57  * and assign it to a ImageFileReader/ImageFileWriter or
58  * ImageSeriesReader/ImageSeriesWriter.
59  *
60  * A Pluggable factory pattern is used this allows different kinds of
61  * readers to be registered (even at run time) without having to
62  * modify the code in this class.
63  *
64  * \sa ImageFileWriter
65  * \sa ImageFileReader
66  * \sa ImageSeriesWriter
67  * \sa ImageSeriesReader
68  *
69  * \ingroup IOFilters
70  *
71  * \ingroup ITKIOImageBase
72  */
73 class ITKIOImageBase_EXPORT ImageIOBase:public LightProcessObject
74 {
75 public:
76   ITK_DISALLOW_COPY_AND_ASSIGN(ImageIOBase);
77 
78   /** Standard class type aliases. */
79   using Self = ImageIOBase;
80   using Superclass = LightProcessObject;
81   using Pointer = SmartPointer< Self >;
82   using ConstPointer = SmartPointer< const Self >;
83 
84   /** Run-time type information (and related methods). */
85   itkTypeMacro(ImageIOBase, Superclass);
86 
87   /** Set/Get the name of the file to be read. */
88   itkSetStringMacro(FileName);
89   itkGetStringMacro(FileName);
90 
91   /** Types for managing image size and image index components. */
92   using IndexValueType = ::itk::IndexValueType;
93   using SizeValueType = ::itk::SizeValueType;
94 
95   /**
96    * \class UnknownType
97    * Used to return information when types are unknown.
98    * \ingroup ITKIOImageBase
99    */
100   class UnknownType {};
101 
102   /** Enums used to manipulate the pixel type. The pixel type provides
103    * context for automatic data conversions (for instance, RGB to
104    * SCALAR, VECTOR to SCALAR). */
105   typedef  enum { UNKNOWNPIXELTYPE, SCALAR, RGB, RGBA, OFFSET, VECTOR,
106                   POINT, COVARIANTVECTOR, SYMMETRICSECONDRANKTENSOR,
107                   DIFFUSIONTENSOR3D, COMPLEX, FIXEDARRAY, MATRIX }  IOPixelType;
108 
109   /** Enums used to manipulate the component type. The component type
110    * refers to the actual storage class associated with either a
111    * SCALAR pixel type or elements of a compound pixel.
112    */
113    // NOTE unsigned char, char, and signed char are 3 distinct types in C++
114    // the enum value UCHAR represents 'unsigned char'
115    // the enum value CHAR represents  'signed char'
116    // and the 'char' type maps to one of UCHAR or CHAR based on the platforms 'signededness'
117   typedef  enum { UNKNOWNCOMPONENTTYPE, UCHAR, CHAR, USHORT, SHORT, UINT, INT,
118                   ULONG, LONG, ULONGLONG, LONGLONG, FLOAT, DOUBLE } IOComponentType;
119 
120   /** Set/Get the number of independent variables (dimensions) in the
121    * image being read or written. Note this is not necessarily what
122    * is written, rather the IORegion controls that. */
123   void SetNumberOfDimensions(unsigned int);
124 
125   itkGetConstMacro(NumberOfDimensions, unsigned int);
126 
127   /** Set/Get the image dimensions in the x, y, z, etc. directions.
128    * GetDimensions() is typically used after reading the data; the
129    * SetDimensions() is used prior to writing the data. */
130   virtual void SetDimensions(unsigned int i, SizeValueType dim);
131 
GetDimensions(unsigned int i)132   virtual SizeValueType GetDimensions(unsigned int i) const
133   { return m_Dimensions[i]; }
134 
135   /** Set/Get the image origin on a axis-by-axis basis. The SetOrigin() method
136    * is required when writing the image. */
137   virtual void SetOrigin(unsigned int i, double origin);
138 
GetOrigin(unsigned int i)139   virtual double GetOrigin(unsigned int i) const
140   {
141     return m_Origin[i];
142   }
143 
144   /** Set/Get the image spacing on an axis-by-axis basis. The
145    * SetSpacing() method is required when writing the image. */
146   virtual void SetSpacing(unsigned int i, double spacing);
147 
GetSpacing(unsigned int i)148   virtual double GetSpacing(unsigned int i) const
149   {
150     return m_Spacing[i];
151   }
152 
153   /** Set/Get the image direction on an axis-by-axis basis. The
154    * SetDirection() method is required when writing the image. */
155   virtual void SetDirection(unsigned int i, const std::vector< double > & direction);
156 
157   virtual void SetDirection(unsigned int i, const vnl_vector< double > & direction);
158 
GetDirection(unsigned int i)159   virtual std::vector< double > GetDirection(unsigned int i) const
160   {
161     return m_Direction[i];
162   }
163 
164   /** Return the directions to be assigned by default to recipient
165    *  images whose dimension is smaller than the image dimension in file.  */
166   virtual std::vector< double > GetDefaultDirection(unsigned int i) const;
167 
168   /** Specify the region of the image data to either read or
169    * write. The IORegion specifies the part of the image to read or
170    * write. Regions are defined with an index and a size vector. These
171    * vectors define the start (lower-left corner) and length of the
172    * region within the image. Make sure that the IORegion lies within
173    * the image. */
174   itkSetMacro(IORegion, ImageIORegion);
175   itkGetConstReferenceMacro(IORegion, ImageIORegion);
176 
177   /** Set/Get the type of the pixel. The PixelTypes provides context
178    * to the IO mechanisms for data conversions.  PixelTypes can be
179    * SCALAR, RGB, RGBA, VECTOR, COVARIANTVECTOR, POINT, INDEX. If
180    * the PIXELTYPE is SCALAR, then the NumberOfComponents should be 1.
181    * Any other of PIXELTYPE will have more than one component. */
182   itkSetEnumMacro(PixelType, IOPixelType);
183   itkGetEnumMacro(PixelType, IOPixelType);
184 
185   /** Set/Get the component type of the image. This is always a native
186    * type. */
187   itkSetEnumMacro(ComponentType, IOComponentType);
188   itkGetEnumMacro(ComponentType, IOComponentType);
189   /** get the type_info for the current pixel component type.
190    * This function is DEPRECATED and only provided for backwards
191    * compatibility.  There is no use for this method that can't
192    * be satisfied by calling GetComponentType.
193    */
194   virtual const std::type_info & GetComponentTypeInfo() const;
195 
196   /** Set/Get the number of components per pixel in the image. This may
197    * be set by the reading process. For SCALAR pixel types,
198    * NumberOfComponents will be 1.  For other pixel types,
199    * NumberOfComponents will be greater than or equal to one. */
200   itkSetMacro(NumberOfComponents, unsigned int);
201   itkGetConstReferenceMacro(NumberOfComponents, unsigned int);
202 
203   /** Set/Get a boolean to use the compression or not. */
204   itkSetMacro(UseCompression, bool);
205   itkGetConstMacro(UseCompression, bool);
206   itkBooleanMacro(UseCompression);
207 
208   /** \brief Set/Get a compression level hint
209    *
210    * If compression is enabled by UseCompression, then the value
211    * may be used for as the compression level dependent upon the
212    * compressor.
213    **/
214   itkSetClampMacro(CompressionLevel, int, 1, this->GetMaximumCompressionLevel() );
215   itkGetConstMacro(CompressionLevel, int);
216 
217   /** \brief Set/Get the compression algorithm to use
218    *
219    * If compression is enabled by UseCompression, then the value is
220    * used to select the compression algorithm. An empty string
221    * represent the default compressor. If string identifier is not
222    * recognized a warning is produced and the default is used.
223    *
224    * \nb These compression hints may be ignored if the ImageIO does
225    * not support compression or the compression is not enabled.
226    **/
227   virtual void SetCompressor( std::string _c );
228   itkGetConstReferenceMacro(Compressor, std::string);
229 
230   /** Set/Get a boolean to use streaming while reading or not. */
231   itkSetMacro(UseStreamedReading, bool);
232   itkGetConstMacro(UseStreamedReading, bool);
233   itkBooleanMacro(UseStreamedReading);
234 
235   /** Set/Get a boolean to use streaming while writing or not. */
236   itkSetMacro(UseStreamedWriting, bool);
237   itkGetConstMacro(UseStreamedWriting, bool);
238   itkBooleanMacro(UseStreamedWriting);
239 
240   /** Set/Get a boolean to perform RGB palette expansion.
241     * If true, palette image is read as RGB,
242     * if false, palette image is read as Scalar+Palette.
243     * A RGB image is always read as RGB.*/
244   itkSetMacro(ExpandRGBPalette, bool);
245   itkGetConstMacro(ExpandRGBPalette, bool);
246   itkBooleanMacro(ExpandRGBPalette);
247 
248   /** Determine whether a paletized image file has been read as a scalar image
249    *  plus a color palette.
250    *  ExpandRGBPalette must be set to true, and the file must be a
251    *  palette image file supported for palette reading.*/
252   itkGetConstMacro(IsReadAsScalarPlusPalette, bool);
253 
254   /** Convenience method returns the IOComponentType as a string. This can be
255    * used for writing output files. */
256   static std::string GetComponentTypeAsString(IOComponentType);
257 
258   /** Convenience method returns the IOComponentType corresponding to a string. */
259   static IOComponentType GetComponentTypeFromString(const std::string &typeString);
260 
261   /** Convenience method returns the IOPixelType as a string. This can be
262    * used for writing output files. */
263   static std::string GetPixelTypeAsString(IOPixelType);
264 
265   /** Convenience method returns the IOPixelType corresponding to a string. */
266   static IOPixelType GetPixelTypeFromString(const std::string &pixelString);
267 
268   /** Enums used to specify write style: whether binary or ASCII. Some
269    * subclasses use this, some ignore it. */
270   typedef  enum { ASCII, Binary, TypeNotApplicable } FileType;
271 
272   /** Enums used to specify byte order; whether Big Endian or Little Endian.
273    * Some subclasses use this, some ignore it. */
274   typedef  enum { BigEndian, LittleEndian, OrderNotApplicable } ByteOrder;
275 
276   /** These methods control whether the file is written binary or ASCII.
277    * Many file formats (i.e., subclasses) ignore this flag. */
278   itkSetEnumMacro(FileType, FileType);
279   itkGetEnumMacro(FileType, FileType);
SetFileTypeToASCII()280   void SetFileTypeToASCII()
281   {
282     this->SetFileType(ASCII);
283   }
284 
SetFileTypeToBinary()285   void SetFileTypeToBinary()
286   {
287     this->SetFileType(Binary);
288   }
289 
290   /** These methods indicate the byte ordering of the file you are
291    * trying to read in. These methods will then either swap or not
292    * swap the bytes depending on the byte ordering of the machine it
293    * is being run on. For example, reading in a BigEndian file on a
294    * BigEndian machine will result in no swapping. Trying to read the
295    * same file on a LittleEndian machine will result in swapping.
296    * Note: most UNIX machines are BigEndian while PC's and VAX's are
297    * LittleEndian. So if the file you are reading in was generated on
298    * a VAX or PC, SetByteOrderToLittleEndian() otherwise
299    * SetByteOrderToBigEndian().  Some ImageIOBase subclasses
300    * ignore these methods. */
301   itkSetEnumMacro(ByteOrder, ByteOrder);
302   itkGetEnumMacro(ByteOrder, ByteOrder);
SetByteOrderToBigEndian()303   void SetByteOrderToBigEndian()
304   {
305     this->SetByteOrder(BigEndian);
306   }
307 
SetByteOrderToLittleEndian()308   void SetByteOrderToLittleEndian()
309   {
310     this->SetByteOrder(LittleEndian);
311   }
312 
313   /** Convenience method returns the FileType as a string. This can be
314    * used for writing output files. */
315   std::string GetFileTypeAsString(FileType) const;
316 
317   /** Convenience method returns the ByteOrder as a string. This can be
318    * used for writing output files. */
319   std::string GetByteOrderAsString(ByteOrder) const;
320 
321   /** Type for representing size of bytes, and or positions along a file */
322   using SizeType = ::itk::intmax_t;
323 
324   /** Type for representing size of bytes, and or positions along a memory
325     buffer */
326   using BufferSizeType = ::itk::OffsetValueType;
327 
328   /** Convenient method for accessing the number of bytes to get to
329    * the next pixel. Returns m_Strides[1];
330    *
331    * Please note that this methods depends the private methods
332    * ComputeStrides being called, otherwise this is the incorrect value.
333    */
334   virtual SizeType GetPixelStride() const;
335 
336   /** Return the number of pixels in the image. */
337   SizeType GetImageSizeInPixels() const;
338 
339   /** Return the number of bytes in the image. */
340   SizeType GetImageSizeInBytes() const;
341 
342   /** Return the number of pixels times the number
343    * of components in the image. */
344   SizeType GetImageSizeInComponents() const;
345 
346   /** Compute the size (in bytes) of the components of a pixel. For
347    * example, and RGB pixel of unsigned char would have a
348    * component size of 1 byte. This method can be invoked only after
349    * the component type is set. */
350   virtual unsigned int GetComponentSize() const;
351 
352   /*-------- This part of the interfaces deals with reading data ----- */
353 
354   /** Determine the file type. Returns true if this ImageIO can read the
355    * file specified. */
356   virtual bool CanReadFile(const char *) = 0;
357 
358   /** Determine if the ImageIO can stream reading from the
359       current settings. Default is false. If this is queried after
360       the header of the file has been read then it will indicate if
361       that file can be streamed */
CanStreamRead()362   virtual bool CanStreamRead()
363   {
364     return false;
365   }
366 
367   /** Read the spacing and dimensions of the image.
368    * Assumes SetFileName has been called with a valid file name. */
369   virtual void ReadImageInformation() = 0;
370 
371   /** Reads the data from disk into the memory buffer provided. */
372   virtual void Read(void *buffer) = 0;
373 
374   /*-------- This part of the interfaces deals with writing data ----- */
375 
376   /** Determine the file type. Returns true if this ImageIO can read the
377    * file specified. */
378   virtual bool CanWriteFile(const char *)  = 0;
379 
380   /** Determine if the ImageIO can stream write from the
381    *  current settings.
382    *
383    * There are two types of non exclusive streaming: pasteing subregions, and iterative
384    *
385    */
CanStreamWrite()386   virtual bool CanStreamWrite()
387   {
388     return false;
389   }
390 
391   /** Writes the spacing and dimensions of the image.
392    * Assumes SetFileName has been called with a valid file name. */
393   virtual void WriteImageInformation() = 0;
394 
395   /** Writes the data to disk from the memory buffer provided. Make sure
396    * that the IORegions has been set properly. The buffer is cast to a
397    * pointer to the beginning of the image data. */
398   virtual void Write(const void *buffer) = 0;
399 
400   /* --- Support reading and writing data as a series of files. --- */
401 
402   /** The different types of ImageIO's can support data of varying
403    * dimensionality. For example, some file formats are strictly 2D
404    * while others can support 2D, 3D, or even n-D. This method returns
405    * true/false as to whether the ImageIO can support the dimension
406    * indicated. */
SupportsDimension(unsigned long dim)407   virtual bool SupportsDimension(unsigned long dim)
408   {
409     return ( dim == 2 );
410   }
411 
412   /** Method for supporting streaming.  Given a requested region, determine what
413    * could be the region that we can read from the file. This is called the
414    * streamable region, which will be equal or smaller than the
415    * LargestPossibleRegion (unless it was dimensionaly clipped) and
416    * greater or equal to the RequestedRegion
417    *
418    * the resulting IORegion may be a greater dimensions the the
419    * requested IORegion, if the the derived class is unable to read
420    * the requested region. For example if the file has a size of [ 10,
421    * 10, 10] but the requested region is [10, 10] the return may be 3 dimensions.
422    */
423   virtual ImageIORegion
424   GenerateStreamableReadRegionFromRequestedRegion(const ImageIORegion & requested) const;
425 
426   /** Before this method is called all the configuration will be done,
427    * that is Streaming/PasteRegion/Compression/Filename etc
428    * If pasting is being used the number of requested splits is for that
429    * region not the largest. The derived ImageIO class should verify that
430    * the file is capable of being written with this configuration.
431    * If pasted is enabled and is not support or does not work with the file,
432    * then an excepetion should be thrown.
433    *
434    * The default implementation depends on CanStreamWrite.
435    * If false then 1 is returned (unless pasting is indicated), so that the whole file will be updated in one region.
436    * If true then its assumed that any arbitrary region can be written
437    * to any file. So the users request will be respected. If a derived
438    * class has more restictive conditions then they should be checked
439    */
440   virtual unsigned int GetActualNumberOfSplitsForWriting(unsigned int numberOfRequestedSplits,
441                                                          const ImageIORegion & pasteRegion,
442                                                          const ImageIORegion & largestPossibleRegion);
443 
444   /** returns the ith IORegion
445    *
446    * numberOfActualSplits should be the value returned from GetActualNumberOfSplitsForWriting with the same parameters
447    *
448    * Derieved classes should overload this method to return a compatible region
449    */
450   virtual ImageIORegion GetSplitRegionForWriting(unsigned int ithPiece,
451                                                  unsigned int numberOfActualSplits,
452                                                  const ImageIORegion & pasteRegion,
453                                                  const ImageIORegion & largestPossibleRegion);
454 
455   /** Type for the list of strings to be used for extensions.  */
456   using ArrayOfExtensionsType = std::vector< std::string >;
457 
458   /** This method returns an array with the list of filename extensions
459    * supported for reading by this ImageIO class. This is intended to
460    * facilitate GUI and application level integration.
461    */
462   const ArrayOfExtensionsType & GetSupportedReadExtensions() const;
463 
464   /** This method returns an array with the list of filename extensions
465    * supported for writing by this ImageIO class. This is intended to
466    * facilitate GUI and application level integration.
467    */
468   const ArrayOfExtensionsType & GetSupportedWriteExtensions() const;
469 
470   template <typename TPixel>
471     void SetTypeInfo(const TPixel *);
472 
473   /** Map between C++ Pixel type and ImageIOBase ComponentType */
474   template <typename TPixel>
475     struct MapPixelType
476   {
477     static constexpr IOComponentType CType =
478       UNKNOWNCOMPONENTTYPE;
479   };
480   template <typename TPixel>
SetPixelTypeInfo(const TPixel *)481     void SetPixelTypeInfo(const TPixel *)
482   {
483     this->SetNumberOfComponents(1);
484     this->SetPixelType(SCALAR);
485     this->SetComponentType(MapPixelType<TPixel>::CType);
486   }
487   template <typename TPixel>
SetPixelTypeInfo(const RGBPixel<TPixel> *)488     void SetPixelTypeInfo(const RGBPixel< TPixel > *)
489   {
490     this->SetNumberOfComponents(3);
491     this->SetPixelType(RGB);
492     this->SetComponentType(MapPixelType<TPixel>::CType);
493   }
494   template <typename TPixel>
SetPixelTypeInfo(const RGBAPixel<TPixel> *)495     void SetPixelTypeInfo(const RGBAPixel< TPixel > *)
496   {
497     this->SetNumberOfComponents(4);
498     this->SetPixelType(RGBA);
499     this->SetComponentType(MapPixelType<TPixel>::CType);
500   }
501   template <typename TPixel, unsigned VLength>
SetPixelTypeInfo(const Vector<TPixel,VLength> *)502     void SetPixelTypeInfo(const Vector< TPixel , VLength > *)
503   {
504     this->SetNumberOfComponents(VLength);
505     this->SetPixelType(VECTOR);
506     this->SetComponentType(MapPixelType<TPixel>::CType);
507   }
508   template <typename TPixel>
SetPixelTypeInfo(const VariableLengthVector<TPixel> *)509     void SetPixelTypeInfo(const VariableLengthVector< TPixel > *)
510   {
511     this->SetNumberOfComponents(1);
512     this->SetPixelType(VECTOR);
513     this->SetComponentType(MapPixelType<TPixel>::CType);
514   }
515   template <typename TPixel, unsigned VLength>
SetPixelTypeInfo(const CovariantVector<TPixel,VLength> *)516     void SetPixelTypeInfo(const CovariantVector< TPixel,VLength > *)
517   {
518     this->SetNumberOfComponents(VLength);
519     this->SetPixelType(COVARIANTVECTOR);
520     this->SetComponentType(MapPixelType<TPixel>::CType);
521   }
522   template <typename TPixel,unsigned VLength>
SetPixelTypeInfo(const FixedArray<TPixel,VLength> *)523     void SetPixelTypeInfo(const FixedArray< TPixel,VLength > *)
524   {
525     this->SetNumberOfComponents(VLength);
526     this->SetPixelType(COVARIANTVECTOR);
527     this->SetComponentType(MapPixelType<TPixel>::CType);
528   }
529 
530   template <typename TPixel, unsigned VLength>
SetPixelTypeInfo(const SymmetricSecondRankTensor<TPixel,VLength> *)531     void SetPixelTypeInfo(const SymmetricSecondRankTensor<TPixel,VLength> *)
532   {
533     this->SetNumberOfComponents(VLength * (VLength + 1) / 2 );
534     this->SetPixelType(SYMMETRICSECONDRANKTENSOR);
535     this->SetComponentType(MapPixelType<TPixel>::CType);
536   }
537 
538   template <typename TPixel>
SetPixelTypeInfo(const DiffusionTensor3D<TPixel> *)539     inline void SetPixelTypeInfo(const DiffusionTensor3D< TPixel > *)
540   {
541     this->SetNumberOfComponents(6);
542     this->SetPixelType(DIFFUSIONTENSOR3D);
543     this->SetComponentType(MapPixelType<TPixel>::CType);
544     }
545 
546   template <typename TPixel, unsigned VLength>
SetPixelTypeInfo(const Matrix<TPixel,VLength,VLength> *)547     void SetPixelTypeInfo(const Matrix< TPixel,VLength, VLength > *)
548   {
549     this->SetNumberOfComponents(VLength * VLength);
550     this->SetPixelType(MATRIX);
551     this->SetComponentType(MapPixelType<TPixel>::CType);
552   }
553 
554   template <typename TPixel>
SetPixelTypeInfo(const std::complex<TPixel> *)555     void SetPixelTypeInfo(const std::complex< TPixel > *)
556   {
557     this->SetNumberOfComponents(2);
558     this->SetPixelType(COMPLEX);
559     this->SetComponentType(MapPixelType<TPixel>::CType);
560   }
561 
562   template <unsigned VLength>
SetPixelTypeInfo(const Offset<VLength> *)563     void SetPixelTypeInfo(const Offset< VLength > *)
564   {
565     this->SetNumberOfComponents(VLength);
566     this->SetPixelType(ImageIOBase::OFFSET);
567     this->SetComponentType(ImageIOBase::LONG);
568   }
569 
570 protected:
571   ImageIOBase();
572   ~ImageIOBase() override;
573   void PrintSelf(std::ostream & os, Indent indent) const override;
574 
575   virtual const ImageRegionSplitterBase* GetImageRegionSplitter() const;
576 
577   /** Check fileName as an extensions contained in the supported
578    * extension list. If ignoreCase is true, the case of the characters
579    * is ignored.
580    */
581   virtual bool HasSupportedReadExtension( const char * fileName, bool ignoreCase = true );
582   virtual bool HasSupportedWriteExtension( const char * fileName, bool ignoreCase = true );
583 
584   /** Used internally to keep track of the type of the pixel. */
585   IOPixelType m_PixelType{SCALAR};
586 
587   /** Used internally to keep track of the type of the component. It is set
588    * when ComputeStrides() is invoked. */
589   IOComponentType m_ComponentType{UNKNOWNCOMPONENTTYPE};
590 
591   /** Big or Little Endian, and the type of the file. (May be ignored.) */
592   ByteOrder m_ByteOrder{OrderNotApplicable};
593 
594   FileType m_FileType{TypeNotApplicable};
595 
596   /** Does the ImageIOBase object have enough info to be of use? */
597   bool m_Initialized;
598 
599   /** Filename to read */
600   std::string m_FileName;
601 
602   /** Stores the number of components per pixel. This will be 1 for
603    * grayscale images, 3 for RGBPixel images, and 4 for RGBPixelA images. */
604   unsigned int m_NumberOfComponents;
605 
606   /** The number of independent dimensions in the image. */
607   unsigned int m_NumberOfDimensions{0};
608 
609   /** Should we compress the data? */
610   bool m_UseCompression{false};
611 
612 
613   int m_CompressionLevel{30};
614   int m_MaximumCompressionLevel{100};
615   std::string m_Compressor{"uninitialized"};
616 
617   /** Set/Get enforced maximum compression level value to limit range  */
618   virtual void SetMaximumCompressionLevel(int);
619   itkGetConstMacro(MaximumCompressionLevel, int);
620 
621   /** Called when the compressor changes value. The compressor string
622    * is converted to uppercase for case insensitive comparisons.
623    **/
624   virtual void InternalSetCompressor(const std::string &COMPRESSOR);
625 
626   /** Should we use streaming for reading */
627   bool m_UseStreamedReading;
628 
629   /** Should we use streaming for writing */
630   bool m_UseStreamedWriting;
631 
632   /** Should we expand RGB palette or stay scalar */
633   bool m_ExpandRGBPalette;
634 
635   /** true if a RGB palette has been read and the image
636     * kept scalar */
637   bool m_IsReadAsScalarPlusPalette;
638 
639   /** The region to read or write. The region contains information about the
640    * data within the region to read or write. */
641   ImageIORegion m_IORegion;
642 
643   /** The array which stores the number of pixels in the x, y, z directions. */
644   std::vector< SizeValueType > m_Dimensions;
645 
646   /** The array which stores the spacing of pixels in the
647    * x, y, z directions. */
648   std::vector< double > m_Spacing;
649 
650   /** The array which stores the origin of the image. */
651   std::vector< double > m_Origin;
652 
653   /** The arrays which store the direction cosines of the image. */
654   std::vector< std::vector< double > > m_Direction;
655 
656   /** Stores the number of bytes it takes to get to the next 'thing'
657    * e.g. component, pixel, row, slice, etc. */
658   std::vector< SizeType > m_Strides;
659 
660   /** Return the object to an initialized state, ready to be used */
661   virtual void Reset(const bool freeDynamic = true);
662 
663   /** Resize the ImageIOBase object to new dimensions. */
664   void Resize(const unsigned int numDimensions,
665               const unsigned int *dimensions);
666 
667   /** Compute the size (in bytes) of the pixel. For
668    * example, and RGB pixel of unsigned char would have size 3 bytes. */
669   virtual unsigned int GetPixelSize() const;
670 
671   /** Calculates the different strides (distance from one thing to the next).
672    * Upon return,
673    * strides[0] = bytes to get to the next component of a pixel,
674    * strides[1] = bytes to get to the next pixel in x direction,
675    * strides[2] = bytes to get to the next row in y direction,
676    * strides[3] = bytes to get to the next slice in z direction, etc. */
677   void ComputeStrides();
678 
679   /** Convenient method for accessing number of bytes to get to the next pixel
680    * component. Returns m_Strides[0]. */
681   SizeType GetComponentStride() const;
682 
683   /** Convenient method for accessing the number of bytes to get to the
684    * next row. Returns m_Strides[2]. */
685   SizeType GetRowStride() const;
686 
687   /** Convenient method for accessing the number of bytes to get to the
688    * next slice. Returns m_Strides[3]. */
689   SizeType GetSliceStride() const;
690 
691   /** \brief Opens a file for reading and random access
692    *
693    * \param[out] inputStream is an istream presumed to be opened for reading
694    * \param[in] filename is the name of the file
695    * \param[in] ascii optional (default is false);
696    *                  if true than the file will be opened in ASCII mode,
697    *                  which generally only applies to Windows
698    *
699    * The stream is closed if it's already opened. If an error is
700    * encountered than an exception will be thrown.
701    */
702   virtual void OpenFileForReading(std::ifstream & inputStream, const std::string & filename,
703                                   bool ascii = false);
704 
705   /** \brief Opens a file for writing and random access
706    *
707    * \param[out] outputStream is an ostream presumed to be opened for writing
708    * \param[in] filename is the name of the file
709    * \param[in] truncate optional (default is true);
710    *                     if true than the file's existing content is truncated,
711    *                     if false than the file is opened for reading and
712    *                     writing with existing content intact
713    * \param[in] ascii optional (default is false);
714    *                  if true than the file will be opened in ASCII mode,
715    *                  which generally only applies to Windows
716    *
717    * The stream is closed if it's already opened. If an error is
718    * encountered than an exception will be thrown.
719    */
720   virtual void OpenFileForWriting(std::ofstream & outputStream, const std::string & filename,
721                                   bool truncate = true, bool ascii = false);
722 
723   /** Convenient method to write a buffer as ASCII text. */
724   virtual void WriteBufferAsASCII(std::ostream & os, const void *buffer,
725                           IOComponentType ctype,
726                           SizeType numberOfBytesToWrite);
727 
728   /** Convenient method to read a buffer as ASCII text. */
729   virtual void ReadBufferAsASCII(std::istream & os, void *buffer,
730                          IOComponentType ctype,
731                          SizeType numberOfBytesToBeRead);
732 
733   /** Convenient method to read a buffer as binary. Return true on success. */
734   bool ReadBufferAsBinary(std::istream & os, void *buffer, SizeType numberOfBytesToBeRead);
735 
736   /** Insert an extension to the list of supported extensions for reading. */
737   void AddSupportedReadExtension(const char *extension);
738 
739   /** Insert an extension to the list of supported extensions for writing. */
740   void AddSupportedWriteExtension(const char *extension);
741 
742   /** an implementation of ImageRegionSplitter:GetNumberOfSplits
743    */
744   virtual unsigned int GetActualNumberOfSplitsForWritingCanStreamWrite(unsigned int numberOfRequestedSplits,
745                                                                        const ImageIORegion & pasteRegion) const;
746 
747   /** an implementation of  ImageRegionSplitter:GetSplit
748    */
749   virtual ImageIORegion GetSplitRegionForWritingCanStreamWrite(unsigned int ithPiece,
750                                                                unsigned int numberOfActualSplits,
751                                                                const ImageIORegion & pasteRegion) const;
752 
753 private:
754 
755   bool HasSupportedExtension( const char * , const ArrayOfExtensionsType &, bool tolower = true );
756 
757   ArrayOfExtensionsType m_SupportedReadExtensions;
758   ArrayOfExtensionsType m_SupportedWriteExtensions;
759 };
760 
761 #define IMAGEIOBASE_TYPEMAP(type,ctype)                         \
762   template <> struct ImageIOBase::MapPixelType<type>    \
763   {                                                     \
764     static constexpr IOComponentType CType = ctype; \
765   }
766 
767 // the following typemaps are not platform independent
768 IMAGEIOBASE_TYPEMAP(signed char, IOComponentType::CHAR);
769 IMAGEIOBASE_TYPEMAP(char, std::numeric_limits<char>::is_signed ? IOComponentType::CHAR : IOComponentType::UCHAR);
770 IMAGEIOBASE_TYPEMAP(unsigned char, IOComponentType::UCHAR);
771 IMAGEIOBASE_TYPEMAP(short, IOComponentType::SHORT);
772 IMAGEIOBASE_TYPEMAP(unsigned short, IOComponentType::USHORT);
773 IMAGEIOBASE_TYPEMAP(int, IOComponentType::INT);
774 IMAGEIOBASE_TYPEMAP(unsigned int, IOComponentType::UINT);
775 IMAGEIOBASE_TYPEMAP(long, IOComponentType::LONG);
776 IMAGEIOBASE_TYPEMAP(unsigned long, IOComponentType::ULONG);
777 IMAGEIOBASE_TYPEMAP(long long, IOComponentType::LONGLONG);
778 IMAGEIOBASE_TYPEMAP(unsigned long long, IOComponentType::ULONGLONG);
779 IMAGEIOBASE_TYPEMAP(float, IOComponentType::FLOAT);
780 IMAGEIOBASE_TYPEMAP(double, IOComponentType::DOUBLE);
781 #undef IMAGIOBASE_TYPEMAP
782 
783 } // end namespace itk
784 
785 #endif // itkImageIOBase_h
786