diff --git a/Data/Baseline/OTB/Files/ioTuImageMetadataAppendTest.txt b/Data/Baseline/OTB/Files/ioTuImageMetadataAppendTest.txt
index 2e250ac78c4b38e62eb214ca6ce05bcb326d35e2..afcaf94e771bae1622b1842445e02b7ea51cce18 100644
--- a/Data/Baseline/OTB/Files/ioTuImageMetadataAppendTest.txt
+++ b/Data/Baseline/OTB/Files/ioTuImageMetadataAppendTest.txt
@@ -1,26 +1,24 @@
-{{"Extra.Comment": "Test Extrakeys",
-"ProductionDate": "2009-08-10T10:30:08.142149Z",
-"ProjectionWKT": "UTM projRef",
-"SensorID": "PHR",
-}Bands[{"PhysicalBias": "1",
-"PhysicalGain": "2",
-"BandName": "B0",
-"NoData": "-10000",
-},{"PhysicalBias": "2",
-"PhysicalGain": "3",
-"BandName": "B1",
-"NoData": "-10000",
-},{"PhysicalBias": "1",
-"PhysicalGain": "2",
-"BandName": "B0",
-"NoData": "-10000",
-},{"PhysicalBias": "2",
-"PhysicalGain": "3",
-"BandName": "B1",
-"NoData": "-10000",
-},{"PhysicalBias": "3",
-"PhysicalGain": "4",
-"BandName": "B2",
-"NoData": "-10000",
-},]
-}
\ No newline at end of file
+SensorID PHR
+ProductionDate 2009-08-10T10:30:08.142149Z
+ProjectionWKT UTM projRef
+Extra.Comment Test Extrakeys
+BandName B0
+NoData -10000
+PhysicalGain 2
+PhysicalBias 1
+BandName B1
+NoData -10000
+PhysicalGain 3
+PhysicalBias 2
+BandName B0
+NoData -10000
+PhysicalGain 2
+PhysicalBias 1
+BandName B1
+NoData -10000
+PhysicalGain 3
+PhysicalBias 2
+BandName B2
+NoData -10000
+PhysicalGain 4
+PhysicalBias 3
diff --git a/Data/Baseline/OTB/Files/ioTuImageMetadataCompactTest.txt b/Data/Baseline/OTB/Files/ioTuImageMetadataCompactTest.txt
index bee7dd32ac397f0031b2003055756007191daff3..3e902ef18d7e9bfd3b8b37c613738c602dce0b4f 100644
--- a/Data/Baseline/OTB/Files/ioTuImageMetadataCompactTest.txt
+++ b/Data/Baseline/OTB/Files/ioTuImageMetadataCompactTest.txt
@@ -1,19 +1,17 @@
-{{"Extra.Information": "Very important",
-"Extra.Comment": "Test Extrakeys",
-"SensorID": "PHR",
-"ProjectionWKT": "UTM projRef",
-"ProductionDate": "2009-08-10T10:30:08.142149Z",
-"Polarization": "Polarization",
-"NoData": "-10000",
-"AcquisitionDate": "2009-08-05T20:34:38.236478Z",
-}Bands[{"PhysicalBias": "1",
-"BandName": "B0",
-"PhysicalGain": "2",
-},{"PhysicalBias": "2",
-"BandName": "B1",
-"PhysicalGain": "3",
-},{"PhysicalBias": "3",
-"BandName": "B2",
-"PhysicalGain": "4",
-},]
-}
\ No newline at end of file
+SensorID PHR
+Polarization Polarization
+NoData -10000
+AcquisitionDate 2009-08-05T20:34:38.236478Z
+ProductionDate 2009-08-10T10:30:08.142149Z
+ProjectionWKT UTM projRef
+Extra.Comment Test Extrakeys
+Extra.Information Very important
+BandName B0
+PhysicalGain 2
+PhysicalBias 1
+BandName B1
+PhysicalGain 3
+PhysicalBias 2
+BandName B2
+PhysicalGain 4
+PhysicalBias 3
diff --git a/Data/Baseline/OTB/Files/ioTuImageMetadataMergeTest.txt b/Data/Baseline/OTB/Files/ioTuImageMetadataMergeTest.txt
index 107001ddf9a5f3bf1dc8fbf45d7c3fe8708c2467..39d5c3a6db32f3071a4de1df1a512eacf4c0ee46 100644
--- a/Data/Baseline/OTB/Files/ioTuImageMetadataMergeTest.txt
+++ b/Data/Baseline/OTB/Files/ioTuImageMetadataMergeTest.txt
@@ -1,16 +1,14 @@
-{{"ProductionDate": "2009-08-10T10:30:08.142149Z",
-"Polarization": "Polarization",
-"ProjectionWKT": "UTM projRef",
-"Extra.Comment": "Test Extrakeys",
-"SensorID": "SPOT",
-}Bands[{"PhysicalBias": "1",
-"PhysicalGain": "2",
-"BandName": "B0",
-"NoData": "-10000",
-},{"PhysicalBias": "2",
-"PhysicalGain": "3",
-"BandName": "B1",
-"SunAzimuth": "20",
-"NoData": "-10000",
-},]
-}
\ No newline at end of file
+SensorID SPOT
+Polarization Polarization
+ProductionDate 2009-08-10T10:30:08.142149Z
+ProjectionWKT UTM projRef
+Extra.Comment Test Extrakeys
+BandName B0
+NoData -10000
+PhysicalGain 2
+PhysicalBias 1
+BandName B1
+NoData -10000
+PhysicalGain 3
+PhysicalBias 2
+SunAzimuth 20
diff --git a/Data/Baseline/OTB/Files/ioTuImageMetadataSliceTest.txt b/Data/Baseline/OTB/Files/ioTuImageMetadataSliceTest.txt
index 828d8ca40d5d016b44f0e229944af80e275042ae..080d58c0b6e2bfa4583fd570e378af271a2ed33d 100644
--- a/Data/Baseline/OTB/Files/ioTuImageMetadataSliceTest.txt
+++ b/Data/Baseline/OTB/Files/ioTuImageMetadataSliceTest.txt
@@ -1,14 +1,12 @@
-{{"Extra.Comment": "Test Extrakeys",
-"ProductionDate": "2009-08-10T10:30:08.142149Z",
-"ProjectionWKT": "UTM projRef",
-"SensorID": "PHR",
-}Bands[{"PhysicalBias": "1",
-"PhysicalGain": "2",
-"BandName": "B0",
-"NoData": "-10000",
-},{"PhysicalBias": "2",
-"PhysicalGain": "3",
-"BandName": "B1",
-"NoData": "-10000",
-},]
-}
\ No newline at end of file
+SensorID PHR
+ProductionDate 2009-08-10T10:30:08.142149Z
+ProjectionWKT UTM projRef
+Extra.Comment Test Extrakeys
+BandName B0
+NoData -10000
+PhysicalGain 2
+PhysicalBias 1
+BandName B1
+NoData -10000
+PhysicalGain 3
+PhysicalBias 2
diff --git a/Data/Baseline/OTB/Files/ioTuImageMetadataToFromKeywordlistTest.txt b/Data/Baseline/OTB/Files/ioTuImageMetadataToFromKeywordlistTest.txt
index 2d936bb2c748d8f6622505e6749fe0542fcb3cff..dac34793037126682a1feadb9adb30589a2736a2 100644
--- a/Data/Baseline/OTB/Files/ioTuImageMetadataToFromKeywordlistTest.txt
+++ b/Data/Baseline/OTB/Files/ioTuImageMetadataToFromKeywordlistTest.txt
@@ -1,26 +1,22 @@
-{{"Extra.Comment": "Test Extrakeys",
-"ProjectionEPSG": "4326",
-"ProjectionWKT": "UTM projRef",
-"ProjectionProj": "+proj=longlat +datum=WGS84 +no_defs ",
-"SpectralSensitivity": "LUT1D.DIM0.SIZE = 3
+SensorID PHR
+ProductionDate 2009-08-10T10:30:08.142149Z
+ProjectionWKT UTM projRef
+ProjectionEPSG 4326
+ProjectionProj +proj=longlat +datum=WGS84 +no_defs 
+SpectralSensitivity LUT1D.DIM0.SIZE = 3
 LUT1D.DIM0.ORIGIN = 0
 LUT1D.DIM0.SPACING = 1
-LUT1D.ARRAY = 1 2 3"
-"RPC": "<RPCParam>",
-"ProductionDate": "2009-08-10T10:30:08.142149Z",
-"GCP": "<GCPParam>",
-"SensorID": "PHR",
-}Bands[{"PhysicalBias": "1",
-"PhysicalGain": "2",
-"BandName": "B0",
-"NoData": "-10000",
-},{"PhysicalBias": "2",
-"PhysicalGain": "3",
-"BandName": "B1",
-"NoData": "-10000",
-},{"PhysicalBias": "3",
-"PhysicalGain": "4",
-"BandName": "B2",
-"NoData": "-10000",
-},]
-}
\ No newline at end of file
+LUT1D.ARRAY = 1 2 3
+Extra.Comment Test Extrakeys
+BandName B0
+NoData -10000
+PhysicalGain 2
+PhysicalBias 1
+BandName B1
+NoData -10000
+PhysicalGain 3
+PhysicalBias 2
+BandName B2
+NoData -10000
+PhysicalGain 4
+PhysicalBias 3
diff --git a/Modules/Core/ImageBase/include/otbImageIOBase.h b/Modules/Core/ImageBase/include/otbImageIOBase.h
index c09f4533db2684130e632271216eb93a0da8fdf6..b0981215a63b8479d231f65fa42840deb7b2525d 100644
--- a/Modules/Core/ImageBase/include/otbImageIOBase.h
+++ b/Modules/Core/ImageBase/include/otbImageIOBase.h
@@ -567,6 +567,11 @@ protected:
   /** Image metadata pre-parsed by the ImageIO */
   ImageMetadata m_Imd;
 
