diff --git a/Code/ApplicationEngine/otbWrapperComplexInputImageParameter.cxx b/Code/ApplicationEngine/otbWrapperComplexInputImageParameter.cxx
index 5fa1f36c20b8acfe4f523626d0cc1fcce2ab5c8b..392645ed6fe778766f2e002704c2f9f7c08e04eb 100644
--- a/Code/ApplicationEngine/otbWrapperComplexInputImageParameter.cxx
+++ b/Code/ApplicationEngine/otbWrapperComplexInputImageParameter.cxx
@@ -17,9 +17,6 @@
 =========================================================================*/
 #include "otbWrapperComplexInputImageParameter.h"
 #include "itksys/SystemTools.hxx"
-#include "otbImageFileReader.h"
-#include "itkCastImageFilter.h"
-#include "otbImageToVectorImageCastFilter.h"
 #include "otbWrapperTypes.h"
 
 
@@ -96,133 +93,6 @@ otbGetImageMacro(ComplexDoubleImage);
 otbGetImageMacro(ComplexFloatVectorImage);
 otbGetImageMacro(ComplexDoubleVectorImage);
 
-template <class TOutputImage>
-TOutputImage *
-ComplexInputImageParameter::GetImage()
-{
-  // Used m_PreviousFileName because if not, when the user call twice GetImage,
-  // it without changing the filename, it returns 2 different
-  // image pointers
-  // Only one image type can be used
-
-  // 2 cases : the user set a filename vs. the user set an image
-  if (m_UseFilename)
-    {
-    if( m_PreviousFileName!=m_FileName && !m_FileName.empty() )
-      {
-      //////////////////////// Filename case:
-      // A new valid filename has been given : a reader is created
-      m_PreviousFileName = m_FileName;
-      typedef otb::ImageFileReader<TOutputImage> ReaderType;
-      typename ReaderType::Pointer reader = ReaderType::New();
-      reader->SetFileName(m_FileName);
-      try
-        {
-        reader->UpdateOutputInformation();
-        }
-      catch(itk::ExceptionObject &)
-        {
-        this->ClearValue();
-        }
-
-      m_Image = reader->GetOutput();
-      m_Reader = reader;
-
-      // Pay attention, don't return m_Image because it is a ImageBase...
-      return reader->GetOutput();
-      }
-    else
-      {
-      // In this case, the reader and the image should already be there
-      if (m_Image.IsNull())
-        {
-        itkExceptionMacro("No input image or filename detected...");
-        }
-      else
-        {
-        // Check if the image type asked here is the same as the one used for the reader
-        if (dynamic_cast<TOutputImage*> (m_Image.GetPointer()))
-          {
-          return dynamic_cast<TOutputImage*> (m_Image.GetPointer());
-          }
-        else
-          {
-          itkExceptionMacro("Cannot ask a different image type");
-          }
-        }
-      }
-    }
-  else
-    {
-    //////////////////////// Image case:
-    if( m_Image.IsNull() )
-      {
-      itkExceptionMacro("No input image or filename detected...");
-      }
-    else
-      {
-      if (dynamic_cast<ComplexFloatVectorImageType*>(m_Image.GetPointer()))
-        {
-        return CastImage<ComplexFloatVectorImageType, TOutputImage>();
-        }
-      else if (dynamic_cast<ComplexDoubleVectorImageType*>(m_Image.GetPointer()))
-        {
-        return CastImage<ComplexDoubleVectorImageType, TOutputImage>();
-        }
-      else if (dynamic_cast<ComplexFloatImageType*>(m_Image.GetPointer()))
-        {
-        return CastImage<ComplexFloatImageType, TOutputImage>();
-        }
-      else if (dynamic_cast<ComplexDoubleImageType*>(m_Image.GetPointer()))
-        {
-        return CastImage<ComplexDoubleImageType, TOutputImage>();
-        }
-      else
-        {
-        itkExceptionMacro("Unknown image type");
-        }
-      }
-    }
-}
-
-
-template <class TComplexInputImage, class TOutputImage>
-TOutputImage*
-ComplexInputImageParameter::SimpleCastImage()
-{
-  TComplexInputImage* realComplexInputImage = dynamic_cast<TComplexInputImage*>(m_Image.GetPointer());
-
-  typedef itk::CastImageFilter<TComplexInputImage, TOutputImage> CasterType;
-  typename CasterType::Pointer caster = CasterType::New();
-
-  caster->SetInput(realComplexInputImage);
-  caster->UpdateOutputInformation();
-
-  m_Image = caster->GetOutput();
-  m_Caster = caster;
-
-  return caster->GetOutput();
-}
-
-
-template <class TComplexInputImage, class TOutputImage>
-TOutputImage*
-ComplexInputImageParameter::CastVectorImageFromImage()
-{
-  TComplexInputImage* realComplexInputImage = dynamic_cast<TComplexInputImage*>(m_Image.GetPointer());
-
-  typedef ImageToVectorImageCastFilter<TComplexInputImage, TOutputImage> CasterType;
-  typename CasterType::Pointer caster = CasterType::New();
-
-  caster->SetInput(realComplexInputImage);
-  caster->UpdateOutputInformation();
-
-  m_Image = caster->GetOutput();
-  m_Caster = caster;
-
-  return caster->GetOutput();
-}
-
 
 #define otbCastImageMacro(ComplexInputImageType, OutputImageType, theMethod)   \
   template<> OutputImageType *                                          \
