diff --git a/.gitignore b/.gitignore
index 17ea701d139816c5301f73b038671b75ac47786b..abe3eaa10177f8486f2ac778a2dd8d8e29d00a1f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,6 @@ archives*
 CMakeLists.txt.user
 .directory*
 build_packages*
+build
+install
+log
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d249b8c87619b15020fef331e940b493c5f63100..d430c3408bb0bac1f6be994f6c43fdb0061c73c3 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -128,6 +128,7 @@ fast-build:
     - git checkout -f -q $CI_COMMIT_SHA
   script:
     - ctest -V -S CI/main_ci.cmake -DIMAGE_NAME:string=ubuntu-22.04-fast
+    - ctest -VV -S CI/FFTW_tests.cmake -DIMAGE_NAME:string=ubuntu-22.04-fast
     - ccache -s
 
 legal-check:
diff --git a/CI/FFTW_tests.cmake b/CI/FFTW_tests.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..abdbada2684dfb4e9e13dc62c715eb5771cd3606
--- /dev/null
+++ b/CI/FFTW_tests.cmake
@@ -0,0 +1,96 @@
+#
+# Copyright (C) 2005-2024 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.
+#
+include( "${CMAKE_CURRENT_LIST_DIR}/macros.cmake" )
+get_filename_component(OTB_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR} DIRECTORY)
+set (ENV{LANG} "C") # Only ascii output
+
+# Build Configuration : Release, Debug..
+if(ci_build_type)
+  set (CTEST_BUILD_CONFIGURATION ${ci_build_type})
+else()
+  set (CTEST_BUILD_CONFIGURATION "Release")
+endif()
+
+set (CTEST_CMAKE_GENERATOR "Ninja")
+
+# detect short sha
+if(NOT DEFINED ENV{CI_COMMIT_SHORT_SHA})
+  execute_process(COMMAND git log -1 --pretty=format:%h
+                  WORKING_DIRECTORY ${OTB_SOURCE_DIR}
+                  OUTPUT_VARIABLE ci_short_sha)
+else()
+  set(ci_short_sha "$ENV{CI_COMMIT_SHORT_SHA}")
+endif()
+
+# Find the build name and CI profile. Customize it with FFTW
+set_dash_build_name()
+set (CTEST_BUILD_NAME "FFTW Tests ${ci_ref_name} P-${ci_pipeline_id}")
+
+# Detect site
+if(NOT DEFINED IMAGE_NAME)
+  if(DEFINED ENV{IMAGE_NAME})
+    set(IMAGE_NAME $ENV{IMAGE_NAME})
+  endif()
+endif()
+set (CTEST_SITE "${IMAGE_NAME}")
+
+# Directory variable
+set (CTEST_SOURCE_DIRECTORY "${OTB_SOURCE_DIR}")
+if(BUILD_DIR)
+  set (CTEST_BINARY_DIRECTORY "${BUILD_DIR}")
+else()
+  set (CTEST_BINARY_DIRECTORY "${OTB_SOURCE_DIR}/build/")
+endif()
+set (CTEST_INSTALL_DIRECTORY "${OTB_SOURCE_DIR}/install/")
+set (PROJECT_SOURCE_DIR "${OTB_SOURCE_DIR}")
+
+# Ctest command value
+set (CMAKE_COMMAND "cmake")
+
+message(STATUS "CI profile : ${ci_profile}")
+
+# Sources are already checked out : do nothing for update
+set(CTEST_GIT_UPDATE_CUSTOM "${CMAKE_COMMAND}" "-E" "echo" "No update")
+# Look for a GIT command-line client.
+find_program(CTEST_GIT_COMMAND NAMES git git.cmd)
+
+
+
+ctest_start (Experimental TRACK CI_Build)
+
+ctest_update()
+
+# Run only onverlapSave tests
+ctest_test(PARALLEL_LEVEL 8
+    RETURN_VALUE _test_rv
+    CAPTURE_CMAKE_ERROR _test_error
+    INCLUDE "OverlapSave"
+    )
+  # Test log
+file ( WRITE 
+"${OTB_SOURCE_DIR}/log/test_return_value_log.txt" "${_test_rv}")
+file ( WRITE 
+"${OTB_SOURCE_DIR}/log/test_cmake_error_log.txt" "${_test_error}")
+
+if ( NOT _test_rv EQUAL 0 )
+  message( SEND_ERROR "An error occurs during ctest_test.")
+endif()
+
+ctest_submit()
diff --git a/CI/ubuntu-22.04-fast.cmake b/CI/ubuntu-22.04-fast.cmake
index 7ca25a3da30627b4449b03e3ccd6c81e9cddc213..78c2303422e2c10c489c17cb9fec208ff0d1ee04 100644
--- a/CI/ubuntu-22.04-fast.cmake
+++ b/CI/ubuntu-22.04-fast.cmake
@@ -26,6 +26,7 @@ CMAKE_CXX_COMPILER:STRING=g++
 CMAKE_C_COMPILER_LAUNCHER:STRING=ccache
 CMAKE_CXX_COMPILER_LAUNCHER:STRING=ccache
 OTB_USE_SHARK:BOOL=OFF