+  /** Mapping between origin components and output components. Note that the buffer is
+  already mapped after calling the DoMapBuffer method. This attribute is useful to write
+  band related metadatas. */
+  std::vector<unsigned int> m_BandList;
+
 private:
   ImageIOBase(const Self&) = delete;
   void operator=(const Self&) = delete;
diff --git a/Modules/Core/ImageBase/src/otbImageCommons.cxx b/Modules/Core/ImageBase/src/otbImageCommons.cxx
index 6b8c86738b935d475c11c54d415972d9feb84d39..4af915ed760b5f9c8bdf402994979e6eb778bd56 100644
--- a/Modules/Core/ImageBase/src/otbImageCommons.cxx
+++ b/Modules/Core/ImageBase/src/otbImageCommons.cxx
@@ -54,8 +54,11 @@ void ImageCommons::SetProjectionRef(const std::string& proj)
 
 std::string ImageCommons::GetGCPProjection(void) const
 {
-  assert(m_Imd.Has(MDGeom::GCP));
-  return m_Imd.GetGCPParam().GCPProjection;
+  if (m_Imd.Has(MDGeom::GCP))
+  {
+    return m_Imd.GetGCPParam().GCPProjection;
+  }
+  return "";
 }
 
 
diff --git a/Modules/Core/ImageBase/src/otbImageIOBase.cxx b/Modules/Core/ImageBase/src/otbImageIOBase.cxx
index 7c0e62a6820e14e9fb9f2e9ae9cae3e914296858..c069924acaad46cc556770dc31c2b8937bc91d5a 100644
--- a/Modules/Core/ImageBase/src/otbImageIOBase.cxx
+++ b/Modules/Core/ImageBase/src/otbImageIOBase.cxx
@@ -1194,6 +1194,8 @@ std::vector<double> ImageIOBase::GetDefaultDirection(unsigned int k) const
 
 void ImageIOBase::DoMapBuffer(void* buffer, size_t numberOfPixels, std::vector<unsigned int>& bandList)
 {
+  m_BandList = bandList;
+
   size_t componentSize = this->GetComponentSize();
   size_t inPixelSize   = componentSize * this->GetNumberOfComponents();
   size_t outPixelSize  = componentSize * bandList.size();
diff --git a/Modules/Core/Metadata/test/otbImageMetadataTest.cxx b/Modules/Core/Metadata/test/otbImageMetadataTest.cxx
index ab17cebde3ce6574527df70112d7713237025049..2eabc05320020d3a6937a95d21a2f99535ad56da 100644
--- a/Modules/Core/Metadata/test/otbImageMetadataTest.cxx
+++ b/Modules/Core/Metadata/test/otbImageMetadataTest.cxx
@@ -26,6 +26,7 @@
 #include <utility>
 #include <cstdlib>
 #include "otbStopwatch.h"
+#include "otbTestTools.h"
 
 void SetUpImageMetadata(otb::ImageMetadata& md, unsigned int nbBands)
 {
@@ -189,7 +190,7 @@ void otbImageMetadataSliceTest(char* argv[])
   SetUpImageMetadata(md, 3);
 
   ImageMetadata md2 = md.slice(0, 1);
-  outfile << md2;
+  otb::testtools::PrintMetadata(md2, outfile);
   outfile.close();
 }
 
@@ -207,7 +208,7 @@ void otbImageMetadataAppendTest(char* argv[])
   SetUpImageMetadata(md2, 3);
 
   md.append(md2);
-  outfile << md;
+  otb::testtools::PrintMetadata(md, outfile);
   outfile.close();
 }
 