diff --git a/Code/ApplicationEngine/otbWrapperComplexInputImageParameter.h b/Code/ApplicationEngine/otbWrapperComplexInputImageParameter.h
index e735ab8a20507997f5fa3b73e622fcd0d1aaa7c2..9d76e575bc3cb0852adac2de6e6ede308cf3a580 100644
--- a/Code/ApplicationEngine/otbWrapperComplexInputImageParameter.h
+++ b/Code/ApplicationEngine/otbWrapperComplexInputImageParameter.h
@@ -74,11 +74,7 @@ public:
 
   /** Generic cast method that will be specified for each image type. */
   template <class TComplexInputImage, class TOutputImage>
-    TOutputImage* CastImage()
-  {
-    itkExceptionMacro("Cast from "<<typeid(TComplexInputImage).name()
-                      <<" to "<<typeid(TOutputImage).name()<<" not authorized.");
-  }
+    TOutputImage* CastImage();
 
   /** Cast an image to an image of the same type
   * Image to Image, VectorImage to VectorImage, RGBAImage to RGBAImage. */
@@ -127,7 +123,38 @@ private:
 
 }; // End class ComplexInputImage Parameter
 
+
+// template specializations of CastImage<> should be declared in header
+// so that the linker knows they exist when building OTB Applications
+
+#define otbDefineCastImageMacro(ComplexInputImageType, OutputImageType)   \
+  template<> OutputImageType *                                          \
+  ComplexInputImageParameter::CastImage<ComplexInputImageType , OutputImageType>();   \
+
+#define otbGenericDefineCastImageMacro(ComplexInputImageType, prefix)     \
+  otbDefineCastImageMacro(ComplexInputImageType, ComplexFloat##prefix##ImageType) \
+  otbDefineCastImageMacro(ComplexInputImageType, ComplexDouble##prefix##ImageType)
+
+
+/*********************************************************************
+********************** Image -> Image
+**********************************************************************/
+
+  otbGenericDefineCastImageMacro(ComplexFloatImageType, )
+  otbGenericDefineCastImageMacro(ComplexDoubleImageType, )
+
+
+/*********************************************************************
+********************** VectorImage -> VectorImage
+**********************************************************************/
+  otbGenericDefineCastImageMacro(ComplexFloatVectorImageType, Vector)
+  otbGenericDefineCastImageMacro(ComplexDoubleVectorImageType, Vector)
+
 } // End namespace Wrapper
 } // End namespace otb
 
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbWrapperComplexInputImageParameter.txx"
+#endif
+
 #endif
