From f1bc32ab6f5b99fe7dac3e9938f831d78a6114bd Mon Sep 17 00:00:00 2001
From: Guillaume Pasero <guillaume.pasero@c-s.fr>
Date: Fri, 2 Oct 2015 17:54:10 +0200
Subject: [PATCH] ENH: new filter to modify image metadata

---
 .../include/otbChangeInformationImageFilter.h |  94 +++++++++++
 .../otbChangeInformationImageFilter.txx       | 150 ++++++++++++++++++
 2 files changed, 244 insertions(+)
 create mode 100644 Modules/Filtering/ImageManipulation/include/otbChangeInformationImageFilter.h
 create mode 100644 Modules/Filtering/ImageManipulation/include/otbChangeInformationImageFilter.txx

diff --git a/Modules/Filtering/ImageManipulation/include/otbChangeInformationImageFilter.h b/Modules/Filtering/ImageManipulation/include/otbChangeInformationImageFilter.h
new file mode 100644
index 0000000000..f92b2c2065
--- /dev/null
+++ b/Modules/Filtering/ImageManipulation/include/otbChangeInformationImageFilter.h
@@ -0,0 +1,94 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef __otbChangeInformationImageFilter_h
+#define __otbChangeInformationImageFilter_h
+
+#include "itkChangeInformationImageFilter.h"
+#include "otbMetaDataKey.h"
+
+namespace otb
+{
+
+/**
+ * \class ChangeInformationImageFilter
+ * \brief Filter to modify image metadata
+ *
+ * The base class is itk::ChangeInformationImageFilter that allows to
+ * modifiy origin, spacing, direction and buffered region. This deriving
+ * filter adds the support of MetaDataDictionary.
+ *
+ * \ingroup OTBImageManipulation
+ */
+template< typename TInputImage >
+class ChangeInformationImageFilter:
+  public itk::ChangeInformationImageFilter< TInputImage >
+{
+public:
+  /** Standard class typedefs. */
+  typedef ChangeInformationImageFilter                   Self;
+  typedef itk::ChangeInformationImageFilter<TInputImage> Superclass;
+  typedef itk::SmartPointer<Self>                        Pointer;
+  typedef itk::SmartPointer<const Self>                  ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Creation through object factory macro */
+  itkTypeMacro(ChangeInformationImageFilter, itk::ChangeInformationImageFilter);
+
+  /** Set key names to change */
+  void SetChangeMetaData(const char *keyname, bool flag);
+
+  /** Ask if a metadata will be changed */
+  bool GetChangeMetaData(const char *keyname);
+
+  /** Set output values for metadata, passing a NULL value will remove the
+   *  metadata from output. If not set for a key name in the change list,
+   *  the metadata will also be set.
+   */
+  template<typename T>
+  void SetOutputMetaData(const char *keyname, const T * value);
+
+protected:
+  ChangeInformationImageFilter() {}
+  virtual ~ChangeInformationImageFilter() {}
+
+  /** Apply changes to the output image metadata. */
+  virtual void GenerateOutputInformation();
+
+private:
+  ChangeInformationImageFilter(const Self &); //purposely not implemented
+  void operator =(const Self&); //purposely not implemented
+
+  /** Removes a field from a metadata dictionary
+   *  After ITK 4.6, an Erase() method has been added to
+   *  itk::MetaDataDictionary, so this function could be tagged as deprecated */
+  bool RemoveKeyFromDictionary(itk::MetaDataDictionary & dict, const std::string & key);
+
+  /** List of metadata keys to change */
+  std::set<std::string> m_ChangedKeys;
+
+};
+
+} // End of namespace OTB
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbChangeInformationImageFilter.txx"
+#endif
+
+#endif
diff --git a/Modules/Filtering/ImageManipulation/include/otbChangeInformationImageFilter.txx b/Modules/Filtering/ImageManipulation/include/otbChangeInformationImageFilter.txx
new file mode 100644
index 0000000000..319684064c
--- /dev/null
+++ b/Modules/Filtering/ImageManipulation/include/otbChangeInformationImageFilter.txx
@@ -0,0 +1,150 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef __otbChangeInformationImageFilter_txx
+#define __otbChangeInformationImageFilter_txx
+
+#include "otbChangeInformationImageFilter.h"
+#include "itkMetaDataObject.h"
+
+namespace otb
+{
+
+template< typename TInputImage >
+void
+ChangeInformationImageFilter<TInputImage>
+::SetChangeMetaData(const char *keyname, bool flag)
+{
+  std::string key(keyname);
+  if (! key.empty())
+    {
+    if (flag)
+      {
+      m_ChangedKeys.insert(key);
+      }
+    else
+      {
+      std::set<std::string>::iterator pos = m_ChangedKeys.find(key);
+      if (pos != m_ChangedKeys.end())
+        {
+        m_ChangedKeys.erase(pos);
+        }
+      }
+    }
+}
+
+template< typename TInputImage >
+bool
+ChangeInformationImageFilter<TInputImage>
+::GetChangeMetaData(const char *keyname)
+{
+  std::string key(keyname);
+  if (! key.empty())
+    {
+    if (m_ChangedKeys.find(key) != m_ChangedKeys.end())
+      {
+      return true;
+      }
+    }
+  return false;
+}
+
+template< typename TInputImage >
+template<typename T>
+void
+ChangeInformationImageFilter<TInputImage>
+::SetOutputMetaData(const char *keyname, const T * value)
+{
+  std::string key(keyname);
+  if (! key.empty())
+    {
+    // enable this key for metadata change
+    m_ChangedKeys.insert(key);
+    itk::MetaDataDictionary &dict = this->GetMetaDataDictionary();
+    if (value == NULL)
+      {
+      // Remove meta-data from dictionary
+      this->RemoveKeyFromDictionary(dict,key);
+      }
+    else
+      {
+      // Set metadata in dictionary
+      const T &valueRef = (*value);
+      itk::EncapsulateMetaData<T>(dict,key,valueRef);
+      }
+    }
+}
+
+template< typename TInputImage >
+void
+ChangeInformationImageFilter<TInputImage>
+::GenerateOutputInformation()
+{
+  Superclass::GenerateOutputInformation();
+
+  // Process the metadatas to be changed
+  itk::MetaDataDictionary &dict = this->GetMetaDataDictionary();
+  itk::MetaDataDictionary &outputDict = this->GetOutput()->GetMetaDataDictionary();
+  std::set<std::string>::iterator it = m_ChangedKeys.begin();
+  for ( ; it != m_ChangedKeys.end() ; ++it)
+    {
+    if (dict.HasKey(*it))
+      {
+      // Replace metadata in output dictionary
+      outputDict[*it] = dict[*it];
+      }
+    else
+      {
+      // Remove metadata from output dictionary
+      this->RemoveKeyFromDictionary(outputDict,*it);
+      }
+    }
+}
+
+template< typename TInputImage >
+bool
+ChangeInformationImageFilter<TInputImage>
+::RemoveKeyFromDictionary(itk::MetaDataDictionary & dict, const std::string & key)
+{
+  std::vector<std::string> keyList = dict.GetKeys();
+  std::vector<std::string>::iterator pos = keyList.begin();
+  while (pos != keyList.end())
+    {
+    if (key.compare(*pos) == 0)
+      {
+      break;
+      }
+    ++pos;
+    }
+  if (pos != keyList.end())
+    {
+    itk::MetaDataDictionary copyDict;
+    keyList.erase(pos);
+    pos = keyList.begin();
+    for ( ; pos != keyList.end();++pos)
+      {
+      copyDict.Set(*pos, const_cast<itk::MetaDataObjectBase*>(dict.Get(*pos)));
+      }
+    dict = copyDict;
+    return true;
+    }
+  return false;
+}
+
+} // End of namespace OTB
+
+#endif
-- 
GitLab