otbImageMetadataInterfaceBase.cxx 22.3 KB
Newer Older
1
/*
2
 * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
20
21
22
23


#include "otbImageMetadataInterfaceBase.h"

24
#include "otbNoDataHelper.h"
Guillaume Pasero's avatar
Guillaume Pasero committed
25
#include "otbGeometryMetadata.h"
26
#include "itkMetaDataObject.h"
27
#include "itksys/SystemTools.hxx"
28

29

30
31
32
namespace otb
{

33
ImageMetadataInterfaceBase::ImageMetadataInterfaceBase()
34
35
36
{
}

37
38
39
40
41
42
43
44
45
46
47
48
49

void ImageMetadataInterfaceBase::SetImage(ImageType* image)
{
  this->SetMetaDataDictionary(image->GetMetaDataDictionary());
}


void ImageMetadataInterfaceBase::SetMetaDataDictionary(const MetaDataDictionaryType& dict)
{
  m_MetaDataDictionary = dict;
}


Guillaume Pasero's avatar
Guillaume Pasero committed
50
51
const ImageMetadataInterfaceBase::MetaDataDictionaryType&
ImageMetadataInterfaceBase::GetMetaDataDictionary() const
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
{
  return m_MetaDataDictionary;
}


void ImageMetadataInterfaceBase::SetImageMetadata(ImageMetadata imd)
{
  m_Imd = std::move(imd);
}


const ImageMetadata& ImageMetadataInterfaceBase::GetImageMetadata() const
{
  return m_Imd;
}


69
std::string ImageMetadataInterfaceBase::GetProjectionRef() const
70
{
71
  std::string                   metadata;
72
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
73
74

  if (dict.HasKey(MetaDataKey::ProjectionRefKey))
75
  {
76
    itk::ExposeMetaData<std::string>(dict, static_cast<std::string>(MetaDataKey::ProjectionRefKey), metadata);
OTB Bot's avatar
STYLE    
OTB Bot committed
77
    return (metadata);
78
79
80
  }
  else
    return ("");
81
82
}

83
std::string ImageMetadataInterfaceBase::GetGCPProjection() const
84
{
85
  std::string                   metadata;
86
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
87
88

  if (dict.HasKey(MetaDataKey::GCPProjectionKey))
89
  {
90
    itk::ExposeMetaData<std::string>(dict, static_cast<std::string>(MetaDataKey::GCPProjectionKey), metadata);
OTB Bot's avatar
STYLE    
OTB Bot committed
91
    return (metadata);
92
93
94
  }
  else
    return ("");
95
96
}

97
unsigned int ImageMetadataInterfaceBase::GetGCPCount() const
98
{
99
100
  unsigned int                  GCPCount = 0;
  const MetaDataDictionaryType& dict     = this->GetMetaDataDictionary();
101
102

  if (dict.HasKey(MetaDataKey::GCPCountKey))
103
  {
104
    itk::ExposeMetaData<unsigned int>(dict, MetaDataKey::GCPCountKey, GCPCount);
105
  }
106
107
108
109

  return (GCPCount);
}

110
GCP& ImageMetadataInterfaceBase::GetGCPs(unsigned int GCPnum)
111
{
112
  std::string                   key;
113
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
114

Emmanuel Christophe's avatar
Emmanuel Christophe committed
115
  std::ostringstream lStream;
116
117
118
119
  lStream << MetaDataKey::GCPParametersKey << GCPnum;
  key = lStream.str();

  if (dict.HasKey(key))
120
  {
121

122
    itk::ExposeMetaData<GCP>(dict, key, m_GCP);
123
  }
OTB Bot's avatar
STYLE    
OTB Bot committed
124
  return (m_GCP);
125
126
}

127
std::string ImageMetadataInterfaceBase::GetGCPId(unsigned int GCPnum) const
128
{
129
  std::string                   key;
130
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
131

Emmanuel Christophe's avatar
Emmanuel Christophe committed
132
  std::ostringstream lStream;
133
134
135
136
  lStream << MetaDataKey::GCPParametersKey << GCPnum;
  key = lStream.str();

  if (dict.HasKey(key))
137
  {
138
139
    GCP gcp;
    itk::ExposeMetaData<GCP>(dict, key, gcp);
OTB Bot's avatar
STYLE    
OTB Bot committed
140
    return (gcp.m_Id);
141
142
143
  }
  else
    return ("");
144
145
}

146
std::string ImageMetadataInterfaceBase::GetGCPInfo(unsigned int GCPnum) const
147
{
148
  std::string                   key;
149
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
150

Emmanuel Christophe's avatar
Emmanuel Christophe committed
151
  std::ostringstream lStream;
152
153
154
155
  lStream << MetaDataKey::GCPParametersKey << GCPnum;
  key = lStream.str();

  if (dict.HasKey(key))
156
  {
157
158
    GCP gcp;
    itk::ExposeMetaData<GCP>(dict, key, gcp);
OTB Bot's avatar
STYLE    
OTB Bot committed
159
    return (gcp.m_Info);
160
161
162
  }
  else
    return ("");
163
164
}

165
double ImageMetadataInterfaceBase::GetGCPRow(unsigned int GCPnum) const
166
{
167
  std::string                   key;
168
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
169

Emmanuel Christophe's avatar
Emmanuel Christophe committed
170
  std::ostringstream lStream;
171
172
173
174
  lStream << MetaDataKey::GCPParametersKey << GCPnum;
  key = lStream.str();

  if (dict.HasKey(key))
175
  {
176
177
    GCP gcp;
    itk::ExposeMetaData<GCP>(dict, key, gcp);
OTB Bot's avatar
STYLE    
OTB Bot committed
178
    return (gcp.m_GCPRow);
179
180
181
  }
  else
    return (0);
182
183
}

184
double ImageMetadataInterfaceBase::GetGCPCol(unsigned int GCPnum) const
185
{
186
  std::string                   key;
187
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
188

Emmanuel Christophe's avatar
Emmanuel Christophe committed
189
  std::ostringstream lStream;
190
191
192
193
  lStream << MetaDataKey::GCPParametersKey << GCPnum;
  key = lStream.str();

  if (dict.HasKey(key))
194
  {
195
196
    GCP gcp;
    itk::ExposeMetaData<GCP>(dict, key, gcp);
OTB Bot's avatar
STYLE    
OTB Bot committed
197
    return (gcp.m_GCPCol);
198
199
200
  }
  else
    return (0);
201
202
}

203
double ImageMetadataInterfaceBase::GetGCPX(unsigned int GCPnum) const
204
{
205
  std::string                   key;
206
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
207

Emmanuel Christophe's avatar
Emmanuel Christophe committed
208
  std::ostringstream lStream;
209
210
211
212
  lStream << MetaDataKey::GCPParametersKey << GCPnum;
  key = lStream.str();

  if (dict.HasKey(key))
213
  {
214
215
    GCP gcp;
    itk::ExposeMetaData<GCP>(dict, key, gcp);
OTB Bot's avatar
STYLE    
OTB Bot committed
216
    return (gcp.m_GCPX);
217
218
219
  }
  else
    return (0);
220
221
}

222
double ImageMetadataInterfaceBase::GetGCPY(unsigned int GCPnum) const
223
{
224
  std::string                   key;
225
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
226

Emmanuel Christophe's avatar
Emmanuel Christophe committed
227
  std::ostringstream lStream;
228
229
230
231
  lStream << MetaDataKey::GCPParametersKey << GCPnum;
  key = lStream.str();

  if (dict.HasKey(key))
232
  {
233
234
    GCP gcp;
    itk::ExposeMetaData<GCP>(dict, key, gcp);
OTB Bot's avatar
STYLE    
OTB Bot committed
235
    return (gcp.m_GCPY);
236
237
238
  }
  else
    return (0);
239
240
}

241
double ImageMetadataInterfaceBase::GetGCPZ(unsigned int GCPnum) const
242
{
243
  std::string                   key;
244
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
245

Emmanuel Christophe's avatar
Emmanuel Christophe committed
246
  std::ostringstream lStream;
247
248
249
250
  lStream << MetaDataKey::GCPParametersKey << GCPnum;
  key = lStream.str();

  if (dict.HasKey(key))
251
  {
252
253
    GCP gcp;
    itk::ExposeMetaData<GCP>(dict, key, gcp);
OTB Bot's avatar
STYLE    
OTB Bot committed
254
    return (gcp.m_GCPZ);
255
256
257
  }
  else
    return (0);
258
259
}

260
bool ImageMetadataInterfaceBase::GetNoDataFlags(std::vector<bool>& flags, std::vector<double>& values) const
261
{
262
  return ReadNoDataFlags(this->GetMetaDataDictionary(), flags, values);
263
264
}

265
ImageMetadataInterfaceBase::VectorType ImageMetadataInterfaceBase::GetGeoTransform() const
266
{
267
  VectorType                    adfGeoTransform;
268
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
269
270

  if (dict.HasKey(MetaDataKey::GeoTransformKey))
271
  {
272
    itk::ExposeMetaData<VectorType>(dict, MetaDataKey::GeoTransformKey, adfGeoTransform);
273
  }
OTB Bot's avatar
STYLE    
OTB Bot committed
274
  return (adfGeoTransform);
275
276
}

277
ImageMetadataInterfaceBase::VectorType ImageMetadataInterfaceBase::GetUpperLeftCorner() const
278
{
279
  VectorType                    UpperLeftCorner;
280
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
281
282

  if (dict.HasKey(MetaDataKey::UpperLeftCornerKey))
283
  {
284
    itk::ExposeMetaData<VectorType>(dict, MetaDataKey::UpperLeftCornerKey, UpperLeftCorner);
285
  }
OTB Bot's avatar
STYLE    
OTB Bot committed
286
  return (UpperLeftCorner);
287
288
}

289
ImageMetadataInterfaceBase::VectorType ImageMetadataInterfaceBase::GetUpperRightCorner() const
290
{
291
  VectorType                    UpperRightCorner;
292
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
293
294

  if (dict.HasKey(MetaDataKey::UpperRightCornerKey))
295
  {
296
    itk::ExposeMetaData<VectorType>(dict, MetaDataKey::UpperRightCornerKey, UpperRightCorner);
297
  }
OTB Bot's avatar
STYLE    
OTB Bot committed
298
  return (UpperRightCorner);
299
300
}

301
ImageMetadataInterfaceBase::VectorType ImageMetadataInterfaceBase::GetLowerLeftCorner() const
302
{
303
  VectorType                    LowerLeftCorner;
304
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
305
306

  if (dict.HasKey(MetaDataKey::LowerLeftCornerKey))
307
  {
308
    itk::ExposeMetaData<VectorType>(dict, MetaDataKey::LowerLeftCornerKey, LowerLeftCorner);
309
  }
OTB Bot's avatar
STYLE    
OTB Bot committed
310
  return (LowerLeftCorner);
311
312
}

313
ImageMetadataInterfaceBase::VectorType ImageMetadataInterfaceBase::GetLowerRightCorner() const
314
{
315
  VectorType                    LowerRightCorner;
316
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
317
318

  if (dict.HasKey(MetaDataKey::LowerRightCornerKey))
319
  {
320
    itk::ExposeMetaData<VectorType>(dict, MetaDataKey::LowerRightCornerKey, LowerRightCorner);
321
  }
OTB Bot's avatar
STYLE    
OTB Bot committed
322
  return (LowerRightCorner);
323
324
}

325
ImageMetadataInterfaceBase::ImageKeywordlistType ImageMetadataInterfaceBase::GetImageKeywordlist()
326
{
327
  ImageKeywordlistType          imageKeywordlist;
328
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
329
330

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
331
  {
332
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
333
  }
334
  return (imageKeywordlist);
335
336
}

337
const ImageMetadataInterfaceBase::ImageKeywordlistType ImageMetadataInterfaceBase::GetImageKeywordlist() const
338
{
339
  ImageKeywordlistType          imageKeywordlist;
340
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
341
342

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
343
  {
344
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
345
  }
346
  return (imageKeywordlist);
347
348
}

349
std::string const ImageMetadataInterfaceBase::GetSensorID() const
350
351
{
  std::string s;
352
  GetSensorID(s);
353
354
355
  return s;
}

356
bool ImageMetadataInterfaceBase::GetSensorID(std::string& sensorId) const
357
{
358
  ImageKeywordlistType          imageKeywordlist;
359
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
360

361
362
  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
  {
363
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
364
  }
365

366
367
  if (!imageKeywordlist.HasKey("sensor"))
  {
368
    return false;
369
  }
370

371
372
373
  sensorId = imageKeywordlist.GetMetadataByKey("sensor");

  return true;
374
375
}

376
unsigned int ImageMetadataInterfaceBase::GetNumberOfBands() const
377
{
378
  ImageKeywordlistType          imageKeywordlist;
379
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
380
381

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
382
  {
383
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
384
  }
385
386

  if (!imageKeywordlist.HasKey("support_data.number_bands"))
387
  {
388
    return 0;
389
  }
390

391
392
  std::string  valueString = imageKeywordlist.GetMetadataByKey("support_data.number_bands");
  unsigned int value       = atoi(valueString.c_str());
393
  return value;
394
395
}

396
std::vector<std::string> ImageMetadataInterfaceBase::GetBandName() const
397
{
398
  ImageKeywordlistType          imageKeywordlist;
399
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
400
401

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
402
  {
403
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
404
  }
405

406
  /* band_name attribut is only used by OSSIM metadata reader otherwise it is band_name_list */