@@ -234,7 +235,7 @@ void otbImageMetadataMergeTest(char* argv[])
   
   md.Merge(md2);
   
-  outfile << md;
+  otb::testtools::PrintMetadata(md, outfile);
   outfile.close();
 }
 void otbImageMetadataToFromKeywordlistTest(char* argv[])
@@ -265,7 +266,7 @@ void otbImageMetadataToFromKeywordlistTest(char* argv[])
   md.AppendToKeywordlists(kwlVect);
   ImageMetadata md2;
   md2.FromKeywordlists(kwlVect);
-  outfile << md2;
+  otb::testtools::PrintMetadata(md2, outfile);
   outfile.close();
 }
 
@@ -288,7 +289,7 @@ void otbImageMetadataCompactTest(char* argv[])
   }
 
   md.compact();
-  outfile << md;
+  otb::testtools::PrintMetadata(md, outfile);
   outfile.close();
 }
 
diff --git a/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx b/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx
index 40940f0b21ceebbc8ca700e6cf8192f3df5df01e..65aa35ffe6319f9e3f1ab1cbbf8b74c71e820282 100644
--- a/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx
+++ b/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx
@@ -1294,9 +1294,19 @@ void GDALImageIO::InternalWriteImageInformation(const void* buffer)
   // char **     papszOptions = NULL;
   std::string driverShortName;
   m_NbBands = this->GetNumberOfComponents();
