Orfeo Toolbox  3.16
otbGDALImageIO.cxx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: ORFEO Toolbox
4  Language: C++
5  Date: $Date$
6  Version: $Revision$
7 
8 
9  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
10  See OTBCopyright.txt for details.
11 
12 
13  This software is distributed WITHOUT ANY WARRANTY; without even
14  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  PURPOSE. See the above copyright notices for more information.
16 
17 =========================================================================*/
18 #include <iostream>
19 #include <fstream>
20 #include <vector>
21 
22 #include "otbGDALImageIO.h"
23 #include "otbMacro.h"
24 #include "otbSystem.h"
25 #include "otbImage.h"
27 
28 #include "itkMetaDataObject.h"
29 #include "otbMetaDataKey.h"
30 
31 #include "itkRGBPixel.h"
32 #include "itkRGBAPixel.h"
33 #include "itkTimeProbe.h"
34 
35 #include "cpl_conv.h"
36 #include "ogr_spatialref.h"
37 #include "ogr_srs_api.h"
38 
40 
41 #include <boost/algorithm/string/predicate.hpp>
42 #include "otbOGRHelpers.h"
43 
44 namespace otb
45 {
46 
48 {
49 public:
50  GDALDataTypeWrapper() : pixType(GDT_Byte) {}
53  {
54  pixType = w.pixType;
55  }
57  {
58  pixType = w.pixType;
59  return *this;
60  }
61  GDALDataType pixType;
62 }; // end of GDALDataTypeWrapper
63 
64 /*
65 template<class InputType>
66 void printOutputData(InputType *pData, int nbBands, int nbPixelToRead)
67 {
68  for (unsigned int itPxl = 0; itPxl < (unsigned int) (nbPixelToRead * nbBands); itPxl++)
69  {
70  std::cout << "Buffer["<< itPxl << "] = " << *(pData + itPxl) << std::endl;
71  }
72 };
73 
74 void printDataBuffer(unsigned char *pData, GDALDataType pxlType, int nbBands, int nbPixelToRead)
75 {
76  if (pxlType == GDT_Int16)
77  {
78  printOutputData( static_cast<short*>( static_cast<void*>(pData) ), nbBands, nbPixelToRead);
79  }
80  else if (pxlType == GDT_Int32)
81  {
82  printOutputData( static_cast<int*>( static_cast<void*>(pData) ), nbBands, nbPixelToRead);
83  }
84  else if (pxlType == GDT_Float32)
85  {
86  printOutputData( static_cast<float*>( static_cast<void*>(pData) ), nbBands, nbPixelToRead);
87  }
88  else if (pxlType == GDT_Float64)
89  {
90  printOutputData( static_cast<double*>( static_cast<void*>(pData) ), nbBands, nbPixelToRead);
91  }
92  else if (pxlType == GDT_CInt16)
93  {
94  printOutputData( static_cast<std::complex<short>*>( static_cast<void*>(pData) ), nbBands, nbPixelToRead);
95  }
96  else if (pxlType == GDT_CInt32)
97  {
98  printOutputData( static_cast<std::complex<int>*>( static_cast<void*>(pData) ), nbBands, nbPixelToRead);
99  }
100  else if (pxlType == GDT_CFloat32)
101  {
102  printOutputData( static_cast<std::complex<float>*>( static_cast<void*>(pData) ), nbBands, nbPixelToRead);
103  }
104  else if (pxlType == GDT_CFloat64)
105  {
106  printOutputData( static_cast<std::complex<double>*>( static_cast<void*>(pData) ), nbBands, nbPixelToRead);
107  }
108  else
109  {
110  std::cerr << "Pixel type unknown" << std::endl;
111  }
112 };
113 */
114 
116 {
117  // By default set number of dimensions to two.
118  this->SetNumberOfDimensions(2);
119 
120  // By default set pixel type to scalar.
122 
123  // By default set component type to unsigned char
125  m_UseCompression = false;
126  m_CompressionLevel = 4; // Range 0-9; 0 = no file compression, 9 = maximum file compression
127 
128  // Set default spacing to one
129  m_Spacing[0] = 1.0;
130  m_Spacing[1] = 1.0;
131  // Set default origin to zero
132  m_Origin[0] = 0.0;
133  m_Origin[1] = 0.0;
134 
135  m_IsIndexed = false;
136  m_DatasetNumber = 0;
137  //m_poBands = NULL;
138  //m_hDriver = NULL;
139  //m_poDataset = NULL;
140 
141  m_NbBands = 0;
143 
144  m_CanStreamWrite = false;
145  m_IsComplex = false;
146  m_IsVectorImage = false;
147 
149 }
150 
152 {
153  delete m_PxType;
154 }
155 
156 // Tell only if the file can be read with GDAL.
157 bool GDALImageIO::CanReadFile(const char* file)
158 {
159  // First check the extension
160  if (file == NULL)
161  {
162  itkDebugMacro(<< "No filename specified.");
163  return false;
164  }
166  return m_Dataset.IsNotNull();
167 }
168 
169 // Used to print information about this object
170 void GDALImageIO::PrintSelf(std::ostream& os, itk::Indent indent) const
171 {
172  Superclass::PrintSelf(os, indent);
173  os << indent << "Compression Level : " << m_CompressionLevel << "\n";
174  os << indent << "IsComplex (otb side) : " << m_IsComplex << "\n";
175  os << indent << "Byte per pixel : " << m_BytePerPixel << "\n";
176 }
177 
178 // Read a 3D image (or event more bands)... not implemented yet
180 {
181 }
182 
183 // Read image with GDAL
184 void GDALImageIO::Read(void* buffer)
185 {
186  // Convert buffer from void * to unsigned char *
187  unsigned char *p = static_cast<unsigned char *>(buffer);
188 
189  // Check if conversion succeed
190  if (p == NULL)
191  {
192  itkExceptionMacro(<< "GDAL : Bad alloc");
193  return;
194  }
195 
196  // Get nb. of lines and columns of the region to read
197  int lNbLines = this->GetIORegion().GetSize()[1];
198  int lNbColumns = this->GetIORegion().GetSize()[0];
199  int lFirstLine = this->GetIORegion().GetIndex()[1]; // [1... ]
200  int lFirstColumn = this->GetIORegion().GetIndex()[0]; // [1... ]
201 
202  GDALDataset* dataset = m_Dataset->GetDataSet();
203 
204  // This special case is due to the fact the CINT/CLONG types
205  // do not exists in ITK. In this case we only report the first band
206  // TODO This should be fixed
207  /*if (GDALDataTypeIsComplex(m_PxType->pixType)
208  && (m_PxType->pixType != GDT_CFloat32)
209  && (m_PxType->pixType != GDT_CFloat64))
210  {
211  int pixelOffset = m_BytePerPixel * m_NbBands;
212  int lineOffset = m_BytePerPixel * m_NbBands * lNbColumns;
213  int bandOffset = m_BytePerPixel;
214  int nbBands = m_NbBands;
215 
216  int nbPixelToRead = lNbColumns * lNbLines;
217  std::streamoff nbBytes = static_cast<std::streamoff>(m_NbBands) * static_cast<std::streamoff>(nbPixelToRead) * static_cast<std::streamoff>(m_BytePerPixel);
218  unsigned char *pBufferTemp = new unsigned char[static_cast<unsigned int>(nbBytes)];
219 
220  // keep it for the moment
221  otbMsgDevMacro(<< "Parameters RasterIO (case CInt and CShort):"
222  << "\n indX = " << lFirstColumn
223  << "\n indY = " << lFirstLine
224  << "\n sizeX = " << lNbColumns
225  << "\n sizeY = " << lNbLines
226  << "\n GDAL Data Type = " << GDALGetDataTypeName(m_PxType->pixType)
227  << "\n pixelOffset = " << pixelOffset
228  << "\n lineOffset = " << lineOffset
229  << "\n bandOffset = " << bandOffset);
230 
231  CPLErr lCrGdal = m_Dataset->GetDataSet()->RasterIO(GF_Read,
232  lFirstColumn,
233  lFirstLine,
234  lNbColumns,
235  lNbLines,
236  pBufferTemp, //p, // pData
237  lNbColumns,
238  lNbLines,
239  m_PxType->pixType,
240  nbBands,
241  // We want to read all bands
242  NULL,
243  pixelOffset,
244  lineOffset,
245  bandOffset);
246  // Check for gdal error
247  if (lCrGdal == CE_Failure)
248  {
249  itkExceptionMacro(<< "Error while reading image (GDAL format) " << m_FileName );
250  delete[] pBufferTemp;
251  return;
252  }
253  //std::cout << "RAW BUFFER:" <<std::endl;
254  //printDataBuffer(pBufferTemp, m_PxType->pixType, m_NbBands, lNbColumns*lNbLines);
255 
256  // Convert the buffer to GDT_Float64 type
257  typedef std::complex<float> RealType;
258  typedef double ScalarRealType;
259 
260  if (m_PxType->pixType == GDT_CInt32)
261  {
262  //std::cout << "Convert input File from GDT_CInt32 to GDT_CFloat32" << std::endl;
263  typedef std::complex<int> ComplexIntType;
264 
265  for (unsigned int itPxl = 0; itPxl < (unsigned int) (nbPixelToRead * m_NbBands); itPxl++)
266  {
267  ComplexIntType pxlValue = *(static_cast<ComplexIntType*>( static_cast<void*>(pBufferTemp)) + itPxl );
268 
269  RealType pxlValueReal( static_cast<ScalarRealType>(pxlValue.real()), static_cast<ScalarRealType>(pxlValue.imag()) );
270 
271  memcpy((void*) (&(p[itPxl*sizeof(RealType)])), (const void*) (&(pxlValueReal)), (size_t) (sizeof(RealType)));
272  }
273  }
274  else if (m_PxType->pixType == GDT_CInt16)
275  {
276  //std::cout << "Convert input File from GDT_CInt16 to GDT_CFloat32" << std::endl;
277  typedef std::complex<short> ComplexShortType;
278 
279  for (unsigned int itPxl = 0; itPxl < (unsigned int) (nbPixelToRead * m_NbBands); itPxl++)
280  {
281  ComplexShortType pxlValue = *(static_cast<ComplexShortType*>( static_cast<void*>(pBufferTemp)) + itPxl );
282 
283  RealType pxlValueReal( static_cast<ScalarRealType>(pxlValue.real()), static_cast<ScalarRealType>(pxlValue.imag()) );
284 
285  memcpy((void*) (&(p[itPxl*sizeof(RealType)])), (const void*) (&(pxlValueReal)), (size_t) (sizeof(RealType)));
286  }
287  }
288  //std::cout << "CONVERTED BUFFER:" <<std::endl;
289  //printDataBuffer(p, GDT_CFloat64, m_NbBands, lNbColumns*lNbLines);
290  delete[] pBufferTemp;
291  }
292 
293  // In the indexed case, one has to retrieve the index image and the
294  // color table, and translate p to a 4 components color values buffer
295  else*/ if (m_IsIndexed)
296  {
297  // TODO: This is a very special case and seems to be working only
298  // for unsigned char pixels. There might be a gdal method to do
299  // the work in a cleaner way
300  std::streamoff lNbPixels = (static_cast<std::streamoff>(lNbColumns))
301  * (static_cast<std::streamoff>(lNbLines));
302  std::streamoff lBufferSize = static_cast<std::streamoff>(m_BytePerPixel) * lNbPixels;
303  itk::VariableLengthVector<unsigned char> value(lBufferSize);
304 
305  std::streamoff step = static_cast<std::streamoff>(this->GetNumberOfComponents())
306  * static_cast<std::streamoff>(m_BytePerPixel);
307 
308  CPLErr lCrGdal = dataset->GetRasterBand(1)->RasterIO(GF_Read,
309  lFirstColumn,
310  lFirstLine,
311  lNbColumns,
312  lNbLines,
313  const_cast<unsigned char*>(value.GetDataPointer()),
314  lNbColumns,
315  lNbLines,
316  m_PxType->pixType,
317  0,
318  0);
319  if (lCrGdal == CE_Failure)
320  {
321  itkExceptionMacro(<< "Error while reading image (GDAL format) " << m_FileName.c_str() << ".");
322  }
323  // Interpret index as color
324  std::streamoff cpt(0);
325  GDALColorTable* colorTable = dataset->GetRasterBand(1)->GetColorTable();
326  for (std::streamoff i = 0; i < lBufferSize; i = i + static_cast<std::streamoff>(m_BytePerPixel))
327  {
328  GDALColorEntry color;
329  colorTable->GetColorEntryAsRGB(value[i], &color);
330  p[cpt] = color.c1;
331  p[cpt + 1] = color.c2;
332  p[cpt + 2] = color.c3;
333  p[cpt + 3] = color.c4;
334  cpt += step;
335  }
336  }
337  else
338  {
339  /******** Nominal case ***********/
340  int pixelOffset = m_BytePerPixel * m_NbBands;
341  int lineOffset = m_BytePerPixel * m_NbBands * lNbColumns;
342  int bandOffset = m_BytePerPixel;
343  int nbBands = m_NbBands;
344 
345  // In some cases, we need to change some parameters for RasterIO
346  if(!GDALDataTypeIsComplex(m_PxType->pixType) && m_IsComplex && m_IsVectorImage && (m_NbBands > 1))
347  {
348  pixelOffset = m_BytePerPixel * 2;
349  lineOffset = pixelOffset * lNbColumns;
350  bandOffset = m_BytePerPixel;
351  }
352 
353  // keep it for the moment
354  //otbMsgDevMacro(<< "Number of bands inside input file: " << m_NbBands);
355  otbMsgDevMacro(<< "Parameters RasterIO : \n"
356  << " indX = " << lFirstColumn << "\n"
357  << " indY = " << lFirstLine << "\n"
358  << " sizeX = " << lNbColumns << "\n"
359  << " sizeY = " << lNbLines << "\n"
360  << " GDAL Data Type = " << GDALGetDataTypeName(m_PxType->pixType) << "\n"
361  << " pixelOffset = " << pixelOffset << "\n"
362  << " lineOffset = " << lineOffset << "\n"
363  << " bandOffset = " << bandOffset);
364 
365  itk::TimeProbe chrono;
366  chrono.Start();
367  CPLErr lCrGdal = m_Dataset->GetDataSet()->RasterIO(GF_Read,
368  lFirstColumn,
369  lFirstLine,
370  lNbColumns,
371  lNbLines,
372  p,
373  lNbColumns,
374  lNbLines,
375  m_PxType->pixType,
376  nbBands,
377  // We want to read all bands
378  NULL,
379  pixelOffset,
380  lineOffset,
381  bandOffset);
382  chrono.Stop();
383  otbMsgDevMacro(<< "RasterIO Read took " << chrono.GetTotal() << " sec")
384 
385  // Check if gdal call succeed
386  if (lCrGdal == CE_Failure)
387  {
388  itkExceptionMacro(<< "Error while reading image (GDAL format) " << m_FileName.c_str() << ".");
389  return;
390  }
391  //printDataBuffer(p, m_PxType->pixType, m_NbBands, lNbColumns*lNbLines);
392  }
393 }
394 
395 bool GDALImageIO::GetSubDatasetInfo(std::vector<std::string> &names, std::vector<std::string> &desc)
396 {
397  // Note: we assume that the subdatasets are in order : SUBDATASET_ID_NAME, SUBDATASET_ID_DESC, SUBDATASET_ID+1_NAME, SUBDATASET_ID+1_DESC
398  char** papszMetadata;
399  papszMetadata = m_Dataset->GetDataSet()->GetMetadata("SUBDATASETS");
400 
401  // Have we find some dataSet ?
402  // This feature is supported only for hdf4 and hdf5 file (regards to the bug 270)
403  if ( (CSLCount(papszMetadata) > 0) &&
404  ( (strcmp(m_Dataset->GetDataSet()->GetDriver()->GetDescription(),"HDF4") == 0) ||
405  (strcmp(m_Dataset->GetDataSet()->GetDriver()->GetDescription(),"HDF5") == 0) ) )
406  {
407  for (int cpt = 0; papszMetadata[cpt] != NULL; ++cpt)
408  {
409  std::string key, name;
410  if (System::ParseHdfSubsetName(papszMetadata[cpt], key, name))
411  {
412  otbMsgDevMacro(<< "- key: " << key);
413  otbMsgDevMacro(<< "- name: " << name);
414  // check if this is a dataset name
415  if (key.find("_NAME") != std::string::npos) names.push_back(name);
416  // check if this is a dataset descriptor
417  if (key.find("_DESC") != std::string::npos) desc.push_back(name);
418  }
419  }
420  }
421  else
422  {
423  return false;
424  }
425  if (names.empty() || desc.empty()) return false;
426  if (names.size() != desc.size())
427  {
428  names.clear();
429  desc.clear();
430  return false;
431  }
432 
433  return true;
434 }
435 
437 {
438  return GDALDataTypeIsComplex(m_PxType->pixType);
439 }
440 
442 {
443  //std::ifstream file;
445 }
446 
448 {
449  // Detecting if we are in the case of an image with subdatasets
450  // example: hdf Modis data
451  // in this situation, we are going to change the filename to the
452  // supported gdal format using the m_DatasetNumber value
453  // HDF4_SDS:UNKNOWN:"myfile.hdf":2
454  // and make m_Dataset point to it.
455  if (m_Dataset->GetDataSet()->GetRasterCount() == 0)
456  {
457  // this happen in the case of a hdf file with SUBDATASETS
458  // Note: we assume that the datasets are in order
459  char** papszMetadata;
460  papszMetadata = m_Dataset->GetDataSet()->GetMetadata("SUBDATASETS");
461  //TODO: we might want to keep the list of names somewhere, at least the number of datasets
462  std::vector<std::string> names;
463  if( CSLCount(papszMetadata) > 0 )
464  {
465  for( int cpt = 0; papszMetadata[cpt] != NULL; ++cpt )
466  {
467  std::string key, name;
468  if (System::ParseHdfSubsetName(papszMetadata[cpt], key, name))
469  {
470  otbMsgDevMacro(<< "- key: " << key);
471  otbMsgDevMacro(<< "- name: " << name);
472  // check if this is a dataset name
473  if (key.find("_NAME") != std::string::npos) names.push_back(name);
474  }
475  }
476  }
477  if (m_DatasetNumber < names.size())
478  {
479  otbMsgDevMacro(<< "Reading: " << names[m_DatasetNumber]);
480  m_Dataset = GDALDriverManagerWrapper::GetInstance().Open(names[m_DatasetNumber]);
481  }
482  else
483  {
484  itkExceptionMacro(<< "Dataset requested does not exist (" << names.size() << " datasets)");
485  }
486  }
487 
488  GDALDataset* dataset = m_Dataset->GetDataSet();
489 
490  // Get image dimensions
491  if ( dataset->GetRasterXSize() == 0 || dataset->GetRasterYSize() == 0 )
492  {
493  itkExceptionMacro(<< "Dimension is undefined.");
494  }
495 
496  // Set image dimensions into IO
497  m_Dimensions[0] = dataset->GetRasterXSize();
498  m_Dimensions[1] = dataset->GetRasterYSize();
499 
500  // Get Number of Bands
501  m_NbBands = dataset->GetRasterCount();
502 
503  otbMsgDevMacro(<< "Input file dimension: " << m_Dimensions[0] << ", " << m_Dimensions[1]);
504  otbMsgDevMacro(<< "Number of bands inside input file: " << m_NbBands);
505 
507 
508  // Set the number of dimensions (verify for the dim )
509  this->SetNumberOfDimensions(2);
510 
511  otbMsgDevMacro(<< "Nb of Dimensions of the input file: " << m_NumberOfDimensions);
512 
513  // Automatically set the Type to Binary for GDAL data
514  this->SetFileTypeToBinary();
515 
516  // Get Data Type
517  // Consider only the data type given by the first band
518  // Maybe be could changed (to check)
519  m_PxType->pixType = dataset->GetRasterBand(1)->GetRasterDataType();
520  otbMsgDevMacro(<< "PixelType inside input file: "<< GDALGetDataTypeName(m_PxType->pixType) );
521  if (m_PxType->pixType == GDT_Byte)
522  {
524  }
525  else if (m_PxType->pixType == GDT_UInt16)
526  {
528  }
529  else if (m_PxType->pixType == GDT_Int16)
530  {
532  }
533  else if (m_PxType->pixType == GDT_UInt32)
534  {
536  }
537  else if (m_PxType->pixType == GDT_Int32)
538  {
540  }
541  else if (m_PxType->pixType == GDT_Float32)
542  {
544  }
545  else if (m_PxType->pixType == GDT_Float64)
546  {
548  }
549  else if (m_PxType->pixType == GDT_CInt16)
550  {
552  }
553  else if (m_PxType->pixType == GDT_CInt32)
554  {
556  }
557  else if (m_PxType->pixType == GDT_CFloat32)
558  {
560  }
561  else if (m_PxType->pixType == GDT_CFloat64)
562  {
564  }
565  else
566  {
567  itkExceptionMacro(<< "Pixel type unknown");
568  }
569 
570  if (this->GetComponentType() == CHAR)
571  {
572  m_BytePerPixel = 1;
573  }
574  else if (this->GetComponentType() == UCHAR)
575  {
576  m_BytePerPixel = 1;
577  }
578  else if (this->GetComponentType() == USHORT)
579  {
580  m_BytePerPixel = 2;
581  }
582  else if (this->GetComponentType() == SHORT)
583  {
584  m_BytePerPixel = 2;
585  }
586  else if (this->GetComponentType() == INT)
587  {
588  m_BytePerPixel = 4;
589  }
590  else if (this->GetComponentType() == UINT)
591  {
592  m_BytePerPixel = 4;
593  }
594  else if (this->GetComponentType() == LONG)
595  {
596  m_BytePerPixel = sizeof(long);
597  }
598  else if (this->GetComponentType() == ULONG)
599  {
600  m_BytePerPixel = sizeof(unsigned long);
601  }
602  else if (this->GetComponentType() == FLOAT)
603  {
604  m_BytePerPixel = 4;
605  }
606  else if (this->GetComponentType() == DOUBLE)
607  {
608  m_BytePerPixel = 8;
609  }
610  else if (this->GetComponentType() == CSHORT)
611  {
612  m_BytePerPixel = sizeof(std::complex<short>);
613  }
614  else if (this->GetComponentType() == CINT)
615  {
616  m_BytePerPixel = sizeof(std::complex<int>);
617  }
618  else if (this->GetComponentType() == CFLOAT)
619  {
620  /*if (m_PxType->pixType == GDT_CInt16)
621  m_BytePerPixel = sizeof(std::complex<short>);
622  else if (m_PxType->pixType == GDT_CInt32)
623  m_BytePerPixel = sizeof(std::complex<int>);
624  else*/
625  m_BytePerPixel = sizeof(std::complex<float>);
626  }
627  else if (this->GetComponentType() == CDOUBLE)
628  {
629  m_BytePerPixel = sizeof(std::complex<double>);
630  }
631  else
632  {
633  itkExceptionMacro(<< "Component type unknown");
634  }
635 
636  /******************************************************************/
637  // Set the pixel type with some special cases linked to the fact
638  // we read some data with complex type.
639  if ( GDALDataTypeIsComplex(m_PxType->pixType) ) // Try to read data with complex type with GDAL
640  {
641  if ( !m_IsComplex && m_IsVectorImage )
642  {
643  // we are reading a complex data set into an image where the pixel
644  // type is Vector<real>: we have to double the number of component
645  // for that to work
646  otbMsgDevMacro( << "GDALtypeIO= Complex and IFReader::InternalPixelType= Scalar and IFReader::PixelType= Vector");
648  this->SetPixelType(VECTOR);
649  }
650  else
651  {
652  this->SetPixelType(COMPLEX);
653  }
654  }
655  else // Try to read data with scalar type with GDAL
656  {
658  if (this->GetNumberOfComponents() == 1)
659  {
660  this->SetPixelType(SCALAR);
661  }
662  else
663  {
664  this->SetPixelType(VECTOR);
665  }
666  }
667 
668  /*** Parameters set by Internal Read function ***/
669  otbMsgDevMacro( << "Pixel Type IFReader = " << GetPixelTypeAsString(this->GetPixelType()) )
670  otbMsgDevMacro( << "Number of component IFReader = " << this->GetNumberOfComponents() )
671  otbMsgDevMacro( << "Byte per pixel set = " << m_BytePerPixel )
672  otbMsgDevMacro( << "Component Type set = " << GetComponentTypeAsString(this->GetComponentType()) );
673 
674  /*----------------------------------------------------------------------*/
675  /*-------------------------- METADATA ----------------------------------*/
676  /*----------------------------------------------------------------------*/
677 
678  // Now initialize the itk dictionary
680 
681  // Report the typical block size if possible
682  if (dataset->GetRasterCount() > 0)
683  {
684  int blockSizeX = 0;
685  int blockSizeY = 0;
686 
687  dataset->GetRasterBand(1)->GetBlockSize(&blockSizeX, &blockSizeY);
688 
689  if(blockSizeX > 0 && blockSizeY > 0)
690  {
691  itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::TileHintX, blockSizeX);
692  itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::TileHintY, blockSizeY);
693  }
694  }
695 
696 
697  /* -------------------------------------------------------------------- */
698  /* Get Spacing */
699  /* -------------------------------------------------------------------- */
700 
701  // Default Spacing
702  m_Spacing[0] = 1;
703  m_Spacing[1] = 1;
704  if (m_NumberOfDimensions == 3) m_Spacing[2] = 1;
705 
706  char** papszMetadata;
707  papszMetadata = dataset->GetMetadata(NULL);
708 
709  /* -------------------------------------------------------------------- */
710  /* Report general info. */
711  /* -------------------------------------------------------------------- */
712  GDALDriverH hDriver;
713 
714  hDriver = dataset->GetDriver();
715 
716  std::string driverShortName = static_cast<std::string>(GDALGetDriverShortName(hDriver));
717  std::string driverLongName = static_cast<std::string>(GDALGetDriverLongName(hDriver));
718 
719  itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::DriverShortNameKey, driverShortName);
720  itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::DriverLongNameKey, driverLongName);
721 
722  /* -------------------------------------------------------------------- */
723  /* Get the projection coordinate system of the image : ProjectionRef */
724  /* -------------------------------------------------------------------- */
725  if (dataset->GetProjectionRef() != NULL && !std::string(dataset->GetProjectionRef()).empty())
726  {
727  OGRSpatialReferenceH pSR = OSRNewSpatialReference(NULL);
728 
729  const char * pszProjection = NULL;
730  pszProjection = dataset->GetProjectionRef();
731 
732  if (OSRImportFromWkt(pSR, (char **) (&pszProjection)) == OGRERR_NONE)
733  {
734  char * pszPrettyWkt = NULL;
735  OSRExportToPrettyWkt(pSR, &pszPrettyWkt, FALSE);
736 
737  itk::EncapsulateMetaData<std::string> (dict, MetaDataKey::ProjectionRefKey,
738  static_cast<std::string>(pszPrettyWkt));
739 
740  CPLFree(pszPrettyWkt);
741  }
742  else
743  {
744  itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey,
745  static_cast<std::string>(dataset->GetProjectionRef()));
746  }
747 
748  if (pSR != NULL)
749  {
750  OSRRelease(pSR);
751  pSR = NULL;
752  }
753  }
754 
755  /* -------------------------------------------------------------------- */
756  /* Get the GCP projection coordinates of the image : GCPProjection */
757  /* -------------------------------------------------------------------- */
758 
759  unsigned int gcpCount = 0;
760  gcpCount = dataset->GetGCPCount();
761  if (gcpCount > 0)
762  {
763  std::string gcpProjectionKey = static_cast<std::string>(dataset->GetGCPProjection());
764  itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::GCPProjectionKey, gcpProjectionKey);
765 
766  if (gcpProjectionKey.empty())
767  {
768  gcpCount = 0; //fix for uninitialized gcpCount in gdal (when
769  //reading Palsar image)
770  }
771 
772  std::string key;
773 
774  itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::GCPCountKey, gcpCount);
775 
776  for (unsigned int cpt = 0; cpt < gcpCount; ++cpt)
777  {
778 
779  const GDAL_GCP *psGCP;
780  psGCP = dataset->GetGCPs() + cpt;
781 
782  OTB_GCP pOtbGCP;
783  pOtbGCP.m_Id = std::string(psGCP->pszId);
784  pOtbGCP.m_Info = std::string(psGCP->pszInfo);
785  pOtbGCP.m_GCPRow = psGCP->dfGCPLine;
786  pOtbGCP.m_GCPCol = psGCP->dfGCPPixel;
787  pOtbGCP.m_GCPX = psGCP->dfGCPX;
788  pOtbGCP.m_GCPY = psGCP->dfGCPY;
789  pOtbGCP.m_GCPZ = psGCP->dfGCPZ;
790 
791  // Complete the key with the GCP number : GCP_i
792  std::ostringstream lStream;
793  lStream << MetaDataKey::GCPParametersKey << cpt;
794  key = lStream.str();
795 
796  itk::EncapsulateMetaData<OTB_GCP>(dict, key, pOtbGCP);
797 
798  }
799 
800  }
801 
802  /* -------------------------------------------------------------------- */
803  /* Get the six coefficients of affine geoTtransform */
804  /* -------------------------------------------------------------------- */
805 
806  double adfGeoTransform[6];
807  MetaDataKey::VectorType VadfGeoTransform;
808 
809  if (dataset->GetGeoTransform(adfGeoTransform) == CE_None)
810  {
811  for (int cpt = 0; cpt < 6; ++cpt)
812  VadfGeoTransform.push_back(adfGeoTransform[cpt]);
813 
814  itk::EncapsulateMetaData<MetaDataKey::VectorType>(dict, MetaDataKey::GeoTransformKey, VadfGeoTransform);
815 
817  m_Origin[0] = VadfGeoTransform[0];
818  m_Origin[1] = VadfGeoTransform[3];
819  m_Spacing[0] = VadfGeoTransform[1];
820  m_Spacing[1] = VadfGeoTransform[5];
821 
822  }
823 
824  // Dataset info
825  otbMsgDevMacro(<< "**** ReadImageInformation() DATASET INFO: ****" );
826  otbMsgDevMacro(<< "Projection Ref: "<< dataset->GetProjectionRef() );
827  double GT[6];
828  if (dataset->GetGeoTransform(GT) == CE_None)
829  {
830  otbMsgDevMacro( <<"Geo Transform: "<< GT[0] << ", " << GT[1] << ", "
831  << GT[2] << ", " << GT[3] << ", "
832  << GT[4] << ", " << GT[5] );
833  }
834  else
835  {
836  otbMsgDevMacro( << "No Geo Transform: ");
837  }
838  otbMsgDevMacro(<< "GCP Projection Ref: "<< dataset->GetGCPProjection() );
839  otbMsgDevMacro(<< "GCP Count: " << dataset->GetGCPCount() );
840 
841  /* -------------------------------------------------------------------- */
842  /* Report metadata. */
843  /* -------------------------------------------------------------------- */
844 
845  papszMetadata = dataset->GetMetadata(NULL);
846  if (CSLCount(papszMetadata) > 0)
847  {
848  std::string key;
849 
850  for (int cpt = 0; papszMetadata[cpt] != NULL; ++cpt)
851  {
852  std::ostringstream lStream;
853  lStream << MetaDataKey::MetadataKey << cpt;
854  key = lStream.str();
855 
856  itk::EncapsulateMetaData<std::string>(dict, key,
857  static_cast<std::string>(papszMetadata[cpt]));
858  }
859  }
860 
861  /* -------------------------------------------------------------------- */
862  /* Report subdatasets. */
863  /* -------------------------------------------------------------------- */
864 
865  papszMetadata = dataset->GetMetadata("SUBDATASETS");
866  if (CSLCount(papszMetadata) > 0)
867  {
868  std::string key;
869 
870  for (int cpt = 0; papszMetadata[cpt] != NULL; ++cpt)
871  {
872  std::ostringstream lStream;
873  lStream << MetaDataKey::SubMetadataKey << cpt;
874  key = lStream.str();
875 
876  itk::EncapsulateMetaData<std::string>(dict, key,
877  static_cast<std::string>(papszMetadata[cpt]));
878  }
879  }
880 
881  /* -------------------------------------------------------------------- */
882  /* Report corners */
883  /* -------------------------------------------------------------------- */
884 
885  double GeoX(0), GeoY(0);
887 
888  GDALInfoReportCorner("Upper Left", 0.0, 0.0, GeoX, GeoY);
889  VGeo.push_back(GeoX);
890  VGeo.push_back(GeoY);
891 
892  itk::EncapsulateMetaData<MetaDataKey::VectorType>(dict, MetaDataKey::UpperLeftCornerKey, VGeo);
893 
894  VGeo.clear();
895 
896  GDALInfoReportCorner("Upper Right", m_Dimensions[0], 0.0, GeoX, GeoY);
897  VGeo.push_back(GeoX);
898  VGeo.push_back(GeoY);
899 
900  itk::EncapsulateMetaData<MetaDataKey::VectorType>(dict, MetaDataKey::UpperRightCornerKey, VGeo);
901 
902  VGeo.clear();
903 
904  GDALInfoReportCorner("Lower Left", 0.0, m_Dimensions[1], GeoX, GeoY);
905  VGeo.push_back(GeoX);
906  VGeo.push_back(GeoY);
907 
908  itk::EncapsulateMetaData<MetaDataKey::VectorType>(dict, MetaDataKey::LowerLeftCornerKey, VGeo);
909 
910  VGeo.clear();
911 
912  GDALInfoReportCorner("Lower Right", m_Dimensions[0], m_Dimensions[1], GeoX, GeoY);
913  VGeo.push_back(GeoX);
914  VGeo.push_back(GeoY);
915 
916  itk::EncapsulateMetaData<MetaDataKey::VectorType>(dict, MetaDataKey::LowerRightCornerKey, VGeo);
917 
918  VGeo.clear();
919 
920  /* -------------------------------------------------------------------- */
921  /* Color Table */
922  /* -------------------------------------------------------------------- */
923 
924  for (int iBand = 0; iBand < dataset->GetRasterCount(); iBand++)
925  {
926  GDALColorTableH hTable;
927  GDALRasterBandH hBand;
928  hBand = GDALGetRasterBand(dataset, iBand + 1);
929  if ((GDALGetRasterColorInterpretation(hBand) == GCI_PaletteIndex)
930  && (hTable = GDALGetRasterColorTable(hBand)) != NULL)
931  {
932  m_IsIndexed = true;
933 
934  unsigned int ColorEntryCount = GDALGetColorEntryCount(hTable);
935 
936  itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ColorTableNameKey,
937  static_cast<std::string>(GDALGetPaletteInterpretationName(
938  GDALGetPaletteInterpretation(hTable))));
939 
940  itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::ColorEntryCountKey, ColorEntryCount);
941 
942  for (int i = 0; i < GDALGetColorEntryCount(hTable); ++i)
943  {
944  GDALColorEntry sEntry;
945  MetaDataKey::VectorType VColorEntry;
946 
947  GDALGetColorEntryAsRGB(hTable, i, &sEntry);
948 
949  VColorEntry.push_back(sEntry.c1);
950  VColorEntry.push_back(sEntry.c2);
951  VColorEntry.push_back(sEntry.c3);
952  VColorEntry.push_back(sEntry.c4);
953 
954  itk::EncapsulateMetaData<MetaDataKey::VectorType>(dict, MetaDataKey::ColorEntryAsRGBKey, VColorEntry);
955 
956  }
957  }
958  }
959  if (m_IsIndexed)
960  {
961  m_NbBands *= 4;
963  this->SetPixelType(VECTOR);
964  }
965 }
966 
967 bool GDALImageIO::CanWriteFile(const char* name)
968 {
969  m_FileName = name;
970 
971  // First check the filename
972  if (name == NULL)
973  {
974  itkDebugMacro(<< "No filename specified.");
975  return false;
976  }
977 
978  // Get the GDAL format ID from the name
979  std::string gdalDriverShortName = FilenameToGdalDriverShortName(name);
980  if (gdalDriverShortName == "NOT-FOUND")
981  {
982  return false;
983  }
984 
985  // Check the driver for support of Create or at least CreateCopy
986  GDALDriver* driver = GDALDriverManagerWrapper::GetInstance().GetDriverByName(gdalDriverShortName);
987  if ( GDALGetMetadataItem( driver, GDAL_DCAP_CREATE, NULL ) == NULL
988  && GDALGetMetadataItem( driver, GDAL_DCAP_CREATECOPY, NULL ) == NULL )
989  {
990  itkDebugMacro(<< "The driver " << GDALGetDriverShortName(driver) << " does not support writing");
991  return false;
992  }
993  return true;
994 }
995 
997 {
998  // Get the GDAL format ID from the name
999  std::string gdalDriverShortName = FilenameToGdalDriverShortName(m_FileName);
1000  GDALDriver* driver = GDALDriverManagerWrapper::GetInstance().GetDriverByName(gdalDriverShortName);
1001 
1002  if (driver == NULL)
1003  {
1004  itkDebugMacro(<< "Unable to instantiate driver " << gdalDriverShortName);
1005  m_CanStreamWrite = false;
1006  }
1007  if ( GDALGetMetadataItem( driver, GDAL_DCAP_CREATE, NULL ) != NULL )
1008  {
1009  m_CanStreamWrite = true;
1010  }
1011  else
1012  {
1013  m_CanStreamWrite = false;
1014  }
1015 
1016  return m_CanStreamWrite;
1017 }
1018 
1019 void GDALImageIO::Write(const void* buffer)
1020 {
1021  // Check if we have to write the image information
1022  if (m_FlagWriteImageInformation == true)
1023  {
1024  this->InternalWriteImageInformation(buffer);
1026  }
1027 
1028  // Check if conversion succeed
1029  if (buffer == NULL)
1030  {
1031  itkExceptionMacro(<< "GDAL : Bad alloc");
1032  return;
1033  }
1034 
1035  // Compute offset and size
1036  unsigned int lNbLines = this->GetIORegion().GetSize()[1];
1037  unsigned int lNbColumns = this->GetIORegion().GetSize()[0];
1038  int lFirstLine = this->GetIORegion().GetIndex()[1]; // [1... ]
1039  int lFirstColumn = this->GetIORegion().GetIndex()[0]; // [1... ]
1040 
1041  // Particular case: checking that the written region is the same size
1042  // of the entire image
1043  // starting at offset 0 (when no streaming)
1044  if ((lNbLines == m_Dimensions[1]) && (lNbColumns == m_Dimensions[0]))
1045  {
1046  lFirstLine = 0;
1047  lFirstColumn = 0;
1048  }
1049 
1050  // Convert buffer from void * to unsigned char *
1051  //unsigned char *p = static_cast<unsigned char*>( const_cast<void *>(buffer));
1052  //printDataBuffer(p, m_PxType->pixType, m_NbBands, 10*2); // Buffer incorrect
1053 
1054  // If driver supports streaming
1055  if (m_CanStreamWrite)
1056  {
1057 
1058  otbMsgDevMacro(<< "RasterIO Write requested region : " << this->GetIORegion() <<
1059  "\n, lNbColumns =" << lNbColumns <<
1060  "\n, lNbLines =" << lNbLines <<
1061  "\n, m_PxType =" << GDALGetDataTypeName(m_PxType->pixType) <<
1062  "\n, m_NbBands =" << m_NbBands <<
1063  "\n, m_BytePerPixel ="<< m_BytePerPixel <<
1064  "\n, Pixel offset =" << m_BytePerPixel * m_NbBands << // is nbComp * BytePerPixel
1065  "\n, Line offset =" << m_BytePerPixel * m_NbBands * lNbColumns << // is pixelOffset * nbColumns
1066  "\n, Band offset =" << m_BytePerPixel) // is BytePerPixel
1067 
1068  itk::TimeProbe chrono;
1069  chrono.Start();
1070  CPLErr lCrGdal = m_Dataset->GetDataSet()->RasterIO(GF_Write,
1071  lFirstColumn,
1072  lFirstLine,
1073  lNbColumns,
1074  lNbLines,
1075  const_cast<void *>(buffer),
1076  lNbColumns,
1077  lNbLines,
1078  m_PxType->pixType,
1079  m_NbBands,
1080  // We want to write all bands
1081  NULL,
1082  // Pixel offset
1083  // is nbComp * BytePerPixel
1085  // Line offset
1086  // is pixelOffset * nbColumns
1087  m_BytePerPixel * m_NbBands * lNbColumns,
1088  // Band offset is BytePerPixel
1089  m_BytePerPixel);
1090  chrono.Stop();
1091  otbMsgDevMacro(<< "RasterIO Write took " << chrono.GetTotal() << " sec")
1092 
1093  // Check if writing succeed
1094  if (lCrGdal == CE_Failure)
1095  {
1096  itkExceptionMacro(<< "Error while writing image (GDAL format) " << m_FileName.c_str() << ".");
1097  }
1098  // Flush dataset cache
1099  m_Dataset->GetDataSet()->FlushCache();
1100  }
1101  else
1102  {
1103  // We only wrote data to the memory dataset
1104  // Now write it to the real file with CreateCopy()
1105  std::string gdalDriverShortName = FilenameToGdalDriverShortName(m_FileName);
1106  std::string realFileName = GetGdalWriteImageFileName(gdalDriverShortName, m_FileName);
1107 
1108  GDALDriver* driver = GDALDriverManagerWrapper::GetInstance().GetDriverByName(gdalDriverShortName);
1109  if (driver == NULL)
1110  {
1111  itkExceptionMacro(<< "Unable to instantiate driver " << gdalDriverShortName << " to write " << m_FileName);
1112  }
1113 
1114  GDALCreationOptionsType creationOptions = m_CreationOptions;
1115  GDALDataset* hOutputDS = driver->CreateCopy( realFileName.c_str(), m_Dataset->GetDataSet(), FALSE,
1116  otb::ogr::StringListConverter(creationOptions).to_ogr(),
1117  NULL, NULL );
1118  GDALClose(hOutputDS);
1119  }
1120 
1121 
1122  if (lFirstLine + lNbLines == m_Dimensions[1]
1123  && lFirstColumn + lNbColumns == m_Dimensions[0])
1124  {
1125  // Last pixel written
1126  // Reinitialize to close the file
1128  }
1129 }
1130 
1133 {
1134 }
1135 
1137 {
1138  char ** papszOptions = NULL;
1139  std::string driverShortName;
1140  m_NbBands = this->GetNumberOfComponents();
1141 
1142  if ((m_Dimensions[0] == 0) && (m_Dimensions[1] == 0))
1143  {
1144  itkExceptionMacro(<< "Dimensions are not defined.");
1145  }
1146 
1147  if ((this->GetPixelType() == COMPLEX) /*&& (m_NbBands / 2 > 0)*/)
1148  {
1149  //m_NbBands /= 2;
1150 
1151  if (this->GetComponentType() == CSHORT)
1152  {
1153  m_BytePerPixel = 4;
1154  m_PxType->pixType = GDT_CInt16;
1155  }
1156  else if (this->GetComponentType() == CINT)
1157  {
1158  m_BytePerPixel = 8;
1159  m_PxType->pixType = GDT_CInt32;
1160  }
1161  else if (this->GetComponentType() == CFLOAT)
1162  {
1163  m_BytePerPixel = 8;
1164  m_PxType->pixType = GDT_CFloat32;
1165  }
1166  else if (this->GetComponentType() == CDOUBLE)
1167  {
1168  m_BytePerPixel = 16;
1169  m_PxType->pixType = GDT_CFloat64;
1170  }
1171  else
1172  {
1173  itkExceptionMacro(<< "This complex type is not defined :" << this->GetPixelTypeAsString(this->GetPixelType()) );
1174  }
1175  }
1176  else
1177  {
1178  if (this->GetComponentType() == CHAR)
1179  {
1180  m_BytePerPixel = 1;
1181  m_PxType->pixType = GDT_Byte;
1182  }
1183  else if (this->GetComponentType() == UCHAR)
1184  {
1185  m_BytePerPixel = 1;
1186  m_PxType->pixType = GDT_Byte;
1187  }
1188  else if (this->GetComponentType() == USHORT)
1189  {
1190  m_BytePerPixel = 2;
1191  m_PxType->pixType = GDT_UInt16;
1192  }
1193  else if (this->GetComponentType() == SHORT)
1194  {
1195  m_BytePerPixel = 2;
1196  m_PxType->pixType = GDT_Int16;
1197  }
1198  else if (this->GetComponentType() == INT)
1199  {
1200  m_BytePerPixel = 4;
1201  m_PxType->pixType = GDT_Int32;
1202  }
1203  else if (this->GetComponentType() == UINT)
1204  {
1205  m_BytePerPixel = 4;
1206  m_PxType->pixType = GDT_UInt32;
1207  }
1208  else if (this->GetComponentType() == LONG)
1209  {
1210  m_BytePerPixel = sizeof(long);
1211  if( m_BytePerPixel == 8 )
1212  {
1213  itkWarningMacro(<< "Cast a long (64 bits) image into an int (32 bits) one.")
1214  }
1215  m_PxType->pixType = GDT_Int32;
1216  }
1217  else if (this->GetComponentType() == ULONG)
1218  {
1219  m_BytePerPixel = sizeof(unsigned long);
1220  if( m_BytePerPixel == 8 )
1221  {
1222  itkWarningMacro(<< "Cast an unsigned long (64 bits) image into an unsigned int (32 bits) one.")
1223  }
1224  m_PxType->pixType = GDT_UInt32;
1225  }
1226  else if (this->GetComponentType() == FLOAT)
1227  {
1228  m_BytePerPixel = 4;
1229  m_PxType->pixType = GDT_Float32;
1230  }
1231  else if (this->GetComponentType() == DOUBLE)
1232  {
1233  m_BytePerPixel = 8;
1234  m_PxType->pixType = GDT_Float64;
1235  }
1236  else
1237  {
1238  m_BytePerPixel = 1;
1239  m_PxType->pixType = GDT_Byte;
1240  }
1241  }
1242 
1243  // Automatically set the Type to Binary for GDAL data
1244  this->SetFileTypeToBinary();
1245 
1246  driverShortName = FilenameToGdalDriverShortName(m_FileName);
1247  if (driverShortName == "NOT-FOUND")
1248  {
1249  itkExceptionMacro(
1250  << "GDAL Writing failed : the image file name '" << m_FileName.c_str() << "' is not recognized by GDAL.");
1251  }
1252 
1253  if (m_CanStreamWrite)
1254  {
1255  GDALCreationOptionsType creationOptions = m_CreationOptions;
1256 /*
1257  // Force tile mode for TIFF format if no creation option are given
1258  if( driverShortName == "GTiff" )
1259  {
1260  if ( CreationOptionContains( "TILED=YES" ) )
1261  {
1262  // User requested tiled TIFF explicitly
1263  //
1264  // Let GDAL set up the BLOCKXSIZE and BLOCKYSIZE
1265  // or suppose the user have set it also along with TILED=YES
1266  // This allows the user to have complete
1267  // control over the tiling scheme
1268  }
1269  else if ( CreationOptionContains( "BLOCKYSIZE=" ) )
1270  {
1271  // User did not set "TILED=YES" but set "BLOCKYSIZE="
1272  // -> He requested a stripped TIFF
1273  }
1274  else
1275  {
1276  // User did not specify "TILED=YES" nor "BLOCKYSIZE=?"
1277  // Switch to TILED mode automatically, and choose BLOCKXSIZE and BLOCKYSIZE for him
1278 
1279  otbMsgDevMacro(<< "Enabling TIFF Tiled mode")
1280 
1281  // Use a fixed tile size
1282  // Take as reference is a 256*256 short int 4 bands tile
1283  const unsigned int ReferenceTileSizeInBytes = 256 * 256 * 4 * 2;
1284  const unsigned int NbPixelPerTile = ReferenceTileSizeInBytes / m_BytePerPixel / m_NbBands;
1285  const unsigned int IdealTileDimension = static_cast<unsigned int>( vcl_sqrt(static_cast<float>(NbPixelPerTile)) );
1286 
1287  // Set tileDimension to the nearest power of two and aligned to
1288  // 16 pixels (needed by TIFF spec)
1289  unsigned int tileDimension = 16;
1290  while(2*tileDimension < IdealTileDimension)
1291  {
1292  tileDimension*=2;
1293  }
1294  otbMsgDevMacro(<< "Tile dimension : " << tileDimension << " * " << tileDimension)
1295 
1296  std::ostringstream tileDimensionStr;
1297  tileDimensionStr << tileDimension;
1298 
1299  creationOptions.push_back( "TILED=YES" );
1300  creationOptions.push_back( std::string("BLOCKXSIZE=") + tileDimensionStr.str() );
1301  creationOptions.push_back( std::string("BLOCKYSIZE=") + tileDimensionStr.str() );
1302  }
1303  }
1304 */
1306  driverShortName,
1307  GetGdalWriteImageFileName(driverShortName, m_FileName),
1308  m_Dimensions[0], m_Dimensions[1],
1310  otb::ogr::StringListConverter(creationOptions).to_ogr());
1311  }
1312  else
1313  {
1314  // buffer casted in unsigned long cause under Win32 the address
1315  // doesn't begin with 0x, the address in not interpreted as
1316  // hexadecimal but alpha numeric value, then the conversion to
1317  // integer make us pointing to an non allowed memory block => Crash.
1318  std::ostringstream stream;
1319  stream << "MEM:::"
1320  << "DATAPOINTER=" << (unsigned long)(buffer) << ","
1321  << "PIXELS=" << m_Dimensions[0] << ","
1322  << "LINES=" << m_Dimensions[1] << ","
1323  << "BANDS=" << m_NbBands << ","
1324  << "DATATYPE=" << GDALGetDataTypeName(m_PxType->pixType) << ","
1325  << "PIXELOFFSET=" << m_BytePerPixel * m_NbBands << ","
1326  << "LINEOFFSET=" << m_BytePerPixel * m_NbBands * m_Dimensions[0] << ","
1327  << "BANDOFFSET=" << m_BytePerPixel;
1328 
1330  }
1331 
1332  if (m_Dataset.IsNull())
1333  {
1334  itkExceptionMacro(
1335  << "GDAL Writing failed : Impossible to create the image file name '" << m_FileName << "'.");
1336  }
1337 
1338  /*----------------------------------------------------------------------*/
1339  /*-------------------------- METADATA ----------------------------------*/
1340  /*----------------------------------------------------------------------*/
1341 
1342  // Now initialize the itk dictionary
1344  std::ostringstream oss;
1345  GDALDataset* dataset = m_Dataset->GetDataSet();
1346 
1347  std::string projectionRef;
1348  itk::ExposeMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey, projectionRef);
1349 
1350  /* -------------------------------------------------------------------- */
1351  /* Set the GCPs */
1352  /* -------------------------------------------------------------------- */
1353  const double Epsilon = 1E-10;
1354  if (projectionRef.empty()
1355  && (vcl_abs(m_Origin[0]) > Epsilon
1356  || vcl_abs(m_Origin[1]) > Epsilon
1357  || vcl_abs(m_Spacing[0] - 1) > Epsilon
1358  || vcl_abs(m_Spacing[1] - 1) > Epsilon) )
1359  {
1360  // See issue #303 :
1361  // If there is no ProjectionRef, and the GeoTransform is not the identity,
1362  // then saving also GCPs is undefined behavior for GDAL, and a WGS84 projection crs
1363  // is assigned arbitrarily
1364  otbMsgDevMacro(<< "Skipping GCPs saving to prevent GDAL from assigning a WGS84 projection ref to the file")
1365  }
1366  else
1367  {
1368  unsigned int gcpCount = 0;
1369  itk::ExposeMetaData<unsigned int>(dict, MetaDataKey::GCPCountKey, gcpCount);
1370 
1371  if (gcpCount > 0)
1372  {
1373 
1374  GDAL_GCP * gdalGcps = new GDAL_GCP[gcpCount];
1375 
1376  for (unsigned int gcpIndex = 0; gcpIndex < gcpCount; ++gcpIndex)
1377  {
1378  //Build the GCP string in the form of GCP_n
1379  std::ostringstream lStream;
1380  lStream << MetaDataKey::GCPParametersKey << gcpIndex;
1381  std::string key = lStream.str();
1382 
1383  OTB_GCP gcp;
1384  itk::ExposeMetaData<OTB_GCP>(dict, key, gcp);
1385 
1386  gdalGcps[gcpIndex].pszId = const_cast<char *>(gcp.m_Id.c_str());
1387  gdalGcps[gcpIndex].pszInfo = const_cast<char *>(gcp.m_Info.c_str());
1388  gdalGcps[gcpIndex].dfGCPPixel = gcp.m_GCPCol;
1389  gdalGcps[gcpIndex].dfGCPLine = gcp.m_GCPRow;
1390  gdalGcps[gcpIndex].dfGCPX = gcp.m_GCPX;
1391  gdalGcps[gcpIndex].dfGCPY = gcp.m_GCPY;
1392  gdalGcps[gcpIndex].dfGCPZ = gcp.m_GCPZ;
1393  }
1394 
1395  std::string gcpProjectionRef;
1396  itk::ExposeMetaData<std::string>(dict, MetaDataKey::GCPProjectionKey, gcpProjectionRef);
1397 
1398  dataset->SetGCPs(gcpCount, gdalGcps, gcpProjectionRef.c_str());
1399 
1400  delete[] gdalGcps;
1401  }
1402  }
1403 
1404  /* -------------------------------------------------------------------- */
1405  /* Set the projection coordinate system of the image : ProjectionRef */
1406  /* -------------------------------------------------------------------- */
1407  if (!projectionRef.empty())
1408  {
1409  dataset->SetProjection(projectionRef.c_str());
1410  }
1411 
1412  /* -------------------------------------------------------------------- */
1413  /* Set the six coefficients of affine geoTransform */
1414  /* -------------------------------------------------------------------- */
1415  itk::VariableLengthVector<double> geoTransform(6);
1417  geoTransform[0] = m_Origin[0];
1418  geoTransform[3] = m_Origin[1];
1419  geoTransform[1] = m_Spacing[0];
1420  geoTransform[5] = m_Spacing[1];
1421 
1422  // FIXME: Here component 1 and 4 should be replaced by the orientation parameters
1423  geoTransform[2] = 0.;
1424  geoTransform[4] = 0.;
1425  dataset->SetGeoTransform(const_cast<double*>(geoTransform.GetDataPointer()));
1426 
1427  /* -------------------------------------------------------------------- */
1428  /* Report metadata. */
1429  /* -------------------------------------------------------------------- */
1430 
1431  std::string svalue = "";
1432  std::vector<std::string> keys = dict.GetKeys();
1433  std::string const metadataKey = MetaDataKey::MetadataKey;
1434 
1435  for (unsigned int itkey = 0; itkey < keys.size(); ++itkey)
1436  {
1438  if (keys[itkey].compare(0, metadataKey.length(), metadataKey) == 0)
1439  {
1440  itk::ExposeMetaData<std::string>(dict, keys[itkey], svalue);
1441  unsigned int equalityPos = svalue.find_first_of('=');
1442  std::string tag = svalue.substr(0, equalityPos);
1443  std::string value = svalue.substr(equalityPos + 1);
1444  otbMsgDevMacro(<< "Metadata: " << tag << "=" << value);
1445  dataset->SetMetadataItem(tag.c_str(), value.c_str(), NULL);
1446  }
1447  }
1448  // END
1449 
1450  // Dataset info
1451  otbMsgDevMacro( << "**** WriteImageInformation() DATASET INFO: ****" );
1452  otbMsgDevMacro( << "Projection Ref: "<<dataset->GetProjectionRef() );
1453  double GT[6];
1454  if (dataset->GetGeoTransform(GT) == CE_None)
1455  {
1456  otbMsgDevMacro( <<"Geo Transform: "<< GT[0] << ", " << GT[1] << ", "
1457  << GT[2] << ", " << GT[3] << ", "
1458  << GT[4] << ", " << GT[5] );
1459  }
1460  else
1461  {
1462  otbMsgDevMacro( << "No Geo Transform: ");
1463  }
1464 
1465  otbMsgDevMacro( << "GCP Projection Ref: "<< dataset->GetGCPProjection() );
1466  otbMsgDevMacro( << "GCP Count: " << dataset->GetGCPCount() );
1467 
1468 }
1469 
1470 std::string GDALImageIO::FilenameToGdalDriverShortName(const std::string& name) const
1471 {
1472  std::string extension;
1473  std::string gdalDriverShortName;
1474 
1475  // Get extension in lowercase
1476  extension = otb::System::SetToLower( System::GetExtension(name) );
1477 
1478  if ( extension == "tif" || extension == "tiff" )
1479  gdalDriverShortName = "GTiff";
1480  else if ( extension == "hdr" )
1481  gdalDriverShortName = "ENVI";
1482  else if ( extension == "img" )
1483  gdalDriverShortName = "HFA";
1484  else if ( extension == "ntf" )
1485  gdalDriverShortName = "NITF";
1486  else if ( extension == "png" )
1487  gdalDriverShortName="PNG";
1488  else if ( extension == "jpg" || extension== "jpeg" )
1489  gdalDriverShortName="JPEG";
1490  else if ( extension == "pix" )
1491  gdalDriverShortName="PCIDSK";
1492  else if ( extension == "lbl" || extension == "pds" )
1493  gdalDriverShortName="ISIS2";
1494  else
1495  gdalDriverShortName = "NOT-FOUND";
1496 
1497  return gdalDriverShortName;
1498 }
1499 
1500 std::string GDALImageIO::GetGdalWriteImageFileName(const std::string& gdalDriverShortName, const std::string& filename) const
1501 {
1502  std::string gdalFileName;
1503 
1504  gdalFileName = filename;
1505  // Suppress hdr extension for ENVI format
1506  if (gdalDriverShortName == "ENVI")
1507  {
1508  gdalFileName = System::GetRootName(filename);
1509  }
1510  return gdalFileName;
1511 }
1512 
1513 bool GDALImageIO::GDALInfoReportCorner(const char * /*corner_name*/, double x, double y, double& GeoX, double& GeoY) const
1514 {
1515  double adfGeoTransform[6];
1516  bool IsTrue;
1517 
1518  /* -------------------------------------------------------------------- */
1519  /* Transform the point into georeferenced coordinates. */
1520  /* -------------------------------------------------------------------- */
1521  if (m_Dataset->GetDataSet()->GetGeoTransform(adfGeoTransform) == CE_None)
1522  {
1523  GeoX = adfGeoTransform[0] + adfGeoTransform[1] * x + adfGeoTransform[2] * y;
1524  GeoY = adfGeoTransform[3] + adfGeoTransform[4] * x + adfGeoTransform[5] * y;
1525  IsTrue = true;
1526  }
1527 
1528  else
1529  {
1530  GeoX = x;
1531  GeoY = y;
1532  IsTrue = false;
1533  }
1534 
1535  return IsTrue;
1536 }
1537 
1538 bool GDALImageIO::CreationOptionContains(std::string partialOption) const
1539 {
1540  size_t i;
1541  for (i = 0; i < m_CreationOptions.size(); ++i)
1542  {
1543  if (boost::algorithm::starts_with(m_CreationOptions[i], partialOption))
1544  {
1545  break;
1546  }
1547  }
1548  return (i != m_CreationOptions.size());
1549 }
1550 
1551 } // end namespace otb

Generated at Sun Feb 3 2013 00:24:12 for Orfeo Toolbox with doxygen 1.8.1.1