407
  std::vector<std::string> outputValues;
OTB Bot's avatar
STYLE    
OTB Bot committed
408
  if (!imageKeywordlist.HasKey("support_data.band_name"))
409
410
  {
    if (imageKeywordlist.HasKey("support_data.band_name_list"))
411
    {
412
413
      std::string valueString = imageKeywordlist.GetMetadataByKey("support_data.band_name_list");
      itksys::SystemTools::Split(valueString, outputValues, ' ');
414
    }
415
416
417
    else
      return outputValues;
  }
418
  else
419
420
421
422
  {
    std::string valueString = imageKeywordlist.GetMetadataByKey("support_data.band_name");
    itksys::SystemTools::Split(valueString, outputValues, '/');
  }
423

424
425
426
  return outputValues;
}

427
double ImageMetadataInterfaceBase::GetXPixelSpacing() const
428
{
429
  ImageKeywordlistType          imageKeywordlist;
430
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
431
432

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
433
  {
434
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
435
  }
436

Emmanuel Christophe's avatar
BUG    
Emmanuel Christophe committed
437
  if (imageKeywordlist.HasKey("meters_per_pixel_x"))
438
  {
439
    std::string valueString = imageKeywordlist.GetMetadataByKey("meters_per_pixel_x");
440
    double      value       = atof(valueString.c_str());
441
    return value;
442
  }
443

Emmanuel Christophe's avatar
BUG    
Emmanuel Christophe committed
444
  if (imageKeywordlist.HasKey("pixel_spacing"))
445
  {
446
    std::string valueString = imageKeywordlist.GetMetadataByKey("pixel_spacing");
447
    double      value       = atof(valueString.c_str());
448
    return value;
449
  }
450

451
  return 0;
452
453
}