diff --git a/Code/ApplicationEngine/otbWrapperComplexInputImageParameter.txx b/Code/ApplicationEngine/otbWrapperComplexInputImageParameter.txx
new file mode 100644
index 0000000000000000000000000000000000000000..9b19bf0acd38f38561add5e54f475748c0292a20
--- /dev/null
+++ b/Code/ApplicationEngine/otbWrapperComplexInputImageParameter.txx
@@ -0,0 +1,173 @@
+/*=========================================================================
+
+  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 __otbWrapperComplexInputImageParameter_txx
+#define __otbWrapperComplexInputImageParameter_txx
+
+#include "otbWrapperComplexInputImageParameter.h"
+
+#include "otbImageFileReader.h"
+#include "itkCastImageFilter.h"
+#include "otbImageToVectorImageCastFilter.h"
+
+namespace otb
+{
+namespace Wrapper
+{
+
+
+template <class TOutputImage>
+TOutputImage *
+ComplexInputImageParameter::GetImage()
+{
+  // Used m_PreviousFileName because if not, when the user call twice GetImage,
+  // it without changing the filename, it returns 2 different
+  // image pointers
+  // Only one image type can be used
+
+  // 2 cases : the user set a filename vs. the user set an image
+  if (m_UseFilename)
+    {
+    if( m_PreviousFileName!=m_FileName && !m_FileName.empty() )
+      {
+      //////////////////////// Filename case:
+      // A new valid filename has been given : a reader is created
+      m_PreviousFileName = m_FileName;
+      typedef otb::ImageFileReader<TOutputImage> ReaderType;
+      typename ReaderType::Pointer reader = ReaderType::New();
+      reader->SetFileName(m_FileName);
+      try
+        {
+        reader->UpdateOutputInformation();
+        }
+      catch(itk::ExceptionObject &)
+        {
+        this->ClearValue();
+        }
+
+      m_Image = reader->GetOutput();
+      m_Reader = reader;
+
+      // Pay attention, don't return m_Image because it is a ImageBase...
+      return reader->GetOutput();
+      }
+    else
+      {
+      // In this case, the reader and the image should already be there
+      if (m_Image.IsNull())
+        {
+        itkExceptionMacro("No input image or filename detected...");
+        }
+      else
+        {
+        // Check if the image type asked here is the same as the one used for the reader
+        if (dynamic_cast<TOutputImage*> (m_Image.GetPointer()))
+          {
+          return dynamic_cast<TOutputImage*> (m_Image.GetPointer());
+          }
+        else
+          {
+          itkExceptionMacro("Cannot ask a different image type");
+          }
+        }
+      }
+    }
+  else
+    {
+    //////////////////////// Image case:
+    if( m_Image.IsNull() )
+      {
+      itkExceptionMacro("No input image or filename detected...");
+      }
+    else
+      {
+      if (dynamic_cast<ComplexFloatVectorImageType*>(m_Image.GetPointer()))
+        {
+        return CastImage<ComplexFloatVectorImageType, TOutputImage>();
+        }
+      else if (dynamic_cast<ComplexDoubleVectorImageType*>(m_Image.GetPointer()))
+        {
+        return CastImage<ComplexDoubleVectorImageType, TOutputImage>();
+        }
+      else if (dynamic_cast<ComplexFloatImageType*>(m_Image.GetPointer()))
+        {
+        return CastImage<ComplexFloatImageType, TOutputImage>();
+        }
+      else if (dynamic_cast<ComplexDoubleImageType*>(m_Image.GetPointer()))
+        {
+        return CastImage<ComplexDoubleImageType, TOutputImage>();
+        }
+      else
+        {
+        itkExceptionMacro("Unknown image type");
+        }
+      }
+    }
+}
+
+
+template <class TComplexInputImage, class TOutputImage>
+TOutputImage*
+ComplexInputImageParameter::CastImage()
+{
+  itkExceptionMacro("Cast from "<<typeid(TComplexInputImage).name()
+                    <<" to "<<typeid(TOutputImage).name()<<" not authorized.");
+}
+
+
+template <class TComplexInputImage, class TOutputImage>
+TOutputImage*
+ComplexInputImageParameter::SimpleCastImage()
+{
+  TComplexInputImage* realComplexInputImage = dynamic_cast<TComplexInputImage*>(m_Image.GetPointer());
+
+  typedef itk::CastImageFilter<TComplexInputImage, TOutputImage> CasterType;
+  typename CasterType::Pointer caster = CasterType::New();
+
+  caster->SetInput(realComplexInputImage);
+  caster->UpdateOutputInformation();
+
+  m_Image = caster->GetOutput();
+  m_Caster = caster;
+
+  return caster->GetOutput();
+}
+
+
+template <class TComplexInputImage, class TOutputImage>
+TOutputImage*
+ComplexInputImageParameter::CastVectorImageFromImage()
+{
+  TComplexInputImage* realComplexInputImage = dynamic_cast<TComplexInputImage*>(m_Image.GetPointer());
+
+  typedef ImageToVectorImageCastFilter<TComplexInputImage, TOutputImage> CasterType;
+  typename CasterType::Pointer caster = CasterType::New();
+
+  caster->SetInput(realComplexInputImage);
+  caster->UpdateOutputInformation();
+
+  m_Image = caster->GetOutput();
+  m_Caster = caster;
+
+  return caster->GetOutput();
+}
+
+
+} // End namespace Wrapper
+} // End namespace otb
+
+#endif