+  
+  // If the band mapping is different from the one of the input (e.g. because an extended filename
+  // has been set, the bands in the imageMetadata object needs to be reorganized.
+  if (!m_BandList.empty())
+  {
+    ImageMetadata::ImageMetadataBandsType bandRangeMetadata;
+    for (auto elem: m_BandList)
+    {
+      bandRangeMetadata.push_back(m_Imd.Bands[elem]);
+    }
+    m_Imd.Bands = bandRangeMetadata;
+  }
 std::cout << m_Imd << std::endl;
-std::cout << "m_NbBands " << (std::size_t)m_NbBands << std::endl;
-std::cout << "m_ImdBands size " << m_Imd.Bands.size() << std::endl;
 
   if ( !m_Imd.Bands.empty() && (std::size_t)m_NbBands != m_Imd.Bands.size())
     {
diff --git a/Modules/IO/ImageIO/include/otbImageFileReader.hxx b/Modules/IO/ImageIO/include/otbImageFileReader.hxx
index 7852c5efd0543851be4aff3569f486d1aa151ea7..6452070af1f3664982b95b0223486868c31af9ab 100644
--- a/Modules/IO/ImageIO/include/otbImageFileReader.hxx
+++ b/Modules/IO/ImageIO/include/otbImageFileReader.hxx
@@ -574,6 +574,15 @@ void ImageFileReader<TOutputImage, ConvertPixelTraits>::GenerateOutputInformatio
     m_IOComponents = m_BandList.size();
   }
 