454
double ImageMetadataInterfaceBase::GetYPixelSpacing() const
455
{
456
  ImageKeywordlistType          imageKeywordlist;
457
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
458
459

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
460
  {
461
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
462
  }
463

Emmanuel Christophe's avatar
BUG    
Emmanuel Christophe committed
464
  if (imageKeywordlist.HasKey("meters_per_pixel_y"))
465
  {
466
    std::string valueString = imageKeywordlist.GetMetadataByKey("meters_per_pixel_y");
467
    double      value       = atof(valueString.c_str());
468
    return value;
469
  }
470

Emmanuel Christophe's avatar
BUG    
Emmanuel Christophe committed
471
  if (imageKeywordlist.HasKey("pixel_spacing"))
472
  {
473
    std::string valueString = imageKeywordlist.GetMetadataByKey("pixel_spacing");
474
    double      value       = atof(valueString.c_str());
475
    return value;
476
  }
477

478
  return 0;
479
480
}

481
void ImageMetadataInterfaceBase::PrintMetadata(std::ostream& os, itk::Indent indent, const MetaDataDictionaryType& dict)
482
483
484
{

  std::vector<std::string> keys = dict.GetKeys();
485
486
487
488

  // an extra dependency just for printing is a bad idea.
  //  VectorDataKeywordlist    vectorDataKeywordlistValue;
  unsigned int i(0);
489
490
491
492
493
494

  // Copy of the const metadata dictionary in a metadata dictionary to be used
  // by the ExposeMetaData method

  MetaDataDictionaryType dict2 = dict;

OTB Bot's avatar
STYLE    
OTB Bot committed
495
  for (unsigned int itkey = 0; itkey < keys.size(); ++itkey)
496
  {
497
    switch (MetaDataKey::GetKeyType(keys[itkey]))
498
499
500
501
    {
    case MetaDataKey::TSTRING:
    {
      std::string svalue;
Julien Michel's avatar
Julien Michel committed
502
503
504
      itk::ExposeMetaData<std::string>(dict2, keys[itkey], svalue);
      os << indent << "---> " << keys[itkey] << " = " << svalue << std::endl;
      break;
505
506
507
    }
    case MetaDataKey::TENTIER:
    {
Julien Michel's avatar
Julien Michel committed
508
509
510
511
      unsigned int ivalue(0);
      itk::ExposeMetaData<unsigned int>(dict2, keys[itkey], ivalue);
      os << indent << "---> " << keys[itkey] << " = " << ivalue << std::endl;
      break;
512
513
514
    }
    case MetaDataKey::TVECTOR:
    {
Julien Michel's avatar
Julien Michel committed
515
516
      VectorType vvalue;
      itk::ExposeMetaData<VectorType>(dict2, keys[itkey], vvalue);
517

Julien Michel's avatar
Julien Michel committed
518
      for (i = 0; i < vvalue.size(); ++i)
519
      {
Julien Michel's avatar
Julien Michel committed
520
        os << indent << "---> " << keys[itkey] << "[" << i << "] = " << vvalue[i] << std::endl;
521
      }
Julien Michel's avatar
Julien Michel committed
522
      vvalue.clear();
523

Julien Michel's avatar
Julien Michel committed
524
      break;
525
526
527
    }
    case MetaDataKey::TDOUBLE:
    {
Julien Michel's avatar
Julien Michel committed
528
529
530
531
      double dvalue(0.0);
      itk::ExposeMetaData<double>(dict2, keys[itkey], dvalue);
      os << indent << "---> " << keys[itkey] << " = " << dvalue << std::endl;
      break;
532
    }
OTB Bot's avatar
STYLE    
OTB Bot committed
533

534
    case MetaDataKey::TGCP:
535
    {
536
537
      GCP gcpvalue;
      itk::ExposeMetaData<GCP>(dict2, keys[itkey], gcpvalue);
OTB Bot's avatar
STYLE    
OTB Bot committed
538

Julien Michel's avatar
Julien Michel committed
539
540
541
      os << indent << "---> " << keys[itkey] << std::endl;
      gcpvalue.Print(os);
      break;
542
543
544
545
    }
    case MetaDataKey::TOSSIMKEYWORDLIST:
    {
      ImageKeywordlist kwl;
Julien Michel's avatar
Julien Michel committed
546
      itk::ExposeMetaData<ImageKeywordlist>(dict2, keys[itkey], kwl);
547

Julien Michel's avatar
Julien Michel committed
548
549
550
      os << indent << "---> " << keys[itkey] << std::endl;
      kwl.Print(os);
      break;
OTB Bot's avatar
STYLE    
OTB Bot committed
551
    }
552
553
554
555
556
557
558
559
560
561
    //      case MetaDataKey::TVECTORDATAKEYWORDLIST:
    //        itk::ExposeMetaData<VectorDataKeywordlist>(dict2, keys[itkey], vectorDataKeywordlistValue);
    //
    //        os << indent << "---> " << keys[itkey] << std::endl;
    //        vectorDataKeywordlistValue.Print(os);
    //        break;
    default:
      break;
    }
  }
562
563
564
}


