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