OTB  8.1.0
Orfeo Toolbox
otbImageFileReader.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2022 Centre National d'Etudes Spatiales (CNES)
3  *
4  * This file is part of Orfeo Toolbox
5  *
6  * https://www.orfeo-toolbox.org/
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef otbImageFileReader_hxx
22 #define otbImageFileReader_hxx
23 
24 #include "otbImageFileReader.h"
25 #include "otbConfigure.h"
26 
27 #include "otbSystem.h"
28 #include <itksys/SystemTools.hxx>
29 #include <fstream>
30 #include <string>
31 
32 #include "itkImageIOFactory.h"
33 #include "itkPixelTraits.h"
34 #include "itkVectorImage.h"
35 #include "itkMetaDataObject.h"
36 
37 #include "otbConvertPixelBuffer.h"
38 #include "otbImageIOFactory.h"
39 #include "otbMetaDataKey.h"
40 #include "otbImageMetadata.h"
42 #include "otbImageCommons.h"
44 
45 #include "otbMacro.h"
46 
47 
48 namespace otb
49 {
50 
51 static const char DerivedSubdatasetPrefix[] = "DERIVED_SUBDATASET:";
53 
54 template <class T>
55 bool PixelIsComplex(const std::complex<T>& /*dummy*/)
56 {
57  return true;
58 }
59 template <class T>
60 bool PixelIsComplex(const T& /*dummy*/)
61 {
62  return false;
63 }
64 
65 template <class TOutputImage, class ConvertPixelTraits>
67  : m_ImageIO(),
68  m_UserSpecifiedImageIO(false),
69  m_FileName(""),
70  m_UseStreaming(true),
71  m_ActualIORegion(),
72  m_FilenameHelper(FNameHelperType::New()),
73  m_AdditionalNumber(0),
74  m_IOComponents(0)
75 {
76 }
77 
78 template <class TOutputImage, class ConvertPixelTraits>
80 {
81 }
82 
83 template <class TOutputImage, class ConvertPixelTraits>
84 void ImageFileReader<TOutputImage, ConvertPixelTraits>::PrintSelf(std::ostream& os, itk::Indent indent) const
85 {
86  Superclass::PrintSelf(os, indent);
87 
88  if (this->m_ImageIO)
89  {
90  os << indent << "ImageIO: \n";
91  this->m_ImageIO->Print(os, indent.GetNextIndent());
92  }
93  else
94  {
95  os << indent << "ImageIO: (null)"
96  << "\n";
97  }
98 
99  os << indent << "UserSpecifiedImageIO flag: " << this->m_UserSpecifiedImageIO << "\n";
100  os << indent << "m_FileName: " << this->m_FileName << "\n";
101  os << indent << "m_UseStreaming flag: " << this->m_UseStreaming << "\n";
102  os << indent << "m_ActualIORegion: " << this->m_ActualIORegion << "\n";
103  os << indent << "m_AdditionalNumber: " << this->m_AdditionalNumber << "\n";
104 }
105 
106 template <class TOutputImage, class ConvertPixelTraits>
108 {
109  if (this->m_ImageIO != imageIO)
110  {
111  this->m_ImageIO = imageIO;
112  this->Modified();
113  }
114  m_UserSpecifiedImageIO = true;
115 }
116 
117 template <class TOutputImage, class ConvertPixelTraits>
119 {
120 
121  typename TOutputImage::Pointer output = this->GetOutput();
122 
123  // allocate the output buffer
124  output->SetBufferedRegion(output->GetRequestedRegion());
125  output->Allocate();
126 
127  // Raise an exception if the file could not be opened
128  // i.e. if this->m_ImageIO is Null
129  this->TestValidImageIO();
130 
131  // Tell the ImageIO to read the file
132  OutputImagePixelType* buffer = output->GetPixelContainer()->GetBufferPointer();
133  this->m_ImageIO->SetFileName(this->m_FileName);
134 
135  itk::ImageIORegion ioRegion(TOutputImage::ImageDimension);
136 
137  itk::ImageIORegion::SizeType ioSize = ioRegion.GetSize();
138  itk::ImageIORegion::IndexType ioStart = ioRegion.GetIndex();
139 
140  /* Init IORegion with size or streaming size */
141  SizeType dimSize;
142  for (unsigned int i = 0; i < TOutputImage::ImageDimension; ++i)
143  {
144  if (i < this->m_ImageIO->GetNumberOfDimensions())
145  {
146  if (!this->m_ImageIO->CanStreamRead())
147  dimSize[i] = this->m_ImageIO->GetDimensions(i);
148  else
149  dimSize[i] = output->GetRequestedRegion().GetSize()[i];
150  }
151  else
152  {
153  // Number of dimensions in the output is more than number of dimensions
154  // in the ImageIO object (the file). Use default values for the size,
155  // spacing, and origin for the final (degenerate) dimensions.
156  dimSize[i] = 1;
157  }
158  }
159 
160  for (unsigned int i = 0; i < dimSize.GetSizeDimension(); ++i)
161  {
162  ioSize[i] = dimSize[i];
163  }
164 
165  IndexType start;
166  if (!this->m_ImageIO->CanStreamRead())
167  start.Fill(0);
168  else
169  start = output->GetRequestedRegion().GetIndex();
170  for (unsigned int i = 0; i < start.GetIndexDimension(); ++i)
171  {
172  ioStart[i] = start[i];
173  }
174 
175  ioRegion.SetSize(ioSize);
176  ioRegion.SetIndex(ioStart);
177 
178  this->m_ImageIO->SetIORegion(ioRegion);
179 
182 
183  if (this->m_ImageIO->GetComponentTypeInfo() == typeid(typename ConvertOutputPixelTraits::ComponentType) &&
184  (this->m_ImageIO->GetNumberOfComponents() == ConvertIOPixelTraits::GetNumberOfComponents()) && !m_FilenameHelper->BandRangeIsSet())
185  {
186  // Have the ImageIO read directly into the allocated buffer
187  this->m_ImageIO->Read(buffer);
188  return;
189  }
190  else // a type conversion is necessary
191  {
192  // note: char is used here because the buffer is read in bytes
193  // regardless of the actual type of the pixels.
194  ImageRegionType region = output->GetBufferedRegion();
195 
196  // Adapt the image size with the region and take into account a potential
197  // remapping of the components. m_BandList is empty if no band range is set
198  std::streamoff nbBytes = (this->m_ImageIO->GetComponentSize() * std::max(this->m_ImageIO->GetNumberOfComponents(), (unsigned int)m_BandList.size())) *
199  static_cast<std::streamoff>(region.GetNumberOfPixels());
200 
201  char* loadBuffer = new char[nbBytes];
202 
203  this->m_ImageIO->Read(loadBuffer);
204 
205  if (m_FilenameHelper->BandRangeIsSet())
206  this->m_ImageIO->DoMapBuffer(loadBuffer, region.GetNumberOfPixels(), this->m_BandList);
207 
208  this->DoConvertBuffer(loadBuffer, region.GetNumberOfPixels());
209 
210  delete[] loadBuffer;
211  }
212 }
213 
214 template <class TOutputImage, class ConvertPixelTraits>
216 {
217  typename TOutputImage::Pointer out = dynamic_cast<TOutputImage*>(output);
218 
219  // If the ImageIO object cannot stream, then set the RequestedRegion to the
220  // LargestPossibleRegion
221  if (!this->m_ImageIO->CanStreamRead())
222  {
223  if (out)
224  {
225  out->SetRequestedRegion(out->GetLargestPossibleRegion());
226  }
227  else
228  {
229  throw otb::ImageFileReaderException(__FILE__, __LINE__, "Invalid output object type");
230  }
231  }
232 }
233 
234 template <class TOutputImage, class ConvertPixelTraits>
236 {
237  typename TOutputImage::Pointer output = this->GetOutput();
238 
239  // Check to see if we can read the file given the name or prefix
240  if (this->m_FileName == "")
241  {
242  throw otb::ImageFileReaderException(__FILE__, __LINE__, "Filename must be specified.");
243  }
244 
245  // Find real image file name
246  // !!!! Update FileName
247  std::string lFileName;
248  bool found = GetGdalReadImageFileName(this->m_FileName, lFileName);
249  if (found)
250  {
251  // Update FileName
252  this->m_FileName = lFileName;
253  }
254 
255  if (this->m_UserSpecifiedImageIO == false) // try creating via factory
256  {
258  }
259 
260  // Raise an exception if the file could not be opened
261  // i.e. if this->m_ImageIO is Null
262  this->TestValidImageIO();
263 
264  // Get the ImageIO MetaData Dictionary
265  itk::MetaDataDictionary& dict = this->m_ImageIO->GetMetaDataDictionary();
266 
267  // Hint the IO whether the OTB image type takes complex pixels
268  // this will determine the strategy to fill up a vector image
269  OutputImagePixelType dummy;
270  bool lVectorImage = false;
271  if (strcmp(output->GetNameOfClass(), "VectorImage") == 0)
272  lVectorImage = true;
273 
274  this->m_ImageIO->SetOutputImagePixelType(PixelIsComplex(dummy), lVectorImage);
275 
276  // Pass the dataset number (used for hdf files for example)
277  if (m_FilenameHelper->SubDatasetIndexIsSet())
278  {
279  itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::SubDatasetIndex, m_FilenameHelper->GetSubDatasetIndex());
280  }
281  else
282  {
283  itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::SubDatasetIndex, m_AdditionalNumber);
284  }
285 
286 
287  if (m_FilenameHelper->ResolutionFactorIsSet())
288  {
289  itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::ResolutionFactor, m_FilenameHelper->GetResolutionFactor());
290  }
291  else
292  {
293  itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::ResolutionFactor, m_AdditionalNumber);
294  }
295 
296  // Got to allocate space for the image. Determine the characteristics of
297  // the image.
298  //
299  this->m_ImageIO->SetFileName(this->m_FileName);
300  this->m_ImageIO->ReadImageInformation();
301  // Initialize the number of component per pixel
302  // THOMAS: This is not in ITK!
303  // output->SetNumberOfComponentsPerPixel(this->m_ImageIO->GetNumberOfComponents());
304 
305  SizeType dimSize;
306  double spacing[TOutputImage::ImageDimension];
307  double origin[TOutputImage::ImageDimension];
308  typename TOutputImage::DirectionType direction;
309  std::vector<double> axis;
310  int spacing_sign(0);
311 
312  for (unsigned int i = 0; i < TOutputImage::ImageDimension; ++i)
313  {
314  if (i < this->m_ImageIO->GetNumberOfDimensions())
315  {
316  dimSize[i] = this->m_ImageIO->GetDimensions(i);
317  if (this->m_ImageIO->GetSpacing(i) < 0)
318  spacing_sign = -1;
319  else
320  spacing_sign = 1;
321  spacing[i] = spacing_sign * this->m_ImageIO->GetSpacing(i);
322  origin[i] = this->m_ImageIO->GetOrigin(i);
323  // Please note: direction cosines are stored as columns of the
324  // direction matrix
325  axis = this->m_ImageIO->GetDirection(i);
326  for (unsigned j = 0; j < TOutputImage::ImageDimension; ++j)
327  {
328  if (j < this->m_ImageIO->GetNumberOfDimensions())
329  {
330  direction[j][i] = spacing_sign * axis[j];
331  }
332  else
333  {
334  direction[j][i] = 0.0;
335  }
336  }
337  }
338  else
339  {
340  // Number of dimensions in the output is more than number of dimensions
341  // in the ImageIO object (the file). Use default values for the size,
342  // spacing, origin and direction for the final (degenerate) dimensions.
343  dimSize[i] = 1;
344  spacing[i] = 1.0;
345  origin[i] = 0.5;
346  for (unsigned j = 0; j < TOutputImage::ImageDimension; ++j)
347  {
348  if (i == j)
349  {
350  direction[j][i] = 1.0;
351  }
352  else
353  {
354  direction[j][i] = 0.0;
355  }
356  }
357  }
358  }
359 
360  if (m_FilenameHelper->GetSkipCarto())
361  {
362  for (unsigned int i = 0; i < TOutputImage::ImageDimension; ++i)
363  {
364  if (m_FilenameHelper->GetResolutionFactor() != 0)
365  {
366  spacing[i] = 1.0 * std::pow((double)2, (double)m_FilenameHelper->GetResolutionFactor());
367  }
368  else
369  {
370  spacing[i] = 1.0;
371  }
372  origin[i] = 0.5 * spacing[i];
373  for (unsigned j = 0; j < TOutputImage::ImageDimension; ++j)
374  {
375  if (i == j)
376  {
377  direction[j][i] = 1.0;
378  }
379  else
380  {
381  direction[j][i] = 0.0;
382  }
383  }
384  }
385  }
386 
387  output->SetOrigin(origin); // Set the image origin
388  output->SetDirection(direction); // Set the image direction cosines
389  output->SetSpacing(spacing); // Set the image spacing
390 
391  // detect Image supporting new ImageMetadata
392  ImageCommons* img_common = dynamic_cast<ImageCommons*>(this->GetOutput());
393 
394  // Get ImageMetadata from ImageIO
395  ImageMetadata imd = m_ImageIO->GetImageMetadata();
396 
397  // Metadata Framework
398  std::string DerivatedFileName = GetDerivedDatasetSourceFileName(m_FileName);
399  std::string extension = itksys::SystemTools::GetFilenameLastExtension(DerivatedFileName);
400  std::string attachedGeom = DerivatedFileName.substr(0, DerivatedFileName.size() - extension.size()) + std::string(".geom");
401  // Case 1: external geom supplied through extended filename
402  if (!m_FilenameHelper->GetSkipGeom() && m_FilenameHelper->ExtGEOMFileNameIsSet())
403  {
404  GeomMetadataSupplier geomSupplier(m_FilenameHelper->GetExtGEOMFileName(), m_FileName);
405  ImageMetadataInterfaceFactory::CreateIMI(imd, geomSupplier);
406  if(imd.Has(MDStr::Mission) && (imd[MDStr::Mission] == "PlĂ©iades"))
407  geomSupplier.FetchRPC(imd, 0.5, 0.5);
408  else
409  geomSupplier.FetchRPC(imd);
410  geomSupplier.FetchGCP(imd);
411  otbLogMacro(Info, << "Loading metadata from external geom file " << m_FilenameHelper->GetExtGEOMFileName());
412  }
413  // Case 2: attached geom (if present)
414  else if (!m_FilenameHelper->GetSkipGeom() && itksys::SystemTools::FileExists(attachedGeom))
415  {
416  GeomMetadataSupplier geomSupplier(attachedGeom, m_FileName);
417  ImageMetadataInterfaceFactory::CreateIMI(imd, geomSupplier);
418  geomSupplier.FetchRPC(imd);
419  geomSupplier.FetchGCP(imd);
420  otbLogMacro(Info, << "Loading metadata from attached geom file " << attachedGeom);
421  }
422  // Case 3: tags in file
423  else
424  {
425  auto gdalMetadataSupplierPointer = dynamic_cast<MetadataSupplierInterface*>(m_ImageIO.GetPointer());
426  if (gdalMetadataSupplierPointer)
427  {
428  ImageMetadataInterfaceFactory::CreateIMI(imd, *gdalMetadataSupplierPointer);
429  otbLogMacro(Info, << "Loading metadata from official product");
430  }
431  }
432 
433  // If Skip ProjectionRef is activated, remove ProjRef from dict
434  if (m_FilenameHelper->GetSkipCarto())
435  {
436  itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey, "");
438  }
439 
440  // Copy MetaDataDictionary from instantiated reader to output image.
441  // TODO: disable when Ossim removed
442  if (!m_FilenameHelper->GetSkipGeom())
443  {
444  output->SetMetaDataDictionary(this->m_ImageIO->GetMetaDataDictionary());
445  this->SetMetaDataDictionary(this->m_ImageIO->GetMetaDataDictionary());
446  }
447  else
448  {
449  itk::MetaDataDictionary dictLight;
450  std::string projRef;
451  itk::ExposeMetaData(dict, MetaDataKey::ProjectionRefKey, projRef);
452  itk::EncapsulateMetaData<std::string>(dictLight, MetaDataKey::ProjectionRefKey, projRef);
453  output->SetMetaDataDictionary(dictLight);
454  this->SetMetaDataDictionary(dictLight);
455  }
456 
457  IndexType start;
458  start.Fill(0);
459 
460  ImageRegionType region;
461  region.SetSize(dimSize);
462  region.SetIndex(start);
463 
464  // detect number of output components
465  m_IOComponents = this->m_ImageIO->GetNumberOfComponents();
466  m_BandList.clear();
467  if (m_FilenameHelper->BandRangeIsSet())
468  {
469  bool ret = m_FilenameHelper->ResolveBandRange(m_FilenameHelper->GetBandRange(), m_IOComponents, m_BandList);
470  if (ret == false || m_BandList.size() == 0)
471  {
472  // invalid range
473  itkGenericExceptionMacro("The given band range is either empty or invalid for a " << m_IOComponents << " bands input image!");
474  }
475  // ImageIO returned the metadata from all bands of the input raster. It needs to be adapted to the layout of m_BandList
476  ImageMetadata::ImageMetadataBandsType bandRangeMetadata;
477  for (auto elem: m_BandList)
478  {
479  bandRangeMetadata.push_back(imd.Bands[elem]);
480  }
481  imd.Bands = bandRangeMetadata;
482  m_IOComponents = m_BandList.size();
483  }
484 
485  // Delete band metadata if the Conversion policy changed the number of bands, in the case of
486  // grayscale to RGB for example. Because we cannot know how the metadata should be mapped.
487  // TODO: define proper behavior in this case.
489  if (strcmp(output->GetNameOfClass(), "Image") == 0 && !(this->m_ImageIO->GetNumberOfComponents() == ConvertIOPixelTraits::GetNumberOfComponents()))
490  {
492  }
493 
494  // THOMAS : ajout
495  // If a VectorImage, this requires us to set the
496  // VectorLength before allocate
497  if (strcmp(output->GetNameOfClass(), "VectorImage") == 0)
498  {
499  typedef typename TOutputImage::AccessorFunctorType AccessorFunctorType;
500  AccessorFunctorType::SetVectorLength(output, m_IOComponents);
501  }
502 
503  if (img_common != nullptr)
504  {
505  img_common->SetImageMetadata(imd);
506  }
507 
508  output->SetLargestPossibleRegion(region);
509 }
510 
511 template <class TOutputImage, class ConvertPixelTraits>
513 {
514 
515  const size_t dsds_pos = filename.find(otb::DerivedSubdatasetPrefix);
516 
517  if (dsds_pos != std::string::npos)
518  {
519  // Derived subdataset from gdal
520  const size_t alg_pos = filename.find(":", dsds_pos + otb::DerivedSubdatasetPrefixLength);
521  if (alg_pos != std::string::npos)
522  {
523  std::string sourceFilename = filename.substr(alg_pos + 1, filename.size() - alg_pos);
524  return sourceFilename;
525  }
526  }
527  return filename;
528 }
529 
530 template <class TOutputImage, class ConvertPixelTraits>
532 {
533  if (this->m_ImageIO.IsNull())
534  {
535  std::string fileToCheck = GetDerivedDatasetSourceFileName(m_FileName);
536 
537  // Test if the file exists.
538  if (!itksys::SystemTools::FileExists(fileToCheck))
539  {
540  throw otb::ImageFileReaderException(__FILE__, __LINE__, std::string("Cannot open image ") + fileToCheck + std::string(". The file does not exist."),
541  fileToCheck);
542  }
543  else
544  {
545  throw otb::ImageFileReaderException(__FILE__, __LINE__, std::string("Cannot open image ") + this->m_FileName +
546  std::string(". Probably unsupported format or incorrect filename extension."),
547  this->m_FileName);
548  }
549  }
550 }
551 
552 template <class TOutputImage, class ConvertPixelTraits>
553 bool ImageFileReader<TOutputImage, ConvertPixelTraits>::GetGdalReadImageFileName(const std::string& filename, std::string& GdalFileName)
554 {
555  std::vector<std::string> listFileSearch;
556  listFileSearch.push_back("DAT_01.001");
557  listFileSearch.push_back("dat_01.001"); // RADARSAT or SAR_ERS2
558  listFileSearch.push_back("IMAGERY.TIF");
559  listFileSearch.push_back("imagery.tif"); // For format SPOT5TIF
560  // Not recognized as a supported file format by GDAL.
561  // listFileSearch.push_back("IMAGERY.BIL"); listFileSearch.push_back("imagery.bil"); //For format SPOT5BIL
562  listFileSearch.push_back("IMAG_01.DAT");
563  listFileSearch.push_back("imag_01.dat"); // For format SPOT4
564 
565  std::string str_FileName;
566  bool fic_trouve(false);
567 
568  // If it's a directory, look at the content to see if it's RADARSAT, ERS
569  std::vector<std::string> listFileFind;
570  listFileFind = System::Readdir(filename);
571  if (listFileFind.empty() == false)
572  {
573  unsigned int cpt(0);
574  while ((cpt < listFileFind.size()) && (fic_trouve == false))
575  {
576  str_FileName = std::string(listFileFind[cpt]);
577  for (unsigned int i = 0; i < listFileSearch.size(); ++i)
578  {
579  if (str_FileName.compare(listFileSearch[i]) == 0)
580  {
581  GdalFileName = std::string(filename) + str_FileName; // listFileSearch[i];
582  fic_trouve = true;
583  }
584  }
585  ++cpt;
586  }
587  }
588  else
589  {
590  std::string strFileName(filename);
591 
592  std::string extension = itksys::SystemTools::GetFilenameLastExtension(strFileName);
593  if ((extension == ".HDR") || (extension == ".hdr"))
594  {
595  GdalFileName = System::GetRootName(strFileName);
596  }
597  else
598  {
599  // Else, the filename is the name of the file to open
600  GdalFileName = std::string(filename);
601  }
602  fic_trouve = true;
603  }
604 
605  return (fic_trouve);
606 }
607 
608 template <class TOutputImage, class ConvertPixelTraits>
609 void ImageFileReader<TOutputImage, ConvertPixelTraits>::SetFileName(const std::string& extendedFileName)
610 {
611  const std::string skip_geom_key = "skipgeom";
612  const std::string geom_key = "geom";
613 
614  // First, see if the simple filename has changed
616 
617  helper->SetExtendedFileName(extendedFileName);
618  std::string simpleFileName = helper->GetSimpleFileName();
619 
620  if (simpleFileName == this->m_FileName)
621  {
622  // Then, see if the option map changed
623  const typename ExtendedFilenameHelper::OptionMapType& newMap = helper->GetOptionMap();
624  const typename ExtendedFilenameHelper::OptionMapType& oldMap = m_FilenameHelper->GetOptionMap();
625 
626  // Both maps are not completely the same
627  if (oldMap.size() != newMap.size() || !std::equal(oldMap.begin(), oldMap.end(), newMap.begin()))
628  {
629  this->Modified();
630  }
631  }
632  else
633  {
634  this->m_FileName = simpleFileName;
635  this->Modified();
636  }
637 
638  m_FilenameHelper = helper;
639 }
640 
641 template <class TOutputImage, class ConvertPixelTraits>
643 {
644  return this->m_FilenameHelper->GetSimpleFileName();
645 }
646 
647 template <class TOutputImage, class ConvertPixelTraits>
649 {
650  this->UpdateOutputInformation();
651 
652  return this->m_ImageIO->GetOverviewsCount();
653 }
654 
655 
656 template <class TOutputImage, class ConvertPixelTraits>
658 {
659  this->UpdateOutputInformation();
660 
661  return this->m_ImageIO->GetOverviewsInfo();
662 }
663 
664 template <class TOutputImage, class ConvertPixelTraits>
665 void ImageFileReader<TOutputImage, ConvertPixelTraits>::DoConvertBuffer(void* inputData, size_t numberOfPixels)
666 {
667  // get the pointer to the destination buffer
668  OutputImagePixelType* outputData = this->GetOutput()->GetPixelContainer()->GetBufferPointer();
669 
670 // TODO:
671 // Pass down the PixelType (RGB, VECTOR, etc.) so that any vector to
672 // scalar conversion be type specific. i.e. RGB to scalar would use
673 // a formula to convert to radiance, VECTOR to scalar would use
674 // vector magnitude.
675 
676 
677 // Create a macro as this code is a bit lengthy and repetitive
678 // if the ImageIO pixel type is typeid(type) then use the ConvertPixelBuffer
679 // class to convert the data block to TOutputImage's pixel type
680 // see DefaultConvertPixelTraits and ConvertPixelBuffer
681 
682 // The first else if block applies only to images of type itk::VectorImage
683 // VectorImage needs to copy out the buffer differently.. The buffer is of
684 // type InternalPixelType, but each pixel is really 'k' consecutive pixels.
685 
686 #define OTB_CONVERT_BUFFER_IF_BLOCK(type) \
687  else if (m_ImageIO->GetComponentTypeInfo() == typeid(type)) \
688  { \
689  if (strcmp(this->GetOutput()->GetNameOfClass(), "VectorImage") == 0) \
690  { \
691  ConvertPixelBuffer<type, OutputImagePixelType, ConvertPixelTraits>::ConvertVectorImage(static_cast<type*>(inputData), m_IOComponents, outputData, \
692  numberOfPixels); \
693  } \
694  else \
695  { \
696  ConvertPixelBuffer<type, OutputImagePixelType, ConvertPixelTraits>::Convert(static_cast<type*>(inputData), m_IOComponents, outputData, numberOfPixels); \
697  } \
698  }
699 #define OTB_CONVERT_CBUFFER_IF_BLOCK(type) \
700  else if (m_ImageIO->GetComponentTypeInfo() == typeid(type)) \
701  { \
702  if (strcmp(this->GetOutput()->GetNameOfClass(), "VectorImage") == 0) \
703  { \
704  if ((typeid(OutputImagePixelType) == typeid(std::complex<double>)) || (typeid(OutputImagePixelType) == typeid(std::complex<float>)) || \
705  (typeid(OutputImagePixelType) == typeid(std::complex<int>)) || (typeid(OutputImagePixelType) == typeid(std::complex<short>))) \
706  { \
707  ConvertPixelBuffer<type::value_type, OutputImagePixelType, ConvertPixelTraits>::ConvertComplexVectorImageToVectorImageComplex( \
708  static_cast<type*>(inputData), m_IOComponents, outputData, numberOfPixels); \
709  } \
710  else \
711  { \
712  ConvertPixelBuffer<type::value_type, OutputImagePixelType, ConvertPixelTraits>::ConvertComplexVectorImageToVectorImage( \
713  static_cast<type*>(inputData), m_IOComponents, outputData, numberOfPixels); \
714  } \
715  } \
716  else \
717  { \
718  ConvertPixelBuffer<type::value_type, OutputImagePixelType, ConvertPixelTraits>::ConvertComplexToGray(static_cast<type*>(inputData), m_IOComponents, \
719  outputData, numberOfPixels); \
720  } \
721  }
722 
723  if (0)
724  {
725  }
726  OTB_CONVERT_BUFFER_IF_BLOCK(unsigned char)
728  OTB_CONVERT_BUFFER_IF_BLOCK(unsigned short)
730  OTB_CONVERT_BUFFER_IF_BLOCK(unsigned int)
732  OTB_CONVERT_BUFFER_IF_BLOCK(unsigned long)
736  OTB_CONVERT_CBUFFER_IF_BLOCK(std::complex<short>)
737  OTB_CONVERT_CBUFFER_IF_BLOCK(std::complex<int>)
738  OTB_CONVERT_CBUFFER_IF_BLOCK(std::complex<float>)
739  OTB_CONVERT_CBUFFER_IF_BLOCK(std::complex<double>)
740  else
741  {
742  otb::ImageFileReaderException e(__FILE__, __LINE__);
743  std::ostringstream msg;
744  msg << "Couldn't convert component type: " << std::endl
745  << " " << ImageIOBase::GetComponentTypeAsString(m_ImageIO->GetComponentType()) << std::endl
746  << "to one of: " << std::endl
747  << " " << typeid(unsigned char).name() << std::endl
748  << " " << typeid(char).name() << std::endl
749  << " " << typeid(unsigned short).name() << std::endl
750  << " " << typeid(short).name() << std::endl
751  << " " << typeid(unsigned int).name() << std::endl
752  << " " << typeid(int).name() << std::endl
753  << " " << typeid(unsigned long).name() << std::endl
754  << " " << typeid(long).name() << std::endl
755  << " " << typeid(float).name() << std::endl
756  << " " << typeid(double).name() << std::endl;
757  e.SetDescription(msg.str());
758  e.SetLocation(ITK_LOCATION);
759  throw e;
760  return;
761  }
762 #undef OTB_CONVERT_BUFFER_IF_BLOCK
763 #undef OTB_CONVERT_CBUFFER_IF_BLOCK
764 }
765 
766 
767 } // namespace otb
768 
769 #endif
itk::Size< Monteverdi_DIMENSION > SizeType
Definition: mvdTypes.h:137
itk::Index< Monteverdi_DIMENSION > IndexType
Definition: mvdTypes.h:133
static constexpr char const * name() noexcept
static const char DerivedSubdatasetPrefix[]
#define OTB_CONVERT_CBUFFER_IF_BLOCK(type)
void SetImageMetadata(ImageMetadata imd)
void DoConvertBuffer(void *buffer, vcl_size_t numberOfPixels)
void GenerateOutputInformation(void) override
static const vcl_size_t DerivedSubdatasetPrefixLength
unsigned int m_AdditionalNumber
static ImageMetadataInterfaceBasePointerType CreateIMI(ImageMetadata &imd, const MetadataSupplierInterface &mds)
vcl_size_t RemoveProjectedGeometry()
std::vector< unsigned int > m_BandList
virtual const char * GetFileName() const
Converts an extended filename to reader options.
bool Has(const MDGeom &key) const
TOutputImage::InternalPixelType OutputImagePixelType
Base class to access metadata information in files/images.
void EnlargeOutputRequestedRegion(itk::DataObject *output) override
OTBMetadata_EXPORT char const * ResolutionFactor
virtual void SetFileName(const std::string &extendedFileName)
std::vector< ImageMetadataBase > ImageMetadataBandsType
bool FetchRPC(ImageMetadata &imd, const double lineOffset=0, const double sampleOffset=0)
Fill the ImageMetadata with the RPC model from the geom file.
static ImageIOBasePointer CreateImageIO(const char *path, FileModeType mode)
TOutputImage::SizeType SizeType
Abstract superclass defines image IO interface.
Generic class containing image metadata used in OTB.
bool FetchGCP(ImageMetadata &imd)
Fill the ImageMetadata with the GCP from the geom file.
unsigned int GetNumberOfComponents(PixelType const &pix)
#define OTB_CONVERT_BUFFER_IF_BLOCK(type)
void GenerateData() override
TOutputImage::RegionType ImageRegionType
static std::string GetRootName(const std::string &filename)
static std::string GetDerivedDatasetSourceFileName(const std::string &filename)
Base exception class for IO conflicts.
itk::ImageIORegion m_ActualIORegion
ImageMetadataBandsType Bands
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
static std::vector< std::string > Readdir(const std::string &pszPath)
static std::string GetComponentTypeAsString(IOComponentType)
#define otbLogMacro(level, msg)
Definition: otbMacro.h:52
void PrintSelf(std::ostream &os, itk::Indent indent) const override
RealType ComponentType
Definition: mvdTypes.h:88
std::map< std::string, std::string > OptionMapType
OTBMetadata_EXPORT char const * SubDatasetIndex
bool PixelIsComplex(const std::complex< T > &)
TOutputImage::IndexType IndexType
Class to access metadata information in a Geom file.
bool GetGdalReadImageFileName(const std::string &filename, std::string &GdalFileName)
FNameHelperType::Pointer m_FilenameHelper
otb::ImageIOBase::Pointer m_ImageIO
std::vector< std::string > GetOverviewsInfo()
unsigned int GetOverviewsCount()
OTBMetadata_EXPORT char const * ProjectionRefKey
void SetImageIO(otb::ImageIOBase *imageIO)