+OTB_USE_FFTW:BOOL=ON
 BUILD_EXAMPLES:BOOL=OFF")
 
 set(ci_skip_testing ON)
diff --git a/Modules/Core/Convolution/CMakeLists.txt b/Modules/Core/Convolution/CMakeLists.txt
index 66dcee34743e4d1d32aee57803fcb6e689d52f23..262a67e7781e527596f3897125a8e86763868c3e 100644
--- a/Modules/Core/Convolution/CMakeLists.txt
+++ b/Modules/Core/Convolution/CMakeLists.txt
@@ -21,13 +21,10 @@
 project(OTBConvolution)
 
 option(OTB_USE_FFTW "Download and compile FFTW third party (license change to GPLv2)" OFF)
-
 if (OTB_USE_FFTW)
-  message(NOTICE "/!\ /!\ /!\ You are actually compiling OTB with FFTW. As FFTW is distributed under GNU GPLv2, OTB is now provided with GNU GPLv2 license /!\ /!\ /!\ ")
+  message(NOTICE "/!\\ /!\\ /!\\ You are actually compiling OTB with FFTW. As FFTW is distributed under GNU GPLv2, OTB is now provided with GNU GPLv2 license /!\\ /!\\ /!\\ ")
 else()
   message(STATUS "Compiling with FFTW disabled, otbOverlapSaveConvolutionImageFilter will not be available")
-  add_compile_definitions(ITK_USE_FFTWD=0)
-  add_compile_definitions(ITK_USE_FFTWF=0)
 endif()
 
 otb_module_impl()
diff --git a/Modules/Core/Convolution/include/otbOverlapSaveConvolutionImageFilter.hxx b/Modules/Core/Convolution/include/otbOverlapSaveConvolutionImageFilter.hxx
index df27d747d15819d9a94e968f43614ba7f65859ba..d09a2f3a488aa3f75a78a50eee3197988dd2cb4b 100644
--- a/Modules/Core/Convolution/include/otbOverlapSaveConvolutionImageFilter.hxx
+++ b/Modules/Core/Convolution/include/otbOverlapSaveConvolutionImageFilter.hxx
@@ -35,7 +35,7 @@
 #include "itkImageRegionIterator.h"
 #include "otbMath.h"
 
-#ifdef ITK_USE_FFTWD
+#ifdef OTB_USE_FFTW
 #include "itkFFTWCommon.h"
 #endif
 
@@ -54,7 +54,7 @@ OverlapSaveConvolutionImageFilter<TInputImage, TOutputImage, TBoundaryCondition>
 template <class TInputImage, class TOutputImage, class TBoundaryCondition>
 void OverlapSaveConvolutionImageFilter<TInputImage, TOutputImage, TBoundaryCondition>::GenerateInputRequestedRegion()
 {
-#if defined ITK_USE_FFTWD
+#if defined OTB_USE_FFTW
   // call the superclass' implementation of this method
   Superclass::GenerateInputRequestedRegion();
 
@@ -108,7 +108,7 @@ void OverlapSaveConvolutionImageFilter<TInputImage, TOutputImage, TBoundaryCondi
      * ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) */
     ::GenerateData()
 {
-#if defined ITK_USE_FFTWD
+#if defined OTB_USE_FFTW
   // Input/Output pointers
   typename OutputImageType::Pointer     output = this->GetOutput();
   typename InputImageType::ConstPointer input  = this->GetInput();
diff --git a/Modules/Core/Convolution/test/CMakeLists.txt b/Modules/Core/Convolution/test/CMakeLists.txt
index e76c0e59fa69f5c06e41f7cfa59f54910b139dbf..b7826c0923845ebd7d86245d10ec1acc48e1e44a 100644
--- a/Modules/Core/Convolution/test/CMakeLists.txt
+++ b/Modules/Core/Convolution/test/CMakeLists.txt
@@ -32,6 +32,11 @@ if (OTB_USE_FFTW)
 endif()
 
 add_executable(otbConvolutionTestDriver ${OTBConvolutionTests})
+# enable FFTW tests when using OTB_USE_FFTW option
+if (OTB_USE_FFTW)
+  target_compile_definitions(otbConvolutionTestDriver PUBLIC "OTB_USE_FFTW=1")
+endif()
+
 target_link_libraries(otbConvolutionTestDriver ${OTBConvolution-Test_LIBRARIES})
 otb_module_target_label(otbConvolutionTestDriver)
 
@@ -74,7 +79,6 @@ if(OTB_USE_FFTW)
       0
       )
   endif()
