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 itkMeshIOBase_h 19 #define itkMeshIOBase_h 20 #include "ITKIOMeshBaseExport.h" 21 22 #include "itkByteSwapper.h" 23 #include "itkCellInterface.h" 24 #include "itkCovariantVector.h" 25 #include "itkDiffusionTensor3D.h" 26 #include "itkIntTypes.h" 27 #include "itkLightProcessObject.h" 28 #include "itkMatrix.h" 29 #include "itkRGBPixel.h" 30 #include "itkRGBAPixel.h" 31 #include "itkSymmetricSecondRankTensor.h" 32 #include "itkVariableLengthVector.h" 33 #include "itkVariableSizeMatrix.h" 34 #include "itkVector.h" 35 #include "itkNumberToString.h" 36 37 #include <string> 38 #include <complex> 39 #include <fstream> 40 41 namespace itk 42 { 43 /** \class MeshIOBase 44 * \brief Abstract superclass defines mesh IO interface. 45 * 46 * MeshIOBase is a class that reads and/or writes Mesh / QuadEdgeMesh data 47 * of a particular format (such as PNG or raw binary). The 48 * MeshIOBase encapsulates both the reading and writing of data. The 49 * MeshIOBase is used by the MeshFileReader class (to read data) 50 * and the MeshFileWriter (to write data) into a single file. 51 * Normally the user does not directly 52 * manipulate this class other than to instantiate it, set the FileName, 53 * and assign it to a MeshFileReader or MeshFileWriter. 54 * 55 * A Pluggable factory pattern is used this allows different kinds of readers 56 * to be registered (even at run time) without having to modify the 57 * code in this class. 58 * 59 * \author Wanlin Zhu. Uviversity of New South Wales, Australia. 60 * 61 * \sa MeshFileWriter 62 * \sa MeshFileReader 63 * 64 * \ingroup IOFilters 65 * \ingroup ITKIOMeshBase 66 * 67 */ 68 69 class ITKIOMeshBase_EXPORT MeshIOBase:public LightProcessObject 70 { 71 public: 72 ITK_DISALLOW_COPY_AND_ASSIGN(MeshIOBase); 73 74 /** Standard class type aliases. */ 75 using Self = MeshIOBase; 76 using Superclass = LightProcessObject; 77 using ConstPointer = SmartPointer< const Self >; 78 using Pointer = SmartPointer< Self >; 79 80 /** Type for the list of strings to be used for extensions. */ 81 using ArrayOfExtensionsType = std::vector< std::string >; 82 83 /** Type for representing size of bytes, and or positions along a file */ 84 using StreamOffsetType = std::streamoff; 85 86 using SizeValueType = IdentifierType; 87 88 /** 89 * \class UnknownType 90 * Used to return information when types are unknown. 91 * \ingroup ITKIOMeshBase 92 */ 93 class UnknownType {}; 94 95 /** Run-time type information (and related methods). */ 96 itkTypeMacro(MeshIOBase, LightProcessObject); 97 98 /** Set/Get the name of the file to be read. */ 99 itkSetStringMacro(FileName); 100 itkGetStringMacro(FileName); 101 102 /** Enums used to manipulate the point/cell 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, ARRAY, MATRIX, 108 VARIABLELENGTHVECTOR, VARIABLESIZEMATRIX} IOPixelType; 109 110 /** Enums used to manipulate the component type. The component type 111 * refers to the actual storage class associated with either a 112 * SCALAR pixel type or elements of a compound pixel. */ 113 typedef enum {UNKNOWNCOMPONENTTYPE, UCHAR, CHAR, USHORT, SHORT, UINT, INT, 114 ULONG, LONG, LONGLONG, ULONGLONG, FLOAT, DOUBLE, LDOUBLE} IOComponentType; 115 116 /** Enums used to specify write style: whether binary or ASCII. Some 117 * subclasses use this, some ignore it. */ 118 typedef enum {ASCII, BINARY, TYPENOTAPPLICABLE} FileType; 119 120 /** Enums used to specify byte order; whether Big Endian or Little Endian. 121 * Some subclasses use this, some ignore it. */ 122 typedef enum {BigEndian, LittleEndian, OrderNotApplicable} ByteOrder; 123 124 /** Enums used to specify cell type */ 125 typedef enum {VERTEX_CELL = 0, LINE_CELL, TRIANGLE_CELL, 126 QUADRILATERAL_CELL, POLYGON_CELL, TETRAHEDRON_CELL, HEXAHEDRON_CELL, 127 QUADRATIC_EDGE_CELL, QUADRATIC_TRIANGLE_CELL, 128 LAST_ITK_CELL, MAX_ITK_CELLS = 255} CellGeometryType; 129 130 /** Set/Get the type of the point/cell pixel. The PixelTypes provides context 131 * to the IO mechanisms for data conversions. PixelTypes can be 132 * SCALAR, RGB, RGBA, VECTOR, COVARIANTVECTOR, POINT, INDEX. If 133 * the PIXELTYPE is SCALAR, then the NumberOfComponents should be 1. 134 * Any other of PIXELTYPE will have more than one component. */ 135 itkSetEnumMacro(PointPixelType, IOPixelType); 136 itkGetEnumMacro(PointPixelType, IOPixelType); 137 itkSetEnumMacro(CellPixelType, IOPixelType); 138 itkGetEnumMacro(CellPixelType, IOPixelType); 139 140 /** Set/Get the component type of the point, cell, point data and cell data. 141 This is always a native type. */ 142 itkSetEnumMacro(PointComponentType, IOComponentType); 143 itkGetEnumMacro(PointComponentType, IOComponentType); 144 itkSetEnumMacro(CellComponentType, IOComponentType); 145 itkGetEnumMacro(CellComponentType, IOComponentType); 146 itkSetEnumMacro(PointPixelComponentType, IOComponentType); 147 itkGetEnumMacro(PointPixelComponentType, IOComponentType); 148 itkSetEnumMacro(CellPixelComponentType, IOComponentType); 149 itkGetEnumMacro(CellPixelComponentType, IOComponentType); 150 151 template< typename T > 152 struct MapComponentType { 153 static constexpr IOComponentType CType = UNKNOWNCOMPONENTTYPE; 154 }; 155 156 template< typename T > 157 void SetPixelType(const T & itkNotUsed(dummy), bool UsePointPixel = true) 158 { 159 if ( UsePointPixel ) 160 { 161 SetNumberOfPointPixelComponents(1); 162 SetPointPixelComponentType(MapComponentType< T >::CType); 163 SetPointPixelType(SCALAR); 164 } 165 else 166 { 167 SetNumberOfCellPixelComponents(1); 168 SetCellPixelComponentType(MapComponentType< T >::CType); 169 SetCellPixelType(SCALAR); 170 } 171 } 172 173 template< typename T > 174 void SetPixelType(const RGBPixel< T > & itkNotUsed(dummy), bool UsePointPixel = true) 175 { 176 if ( UsePointPixel ) 177 { 178 SetNumberOfPointPixelComponents(3); 179 SetPointPixelComponentType(MapComponentType< T >::CType); 180 SetPointPixelType(RGB); 181 } 182 else 183 { 184 SetNumberOfCellPixelComponents(3); 185 SetCellPixelComponentType(MapComponentType< T >::CType); 186 SetCellPixelType(RGB); 187 } 188 } 189 190 template< typename T > 191 void SetPixelType(const RGBAPixel< T > & itkNotUsed(dummy), bool UsePointPixel = true) 192 { 193 if ( UsePointPixel ) 194 { 195 SetNumberOfPointPixelComponents(4); 196 SetPointPixelComponentType(MapComponentType< T >::CType); 197 SetPointPixelType(RGBA); 198 } 199 else 200 { 201 SetNumberOfCellPixelComponents(4); 202 SetCellPixelComponentType(MapComponentType< T >::CType); 203 SetCellPixelType(RGBA); 204 } 205 } 206 207 template< typename T, unsigned int VLength > 208 void SetPixelType(const Vector< T, VLength > & itkNotUsed(dummy), bool UsePointPixel = true) 209 { 210 if ( UsePointPixel ) 211 { 212 SetNumberOfPointPixelComponents(VLength); 213 SetPointPixelComponentType(MapComponentType< T >::CType); 214 SetPointPixelType(VECTOR); 215 } 216 else 217 { 218 SetNumberOfCellPixelComponents(VLength); 219 SetCellPixelComponentType(MapComponentType< T >::CType); 220 SetCellPixelType(VECTOR); 221 } 222 } 223 224 template< typename T, unsigned int VLength > 225 void SetPixelType(const CovariantVector< T, VLength > & itkNotUsed(dummy), bool UsePointPixel = true) 226 { 227 if ( UsePointPixel ) 228 { 229 SetNumberOfPointPixelComponents(VLength); 230 SetPointPixelComponentType(MapComponentType< T >::CType); 231 SetPointPixelType(COVARIANTVECTOR); 232 } 233 else 234 { 235 SetNumberOfCellPixelComponents(VLength); 236 SetCellPixelComponentType(MapComponentType< T >::CType); 237 SetCellPixelType(COVARIANTVECTOR); 238 } 239 } 240 241 template< typename T, unsigned int VLength > 242 void SetPixelType(const FixedArray< T, VLength > & itkNotUsed(dummy), bool UsePointPixel = true) 243 { 244 if ( UsePointPixel ) 245 { 246 SetNumberOfPointPixelComponents(VLength); 247 SetPointPixelComponentType(MapComponentType< T >::CType); 248 SetPointPixelType(FIXEDARRAY); 249 } 250 else 251 { 252 SetNumberOfCellPixelComponents(VLength); 253 SetCellPixelComponentType(MapComponentType< T >::CType); 254 SetCellPixelType(FIXEDARRAY); 255 } 256 } 257 258 template< typename T, unsigned int VLength > 259 void SetPixelType(const SymmetricSecondRankTensor< T, VLength > itkNotUsed(dummy), bool UsePointPixel = true) 260 { 261 if ( UsePointPixel ) 262 { 263 SetNumberOfPointPixelComponents(VLength * ( VLength + 1 ) / 2); 264 SetPointPixelComponentType(MapComponentType< T >::CType); 265 SetPointPixelType(SYMMETRICSECONDRANKTENSOR); 266 } 267 else 268 { 269 SetNumberOfCellPixelComponents(VLength * ( VLength + 1 ) / 2); 270 SetCellPixelComponentType(MapComponentType< T >::CType); 271 SetCellPixelType(SYMMETRICSECONDRANKTENSOR); 272 } 273 } 274 275 template< typename T > 276 void SetPixelType(const DiffusionTensor3D< T > & itkNotUsed(dummy), bool UsePointPixel = true) 277 { 278 if ( UsePointPixel ) 279 { 280 SetNumberOfPointPixelComponents(6); 281 SetPointPixelComponentType(MapComponentType< T >::CType); 282 SetPointPixelType(DIFFUSIONTENSOR3D); 283 } 284 else 285 { 286 SetNumberOfCellPixelComponents(6); 287 SetCellPixelComponentType(MapComponentType< T >::CType); 288 SetCellPixelType(DIFFUSIONTENSOR3D); 289 } 290 } 291 292 template< typename T, unsigned int NR, unsigned int NC > 293 void SetPixelType(const Matrix< T, NR, NC > & itkNotUsed(dummy), bool UsePointPixel = true) 294 { 295 if ( UsePointPixel ) 296 { 297 SetNumberOfPointPixelComponents(NR * NC); 298 SetPointPixelComponentType(MapComponentType< T >::CType); 299 SetPointPixelType(MATRIX); 300 } 301 else 302 { 303 SetNumberOfCellPixelComponents(NR * NC); 304 SetCellPixelComponentType(MapComponentType< T >::CType); 305 SetCellPixelType(MATRIX); 306 } 307 } 308 309 template< typename T > 310 void SetPixelType(const std::complex< T > & itkNotUsed(dummy), bool UsePointPixel = true) 311 { 312 if ( UsePointPixel ) 313 { 314 SetNumberOfPointPixelComponents(2); 315 SetPointPixelComponentType(MapComponentType< T >::CType); 316 SetPointPixelType(COMPLEX); 317 } 318 else 319 { 320 SetNumberOfCellPixelComponents(2); 321 SetCellPixelComponentType(MapComponentType< T >::CType); 322 SetCellPixelType(COMPLEX); 323 } 324 } 325 326 template< typename T > 327 void SetPixelType(const Array< T > & array, bool UsePointPixel = true) 328 { 329 if ( UsePointPixel ) 330 { 331 SetNumberOfPointPixelComponents( array.Size() ); 332 SetPointPixelComponentType(MapComponentType< T >::CType); 333 SetPointPixelType(ARRAY); 334 } 335 else 336 { 337 SetNumberOfCellPixelComponents( array.Size() ); 338 SetCellPixelComponentType(MapComponentType< T >::CType); 339 SetCellPixelType(ARRAY); 340 } 341 } 342 343 template< typename T > 344 void SetPixelType(const VariableLengthVector< T > & vector, bool UsePointPixel = true) 345 { 346 if ( UsePointPixel ) 347 { 348 SetNumberOfPointPixelComponents( vector.Size() ); 349 SetPointPixelComponentType(MapComponentType< T >::CType); 350 SetPointPixelType(VARIABLELENGTHVECTOR); 351 } 352 else 353 { 354 SetNumberOfCellPixelComponents( vector.Size() ); 355 SetCellPixelComponentType(MapComponentType< T >::CType); 356 SetCellPixelType(VARIABLELENGTHVECTOR); 357 } 358 } 359 360 template< typename T > 361 void SetPixelType(const VariableSizeMatrix< T > & matrix, bool UsePointPixel = true) 362 { 363 if ( UsePointPixel ) 364 { 365 SetNumberOfPointPixelComponents( matrix.Rows() * matrix.Cols() ); 366 SetPointPixelComponentType(MapComponentType< T >::CType); 367 SetPointPixelType(VARIABLESIZEMATRIX); 368 } 369 else 370 { 371 SetNumberOfCellPixelComponents( matrix.Rows() * matrix.Cols() ); 372 SetCellPixelComponentType(MapComponentType< T >::CType); 373 SetCellPixelType(VARIABLESIZEMATRIX); 374 } 375 } 376 377 /** Set/Get the number of components per pixel in the mesh. This may 378 * be set by the reading process. For SCALAR pixel types, 379 * NumberOfComponents will be 1. For other pixel types, 380 * NumberOfComponents will be greater than or equal to one. */ 381 itkSetMacro(NumberOfPointPixelComponents, unsigned int); 382 itkGetConstMacro(NumberOfPointPixelComponents, unsigned int); 383 itkSetMacro(NumberOfCellPixelComponents, unsigned int); 384 itkGetConstMacro(NumberOfCellPixelComponents, unsigned int); 385 itkSetMacro(PointDimension, unsigned int); 386 itkGetConstMacro(PointDimension, unsigned int); 387 itkSetMacro(NumberOfPoints, SizeValueType); 388 itkGetConstMacro(NumberOfPoints, SizeValueType); 389 itkSetMacro(NumberOfCells, SizeValueType); 390 itkGetConstMacro(NumberOfCells, SizeValueType); 391 itkSetMacro(NumberOfPointPixels, SizeValueType); 392 itkGetConstMacro(NumberOfPointPixels, SizeValueType); 393 itkSetMacro(NumberOfCellPixels, SizeValueType); 394 itkGetConstMacro(NumberOfCellPixels, SizeValueType); 395 itkSetMacro(CellBufferSize, SizeValueType); 396 itkGetConstMacro(CellBufferSize, SizeValueType); 397 itkSetMacro(UpdatePoints, bool); 398 itkGetConstMacro(UpdatePoints, bool); 399 itkSetMacro(UpdateCells, bool); 400 itkGetConstMacro(UpdateCells, bool); 401 itkSetMacro(UpdatePointData, bool); 402 itkGetConstMacro(UpdatePointData, bool); 403 itkSetMacro(UpdateCellData, bool); 404 itkGetConstMacro(UpdateCellData, bool); 405 406 unsigned int GetComponentSize(IOComponentType componentType) const; 407 408 /** Convenience method returns the IOComponentType as a string. This can be 409 * used for writing output files. */ 410 std::string GetComponentTypeAsString(IOComponentType) const; 411 412 /** Convenience method returns the IOPixelType as a string. This can be 413 * used for writing output files. */ 414 std::string GetPixelTypeAsString(IOPixelType) const; 415 416 /** These methods control whether the file is written binary or ASCII. 417 * Many file formats (i.e., subclasses) ignore this flag. */ 418 itkSetEnumMacro(FileType, FileType); 419 itkGetEnumMacro(FileType, FileType); 420 SetFileTypeToASCII()421 void SetFileTypeToASCII() 422 { 423 this->SetFileType(ASCII); 424 } 425 SetFileTypeToBinary()426 void SetFileTypeToBinary() 427 { 428 this->SetFileType(BINARY); 429 } 430 431 /** These methods indicate the byte ordering of the file you are 432 * trying to read in. These methods will then either swap or not 433 * swap the bytes depending on the byte ordering of the machine it 434 * is being run on. For example, reading in a BigEndian file on a 435 * BigEndian machine will result in no swapping. Trying to read the 436 * same file on a LittleEndian machine will result in swapping. 437 * Note: most UNIX machines are BigEndian while PC's and VAX's are 438 * LittleEndian. So if the file you are reading in was generated on 439 * a VAX or PC, SetByteOrderToLittleEndian() otherwise 440 * SetByteOrderToBigEndian(). Some MeshIOBase subclasses 441 * ignore these methods. */ 442 itkSetEnumMacro(ByteOrder, ByteOrder); 443 itkGetEnumMacro(ByteOrder, ByteOrder); 444 SetByteOrderToBigEndian()445 void SetByteOrderToBigEndian() 446 { 447 this->SetByteOrder(BigEndian); 448 } 449 SetByteOrderToLittleEndian()450 void SetByteOrderToLittleEndian() 451 { 452 this->SetByteOrder(LittleEndian); 453 } 454 455 /** Set/Get a boolean to use the compression or not. */ 456 itkSetMacro(UseCompression, bool); 457 itkGetConstMacro(UseCompression, bool); 458 itkBooleanMacro(UseCompression); 459 460 /** Convenience method returns the FileType as a string. This can be 461 * used for writing output files. */ 462 std::string GetFileTypeAsString(FileType) const; 463 464 /** Convenience method returns the ByteOrder as a string. This can be 465 * used for writing output files. */ 466 std::string GetByteOrderAsString(ByteOrder) const; 467 468 /*-------- This part of the interfaces deals with reading data ----- */ 469 /** Determine the file type. Returns true if this MeshIO can read the 470 * file specified. */ 471 virtual bool CanReadFile(const char *) = 0; 472 473 /** Determin the required information and whether need to ReadPoints, 474 ReadCells, ReadPointData and ReadCellData */ 475 virtual void ReadMeshInformation() = 0; 476 477 /** Reads the data from disk into the memory buffer provided. */ 478 virtual void ReadPoints(void *buffer) = 0; 479 480 virtual void ReadCells(void *buffer) = 0; 481 482 virtual void ReadPointData(void *buffer) = 0; 483 484 virtual void ReadCellData(void *buffer) = 0; 485 486 /*-------- This part of the interfaces deals with writing data ----- */ 487 488 /** Writes the data to disk from the memory buffer provided. Make sure 489 * that the IORegions has been set properly. */ 490 virtual bool CanWriteFile(const char *) = 0; 491 492 virtual void WriteMeshInformation() = 0; 493 494 virtual void WritePoints(void *buffer) = 0; 495 496 virtual void WriteCells(void *buffer) = 0; 497 498 virtual void WritePointData(void *buffer) = 0; 499 500 virtual void WriteCellData(void *buffer) = 0; 501 502 virtual void Write() = 0; 503 504 /** This method returns an array with the list of filename extensions 505 * supported for reading by this MeshIO class. This is intended to 506 * facilitate GUI and application level integration. 507 */ 508 const ArrayOfExtensionsType & GetSupportedReadExtensions() const; 509 510 /** This method returns an array with the list of filename extensions 511 * supported for writing by this MeshIO class. This is intended to 512 * facilitate GUI and application level integration. 513 */ 514 const ArrayOfExtensionsType & GetSupportedWriteExtensions() const; 515 516 protected: 517 MeshIOBase(); 518 ~MeshIOBase() override = default; 519 520 void PrintSelf(std::ostream & os, Indent indent) const override; 521 522 /** Insert an extension to the list of supported extensions for reading. */ 523 void AddSupportedReadExtension(const char *extension); 524 525 /** Insert an extension to the list of supported extensions for writing. */ 526 void AddSupportedWriteExtension(const char *extension); 527 528 /** Read data from input file stream to buffer with ascii style */ 529 template< typename T > ReadBufferAsAscii(T * buffer,std::ifstream & inputFile,SizeValueType numberOfComponents)530 void ReadBufferAsAscii(T *buffer, std::ifstream & inputFile, SizeValueType numberOfComponents) 531 { 532 for ( SizeValueType i = 0; i < numberOfComponents; i++ ) 533 { 534 inputFile >> buffer[i]; 535 } 536 } 537 538 /** Read data from input file to buffer with binary style */ 539 template< typename T > ReadBufferAsBinary(T * buffer,std::ifstream & inputFile,SizeValueType numberOfComponents)540 void ReadBufferAsBinary(T *buffer, std::ifstream & inputFile, SizeValueType numberOfComponents) 541 { 542 inputFile.read( reinterpret_cast< char * >( buffer ), numberOfComponents * sizeof( T ) ); 543 544 if ( m_ByteOrder == BigEndian ) 545 { 546 if ( itk::ByteSwapper< T >::SystemIsLittleEndian() ) 547 { 548 itk::ByteSwapper< T >::SwapRangeFromSystemToBigEndian(buffer, numberOfComponents); 549 } 550 } 551 else if ( m_ByteOrder == LittleEndian ) 552 { 553 if ( itk::ByteSwapper< T >::SystemIsBigEndian() ) 554 { 555 itk::ByteSwapper< T >::SwapRangeFromSystemToLittleEndian(buffer, numberOfComponents); 556 } 557 } 558 } 559 560 /** Write buffer to output file stream with ascii style */ 561 template< typename T > WriteBufferAsAscii(T * buffer,std::ofstream & outputFile,SizeValueType numberOfLines,SizeValueType numberOfComponents)562 void WriteBufferAsAscii(T *buffer, std::ofstream & outputFile, SizeValueType numberOfLines, SizeValueType numberOfComponents) 563 { 564 NumberToString<T> convert; 565 for ( SizeValueType ii = 0; ii < numberOfLines; ii++ ) 566 { 567 for ( SizeValueType jj = 0; jj < numberOfComponents; jj++ ) 568 { 569 outputFile << convert(buffer[ii * numberOfComponents + jj]) << " "; 570 } 571 outputFile << '\n'; 572 } 573 } 574 575 /** Write buffer to output file stream with binary style */ 576 template< typename TOutput, typename TInput > WriteBufferAsBinary(TInput * buffer,std::ofstream & outputFile,SizeValueType numberOfComponents)577 void WriteBufferAsBinary(TInput *buffer, std::ofstream & outputFile, SizeValueType numberOfComponents) 578 { 579 if ( typeid( TInput ) == typeid( TOutput ) ) 580 { 581 if ( m_ByteOrder == BigEndian && itk::ByteSwapper< TInput >::SystemIsLittleEndian() ) 582 { 583 itk::ByteSwapper< TInput >::SwapRangeFromSystemToBigEndian(buffer, numberOfComponents); 584 } 585 else if ( m_ByteOrder == LittleEndian && itk::ByteSwapper< TInput >::SystemIsBigEndian() ) 586 { 587 itk::ByteSwapper< TInput >::SwapRangeFromSystemToLittleEndian(buffer, numberOfComponents); 588 } 589 590 outputFile.write(reinterpret_cast< char * >( buffer ), numberOfComponents); 591 } 592 else 593 { 594 auto * data = new TOutput[numberOfComponents]; 595 for ( SizeValueType ii = 0; ii < numberOfComponents; ii++ ) 596 { 597 data[ii] = static_cast< TOutput >( buffer[ii] ); 598 } 599 600 if ( m_ByteOrder == BigEndian && itk::ByteSwapper< TOutput >::SystemIsLittleEndian() ) 601 { 602 itk::ByteSwapper< TOutput >::SwapRangeFromSystemToBigEndian(data, numberOfComponents); 603 } 604 else if ( m_ByteOrder == LittleEndian && itk::ByteSwapper< TOutput >::SystemIsBigEndian() ) 605 { 606 itk::ByteSwapper< TOutput >::SwapRangeFromSystemToLittleEndian(data, numberOfComponents); 607 } 608 609 outputFile.write(reinterpret_cast< char * >( data ), numberOfComponents); 610 delete[] data; 611 } 612 } 613 614 /** Read cells from a data buffer, used when writting cells. This function 615 write all kind of cells as it is stored in cells container. It is used when 616 cells container have only one kind of cells */ 617 template< typename TInput, typename TOutput > ReadCellsBuffer(TInput * input,TOutput * output)618 void ReadCellsBuffer(TInput *input, TOutput *output) 619 { 620 if ( input && output ) 621 { 622 SizeValueType inputIndex = NumericTraits< SizeValueType >::ZeroValue(); 623 SizeValueType outputIndex = NumericTraits< SizeValueType >::ZeroValue(); 624 for ( SizeValueType ii = 0; ii < m_NumberOfCells; ii++ ) 625 { 626 inputIndex++; // ignore the cell type 627 auto numberOfPoints = static_cast< unsigned int >( input[inputIndex++] ); 628 for ( unsigned int jj = 0; jj < numberOfPoints; jj++ ) 629 { 630 output[outputIndex++] = static_cast< TOutput >( input[inputIndex++] ); 631 } 632 } 633 } 634 } 635 636 /** Read cells from input buffer, used when Writting cells. This function only 637 write specified type of cells(used when input cells container composes 638 multiple type of cells and only want to write a specified cell type */ 639 template< typename TInput, typename TOutput > ReadCellsBuffer(TInput * input,TOutput * output,MeshIOBase::CellGeometryType type)640 void ReadCellsBuffer(TInput *input, TOutput *output, MeshIOBase::CellGeometryType type) 641 { 642 if ( input && output ) 643 { 644 SizeValueType inputIndex = itk::NumericTraits< SizeValueType >::ZeroValue(); 645 SizeValueType outputIndex = itk::NumericTraits< SizeValueType >::ZeroValue(); 646 647 for ( SizeValueType ii = 0; ii < m_NumberOfCells; ii++ ) 648 { 649 auto cellType = static_cast< MeshIOBase::CellGeometryType >( input[inputIndex++] ); 650 auto nn = static_cast< unsigned int >( input[inputIndex++] ); 651 if ( cellType == type ) 652 { 653 output[outputIndex++] = nn; 654 for ( unsigned int jj = 0; jj < nn; jj++ ) 655 { 656 output[outputIndex++] = static_cast< TOutput >( input[inputIndex++] ); 657 } 658 } 659 else 660 { 661 inputIndex += nn; 662 } 663 } 664 } 665 } 666 667 /** Write cells to a data buffer, used when readding mesh, used for cellType 668 with constant number of points */ 669 template< typename TInput, typename TOutput > WriteCellsBuffer(TInput * input,TOutput * output,CellGeometryType cellType,unsigned int numberOfPoints,SizeValueType numberOfCells)670 void WriteCellsBuffer(TInput *input, TOutput *output, CellGeometryType cellType, unsigned int numberOfPoints, SizeValueType numberOfCells) 671 { 672 if ( input && output ) 673 { 674 SizeValueType inputIndex = NumericTraits< SizeValueType >::ZeroValue(); 675 SizeValueType outputIndex = NumericTraits< SizeValueType >::ZeroValue(); 676 for ( SizeValueType ii = 0; ii < numberOfCells; ii++ ) 677 { 678 output[outputIndex++] = static_cast< TOutput >( cellType ); 679 output[outputIndex++] = static_cast< TOutput >( numberOfPoints ); 680 for ( unsigned int jj = 0; jj < numberOfPoints; jj++ ) 681 { 682 output[outputIndex++] = static_cast< TOutput >( input[inputIndex++] ); 683 } 684 } 685 } 686 } 687 688 /** Write cells to a data buffer, used when readding mesh, used for cellType 689 with non-constant number of points */ 690 template< typename TInput, typename TOutput > WriteCellsBuffer(TInput * input,TOutput * output,CellGeometryType cellType,SizeValueType numberOfCells)691 void WriteCellsBuffer(TInput *input, TOutput *output, CellGeometryType cellType, SizeValueType numberOfCells) 692 { 693 if ( input && output ) 694 { 695 SizeValueType inputIndex = NumericTraits< SizeValueType >::ZeroValue(); 696 SizeValueType outputIndex = NumericTraits< SizeValueType >::ZeroValue(); 697 for ( SizeValueType ii = 0; ii < numberOfCells; ii++ ) 698 { 699 auto numberOfPoints = static_cast< unsigned int >( input[inputIndex++] ); 700 output[outputIndex++] = static_cast< TOutput >( cellType ); 701 output[outputIndex++] = static_cast< TOutput >( numberOfPoints ); 702 for ( unsigned int jj = 0; jj < numberOfPoints; jj++ ) 703 { 704 output[outputIndex++] = static_cast< TOutput >( input[inputIndex++] ); 705 } 706 } 707 } 708 } 709 710 protected: 711 /** Big or Little Endian, and the type of the file. (May be ignored.) */ 712 ByteOrder m_ByteOrder{OrderNotApplicable}; 713 FileType m_FileType{ASCII}; 714 715 /** Filename to read */ 716 std::string m_FileName; 717 718 /** Should we compress the data? */ 719 bool m_UseCompression{false}; 720 721 /** Used internally to keep track of the type of the component. */ 722 IOComponentType m_PointComponentType{UNKNOWNCOMPONENTTYPE}; 723 IOComponentType m_CellComponentType{UNKNOWNCOMPONENTTYPE}; 724 IOComponentType m_PointPixelComponentType{UNKNOWNCOMPONENTTYPE}; 725 IOComponentType m_CellPixelComponentType{UNKNOWNCOMPONENTTYPE}; 726 727 /** Used internally to keep track of the type of the pixel. */ 728 IOPixelType m_PointPixelType{SCALAR}; 729 IOPixelType m_CellPixelType{SCALAR}; 730 731 /** Stores the number of components per pixel. This will be 1 for 732 * grayscale images, 3 for RGBPixel images, and 4 for RGBPixelA images. */ 733 unsigned int m_NumberOfPointPixelComponents{0}; 734 unsigned int m_NumberOfCellPixelComponents{0}; 735 736 /** The number of independent dimensions in the point. */ 737 SizeValueType m_PointDimension{3}; 738 739 /** The number of points and cells */ 740 SizeValueType m_NumberOfPoints; 741 SizeValueType m_NumberOfCells; 742 SizeValueType m_NumberOfPointPixels; 743 SizeValueType m_NumberOfCellPixels; 744 745 /** The buffer size of cells */ 746 SizeValueType m_CellBufferSize; 747 748 /** Flags indicate whether read or write points, cells, point data and cell 749 data */ 750 bool m_UpdatePoints{false}; 751 bool m_UpdateCells{false}; 752 bool m_UpdatePointData{false}; 753 bool m_UpdateCellData{false}; 754 755 private: 756 ArrayOfExtensionsType m_SupportedReadExtensions; 757 ArrayOfExtensionsType m_SupportedWriteExtensions; 758 }; 759 #define MESHIOBASE_TYPEMAP(type, ctype) \ 760 template< > \ 761 struct MeshIOBase:: MapComponentType< type > \ 762 { \ 763 static constexpr IOComponentType CType = ctype; \ 764 } 765 766 MESHIOBASE_TYPEMAP(unsigned char, UCHAR); 767 MESHIOBASE_TYPEMAP(char, CHAR); 768 MESHIOBASE_TYPEMAP(unsigned short, USHORT); 769 MESHIOBASE_TYPEMAP(short, SHORT); 770 MESHIOBASE_TYPEMAP(unsigned int, UINT); 771 MESHIOBASE_TYPEMAP(int, INT); 772 MESHIOBASE_TYPEMAP(unsigned long, ULONG); 773 MESHIOBASE_TYPEMAP(long, LONG); 774 MESHIOBASE_TYPEMAP(unsigned long long, ULONGLONG); 775 MESHIOBASE_TYPEMAP(long long, LONGLONG); 776 MESHIOBASE_TYPEMAP(float, FLOAT); 777 MESHIOBASE_TYPEMAP(double, DOUBLE); 778 MESHIOBASE_TYPEMAP(long double, LDOUBLE); 779 #undef MESHIOBASE_TYPEMAP 780 } // end namespace itk 781 782 #endif 783