565
void ImageMetadataInterfaceBase::PrintSelf(std::ostream& os, itk::Indent indent) const
566
567
{
  this->Superclass::PrintSelf(os, indent);
568

569
  bool canRead = this->CanRead();
570

571
572
  os << indent << "Initialized: " << (canRead ? true : false) << std::endl;
  if (canRead)
573
  {
574
    std::vector<unsigned int> defaultDisplay = this->GetDefaultDisplay();
575
576
577
578
579
    os << indent << "Default RGB Display: [" << defaultDisplay[0] << ", " << defaultDisplay[1] << ", " << defaultDisplay[2] << "]" << std::endl;
    os << indent << "ProjectionRef:   " << this->GetProjectionRef() << std::endl;
    os << indent << "GCPProjection:   " << this->GetGCPProjection() << std::endl;
    os << indent << "GCPCount:        " << this->GetGCPCount() << std::endl;
    for (unsigned int gcpIdx = 0; gcpIdx < this->GetGCPCount(); ++gcpIdx)
580
    {
581
      // os << indent << "GCPs:            " << this->GetGCPs(gcpIdx) << std::endl;
582
583
584
      os << indent << "GCPId:           " << this->GetGCPId(gcpIdx) << std::endl;
      os << indent << "GCPInfo:         " << this->GetGCPInfo(gcpIdx) << std::endl;
    }
585
586
587
588
589
590
    // os << indent << "GeoTransform:    " << this->GetGeoTransform( ) << std::endl;
    // os << indent << "UpperLeftCorner: " << this->GetUpperLeftCorner( ) << std::endl;
    // os << indent << "UpperRightCorner:" << this->GetUpperRightCorner( ) << std::endl;
    // os << indent << "LowerLeftCorner: " << this->GetLowerLeftCorner( ) << std::endl;
    // os << indent << "LowerRightCorner:" << this->GetLowerRightCorner( ) << std::endl;
    // os << indent << "ImageKeywordlist:" << this->GetImageKeywordlist( ) << std::endl;
591
    std::string sensorId;
592
    this->GetSensorID(sensorId);
593
    os << indent << "SensorID:        " << sensorId << std::endl;
594
    os << indent << "NumberOfBands:   " << this->GetNumberOfBands() << std::endl;
595
596
597

    std::vector<std::string> bandNameList = this->GetBandName();
    if (bandNameList.size() == 1)
598
    {
599
      os << indent << "BandName:        " << bandNameList[0] << std::endl;
600
    }
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
    else if (bandNameList.size() > 1)
    {
      os << indent << "BandNameList:        ";
      for (std::vector<std::string>::iterator it = bandNameList.begin(); it != bandNameList.end(); ++it)
      {
        os << *it << ", ";
      }
      os << std::endl;
    }
    os << indent << "XPixelSpacing:   " << this->GetXPixelSpacing() << std::endl;
    os << indent << "YPixelSpacing:   " << this->GetYPixelSpacing() << std::endl;
    os << indent << "Day:             " << this->GetDay() << std::endl;
    os << indent << "Month:           " << this->GetMonth() << std::endl;
    os << indent << "Year:            " << this->GetYear() << std::endl;
    os << indent << "Hour:            " << this->GetHour() << std::endl;
    os << indent << "Minute:          " << this->GetMinute() << std::endl;
    os << indent << "ProductionDay:   " << this->GetProductionDay() << std::endl;
    os << indent << "ProductionMonth: " << this->GetProductionMonth() << std::endl;
    os << indent << "ProductionYear:  " << this->GetProductionYear() << std::endl;
  }
621
622
}