-
 endif()
 
 otb_add_test(NAME bfTvGaborFilterGenerator COMMAND otbConvolutionTestDriver
diff --git a/Modules/Core/Convolution/test/otbConvolutionTestDriver.cxx b/Modules/Core/Convolution/test/otbConvolutionTestDriver.cxx
index 9e5a6dc2d2c7aff68a00fb3e76c7e8577cdb5de4..f239f6d761593ed895a5378f6832b1f9032efb26 100644
--- a/Modules/Core/Convolution/test/otbConvolutionTestDriver.cxx
+++ b/Modules/Core/Convolution/test/otbConvolutionTestDriver.cxx
@@ -19,11 +19,12 @@
  */
 
 #include "otbTestMain.h"
+#include <iostream>
 
 void RegisterTests()
 {
   REGISTER_TEST(otbConvolutionImageFilter);
-#if defined(ITK_USE_FFTWD)
+#if defined(OTB_USE_FFTW)
   REGISTER_TEST(otbOverlapSaveConvolutionImageFilter);
   REGISTER_TEST(otbCompareOverlapSaveAndClassicalConvolutionWithGaborFilter);
 #endif
diff --git a/Modules/Core/Descriptors/test/otbFourierMellinImageFilter.cxx b/Modules/Core/Descriptors/test/otbFourierMellinImageFilter.cxx
index 5fb2f52df63a89d90ae1374119be53b49b396b32..827d8a15d87fa7b90aac7692dd57d82e8151bb03 100644
--- a/Modules/Core/Descriptors/test/otbFourierMellinImageFilter.cxx
+++ b/Modules/Core/Descriptors/test/otbFourierMellinImageFilter.cxx
@@ -87,6 +87,7 @@ int otbFourierMellinImageFilter(int itkNotUsed(argc), char* argv[])
   imaginaryWriter->SetInput(imaginaryRescaler->GetOutput());
   imaginaryWriter->Update();
 // Hugly hack for cleaning fftw threads
+#if defined(OTB_USE_FFTW)
 #if defined(ITK_USE_FFTWF)
     fftwf_cleanup_threads();
     fftwf_cleanup();
@@ -94,6 +95,7 @@ int otbFourierMellinImageFilter(int itkNotUsed(argc), char* argv[])
 #if defined(ITK_USE_FFTWD)
     fftw_cleanup_threads();
     fftw_cleanup();
+#endif
 #endif
   return EXIT_SUCCESS;
 }
diff --git a/SuperBuild/CMake/External_itk.cmake b/SuperBuild/CMake/External_itk.cmake
index a03dccb487c7bd1b5a73ed6cd6db296a7db3fa06..1e69a8572e5d616bfc40c3aa1a2a9efe32279231 100644
--- a/SuperBuild/CMake/External_itk.cmake
+++ b/SuperBuild/CMake/External_itk.cmake
@@ -120,8 +120,6 @@ if (OTB_USE_FFTW)
   ADDTO_DEPENDENCIES_IF_NOT_SYSTEM(ITK ZLIB FFTW)
 else()
   ADDTO_DEPENDENCIES_IF_NOT_SYSTEM(ITK ZLIB)
-  add_compile_definitions(ITK_USE_FFTWD=0)
-  add_compile_definitions(ITK_USE_FFTWF=0)
 endif()
 ADD_SUPERBUILD_CMAKE_VAR(ITK ZLIB_INCLUDE_DIR)
 ADD_SUPERBUILD_CMAKE_VAR(ITK ZLIB_LIBRARY)