+  // Delete band metadata if the Conversion policy changed the number of bands, in the case of 
+  // grayscale to RGB for example. Because we cannot know how the metadata should be mapped.
+  // TODO: define proper behavior in this case.
+  using ConvertIOPixelTraits = otb::DefaultConvertPixelTraits<typename TOutputImage::IOPixelType>;
+  if (strcmp(output->GetNameOfClass(), "Image") == 0 && !(this->m_ImageIO->GetNumberOfComponents() == ConvertIOPixelTraits::GetNumberOfComponents()))
+  {
+    imd.Bands = ImageMetadata::ImageMetadataBandsType (ConvertIOPixelTraits::GetNumberOfComponents());
+  }
+
   // THOMAS : ajout
   // If a VectorImage, this requires us to set the
   // VectorLength before allocate
diff --git a/Modules/IO/TestKernel/include/otbTestTools.h b/Modules/IO/TestKernel/include/otbTestTools.h
new file mode 100644
index 0000000000000000000000000000000000000000..04cfdd93b64af669d130542d90246c23bc2f2edf
--- /dev/null
+++ b/Modules/IO/TestKernel/include/otbTestTools.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES)
+ *
+ * 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.
+ */
+
+#ifndef otbTestTools_h
+#define otbTestTools_h
+
+#include "otbMetaDataKey.h"
+#include "otbImageMetadata.h"
+
+namespace otb
+{
+namespace testtools
+{
+
+void PrintMetadataBase(ImageMetadataBase imdb, std::ostream& oss)
+{
+  std::unordered_map<std::string, std::string> kwl;
+  imdb.ToKeywordlist(kwl);
+  for (auto It = otb::MetaData::MDStrNames.left.begin() ; It != otb::MetaData::MDStrNames.left.end() ; ++It)
+  {
+    auto Key = kwl.find(It->second);
+    if (Key != kwl.end())
+      oss << It->second << ' ' << Key->second << '\n';
+  }
+
+  for (auto It = otb::MetaData::MDNumNames.left.begin() ; It != otb::MetaData::MDNumNames.left.end() ; ++It)
+  {
+    auto Key = kwl.find(It->second);
+    if (Key != kwl.end())
+      oss << It->second << ' ' << Key->second << '\n';
+  }
+
+  for (auto It = otb::MetaData::MDTimeNames.left.begin() ; It != otb::MetaData::MDTimeNames.left.end() ; ++It)
+  {
+    auto Key = kwl.find(It->second);
+    if (Key != kwl.end())
+      oss << It->second << ' ' << Key->second << '\n';
+  }
+
+  for (auto It = otb::MetaData::MDGeomNames.left.begin() ; It != otb::MetaData::MDGeomNames.left.end() ; ++It)
+  {
+    auto Key = kwl.find(It->second);
+    if (Key != kwl.end())
+      oss << It->second << ' ' << Key->second << '\n';
+  }
+
+  for (auto It = otb::MetaData::MDL1DNames.left.begin() ; It != otb::MetaData::MDL1DNames.left.end() ; ++It)
+  {
+    auto Key = kwl.find(It->second);
+    if (Key != kwl.end())
+      oss << It->second << ' ' << Key->second << '\n';
+  }
+
+  for (auto It = otb::MetaData::MDL2DNames.left.begin() ; It != otb::MetaData::MDL2DNames.left.end() ; ++It)
+  {
+    auto Key = kwl.find(It->second);
+    if (Key != kwl.end())
+      oss << It->second << ' ' << Key->second << '\n';
+  }
+
+  std::string prefix("Extra.");
+  for (const auto& kv : imdb.ExtraKeys)
+    oss << prefix + kv.first << ' ' << kv.second << '\n';
+}
+
+void PrintMetadata(ImageMetadata imd, std::ostream& oss)
+{
+  PrintMetadataBase(imd, oss);
+  for (ImageMetadataBase imdb : imd.Bands)
+    PrintMetadataBase(imdb, oss);
+}
+
+}
+}
+#endif