623
const std::string&
624
ImageMetadataInterfaceBase::Fetch(
625
  MDStr key,
626
  const MetadataSupplierInterface & mds,
627
628
629
630
631
  const char *path,
  int band)
{
  if (band >= 0)
    {
632
    assert( (size_t)(band) < m_Imd.Bands.size());
633
    m_Imd.Bands[band].Add(key, mds.GetAs<std::string>(path, band));
634
    return m_Imd.Bands[band][key];
635
    }
636
  m_Imd.Add(key, mds.GetAs<std::string>(path) );
637
  return m_Imd[key];
638
639
}

640
const double&
641
ImageMetadataInterfaceBase::Fetch(
642
  MDNum key,
643
  const MetadataSupplierInterface & mds,
644
645
646
647
648
  const char *path,
  int band)
{
  if (band >= 0)
    {
649
    assert( (size_t)(band) < m_Imd.Bands.size());
650
    m_Imd.Bands[band].Add(key, mds.GetAs<double>(path, band));
651
    return m_Imd.Bands[band][key];
652
    }
653
  m_Imd.Add(key, mds.GetAs<double>(path));
654
  return m_Imd[key];
655
656
}

657
658
659
const MetaData::Time&
ImageMetadataInterfaceBase::Fetch(
  MDTime key,
660
  const MetadataSupplierInterface & mds,
661
662
663
664
665
666
  const char *path,
  int band)
{
  if (band >= 0)
    {
    assert( (size_t)(band) < m_Imd.Bands.size());
667
    m_Imd.Bands[band].Add(key, mds.GetAs<MetaData::Time>(path, band));
668
669
    return m_Imd.Bands[band][key];
    }
Julie Brossard's avatar
Julie Brossard committed
670

671
  m_Imd.Add(key, mds.GetAs<MetaData::Time>(path));
672
673
674
  return m_Imd[key];
}

675
676
677
const std::string&
ImageMetadataInterfaceBase::Fetch(
		std::string key,
678
		const MetadataSupplierInterface & mds,
679
680
681
682
683
684
		const char *path,
		int band)
{
  if (band >= 0)
    {
    assert( (size_t)(band) < m_Imd.Bands.size());
685
    m_Imd.Bands[band].Add(key, mds.GetAs<std::string>(path, band));
686
687
    return m_Imd.Bands[band][key];
    }
688
  m_Imd.Add(key, mds.GetAs<std::string>(path) );
689
690
691
  return m_Imd[key];
}

692
693
const boost::any& ImageMetadataInterfaceBase::FetchRPC(const MetadataSupplierInterface & mds,
						       const double lineOffset, const double sampleOffset)
Guillaume Pasero's avatar
Guillaume Pasero committed
694
695
{
  Projection::RPCParam rpcStruct;
696
697
698
699
700
701
702
703
704
705

  // In some products, RPC metadata read by GDAL have an unit attached, and the
  // fetched string cannot be converted to double directly, e.g.
  // LINE_OFF=+002320.00 pixels (from an Ikonos product)
  // This lambda removes the unit suffix from the metadata.
  auto GetMetadataWithoutUnit = [](const std::string & path, 
                                    const MetadataSupplierInterface & mds)
  {
    auto metadataAsString = mds.GetAs<std::string>(path);

Cédric Traizet's avatar
Cédric Traizet committed
706
    for (const auto & name : {"meters", "degrees", "pixels"})
707
708
709
710
    {
      auto i = metadataAsString.find(name);
      if (i != std::string::npos)
      {
Cédric Traizet's avatar
Cédric Traizet committed
711
        metadataAsString.erase(i, strlen(name));
712
713
714
715
716
717
718
719
720
721
722
723
724
725
        break;
      }
    }
    
    try
    {
      return std::stod(metadataAsString);
    }
    catch (const std::invalid_argument&)
    {
      otbGenericExceptionMacro(MissingMetadataException,<<"Bad metadata value for '"<<path<<"', got: "<<metadataAsString)
    }
  };

726
727
  rpcStruct.LineOffset    = GetMetadataWithoutUnit("RPC/LINE_OFF", mds) + lineOffset;
  rpcStruct.SampleOffset  = GetMetadataWithoutUnit("RPC/SAMP_OFF", mds) + sampleOffset;
728
729
730
731
732
733
734
735
736
  rpcStruct.LatOffset     = GetMetadataWithoutUnit("RPC/LAT_OFF", mds);
  rpcStruct.LonOffset     = GetMetadataWithoutUnit("RPC/LONG_OFF", mds);
  rpcStruct.HeightOffset  = GetMetadataWithoutUnit("RPC/HEIGHT_OFF", mds);

  rpcStruct.LineScale    = GetMetadataWithoutUnit("RPC/LINE_SCALE", mds);
  rpcStruct.SampleScale  = GetMetadataWithoutUnit("RPC/SAMP_SCALE", mds);
  rpcStruct.LatScale     = GetMetadataWithoutUnit("RPC/LAT_SCALE", mds);
  rpcStruct.LonScale     = GetMetadataWithoutUnit("RPC/LONG_SCALE", mds);
  rpcStruct.HeightScale  = GetMetadataWithoutUnit("RPC/HEIGHT_SCALE", mds);
Guillaume Pasero's avatar
Guillaume Pasero committed
737
738
739

  std::vector<double> coeffs(20);

740
  coeffs = mds.GetAsVector<double>("RPC/LINE_NUM_COEFF",' ',20);
Guillaume Pasero's avatar
Guillaume Pasero committed
741
742
  std::copy(coeffs.begin(), coeffs.end(), rpcStruct.LineNum);

743
  coeffs = mds.GetAsVector<double>("RPC/LINE_DEN_COEFF",' ',20);
Guillaume Pasero's avatar
Guillaume Pasero committed
744
745
  std::copy(coeffs.begin(), coeffs.end(), rpcStruct.LineDen);

746
  coeffs = mds.GetAsVector<double>("RPC/SAMP_NUM_COEFF",' ',20);
Guillaume Pasero's avatar
Guillaume Pasero committed
747
748
  std::copy(coeffs.begin(), coeffs.end(), rpcStruct.SampleNum);

749
  coeffs = mds.GetAsVector<double>("RPC/SAMP_DEN_COEFF",' ',20);
Guillaume Pasero's avatar
Guillaume Pasero committed
750
751
  std::copy(coeffs.begin(), coeffs.end(), rpcStruct.SampleDen);

752
753
754
  m_Imd.Add(MDGeom::RPC, rpcStruct);
  assert(m_Imd.Has(MDGeom::RPC));
  assert(rpcStruct == boost::any_cast<Projection::RPCParam>(m_Imd[MDGeom::RPC]));
755
  return m_Imd[MDGeom::RPC];
Guillaume Pasero's avatar
Guillaume Pasero committed
756
757
}

758
759
760
761
762
bool ImageMetadataInterfaceBase::ConvertImageKeywordlistToImageMetadata()
{
  // by default, no conversion
  return false;
}
763

764
} // end namespace otb