diff --git a/.hgignore b/.hgignore deleted file mode 100644 index 7e842947378e7a678021ab2c61f0d1ed063e68f1..0000000000000000000000000000000000000000 --- a/.hgignore +++ /dev/null @@ -1,10 +0,0 @@ -syntax: glob -*~ -.*.swp -*.orig -*.pyc -.\#* -\#*\# -tags -*vim* -*.template diff --git a/.hgsigs b/.hgsigs deleted file mode 100644 index 3a827ea0c1107475983f15a35a0a7ee6f740a4cb..0000000000000000000000000000000000000000 --- a/.hgsigs +++ /dev/null @@ -1,3 +0,0 @@ -68eebc1b170a636794feda66523e6c0135ebfef2 0 iEYEABECAAYFAkmvX3cACgkQwRJnCg+r8KFSCgCfVYSnx2ev+hIlpbM/arxzLVf3KvsAn3nqaJXaj62RcNUIjv+qcNWlJ5WG -e0fdaae06d33190d9b17356c5d51f878fd8fa0b6 0 iEYEABECAAYFAkoNOJEACgkQwRJnCg+r8KHMrACeJMcezNBgXjfx57UNdd/WfXw8kf8An1VEqFVTeG/wUd6QiiVy2icgfLGl -c07af3906a803b43018e1a7e15db5c11f54d14b4 0 iEYEABECAAYFAkw68W0ACgkQwRJnCg+r8KGhjgCfR4LL9xW8xYGFXWEpbxSSRsCFVhIAn2nPMTqZvUW0cQvU6pkJD1+eENNj diff --git a/.travis.yml b/.travis.yml index 57e2a46096cd5394605d34555e99f75278249c4a..ec99d4dea9a1ee15fcf3db29a8e2d6244e39ab90 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,10 @@ dist: trusty compiler: - clang -addons: - apt: - packages: - - libboost-all-dev +# addons: +# apt: +# packages: +# - libboost-all-dev cache: ccache diff --git a/CMake/FindGBenchmark.cmake b/CMake/FindGBenchmark.cmake index ed2a3674dcba34c43edf2bac0f7025ba585587fa..72d79260fb289a583396214a29e002539835328e 100644 --- a/CMake/FindGBenchmark.cmake +++ b/CMake/FindGBenchmark.cmake @@ -4,10 +4,11 @@ # GBENCHMARK_LIBRARY - gbenchmark library file # GBENCHMARK_FOUND - TRUE if gbenchmark is found -if (GBENCHMARK_INCLUDE_DIR) - #check cache - set(GBENCHMARK_FIND_QUIETLY TRUE) -endif () +set(GBENCHMARK_FIND_QUIETLY TRUE) +# if (GBENCHMARK_INCLUDE_DIR) +# #check cache +# set(GBENCHMARK_FIND_QUIETLY TRUE) +# endif () if (NOT GBENCHMARK_INCLUDE_DIR) find_path(GBENCHMARK_INCLUDE_DIR NAMES benchmark.h PATH_SUFFIXES benchmark) diff --git a/CMake/FindMuParserX.cmake b/CMake/FindMuParserX.cmake index 095aacc12f0d0f338685abd9dcba6f70f5d2dcf9..467d335d661d736aa86f6137c786b219c7466846 100644 --- a/CMake/FindMuParserX.cmake +++ b/CMake/FindMuParserX.cmake @@ -16,7 +16,7 @@ if( MUPARSERX_INCLUDE_DIR ) endif() find_path( MUPARSERX_INCLUDE_DIR mpParser.h - PATH_SUFFIXES mpParser ) + PATH_SUFFIXES mpParser muparserx) if(EXISTS "${MUPARSERX_INCLUDE_DIR}/mpDefines.h") file(READ "${MUPARSERX_INCLUDE_DIR}/mpDefines.h" _mpDefines_h_CONTENTS) diff --git a/CMake/OTBCheckCpp11Keywords.cmake b/CMake/OTBCheckCpp11Keywords.cmake index da3022688000b361e8f2a3d0d5fe44febfc96be2..8afdcf05b8ac77f258bad0593fcc7343894cb30a 100644 --- a/CMake/OTBCheckCpp11Keywords.cmake +++ b/CMake/OTBCheckCpp11Keywords.cmake @@ -1,6 +1,7 @@ include(CheckCXXSourceCompiles) -unset(OTB_HAS_CXX11 CACHE) +set(CMAKE_REQUIRED_FLAGS ${CMAKE_CXX_FLAGS}) + CHECK_CXX_SOURCE_COMPILES(" #ifdef _MSC_VER #if _MSC_VER <= 1700 @@ -20,7 +21,7 @@ int main(int argc, char *argv[]) " OTB_HAS_CXX11 ) -unset(OTB_CXX_HAS_UNIQUE_PTR CACHE) + CHECK_CXX_SOURCE_COMPILES(" #include <memory> struct Foo @@ -38,7 +39,6 @@ int main(int argc, char *argv[]) " OTB_CXX_HAS_UNIQUE_PTR ) -unset(OTB_CXX_HAS_OVERRIDE_SPECIFIER CACHE) CHECK_CXX_SOURCE_COMPILES(" struct A { @@ -64,7 +64,6 @@ int main(int argc, char *argv[]) " OTB_CXX_HAS_OVERRIDE_SPECIFIER ) -unset(OTB_CXX_HAS_NULLPTR CACHE) CHECK_CXX_SOURCE_COMPILES(" #include <cstddef> int main(int argc, char *argv[]) diff --git a/CMake/OTBConfig.cmake.in b/CMake/OTBConfig.cmake.in index 479674cc5c033c0f37b52b1803812423004e188c..1ecbbc5bf3e90332e9ca52aff1548d76d4f45c33 100644 --- a/CMake/OTBConfig.cmake.in +++ b/CMake/OTBConfig.cmake.in @@ -28,6 +28,8 @@ set(OTB_BUILD_SHARED "@BUILD_SHARED_LIBS@") # List of available OTB modules. set(OTB_MODULES_ENABLED "@OTB_CONFIG_MODULES_ENABLED@") +set(OTB_APPLICATION_PATH "@OTB_CONFIG_APPLICATION_PATH@") + # Import OTB targets. set(OTB_CONFIG_TARGETS_FILE "@OTB_CONFIG_TARGETS_FILE@") if(NOT OTB_TARGETS_IMPORTED@OTB_CONFIG_TARGETS_CONDITION@) diff --git a/CMake/OTBModuleEnablement.cmake b/CMake/OTBModuleEnablement.cmake index a2d78ac07cc8735a5e5452276eb38eade0ca1214..be1475f008cb6b17a748239716630220eb282681 100644 --- a/CMake/OTBModuleEnablement.cmake +++ b/CMake/OTBModuleEnablement.cmake @@ -169,6 +169,11 @@ set(OTB_MODULES_ENABLED "") set(OTB_MODULES_DISABLED "") foreach(otb-module ${OTB_MODULES_ALL}) if(${otb-module}_ENABLED) + # check cxx11 requirement after all enable/disable macros have been passed + if(OTB_MODULE_${otb-module}_REQUIRES_CXX11 AND NOT OTB_HAS_CXX11) + message(FATAL_ERROR "Module ${otb-module} requires C++11 support. Consider adding --std=c++11 to your compiler flags or disabling it.") + endif() + list(APPEND OTB_MODULES_ENABLED ${otb-module}) # We will sort modules according to their dependency graph, diff --git a/CMake/OTBModuleMacros.cmake b/CMake/OTBModuleMacros.cmake index 5a3e256db2a0ed6f0b544a61ce0f7e3a8a795402..0580f8e50c915e915f0b6a3fb053f0437240e6aa 100644 --- a/CMake/OTBModuleMacros.cmake +++ b/CMake/OTBModuleMacros.cmake @@ -284,8 +284,10 @@ endmacro() macro(otb_module_target_name _name) get_property(_target_type TARGET ${_name} PROPERTY TYPE) if (NOT ${_target_type} STREQUAL "EXECUTABLE") - set_property(TARGET ${_name} PROPERTY VERSION 1) - set_property(TARGET ${_name} PROPERTY SOVERSION 1) + if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") + set_property(TARGET ${_name} PROPERTY VERSION 1) + set_property(TARGET ${_name} PROPERTY SOVERSION 1) + endif() if("${_name}" MATCHES "^[Oo][Tt][Bb]") set(_otb "") else() @@ -334,7 +336,5 @@ macro(otb_module_target _name) endmacro() macro(otb_module_requires_cxx11) - if(${otb-module}_ENABLED AND NOT ${OTB_HAS_CXX11}) - message(FATAL_ERROR "Module ${otb-module} requires C++11 support. Consider adding --std=c++11 to your compiler flags or disabling it.") - endif() + set(OTB_MODULE_${otb-module}_REQUIRES_CXX11 1) endmacro() diff --git a/CMake/SourceStatus.cmake b/CMake/SourceStatus.cmake index 4b245c81fa47ae5259f14dae77f986758374a95a..19d6facb7ce17a67a0d8a6d003770cfc77ea3fae 100644 --- a/CMake/SourceStatus.cmake +++ b/CMake/SourceStatus.cmake @@ -61,7 +61,7 @@ function(repository_status root_repo_dir result_var1) if(OTB_WC_STATUS) message(STATUS " Local file modifications (${dir_name}) :") string(REPLACE "\n" "\n-- " OTB_WC_STATUS_PRETTYPRINT " ${OTB_WC_STATUS}") - message(WARNING "${OTB_WC_STATUS_PRETTYPRINT}") + message(STATUS "${OTB_WC_STATUS_PRETTYPRINT}") else() message(STATUS " No files modified locally (${dir_name})") endif() diff --git a/CMake/UseOTB.cmake b/CMake/UseOTB.cmake index 5a891e450f5c925715a561f14df2a1e29cf5bef4..d09ea33fb9907391c83d8f7b67bcad2885eab244 100644 --- a/CMake/UseOTB.cmake +++ b/CMake/UseOTB.cmake @@ -27,3 +27,11 @@ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${ITK_REQUIRED_LINK_ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${ITK_REQUIRED_LINK_FLAGS}") # OpenCV : no USE_FILE defined + +#PYTHONPATH + +if( OTB_PYTHONPATH ) + if(DEFINED ENV{PYTHONPATH}) + set(ENV{PYTHONPATH} "${OTB_PYTHONPATH};$ENV{PYTHONPATH}") + endif() +endif() diff --git a/CMake/otbcli.bat.in b/CMake/otbcli.bat.in index ffe1fb2a3f4695e6d1377f453cda524d90723bf2..165d8338726754d5f7188bc7ae3ae3e52a41685d 100644 --- a/CMake/otbcli.bat.in +++ b/CMake/otbcli.bat.in @@ -16,8 +16,13 @@ if exist %CURRENT_SCRIPT_DIR%otbApplicationLauncherCommandLine.exe ( setlocal :: works for install tree -if exist %CURRENT_SCRIPT_DIR%../@OTB_INSTALL_APP_DIR@ ( - set OTB_APPLICATION_PATH=%CURRENT_SCRIPT_DIR%../@OTB_INSTALL_APP_DIR@;%OTB_APPLICATION_PATH% +if exist %CURRENT_SCRIPT_DIR%..\@OTB_INSTALL_APP_DIR_NATIVE@ ( + set OTB_APPLICATION_PATH=%CURRENT_SCRIPT_DIR%..\@OTB_INSTALL_APP_DIR_NATIVE@;%OTB_APPLICATION_PATH% +) + +::set GDAL_DATA, EPSG_CSV and update PATH +if exist %CURRENT_SCRIPT_DIR%\..\otbenv.cmd ( + call %CURRENT_SCRIPT_DIR%\..\otbenv.cmd ) set LC_NUMERIC=C diff --git a/CMake/otbcli.sh.in b/CMake/otbcli.sh.in index 3fd44c745969e689e71bcaef43483d4ef0d36051..3026dad88730fcaca2543bff9e97c5db66a85c6a 100644 --- a/CMake/otbcli.sh.in +++ b/CMake/otbcli.sh.in @@ -28,9 +28,10 @@ export OTB_APPLICATION_PATH # avoid numerical issues caused by locale export LC_NUMERIC=C -# Source GDAL_DATA, EPSG_CSV -if [ -f "$CURRENT_SCRIPT_DIR/env_exports" ]; then - . "$CURRENT_SCRIPT_DIR/env_exports" +# Export GDAL_DATA, EPSG_CSV +# Note that OTB_APPLICATION_PATH is reset here. +if [ -f "$CURRENT_SCRIPT_DIR/../otbenv.profile" ]; then + . "$CURRENT_SCRIPT_DIR/../otbenv.profile" fi # start the application diff --git a/CMake/otbgui.sh.in b/CMake/otbgui.sh.in index 5b389e1d9b5de73f0aa57766fb52c1c01f5c3543..5f6354a75ced0919941e7012083e02cda4696a4c 100644 --- a/CMake/otbgui.sh.in +++ b/CMake/otbgui.sh.in @@ -28,9 +28,9 @@ export OTB_APPLICATION_PATH # avoid numerical issues caused by locale export LC_NUMERIC=C -# Source GDAL_DATA, EPSG_CSV -if [ -f "$CURRENT_SCRIPT_DIR/env_exports" ]; then - . "$CURRENT_SCRIPT_DIR/env_exports" +# Export GDAL_DATA, EPSG_CSV +if [ -f "$CURRENT_SCRIPT_DIR/../otbenv.profile" ]; then + . "$CURRENT_SCRIPT_DIR/../otbenv.profile" fi # start the application diff --git a/CMakeLists.txt b/CMakeLists.txt index 998f03945a1075b1f0b95b88d371c22c007d202b..fb6ce64896ae1ed56060adfab4ae37bb414e9efc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,7 +86,7 @@ set(main_project_name ${_OTBModuleMacros_DEFAULT_LABEL}) #----------------------------------------------------------------------------- # OTB version number. set(OTB_VERSION_MAJOR "5") -set(OTB_VERSION_MINOR "8") +set(OTB_VERSION_MINOR "10") set(OTB_VERSION_PATCH "0") set(OTB_VERSION_STRING "${OTB_VERSION_MAJOR}.${OTB_VERSION_MINOR}.${OTB_VERSION_PATCH}") @@ -134,6 +134,9 @@ if(NOT OTB_INSTALL_PACKAGE_DIR) set(OTB_INSTALL_PACKAGE_DIR "${OTB_INSTALL_LIBRARY_DIR}/cmake/OTB-${OTB_VERSION_MAJOR}.${OTB_VERSION_MINOR}") endif() +#convert path to native for reconfiguring otbcli.bat.in +file(TO_NATIVE_PATH "${OTB_INSTALL_APP_DIR}" OTB_INSTALL_APP_DIR_NATIVE) + # Override CMake's built-in add_* commands: assign LABELS to tests and targets # automatically. Depends on the CMake variable otb-module being set to the # "current" module when add_* is called. @@ -305,6 +308,17 @@ set(OTB_CONFIG_CODE " set(OTB_MODULES_DIR \"${OTB_MODULES_DIR}\")") set(OTB_CONFIG_CMAKE_DIR "${OTB_SOURCE_DIR}/CMake") set(OTB_USE_FILE "${OTB_CONFIG_CMAKE_DIR}/UseOTB.cmake") +if(OTB_WRAP_PYTHON) +set(OTB_CONFIG_CODE "${OTB_CONFIG_CODE} +set(OTB_PYTHONPATH \"${OTB_BINARY_DIR}/${OTB_INSTALL_PYTHON_DIR}\")") +endif() +if(OTB_HAS_CXX11) + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR + "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + set(OTB_REQUIRED_CXX_FLAGS " -std=c++11") + endif() +endif() +set(OTB_CONFIG_APPLICATION_PATH "${OTB_BINARY_DIR}/${OTB_INSTALL_APP_DIR}") set(OTB_CONFIG_TARGETS_CONDITION " AND NOT OTB_BINARY_DIR") set(OTB_CONFIG_TARGETS_FILE "${OTB_BINARY_DIR}/OTBTargets.cmake") set(OTB_CONFIG_MODULE_API_FILE "${OTB_SOURCE_DIR}/CMake/OTBModuleAPI.cmake") @@ -326,6 +340,11 @@ set(OTB_CONFIG_CODE "${OTB_CONFIG_CODE} set(OTB_MODULES_DIR \"\${OTB_INSTALL_PREFIX}/${OTB_INSTALL_PACKAGE_DIR}/Modules\")") set(OTB_USE_FILE "\${OTB_INSTALL_PREFIX}/${OTB_INSTALL_PACKAGE_DIR}/UseOTB.cmake") set(OTB_CONFIG_CMAKE_DIR "\${OTB_INSTALL_PREFIX}/${OTB_INSTALL_PACKAGE_DIR}") +if(OTB_WRAP_PYTHON) +set(OTB_CONFIG_CODE "${OTB_CONFIG_CODE} +set(OTB_PYTHONPATH \"\${OTB_INSTALL_PREFIX}/${OTB_INSTALL_PYTHON_DIR}\")") +endif() +set(OTB_CONFIG_APPLICATION_PATH "\${OTB_INSTALL_PREFIX}/${OTB_INSTALL_APP_DIR}") set(OTB_CONFIG_TARGETS_CONDITION "") set(OTB_CONFIG_TARGETS_FILE "\${OTB_INSTALL_PREFIX}/${OTB_INSTALL_PACKAGE_DIR}/OTBTargets.cmake") set(OTB_CONFIG_MODULE_API_FILE "\${OTB_INSTALL_PREFIX}/${OTB_INSTALL_PACKAGE_DIR}/OTBModuleAPI.cmake") diff --git a/Documentation/Cookbook/CMake/RunApplicationsRstGenerator.sh.cmake.in b/Documentation/Cookbook/CMake/RunApplicationsRstGenerator.sh.cmake.in index d5f17f1f07bc0822f83edadfcdfce58e47b67f7d..3c3a810ca20cd0987143828e74ee9e2d9d1771be 100644 --- a/Documentation/Cookbook/CMake/RunApplicationsRstGenerator.sh.cmake.in +++ b/Documentation/Cookbook/CMake/RunApplicationsRstGenerator.sh.cmake.in @@ -1,6 +1,6 @@ #!/bin/sh export LD_LIBRARY_PATH=@OTB_INSTALL_PREFIX@/lib:$LD_LIBRARY_PATH -export PYTHONPATH=@OTB_INSTALL_PREFIX@/lib:@OTB_PYTHONPATH@:$PYTHONPATH -export OTB_APPLICATION_PATH=@OTB_INSTALL_PREFIX@/lib/otb/applications -@PYTHON_EXECUTABLE@ @CMAKE_SOURCE_DIR@/Scripts/otbGenerateWrappersRstDoc.py +export PYTHONPATH=@OTB_PYTHONPATH@:$PYTHONPATH +export OTB_APPLICATION_PATH=@OTB_APPLICATION_PATH@ +@PYTHON_EXECUTABLE@ @CMAKE_SOURCE_DIR@/Scripts/otbGenerateWrappersRstDoc.py -o "$1" diff --git a/Documentation/Cookbook/CMakeLists.txt b/Documentation/Cookbook/CMakeLists.txt index 7228a6a1e4c5e60f2393baec4a1d91204870cf67..cd3eae702ae49a23e4f389cde7b891a3359bb22f 100644 --- a/Documentation/Cookbook/CMakeLists.txt +++ b/Documentation/Cookbook/CMakeLists.txt @@ -1,12 +1,20 @@ - set(OUT_OF_SOURCE_BUILD FALSE) if(NOT PROJECT_NAME) - cmake_minimum_required(VERSION 2.8) + cmake_minimum_required(VERSION 3.0) project(OTBCookBook) set(OUT_OF_SOURCE_BUILD TRUE) + option(BUILD_TESTING "Build the testing tree." ON) +endif() + +if(BUILD_TESTING) + enable_testing() + include(CTest) endif() +string(TIMESTAMP OTB_COPYRIGHT_YEAR "%Y") +set(OTB_COPYRIGHT_TEXT "${OTB_COPYRIGHT_YEAR}, OTB Team") + #find OTB find_package(OTB REQUIRED) @@ -18,153 +26,141 @@ else() return() endif() -set(OTB_PYTHONPATH) -if( EXISTS "${OTB_DIR}/CMakeCache.txt" ) - set(OTB_INSTALL_PREFIX ${OTB_DIR}) - set(OTB_PYTHONPATH "${OTB_INSTALL_PREFIX}/Modules/Wrappers/SWIG/src") -elseif( EXISTS "${OTB_DIR}/UseOTB.cmake" ) - get_filename_component(OTB_INSTALL_PREFIX ${OTB_DIR} PATH) - get_filename_component(OTB_INSTALL_PREFIX ${OTB_INSTALL_PREFIX} PATH) - get_filename_component(OTB_INSTALL_PREFIX ${OTB_INSTALL_PREFIX} PATH) - set(OTB_PYTHONPATH "${OTB_INSTALL_PREFIX}/lib/otb/python") -endif() +get_filename_component(OTB_INSTALL_PREFIX ${OTB_MODULES_DIR} PATH) +get_filename_component(OTB_INSTALL_PREFIX ${OTB_INSTALL_PREFIX} PATH) +get_filename_component(OTB_INSTALL_PREFIX ${OTB_INSTALL_PREFIX} PATH) +get_filename_component(OTB_INSTALL_PREFIX ${OTB_INSTALL_PREFIX} PATH) -#find Python -find_package(PythonInterp REQUIRED) +message(STATUS "OTB_PYTHONPATH = '${OTB_PYTHONPATH}'") +message(STATUS "OTB_APPLICATION_PATH = '${OTB_APPLICATION_PATH}'") +message(STATUS "OTB_INSTALL_PREFIX = '${OTB_INSTALL_PREFIX}'") -find_program(SH_INTERP sh) -if(NOT SH_INTERP) - message(FATAL_ERROR "'sh' program not found") +if(NOT OTB_PYTHONPATH) + message(FATAL_ERROR "OTB_PYTHONPATH empty") endif() -find_program(SPHINX_BUILD sphinx-build) +if(NOT OTB_APPLICATION_PATH) + message(FATAL_ERROR "OTB_APPLICATION_PATH empty") +endif() -if(NOT SPHINX_BUILD) - message(FATAL_ERROR "The 'sphinx-build' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the 'sphinx-build' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org") +if(NOT OTB_INSTALL_PREFIX) + message(FATAL_ERROR "OTB_INSTALL_PREFIX empty") endif() -string(TIMESTAMP OTB_COPYRIGHT_YEAR "%Y") -set(OTB_COPYRIGHT_TEXT "${OTB_COPYRIGHT_YEAR}, OTB Team") -set(RST_GENERATED_SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/rst) +macro(remove_and_make_directories) + foreach(dir in ${ARGV}) + execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory ${dir}) + execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${dir}) + endforeach() +endmacro() -set(RST_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/_build") -set(RST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/rst) +#find Python +find_package(PythonInterp REQUIRED) -#make some directories -execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${RST_GENERATED_SOURCE_DIR}/Applications) -execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${RST_GENERATED_SOURCE_DIR}/recipes) -execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${RST_GENERATED_SOURCE_DIR}/Art) -execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${RST_GENERATED_SOURCE_DIR}/Art/MonteverdiImages) -execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${RST_GENERATED_SOURCE_DIR}/Art/ClassifImages) -execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${RST_GENERATED_SOURCE_DIR}/Art/QtImages) -execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${RST_GENERATED_SOURCE_DIR}/_static) -execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${RST_GENERATED_SOURCE_DIR}/_templates) +find_program(SH_INTERP sh) +mark_as_advanced(SH_INTERP) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMake/RunApplicationsRstGenerator.sh.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/RunApplicationsRstGenerator.sh - @ONLY) +find_program(LATEX_COMMAND NAMES latex) +mark_as_advanced(LATEX_COMMAND) -file(GLOB images ${CMAKE_CURRENT_SOURCE_DIR}/Art/*.*) -foreach(image ${images}) - get_filename_component(out_file ${image} NAME) - configure_file(${image} ${RST_GENERATED_SOURCE_DIR}/Art/${out_file} COPYONLY) -endforeach() +find_program(TAR_COMMAND NAMES tar) +mark_as_advanced(TAR_COMMAND) -file(GLOB mvd_images ${CMAKE_CURRENT_SOURCE_DIR}/Art/MonteverdiImages/*.*) -foreach(mvd_image ${mvd_images}) - get_filename_component(out_file ${mvd_image} NAME) - configure_file(${mvd_image} ${RST_GENERATED_SOURCE_DIR}/Art/MonteverdiImages/${out_file} COPYONLY) -endforeach() +find_program(SPHINX_BUILD NAMES sphinx-build) +mark_as_advanced(SPHINX_BUILD) -file(GLOB classif_images ${CMAKE_CURRENT_SOURCE_DIR}/Art/ClassifImages/*.*) -foreach(classif_image ${classif_images}) - get_filename_component(out_file ${classif_image} NAME) - configure_file(${classif_image} ${RST_GENERATED_SOURCE_DIR}/Art/ClassifImages/${out_file} COPYONLY) -endforeach() +find_program(PDFLATEX_COMMAND NAMES pdflatex ) +mark_as_advanced(PDFLATEX_COMMAND) -file(GLOB qt_images ${CMAKE_CURRENT_SOURCE_DIR}/Art/QtImages/*.png) -foreach(qt_image ${qt_images}) - get_filename_component(out_file ${qt_image} NAME) - configure_file(${qt_image} ${RST_GENERATED_SOURCE_DIR}/Art/QtImages/${out_file} COPYONLY) +foreach(cmd LATEX_COMMAND TAR_COMMAND PDFLATEX_COMMAND SPHINX_BUILD SH_INTERP) + if(NOT ${cmd}) + message(FATAL_ERROR "${cmd} not set. Cannot continue") + endif() endforeach() -file(GLOB sar_images ${CMAKE_CURRENT_SOURCE_DIR}/Art/SARImages/*.png) -foreach(sar_image ${sar_images}) - get_filename_component(out_file ${sar_image} NAME) - configure_file(${sar_image} ${RST_GENERATED_SOURCE_DIR}/Art/SARImages/${out_file} COPYONLY) -endforeach() +set(RST_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/rst) -file(GLOB rst_sources1 ${RST_SOURCES}/*.rst) -foreach(rst_file ${rst_sources1}) - get_filename_component(out_file ${rst_file} NAME) - configure_file(${rst_file} ${RST_GENERATED_SOURCE_DIR}/${out_file} COPYONLY) -endforeach() +set(RST_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/rst) +set(LATEX_DIR ${CMAKE_CURRENT_BINARY_DIR}/latex) +set(HTML_DIR ${CMAKE_CURRENT_BINARY_DIR}/html) -file(GLOB rst_sources2 ${RST_SOURCES}/recipes/*.rst) -foreach(rst_file ${rst_sources2}) - get_filename_component(out_file ${rst_file} NAME) - configure_file(${rst_file} ${RST_GENERATED_SOURCE_DIR}/recipes/${out_file} COPYONLY) -endforeach() -file(GLOB rst_sources3 ${RST_SOURCES}/Applications/*.rst) -foreach(rst_file ${rst_sources3}) - get_filename_component(out_file ${rst_file} NAME) - configure_file(${rst_file} ${RST_GENERATED_SOURCE_DIR}/Applications/${out_file} COPYONLY) -endforeach() +remove_and_make_directories( + ${HTML_DIR} + ${RST_BINARY_DIR} + ${RST_BINARY_DIR}/Applications/ + ${HTML_DIR} + ${LATEX_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/_static + ) -file(GLOB rst_sources4 ${RST_SOURCES}/*.txt) -foreach(rst_file ${rst_sources4}) - get_filename_component(out_file ${rst_file} NAME) - configure_file(${rst_file} ${RST_GENERATED_SOURCE_DIR}/${out_file} COPYONLY) -endforeach() +execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_CURRENT_BINARY_DIR}/RunApplicationsRstGenerator.sh) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMake/RunApplicationsRstGenerator.sh.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/RunApplicationsRstGenerator.sh + @ONLY) + +file(COPY ${RST_SOURCE_DIR} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/Art DESTINATION ${RST_BINARY_DIR}) -configure_file(${RST_SOURCES}/conf.py.in ${RST_GENERATED_SOURCE_DIR}/conf.py @ONLY) -configure_file(${RST_SOURCES}/Makefile.in ${RST_GENERATED_SOURCE_DIR}/Makefile @ONLY) +set(SPHINX_CONF_DIR ${CMAKE_CURRENT_BINARY_DIR}) +configure_file(${RST_SOURCE_DIR}/conf.py.in ${SPHINX_CONF_DIR}/conf.py @ONLY) + +#configure_file(${RST_SOURCE_DIR}/Makefile.in ${RST_GENERATED_SOURCE_DIR}/Makefile.sphinx @ONLY) +# Internal variables. +# PAPEROPT_a4 = -D latex_paper_size=a4 +# PAPEROPT_letter = -D latex_paper_size=letter +# ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# # the i18n builder cannot share the environment and doctrees with the others +# I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . add_custom_target(generate_otbapps_rst - ALL COMMAND ${SH_INTERP} ${CMAKE_CURRENT_BINARY_DIR}/RunApplicationsRstGenerator.sh - WORKING_DIRECTORY ${RST_GENERATED_SOURCE_DIR} + ${RST_BINARY_DIR} + WORKING_DIRECTORY ${RST_BINARY_DIR} COMMENT "Auto-generating Application Reference Documentation in RST" ) -add_custom_target(CookBookHTMLFromRST - ALL - COMMAND ${CMAKE_MAKE_PROGRAM} html - WORKING_DIRECTORY ${RST_GENERATED_SOURCE_DIR} +add_custom_target(CookBookHTML + COMMAND ${SPHINX_BUILD} + -b html + ${RST_BINARY_DIR} + ${HTML_DIR} + -W + -v + -c ${SPHINX_CONF_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS generate_otbapps_rst COMMENT "Building RST documentation in html") -find_program(TAR_COMMAND - NAMES tar - PATHS /usr/bin -) -mark_as_advanced(TAR_COMMAND) - -if(TAR_COMMAND) - add_custom_target(CookBookArchive - ALL - COMMAND ${TAR_COMMAND} - --transform "s/^html/CookBook-${OTB_VERSION_MAJOR}.${OTB_VERSION_MINOR}/" - -czf ${CMAKE_BINARY_DIR}/CookBook-${OTB_VERSION_MAJOR}.${OTB_VERSION_MINOR}-html.tar.gz html - WORKING_DIRECTORY ${RST_BUILD_DIR} - DEPENDS CookBookHTMLFromRST - COMMENT "Creating archive for html CookBook") -endif() - -find_program(PDFLATEX_COMMAND - NAMES pdflatex - PATHS /usr/bin -) -mark_as_advanced(PDFLATEX_COMMAND) - -if(PDFLATEX_COMMAND) - add_custom_target(CookBookPDFFromRST - ALL - COMMAND ${CMAKE_MAKE_PROGRAM} latexpdf - WORKING_DIRECTORY ${RST_GENERATED_SOURCE_DIR} - DEPENDS generate_otbapps_rst - COMMENT "Building RST documentation in pdf") -endif() +add_custom_target(CookBookArchive + ALL + COMMAND ${TAR_COMMAND} + --transform "s/^html/CookBook-${OTB_VERSION_MAJOR}.${OTB_VERSION_MINOR}/" + -czf ${CMAKE_BINARY_DIR}/CookBook-${OTB_VERSION_MAJOR}.${OTB_VERSION_MINOR}-html.tar.gz html + WORKING_DIRECTORY ${RST_BUILD_DIR} + DEPENDS CookBookHTML + COMMENT "Creating archive for html CookBook") + + add_custom_target(CookBookTexFromRST + COMMAND ${SPHINX_BUILD} + -b latex + ${RST_BINARY_DIR} + ${LATEX_DIR} + -W + -v + -c ${SPHINX_CONF_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS CookBookHTML + COMMENT "Generating Tex files from rst" + VERBATIM) + + add_custom_target(CookBookPDF + ALL + COMMAND ${CMAKE_MAKE_PROGRAM} all-pdf + WORKING_DIRECTORY ${LATEX_DIR} + DEPENDS CookBookTexFromRST + COMMENT "Building RST documentation in pdf") diff --git a/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py b/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py index 3e306e23d29baa1be7f57db3e64c741714f0f63e..21c79fc446994da68d1b75ad38a304e2399538a5 100755 --- a/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py +++ b/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py @@ -430,7 +430,11 @@ def RstHeading(text, delimiter): def ApplicationToRst(appname): output = "" - app = otbApplication.Registry.CreateApplication(appname) + app = None + try: + app = otbApplication.Registry.CreateApplication(appname) + except e: + print e # TODO: remove this when bug 440 is fixed app.Init() output += RstHeading(app.GetDocName(), '^') @@ -487,74 +491,108 @@ def GetApplicationTags(appname): import shutil -def RstPageHeading(text): +def RstPageHeading(text, maxdepth): output = RstHeading(text, "=") + linesep output += ".. toctree::" + linesep - output += "\t:maxdepth: 2" + linesep + output += "\t:maxdepth: " + maxdepth + linesep output += linesep + linesep return output def GenerateRstForApplications(): out = "" - blackList = ["TestApplication", "Example"] - appIndexFile = open('Applications.rst', 'w') - appNames = [app for app in otbApplication.Registry.GetAvailableApplications() if app not in blackList] - if not appNames: - print 'No OTB applications available. Please check ITK_AUTOLOAD_PATH env variable' - sys.exit(1) - sectionTags = ["Image Manipulation","Vector Data Manipulation", "Calibration","Geometry", "Image Filtering","Feature Extraction","Stereo","Learning","Segmentation"] - appIndexFile.write(RstPageHeading("Applications")) - - for tag in sectionTags: - directory= "Applications/" + tag - if not os.path.exists(directory): - os.makedirs(directory) - tag_ = tag.replace(' ', '_') - appIndexFile.write('\tApplications/' + tag_ + '.rst' + linesep) - #chapterIndexFile = open('Applications/' + tag + '.rst', 'w') - #chapterIndexFile.write(RstPageHeading(tag)) - #print linesep + RstHeading(tag, '=') - appsRemoved = [] - for appName in appNames: - apptags = GetApplicationTags(appName) - - if apptags.count(tag) > 0: - print "Generating " + appName + ".rst" - #chapterIndexFile.write("\t" + tag + '/' + appName + linesep) - appFile = open('Applications/app_' + appName + '.rst', 'w') - out = ApplicationToRst(appName) - appFile.write(out) - appFile.close() - appsRemoved.append(appName) - for appName in appsRemoved: - appNames.remove(appName) - #chapterIndexFile.close() - - misctag = "Miscellaneous" #should this be Utilities - if not os.path.exists("Applications/" + misctag): - os.makedirs("Applications/" + misctag) - - appIndexFile.write('\tApplications/' + misctag + linesep) - appIndexFile.close() - #miscChapterIndexFile = open("Applications/" + misctag + '.rst', 'w') - #miscChapterIndexFile.write(RstPageHeading(misctag)) + blackList = ["TestApplication", "Example", "ApplicationExample"] + allApps = None + try: + allApps = otbApplication.Registry.GetAvailableApplications( ) + except e: + print 'error in otbApplication.Registry.GetAvailableApplications()' + sys.exit(1) + +# appNames = [app for app in otbApplication.Registry.GetAvailableApplications() if app not in blackList] + if not allApps: + print 'No OTB applications available. Please check OTB_APPLICATION_PATH env variable' + sys.exit(1) + + # sectionTags = ["Image Manipulation", + # "Vector Data Manipulation", + # "Calibration","Geometry", "Image Filtering","Feature Extraction", + # "Stereo","Learning","Segmentation", "Miscellaneous"] + # for tag in sectionTags: + # #directory= "Applications/" + tag + # # if not os.path.exists(directory): + # # os.makedirs(directory) + # appIndexFile.write('\tApplications/' + tag.replace(' ', '_') + '.rst' + linese) + # #chapterIndexFile = open('Applications/' + tag + '.rst', 'w') + # #chapterIndexFile.write(RstPageHeading(tag)) + # #print linesep + RstHeading(tag, '=') + + + #miscFile = open('Applications/Miscellaneous.rst', 'w') + # misctag = "Miscellaneous" #should this be Utilities + # if not os.path.exists("Applications/" + misctag): + # os.makedirs("Applications/" + misctag) + +# appIndexFile.write('\tApplications/' + misctag + linesep) + + + writtenTags = [] + appNames = [app for app in allApps if app not in blackList] + + print "All apps: %s" % (appNames,) + + appIndexFile = open(RST_DIR + '/Applications.rst', 'w') + appIndexFile.write(RstPageHeading("Applications", "2")) for appName in appNames: - print "Generating " + appName + ".rst" - appFile = open("Applications/app_" + appName + ".rst", 'w') + tags = GetApplicationTags(appName) + + if not tags: + print "No tags for application: " + appName + sys.exit(1) + + tag = tags[0] + + tag_ = tag + if tag.find(' '): + tag_ = tag.replace(' ', '_') + + if not tag_: + print 'empty tag found for ' + appName + + if not tag_ in writtenTags: + appIndexFile.write('\tApplications/' + tag_ + '.rst' + linesep) + writtenTags.append(tag_) + + tagFileName = RST_DIR + '/Applications/' + tag_ + '.rst' + if os.path.isfile(tagFileName): + tagFile = open(tagFileName, 'a') + tagFile.write("\tapp_" + appName + linesep) + tagFile.close() + else: + tagFile = open(tagFileName, 'w') + tagFile.write( RstPageHeading(tag, "1") ) + tagFile.write("\tapp_" + appName + linesep) + tagFile.close() + + print "Generating " + appName + ".rst" + " on tag " + tag_ + appFile = open(RST_DIR + '/Applications/app_' + appName + '.rst', 'w') out = ApplicationToRst(appName) appFile.write(out) appFile.close() - #miscChapterIndexFile.write('\t' + misctag + '/' + appName + linesep) - out = "" + + appIndexFile.close() + return out # Start parsing options -parser = OptionParser(usage="Export application(s) to tex or pdf file.") +parser = OptionParser(usage="Export application(s) to rst file.") parser.add_option("-a",dest="appname",help="Generate rst only for this application (eg: OrthoRectification)") parser.add_option("-m",dest="module",help="Generate rst only for this module (eg: Image Manipulation)") +parser.add_option("-o",dest="rstdir",help="directory where rst files are generated") (options, args) = parser.parse_args() +RST_DIR = options.rstdir + if not options.appname is None: out = ApplicationToRst(options.appname) #print out diff --git a/Documentation/Cookbook/rst/Applications/Calibration.rst b/Documentation/Cookbook/rst/Applications/Calibration.rst deleted file mode 100644 index 478a93b2bf1e22fdb3e695d82fa1b83ba465c73f..0000000000000000000000000000000000000000 --- a/Documentation/Cookbook/rst/Applications/Calibration.rst +++ /dev/null @@ -1,13 +0,0 @@ -Calibration -=========== - - -.. toctree:: - :maxdepth: 1 - - app_OpticalCalibration - app_SARCalibration - app_SARDecompositions - app_SARPolarMatrixConvert - app_SARPolarSynth - app_SarRadiometricCalibration diff --git a/Documentation/Cookbook/rst/Applications/Feature_Extraction.rst b/Documentation/Cookbook/rst/Applications/Feature_Extraction.rst deleted file mode 100644 index 3f551afaa133bb70ccda051e1dd4d2c6771a0e84..0000000000000000000000000000000000000000 --- a/Documentation/Cookbook/rst/Applications/Feature_Extraction.rst +++ /dev/null @@ -1,21 +0,0 @@ -Feature Extraction -================== - - -.. toctree:: - :maxdepth: 1 - - - app_BinaryMorphologicalOperation - app_ComputePolylineFeatureFromImage - app_DSFuzzyModelEstimation - app_EdgeExtraction - app_GrayScaleMorphologicalOperation - app_HaralickTextureExtraction - app_HomologousPointsExtraction - app_LineSegmentDetection - app_LocalStatisticExtraction - app_MultivariateAlterationDetector - app_RadiometricIndices - app_SFSTextureExtraction - app_VectorDataDSValidation diff --git a/Documentation/Cookbook/rst/Applications/Geometry.rst b/Documentation/Cookbook/rst/Applications/Geometry.rst deleted file mode 100644 index 1d23508af71e9e431b480a392a778cb6cc7ccda0..0000000000000000000000000000000000000000 --- a/Documentation/Cookbook/rst/Applications/Geometry.rst +++ /dev/null @@ -1,19 +0,0 @@ -Geometry -======== - - -.. toctree:: - :maxdepth: 1 - - app_BundleToPerfectSensor - app_ConvertCartoToGeoPoint - app_ConvertSensorToGeoPoint - app_GeneratePlyFile - app_GenerateRPCSensorModel - app_GridBasedImageResampling - app_ImageEnvelope - app_OrthoRectification - app_Pansharpening - app_RefineSensorModel - app_RigidTransformResample - app_Superimpose diff --git a/Documentation/Cookbook/rst/Applications/Image_Filtering.rst b/Documentation/Cookbook/rst/Applications/Image_Filtering.rst deleted file mode 100644 index 39300f14b757a175f25644f86946373f9eec8753..0000000000000000000000000000000000000000 --- a/Documentation/Cookbook/rst/Applications/Image_Filtering.rst +++ /dev/null @@ -1,12 +0,0 @@ -Image Filtering -=============== - - -.. toctree:: - :maxdepth: 1 - - - app_Despeckle - app_DimensionalityReduction - app_MeanShiftSmoothing - app_Smoothing diff --git a/Documentation/Cookbook/rst/Applications/Image_Manipulation.rst b/Documentation/Cookbook/rst/Applications/Image_Manipulation.rst deleted file mode 100644 index f1b1ca98c5973d68337b8dea027e392c49a6ed89..0000000000000000000000000000000000000000 --- a/Documentation/Cookbook/rst/Applications/Image_Manipulation.rst +++ /dev/null @@ -1,21 +0,0 @@ -Image Manipulation -================== - - -.. toctree:: - :maxdepth: 1 - - - app_ColorMapping - app_ConcatenateImages - app_Convert - app_DEMConvert - app_DownloadSRTMTiles - app_ExtractROI - app_ManageNoData - app_MultiResolutionPyramid - app_Quicklook - app_ReadImageInfo - app_Rescale - app_SplitImage - app_TileFusion diff --git a/Documentation/Cookbook/rst/Applications/Learning.rst b/Documentation/Cookbook/rst/Applications/Learning.rst deleted file mode 100644 index 836eb0a2258959719d6dd29bc0e64d435211ce63..0000000000000000000000000000000000000000 --- a/Documentation/Cookbook/rst/Applications/Learning.rst +++ /dev/null @@ -1,22 +0,0 @@ -Learning -======== - - -.. toctree:: - :maxdepth: 1 - - app_ClassificationMapRegularization - app_ComputeConfusionMatrix - app_ComputeImagesStatistics - app_FusionOfClassifications - app_ImageClassifier - app_KMeansClassification - app_MultiImageSamplingRate - app_PolygonClassStatistics - app_PredictRegression - app_SampleExtraction - app_SampleSelection - app_SOMClassification - app_TrainImagesClassifier - app_TrainRegression - app_TrainVectorClassifier diff --git a/Documentation/Cookbook/rst/Applications/Miscellaneous.rst b/Documentation/Cookbook/rst/Applications/Miscellaneous.rst deleted file mode 100644 index 67289bd885f30b4b5eeb247360a060d85c757125..0000000000000000000000000000000000000000 --- a/Documentation/Cookbook/rst/Applications/Miscellaneous.rst +++ /dev/null @@ -1,16 +0,0 @@ -Miscellaneous -============= - - -.. toctree:: - :maxdepth: 1 - - app_BandMath - app_BandMathX - app_CompareImages - app_HyperspectralUnmixing - app_KmzExport - app_OSMDownloader - app_ObtainUTMZoneFromGeoPoint - app_PixelValue - app_VertexComponentAnalysis diff --git a/Documentation/Cookbook/rst/Applications/Segmentation.rst b/Documentation/Cookbook/rst/Applications/Segmentation.rst deleted file mode 100644 index f9530fa784c50504037aa1ad64848b5d59ce80d6..0000000000000000000000000000000000000000 --- a/Documentation/Cookbook/rst/Applications/Segmentation.rst +++ /dev/null @@ -1,16 +0,0 @@ -Segmentation -============ - - -.. toctree:: - :maxdepth: 1 - - app_ComputeOGRLayersFeaturesStatistics - app_ConnectedComponentSegmentation - app_HooverCompareSegmentation - app_LSMSSegmentation - app_LSMSSmallRegionsMerging - app_LSMSVectorization - app_OGRLayerClassifier - app_Segmentation - app_TrainOGRLayersClassifier diff --git a/Documentation/Cookbook/rst/Applications/Stereo.rst b/Documentation/Cookbook/rst/Applications/Stereo.rst deleted file mode 100644 index feadf0508abcd751e1eb771cde429042d25aa41f..0000000000000000000000000000000000000000 --- a/Documentation/Cookbook/rst/Applications/Stereo.rst +++ /dev/null @@ -1,12 +0,0 @@ -Stereo -====== - - -.. toctree:: - :maxdepth: 1 - - app_BlockMatching - app_DisparityMapToElevationMap - app_FineRegistration - app_StereoFramework - app_StereoRectificationGridGenerator diff --git a/Documentation/Cookbook/rst/Applications/Vector_Data_Manipulation.rst b/Documentation/Cookbook/rst/Applications/Vector_Data_Manipulation.rst deleted file mode 100644 index 09f55741573142c04285c50fa5a454b3f5c48854..0000000000000000000000000000000000000000 --- a/Documentation/Cookbook/rst/Applications/Vector_Data_Manipulation.rst +++ /dev/null @@ -1,13 +0,0 @@ -Vector Data Manipulation -======================== - - -.. toctree:: - :maxdepth: 1 - - app_ConcatenateVectorData - app_Rasterization - app_VectorDataExtractROI - app_VectorDataReprojection - app_VectorDataSetField - app_VectorDataTransform diff --git a/Documentation/Cookbook/rst/Installation_Linux.txt b/Documentation/Cookbook/rst/Installation_Linux.txt index f86681bd63bad76344e1fea96780ac4cc3342953..8a6e941d15f3de94da5f53739af25686a2e000db 100644 --- a/Documentation/Cookbook/rst/Installation_Linux.txt +++ b/Documentation/Cookbook/rst/Installation_Linux.txt @@ -49,6 +49,18 @@ The applications can be launched from the Mapla launcher. If you want to use the otbcli and otbgui launchers, you can initialize your environment with ``source otbenv.profile``. +Python bindings +--------------- +Starting from OTB 5.8.0, OTB python bindings are distributed with binary package. +currently only Python 2.x is supported. If no compatible python is found, installation +notify you about it. If everything works fine, you will be given information about +using python bindings. + +You must have python numpy bindings installed in your system. you can install it locally +without admin rights with "pip install --user numpy". This is to give users to choose +their own existing python installation rather than distributing one in OTB package + + Notes: - You must use monteverdi and mapla through ``mapla.sh`` and ``monteverdi.sh`` helper scripts in extracted directory. @@ -81,17 +93,17 @@ A: This is due to a conflict with system Qt4 (usually seen on KDE) and Qt4 + gtk Q: Monteverdi and Mapla applications look different from my other applications. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A: By default, Monteverdi, Mapla and otbapplication (otbgui\_\*) uses a default gtk theme (plastic) -which is distributed with the OTB package!. We do this to be on safe side, like when a user does -not have gtk libraries installed when using our package. +A: By default, Monteverdi, Mapla and otbapplication (otbgui\_\*) uses a the +system gtk theme. If you can't install GTK on your system you can use the +distributed with the OTB package. Note that using system GTK is the preferred +way with the OTB standalone package as the distributed version of GTK do not +work on recent Linux distributions. -gtk libraries in the package is the reason why you are getting a default "plastic" look & feel that -makes it look different from other GUI applications. -To get same look and feel, you can "force" Monteverdi and Mapla to use system GTK. +To use the distributed GTK libraries you need to set the OTB_USE_LOCAL_GTK: :: - export OTB_USE_SYSTEM_GTK=1 + export OTB_USE_LOCAL_GTK=1 And now start ``monteverdi.sh`` or ``mapla.sh`` from OTB-|release|-Linux64 -To get back default behaviour, unset OTB_USE_SYSTEM_GTK=1 or set OTB_USE_SYSTEM_GTK=0 +To get back default behaviour, unset OTB_USE_LOCAL_GTK=1 or set OTB_USE_LOCAL_GTK=0 diff --git a/Documentation/Cookbook/rst/Installation_Linux_xdk.txt b/Documentation/Cookbook/rst/Installation_Linux_xdk.txt new file mode 100644 index 0000000000000000000000000000000000000000..9542af41aa905cc367b97c264b118a07ba11f5cd --- /dev/null +++ b/Documentation/Cookbook/rst/Installation_Linux_xdk.txt @@ -0,0 +1,66 @@ +Synopsis +-------- + +This archive provides a development kit for the ORFEO ToolBox library which +allows to easily compile OTB and facilitate the creation of programs based on +OTB. + +It contains shared libraries of OTB dependencies and helper scripts for the +configuration and the compilation of the library. + +Note that OTB sources are not included in the archive (see instructions below). + +Prerequisites +------------- + +- cmake (>= 3.2) +- gcc (>= 4.9) +- git + +Extract XDK +----------- + +:: + + cd /opt (You can use another a directory of your own choice) + chmod +x OTB-|release|-xdk-Linux64.run + ./OTB-|release|-xdk-Linux64.run + +**You now will have a directory named **OTB-|release|-xdk-Linux64** in **/opt** + +Setup environment +----------------- +There is a helper script in package called **xdkenv.profile**. This script export +required environments to configure and build OTB. + +:: + + cd /opt/OTB-|release|-xdk-Linux64 + . ./xdkenv.profile + +Test environment setup by checking value of CMAKE_PREFIX_PATH + +:: + + echo $CMAKE_PREFIX_PATH + +The above command will output: + /opt/OTB-|release|-xdk-Linux64 + + +Download, Configure and build OTB +--------------------------------- + +:: + + mkdir -p /opt/OTB/build && cd /opt/OTB + git clone --depth=1 --branch=develop https://git@git.orfeo-toolbox.org/git/otb.git source + cd build && cmake ../source + make -j2 + + +Notes +~~~~~ + +By default, all OTB\_USE\_\* variables in OTB are set to FALSE except for 6S and SiftFast. You can check/activate them in your cmake-gui/ccmake. + diff --git a/Documentation/Cookbook/rst/Installation_Macx.txt b/Documentation/Cookbook/rst/Installation_Macx.txt index 1e498c9b4330ff7047b325a918833d257ac6990a..cf7f3f9bc462ef081facf3c93527c0c73b953d76 100644 --- a/Documentation/Cookbook/rst/Installation_Macx.txt +++ b/Documentation/Cookbook/rst/Installation_Macx.txt @@ -4,8 +4,8 @@ uncompress it with the command line : .. parsed-literal:: - chmod +x OTB-|release|-Linux64.run - ./OTB-|release|-Linux64.run + chmod +x OTB-|release|-Darwin64.run + ./OTB-|release|-Darwin64.run Once the archive is extracted, you can see OTB-|release|-Darwin64 directory in the same direcrtory along with OTB-|release|-Darwin64.run @@ -25,6 +25,17 @@ Contents of OTB-|release|-Darwin64 is briefly listed below: - ``share`` : A folder containing common resources and copyright mentions. +Python bindings +--------------- +Starting from OTB 5.8.0, OTB python bindings are distributed with binary package. +currently only Python 2.x is supported. If no compatible python is found, installation +notify you about it. If everything works fine, you will be given information about +using python bindings. + +You must have python numpy bindings installed in your system. you can install it locally +without admin rights with "pip install --user numpy". This is to give users to choose +their own existing python installation rather than distributing one in OTB package + Notes: - If you want to use the otbcli and otbgui launchers, you must access diff --git a/Documentation/Cookbook/rst/Installation_Macx_xdk.txt b/Documentation/Cookbook/rst/Installation_Macx_xdk.txt new file mode 100644 index 0000000000000000000000000000000000000000..648393dc3496a11f07ebc0a2f4353df09bbcab57 --- /dev/null +++ b/Documentation/Cookbook/rst/Installation_Macx_xdk.txt @@ -0,0 +1,2 @@ +README.md + diff --git a/Documentation/Cookbook/rst/Installation_Windows.txt b/Documentation/Cookbook/rst/Installation_Windows.txt index 3c2884969a197f87b0dffb8dcf40358af5ccb589..f7a967190ee2f6b418753bac799cc7d31c18e37a 100644 --- a/Documentation/Cookbook/rst/Installation_Windows.txt +++ b/Documentation/Cookbook/rst/Installation_Windows.txt @@ -22,6 +22,17 @@ The applications can be launched from the Mapla launcher. If you want to use the otbcli and otbgui launchers, you can initialize a command prompt with ``otbenv.bat``. +Python bindings +--------------- +Starting from OTB 5.8.0, OTB python bindings are distributed with binary package. +currently only Python 2.x is supported. If no compatible python is found, installation +notify you about it. If everything works fine, you will be given information about +using python bindings. + +You must have python numpy bindings installed in your system. you can install it locally +without admin rights with "pip install --user numpy". This is to give users to choose +their own existing python installation rather than distributing one in OTB package + Notes: ~~~~~~ - You must have "Visual C++ Redistributable for Visual Studio 2015" installed for using this package. diff --git a/Documentation/Cookbook/rst/Installation_Windows_xdk.txt b/Documentation/Cookbook/rst/Installation_Windows_xdk.txt new file mode 100644 index 0000000000000000000000000000000000000000..b43bf86b50fd8d3529a0dc062c30006ed38f309e --- /dev/null +++ b/Documentation/Cookbook/rst/Installation_Windows_xdk.txt @@ -0,0 +1 @@ +README.md diff --git a/Documentation/Cookbook/rst/Makefile.in b/Documentation/Cookbook/rst/Makefile.in index 83ba8f3b2f8580bb6ff65d092a091e54f612cd3a..a2440433de3bd3894af3cfe43637021afff8153b 100644 --- a/Documentation/Cookbook/rst/Makefile.in +++ b/Documentation/Cookbook/rst/Makefile.in @@ -7,10 +7,6 @@ SPHINXBUILD = sphinx-build PAPER = BUILDDIR = @RST_BUILD_DIR@ -# User-friendly check for sphinx-build -ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) -$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) -endif # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 diff --git a/Documentation/Cookbook/rst/Monteverdi.rst b/Documentation/Cookbook/rst/Monteverdi.rst index 6fb7c21db040abe0f06762efdaa3c3e2ce3fc0fe..57614e613d75aa505fa9cce1ce6cbf94f9f481b2 100644 --- a/Documentation/Cookbook/rst/Monteverdi.rst +++ b/Documentation/Cookbook/rst/Monteverdi.rst @@ -12,22 +12,19 @@ Monteverdi is a satellite image viewer. Its main features are: - **Powerful**: Access to all processing application from OTB. Orthorectification, optical calibration, classification, SAR processing, and much more! -GUI : what does it look like ? ------------------------------- - .. image:: Art/MonteverdiImages/gui.png -This is Monteverdi’s main window where the different functionalities are reachable: +This is Monteverdi’s main window where the different functionalities are: #. Main menu #. Top toolbar -#. Image displaying +#. Image View -#. Right side dock +#. Widgets -#. Stack layer +#. Layer stack Main menu ~~~~~~~~~ @@ -92,9 +89,9 @@ In the image displaying part: - CTRL+Mouse drag = Quick scroll view (rending is done after releasing CTRL key) -- CTRL+Mouse wheel = Zoom in out +- Mouse wheel = Zoom -- + or - = Zoom in out +- + or - = Zoom In the layer stack part: diff --git a/Documentation/Cookbook/rst/OTB-Applications.rst b/Documentation/Cookbook/rst/OTB-Applications.rst index a69fe4eff5f7f76ac336196bfd706a7529ce39f4..eea59f1a7291920ac8bee0b30ae1f689b6fedf21 100644 --- a/Documentation/Cookbook/rst/OTB-Applications.rst +++ b/Documentation/Cookbook/rst/OTB-Applications.rst @@ -31,7 +31,7 @@ entry points. The framework can be extended, but Orfeo Toolbox ships with the fo QGIS. The OTB Applications are now rich of more than 90 tools, which are -listed in the the applications reference documentation, presented in +listed in the applications reference documentation, presented in chapter [chap:apprefdoc], page. Running the applications @@ -40,7 +40,7 @@ Running the applications Common framework ~~~~~~~~~~~~~~~~ -All standard applications shared the same implementation and expose +All standard applications share the same implementation and expose automatically generated interfaces. Thus, the command-line interface is prefixed by ``otbcli_``, while the Qt interface is prefixed by ``otbgui_``. For instance, calling ``otbcli_Convert`` will launch the @@ -149,8 +149,6 @@ The graphical interface for the applications provides a useful interactive user interface to set the parameters, choose files, and monitor the execution progress. -This interface can be activated through the CMake option . - This launcher needs the same two arguments as the command line launcher : @@ -194,12 +192,12 @@ Using the Python interface ~~~~~~~~~~~~~~~~~~~~~~~~~~ The applications can also be accessed from Python, through a module -named ``otbApplication`` +named ``otbApplication``. -On Unix systems it is typically available in the ``/usr/lib/otb/python`` -directory. You may need to configure the environment variable -``PYTHONPATH`` to include this directory so that the module becomes -available from an Python shell. +On Unix systems, it is typically available in the ``/usr/lib/otb/python`` +directory. Depending on how you installed OTB, you may need to configure the +environment variable ``PYTHONPATH`` to include this directory so that the module +becomes available from Python. On Windows, you can install the ``otb-python`` package, and the module will be available from an OSGeo4W shell automatically. diff --git a/Documentation/Cookbook/rst/conf.py.in b/Documentation/Cookbook/rst/conf.py.in index 4c927cc3566189e398b34f42498815c6ffb2e520..30ce0dc728056846e6a2bdf192840a2beb1b0df6 100644 --- a/Documentation/Cookbook/rst/conf.py.in +++ b/Documentation/Cookbook/rst/conf.py.in @@ -14,7 +14,12 @@ import sys import os -import sphinx_rtd_theme +HAVE_RTD_THEME=False +try: + import sphinx_rtd_theme + HAVE_RTD_THEME=True +except: + pass # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -31,10 +36,12 @@ import sphinx_rtd_theme # ones. extensions = [ 'sphinx.ext.todo', - 'sphinx.ext.mathjax', + 'sphinx.ext.imgmath', 'sphinx.ext.viewcode', ] +imgmath_latex='@LATEX_COMMAND@' + # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -104,15 +111,17 @@ pygments_style = 'sphinx' # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'sphinx_rtd_theme' - +if HAVE_RTD_THEME: + html_theme = 'sphinx_rtd_theme' + # Add any paths that contain custom themes here, relative to this directory. + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + # The name for this set of Sphinx documents. If None, it defaults to # "<project> v<release> documentation". @@ -123,7 +132,7 @@ html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # The name of an image file (relative to this directory) to place at the top # of the sidebar. -html_logo = "Art/logo.png" +html_logo = "rst/Art/logo.png" # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 @@ -165,13 +174,13 @@ html_static_path = ['_static'] #html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a <link> tag referring to it. The value of this option must be the diff --git a/Documentation/Cookbook/rst/recipes/numpy.rst b/Documentation/Cookbook/rst/recipes/numpy.rst index 76df92daf470f3f9bee5e02d1a549c8e16a5eafd..4f9ef0e6d834d275b12f4fc56c947ab022ff568b 100644 --- a/Documentation/Cookbook/rst/recipes/numpy.rst +++ b/Documentation/Cookbook/rst/recipes/numpy.rst @@ -14,9 +14,10 @@ GIS/Image processing tools such as GDAL, GRASS GIS, OSSIM that can deal with num Below code reads an input image using python pillow (PIL) and convert it to numpy array. This numpy array is -used an input to the application set *SetImageFromNumpyArray(...)* method. -The application used in this example is `ExtractROI <../Applications/app_ExtractROI.html>`_. After extracting -a small area the output image is taken as numpy array with *GetImageFromNumpyArray(...)* method +used an input to the application via *SetImageFromNumpyArray(...)* method. +The application used in this example is ExtractROI. After extracting +a small area the output image is taken as numpy array with *GetImageFromNumpyArray(...)* method thus avoid wiriting +output to a temporary file. :: diff --git a/Documentation/Cookbook/rst/recipes/optpreproc.rst b/Documentation/Cookbook/rst/recipes/optpreproc.rst index 70fc1a0d4b9593f05c93aa92ec8fc47284468bd0..a88dceceeb7cc776f78666988b5b3985f6af31ce 100644 --- a/Documentation/Cookbook/rst/recipes/optpreproc.rst +++ b/Documentation/Cookbook/rst/recipes/optpreproc.rst @@ -333,9 +333,9 @@ model can’t be observed if the map projection is used. In order to perform an ortho-rectification on this type of product, the map projection has to be hidden from **Orfeo Toolbox** . -You can see if a product is an “ortho-ready†product by using tools such -as ``gdalinfo`` or `ReadImageInfo <../Applications/app_ReadImageInfo.html>`_, and check -if the product verifies the 2 following conditions : +You can see if a product is an “ortho-ready†product by using ``gdalinfo`` or +OTB ReadImageInfo application. +Check if your product verifies following two conditions : - The product is in raw geometry : you should expect the presence of RPC coefficients and a non-empty OSSIM keywordlist. diff --git a/Documentation/Cookbook/rst/recipes/pbclassif.rst b/Documentation/Cookbook/rst/recipes/pbclassif.rst index c537dad6f25737af36ccd6c843fdd90e35698754..8de90bce37a3cee246b18c9664f035268b394947 100644 --- a/Documentation/Cookbook/rst/recipes/pbclassif.rst +++ b/Documentation/Cookbook/rst/recipes/pbclassif.rst @@ -457,12 +457,19 @@ roofs. Data is available in the OTB-Data and this image is produced with the commands inside this `file <http://hg.orfeo-toolbox.org/OTB-Applications/file/3ce975605013/Testing/Classification/CMakeLists.txt>`_ . +.. |image_21| image:: ../Art/MonteverdiImages/classification_chain_inputimage.jpg +.. |image_22| image:: ../Art/MonteverdiImages/classification_chain_fancyclassif_fusion.jpg +.. |image_23| image:: ../Art/MonteverdiImages/classification_chain_fancyclassif.jpg -.. figure:: ../Art/MonteverdiImages/classification_chain_inputimage.jpg -.. figure:: ../Art/MonteverdiImages/classification_chain_fancyclassif_fusion.jpg -.. figure:: ../Art/MonteverdiImages/classification_chain_fancyclassif.jpg +.. _Figure2: + + ++---------------------------+---------------------------+---------------------------+ +| |image_21| | |image_22| | |image_23| | ++---------------------------+---------------------------+---------------------------+ + +Figure 2: From left to right: Original image, result image with fusion (with monteverdi viewer) of original image and fancy classification and input image with fancy color classification from labeled image. -Figure 2: From left to right: Original image, result image with fusion (with monteverdi viewer) of original image and fancy classification and input image with fancy color classification from labeled image. Fusion of classification maps ----------------------------- @@ -476,8 +483,7 @@ Classifications generates a single more robust and precise classification map which combines the information extracted from the input list of labeled images. -The *FusionOfClassifications* application has the following input -parameters : +The *FusionOfClassifications* application has the following input parameters: - ``-il`` list of input labeled classification images to fuse @@ -516,30 +522,45 @@ The application can be used like this: -out MVFusedClassificationMap.tif Let us consider 6 independent classification maps of the same input -image (Cf. left image in `Figure 1`) generated from 6 different SVM models. -The `Figure 2` represents them after a color mapping by the same LUT. +image (Cf. left image in Figure2_) generated from 6 different SVM models. +The Figure3_ represents them after a color mapping by the same LUT. Thus, 4 classes (water: blue, roads: gray,vegetation: green, buildings with red roofs: red) are observable on each of them. -.. figure:: ../Art/MonteverdiImages/QB_1_ortho_C1_CM.png -.. figure:: ../Art/MonteverdiImages/QB_1_ortho_C2_CM.png -.. figure:: ../Art/MonteverdiImages/QB_1_ortho_C3_CM.png -.. figure:: ../Art/MonteverdiImages/QB_1_ortho_C4_CM.png -.. figure:: ../Art/MonteverdiImages/QB_1_ortho_C5_CM.png -.. figure:: ../Art/MonteverdiImages/QB_1_ortho_C6_CM.png +.. |image_31| image:: ../Art/MonteverdiImages/QB_1_ortho_C1_CM.png +.. |image_32| image:: ../Art/MonteverdiImages/QB_1_ortho_C2_CM.png +.. |image_33| image:: ../Art/MonteverdiImages/QB_1_ortho_C3_CM.png +.. |image_34| image:: ../Art/MonteverdiImages/QB_1_ortho_C4_CM.png +.. |image_35| image:: ../Art/MonteverdiImages/QB_1_ortho_C5_CM.png +.. |image_36| image:: ../Art/MonteverdiImages/QB_1_ortho_C6_CM.png + +.. _Figure3: + ++---------------------------+---------------------------+---------------------------+ +| |image_31| | |image_32| | |image_33| | ++---------------------------+---------------------------+---------------------------+ +| |image_34| | |image_35| | |image_36| | ++---------------------------+---------------------------+---------------------------+ Figure 3: Six fancy colored classified images to be fused, generated from 6 different SVM models. + As an example of the *FusionOfClassifications* application by *majority voting*, the fusion of the six input classification maps represented in -`Figure 3` leads to the classification map illustrated on the right in `Figure 4`. +Figure3_ leads to the classification map illustrated on the right in Figure4_. Thus, it appears that this fusion highlights the more relevant classes among the six different input classifications. The white parts of the fused image correspond to the undecided class labels, i.e. to pixels for which there is not a unique majority voting. -.. figure:: ../Art/MonteverdiImages/classification_chain_inputimage.jpg -.. figure:: ../Art/MonteverdiImages/QB_1_ortho_MV_C123456_CM.png +.. |image_41| image:: ../Art/MonteverdiImages/classification_chain_inputimage.jpg +.. |image_42| image:: ../Art/MonteverdiImages/QB_1_ortho_MV_C123456_CM.png + +.. _Figure4: + ++------------------------------------------------+------------------------------------------------+ +| |image_41| | |image_42| | ++------------------------------------------------+------------------------------------------------+ Figure 4: From left to right: Original image, and fancy colored classified image obtained by a majority voting fusion of the 6 classification maps represented in Fig. 4.13 (water: blue, roads: gray, vegetation: green, buildings with red roofs: red, undecided: white) @@ -586,16 +607,23 @@ The application can be used like this: -out DSFusedClassificationMap.tif As an example of the *FusionOfClassifications* application by *Dempster -Shafer*, the fusion of the six input classification maps represented in -`Figure 3` leads to the classification map illustrated on the right in `Figure 5` -[fig:ClassificationMapFusionApplicationDS]. Thus, it appears that this -fusion gives access to a more precise and robust classification map +Shafer*, the fusion of the six input classification maps represented in Figure3_ +leads to the classification map illustrated on the right in Figure5_. +Thus, it appears that this fusion gives access to a more precise and robust classification map based on the confidence level in each classifier. -.. figure:: ../Art/MonteverdiImages/classification_chain_inputimage.jpg -.. figure:: ../Art/MonteverdiImages/QB_1_ortho_DS_V_P_C123456_CM.png -Figure 5: From left to right: Original image, and fancy colored classified image obtained by a Dempster-Shafer fusion of the 6 classification maps represented in Fig. 4.13 (water: blue, roads: gray, vegetation: green, buildings with red roofs: red, undecided: white). +.. |image_51| image:: ../Art/MonteverdiImages/classification_chain_inputimage.jpg +.. |image_52| image:: ../Art/MonteverdiImages/QB_1_ortho_DS_V_P_C123456_CM.png + +.. _Figure5: + ++------------------------------------------------+------------------------------------------------+ +| |image_51| | |image_52| | ++------------------------------------------------+------------------------------------------------+ + +Figure 5: From left to right: Original image, and fancy colored classified image obtained by a Dempster-Shafer fusion of the 6 classification maps represented in Figure3_ (water: blue, roads: gray, vegetation: green, buildings with red roofs: red, undecided: white). + Recommendations to properly use the fusion of classification maps ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -701,15 +729,14 @@ Example ~~~~~~~ Resulting from the application presented in section :ref:`fancy_classification_results` -and illustrated in Fig. [fig:MeanShiftVectorImageFilter], -the Fig.[fig:ClassificationMapRegularizationApplication] shows a regularization +and illustrated in Figure2_, the Figure6_ shows a regularization of a classification map composed of 4 classes: water, roads, vegetation and buildings with red roofs. The radius of the ball shaped structuring element is equal to 3 pixels, which corresponds to a ball included in a 7 x 7 pixels square. Pixels with more than one majority class keep their original labels. -|image| |image| |image| [fig:ClassificationMapRegularizationApplication] + Regression ---------- @@ -720,10 +747,17 @@ a class index) from an input predictor. The workflow is the same as classification. First, the regression model is trained, then it can be used to predict output values. The applications to do that are and . -.. figure:: ../Art/MonteverdiImages/classification_chain_inputimage.jpg -.. figure:: ../Art/MonteverdiImages/classification_chain_fancyclassif_CMR_input.png -.. figure:: ../Art/MonteverdiImages/classification_chain_fancyclassif_CMR_3.png +.. |image_61| image:: ../Art/MonteverdiImages/classification_chain_inputimage.jpg +.. |image_62| image:: ../Art/MonteverdiImages/classification_chain_fancyclassif_CMR_input.png +.. |image_63| image:: ../Art/MonteverdiImages/classification_chain_fancyclassif_CMR_3.png + + +.. _Figure6: ++---------------------------+---------------------------+---------------------------+ +| |image_61| | |image_62| | |image_63| | ++---------------------------+---------------------------+---------------------------+ + Figure 6: From left to right: Original image, fancy colored classified image and regularized classification map with radius equal to 3 pixels. The input data set for training must have the following structure : diff --git a/Documentation/SoftwareGuide/Latex/ContributorList.tex b/Documentation/SoftwareGuide/Latex/ContributorList.tex index dc42ae456a7fc58cc2a8d22e1f1d19ac125f5916..d17508de9313fa479c70eac7773d244c213dc383 100644 --- a/Documentation/SoftwareGuide/Latex/ContributorList.tex +++ b/Documentation/SoftwareGuide/Latex/ContributorList.tex @@ -33,6 +33,7 @@ Julien Osman, Julien Radoux (UCL), Laurentiu Nicola (CS Romania), Luc Hermitte (CS), +Ludovic Hussonnois (CS), Manuel Grizonnet (CNES), Massimo Di Stefano, Mathieu Deltorre (CS), diff --git a/Documentation/SoftwareGuide/Latex/Installation.tex b/Documentation/SoftwareGuide/Latex/Installation.tex index 319e049a18794e80dbcb4b10b056eae2ec782f2e..52136bbe04b2f4c93b379924d8b27c02a5060e9e 100644 --- a/Documentation/SoftwareGuide/Latex/Installation.tex +++ b/Documentation/SoftwareGuide/Latex/Installation.tex @@ -118,7 +118,7 @@ See table \ref{tab:otb-dependencies} for the full list of dependencies. \hline \textbf{MuParser} & \url{http://www.muparser.sourceforge.net} & no & - \\ \hline -\textbf{MuParserX} & \url{http://muparserx.beltoforion.de} & no & 3.0.5 \\ +\textbf{MuParserX} & \url{http://muparserx.beltoforion.de} & no & 4.0.7 \\ \hline \textbf{OpenCV} & \url{http://opencv.org} & no & 2 \\ \hline @@ -251,25 +251,22 @@ Therefore this directory will be used even if you don't use make install target. In fact there is no make install target for the SuperBuild. By default, SuperBuild will not use any of libraries installed on -system. All \texttt{USE\_SYSTEM\_\textit{XXX}} are are set to FALSE. This is our +system. All \texttt{USE\_SYSTEM\_\textit{XXX}} are set to FALSE. This is our recommended way of using SuperBuild. You are however free to use a system library if you want!. You must be very much aware of dependencies of those libraries you use from system. For example, if libjpeg is not used from -superbuild using \texttt{USE\_SYSTEM\_JPEG=TRUE} then you should not use zlib -from superbuild because zlib is a dependency of libjpeg. Here SuperBuild will -not automagically set \texttt{USE\_SYSTEM\_ZLIB=FALSE}. You must do it -yourself. The example of libjpeg - zlib dependency chain is so simple. Imagine -the same case for GDAL which depends on zlib, libjpeg, libtiff(with big tiff +superbuild then you should not use zlib from superbuild because zlib is a dependency of libjpeg. +Here SuperBuild will NOT set \texttt{USE\_SYSTEM\_ZLIB=FALSE}. One must re-run cmake +with \texttt{-DUSE\_SYSTEM\_ZLIB=FALSE}. +Above example of libjpeg-zlib dependency is so simple. Imagine +the case for GDAL which depends on zlib, libjpeg, libtiff(with big tiff support), geotiff, sqlite, curl, geos, libkml, openjpeg. This is one of the -reasons we recommend to use SuperBuild exclusively or not. +reasons we recommend to use SuperBuild exclusively. All dependencies are configured and built in a way that help us to get an efficient build OTB. So we enable geotiff (with proj4 support), openjpeg, geos in GDAL build. -It is also important to note that SuperBuild is tested daily on all three -platforms. It simply works! - (see table~\ref{tab:installation-cmake-variables}). SuperBuild downloads dependencies into the \texttt{DOWNLOAD\_LOCATION} @@ -285,6 +282,20 @@ want to build) : \url{https://www.orfeo-toolbox.org/packages} \end{center} +Qt library: Unlike other dependencies building Qt4 on all platform is not trivial task but +OTB SuperBuild makes best effort to make it easier for you. So there is still +some additional package installation, one has to do as a pre-requistie for SuperBuild +On a GNU/Linux you must have Qt X11 dependencies installed. +See Qt 4.8 documentation for list of packages that needs to be installed +before starting superbuild. http://doc.qt.io/qt-4.8/requirements-x11.html +For a debian 8.1 systeme, I installed all Qt4 dependencies with below 'apt-get install' +\texttt{apt-get install libx11-dev libxext-dev libxt-dev libxi-dev libxrandr-dev libgl-dev libglu-dev} + +You can also deactivate QT4 and skip this by passing \texttt{-DOTB\_USE\_QT4=OFF} to cmake. +This will give you OTB install without monteverdi, mapla and gui application launchers. + +For Mac OSX you need to install XCode and Windows 7,8.1,10 requires MSVC 2015 or higher. + You are now ready to compile OTB! Simply use the make command (other targets can be generated with CMake's \texttt{-G} option): \begin{verbatim} @@ -385,8 +396,6 @@ $ make install \hline \textbf{OTB\_USE\_MUPARSERX} & OTBMuParserX & OTBMathParserX OTBAppMathParserX \\ \hline -\textbf{OTB\_USE\_OPENJPEG} & OTBOpenJPEG & OTBIOJPEG2000 \\ -\hline \textbf{OTB\_USE\_CURL} & OTBCurl & \\ \hline \textbf{OTB\_USE\_MUPARSER} & OTBMuParser & OTBMathParser OTBDempsterShafer OTBAppClassification OTBAppMathParser OTBAppStereo OTBAppProjection OTBAppSegmentation OTBAppClassification OTBRoadExtraction OTBRCC8 OTBCCOBIA OTBAppSegmentation OTBMeanShift OTBAppSegmentation OTBMeanShift OTBAppSegmentation \\ diff --git a/Documentation/SoftwareGuide/Latex/WriteAnApplication.tex b/Documentation/SoftwareGuide/Latex/WriteAnApplication.tex index 992bbf3d2001593fd640e427f692ca6435a34b36..6c04a8c1422903d190cb3e1a88539034f6263961 100644 --- a/Documentation/SoftwareGuide/Latex/WriteAnApplication.tex +++ b/Documentation/SoftwareGuide/Latex/WriteAnApplication.tex @@ -59,7 +59,7 @@ contain the following actions: \label{sec:appDoUpdateParameters} This method is called after every modification of a parameter value. With the command line launcher, it is called each time a parameter is loaded. With the Qt launcher, it -is called each time a parameter field is modified. It can be used to maintain consistency et relationship +is called each time a parameter field is modified. It can be used to maintain consistency and relationship between parameters (e.g. in ExtractROI: when changing the input image, maybe the ROI size has to be updated). @@ -111,7 +111,7 @@ types of parameters: \item \code{ParameterType\_Choice} : parameter storing a list of choices (doesn't support multi-choice). It also allows to create specific sub-parameters for each available choice. \item \code{ParameterType\_ListView} : parameter storing a list of choices (support - multi-choice). + multi-choice and single-choice). \item \code{ParameterType\_InputImage} : parameter storing an input image. \item \code{ParameterType\_InputImageList} : parameter storing a list of input image. \item \code{ParameterType\_ComplexInputImage} : parameter storing a complex input image. @@ -147,6 +147,107 @@ readers needed to produce the input data. The output types \code{OutputImage}, \code{ComplexOutputImage} and \code{OutputVectorData} store the name of the files to write, but they also encapsulate the corresponding writers. +\section{Composite application} + +The application framework has been extended to allow the implementation of composite applications : +applications that use other applications. The concept is simple : you have two applications A and B +that you want to chain in order to build a third application C. Rather than writing C by copying +the code of A and B, you would like to re-use applications A and B. This plain example will be +re-used in this section for explanations. + +A dedicated class \doxygen{otb}{Wrapper::CompositeApplication} has been added to create such applications. +If you derive this class to implement application C, you will be able to create a composite application. + +\subsection{Creating internal applications} + +Like with standard applications, you have to write a \code{DoInit()} function. In this function, +you should first clean any internal application with the function \code{ClearApplications()} +(the \code{DoInit()} function is called twice in some cases). Then you can +instanciate the internal applications that you want to use (for instance A and B). +The function \code{AddApplication()} will do that, based on : +\begin{itemize} +\item The application type (i.e. its official name, such as ExtractROI, BandMath, \dots) +\item An identifier : like with parameter keys, you have to specify an identifier +to refer to this internal application. Use the same naming conventions as parameters. +\item A description : give a small description of the role of this internal application. +\end{itemize} + +Using the function \code{GetInternalApplication()}, you can get a pointer to the +internal application corresponding to a given identifier. + +In the example given in introduction, we assume that : +\begin{itemize} +\item An internal application of type A has been added with identifier \code{a} +\item An internal application of type B has been added with identifier \code{b} +\end{itemize} + +\subsection{Connecting parameters} + +Once you have internal applications, you may want to setup their parameters. There +are typically 3 cases. + +You may want to expose a parameter of an internal application as a parameter of +your composite application. Let say you want to expose parameter \code{io.in} from application +\code{a} into your composite application C with the key \code{input}. You can call the function : + +\code{ShareParameter("input","a.io.in")} + +As a result, the parameters \code{input} in application C and \code{io.in} in application \code{a} +will point to the same object. Under the two parameter keys, there is a unique value. +These two parameters can be considered as synchronized. + +This leads to the second case : you may want to synchronize two parameters from internal +applications. Let say you want to synchronize parameter \code{field} from application +\code{a} with parameter \code{fname} from application \code{b}. You can call the function : + +\code{Connect("a.field","b.fname")} + +Note that the functions \code{ShareParameter()} and \code{Connect()} : +\begin{itemize} +\item Use the same syntax to access internal parameters ("application identifier" +dot "parameter key"). +\item Shall be used in the DoInit() function, after the internal applications +have been added. +\end{itemize} + +In this synchronization, the two parameters should have the same type, or have a +similar interface, such as input and output filenames that are both accessed using +\code{GetParameterString()} and \code{SetParameterString()}. + +This type of connection is a transition to the third case : you may want to connect +the output of an internal application to the input of an other internal application. +Here the difficulty is that the two parameters to connect probably have different +types. Let say you want to connect parameter \code{a.out} to parameter \code{b.in}. +The "Connect()" function may work in favorable cases (see previous paragraph), +but for images, you have two options : +\begin{itemize} +\item Explicitely copy the image pointer from the output image parameter in the input +image parameter (with functions \code{SetParameterInputImage()} and +\code{GetParameterOutputImage()}). It will connect the pipelines in applications +A and B, to form an "in-memory" connexion. This has to be done between the calls +to \code{DoExecute()} of application A and B. +\item Use a temporary filename to store the output image \code{a.out} and read it +with \code{b.in}. In this case, you have to manually call the writers of parameter +\code{a.out}. +\end{itemize} + +At the moment, the connexion of vector data parameters is not supported. + +\subsection{Orchestration} + +In the \code{DoUpdateParameters()} of your composite application, you can call +the same function on an internal application with the function \code{UpdateInternalParameters()}. +This is needed only if your internal applications have a specific behaviour during +parameter update. + +In the \code{DoExecute()} of your composite application, you have to call \code{ExecuteInternal()} +in order to launch each internal application. The order should be compatible with +image parameter connexions. If you want to do "in-memory" connexions, you can to it between +two calls to \code{ExecuteInternal()}. + +The application BundleToPerfectSensor is a simple example of composite applications. +For a more complex example, you can check the application TrainImagesClassifier. + \section{Compile your application} In order to compile your application you must call the macro \code{OTB\_CREATE\_APPLICATION} in the \emph{CMakelists.txt} file. @@ -154,7 +255,7 @@ This macro generates the lib \emph{otbapp\_XXX.so}, in (OTB\_BINARY\_DIR/lib/otb \section{Execute your application} -their are different ways to launch applicatons : +There are different ways to launch applicatons : \begin{description} \item[CommandLine :] The command line option is invoked using \emph{otbApplicationLauncherCommandLine} executable followed by the classname, the application dir and the application parameters. diff --git a/Examples/FeatureExtraction/AsymmetricFusionOfLineDetectorExample.cxx b/Examples/FeatureExtraction/AsymmetricFusionOfLineDetectorExample.cxx index 7a8e700791970ec50d5440f717cc0030a5aca528..3cac44998526a0c940adcd6888bad1f2cadbf549 100644 --- a/Examples/FeatureExtraction/AsymmetricFusionOfLineDetectorExample.cxx +++ b/Examples/FeatureExtraction/AsymmetricFusionOfLineDetectorExample.cxx @@ -203,7 +203,16 @@ int main(int argc, char * argv[]) // Software Guide : EndLatex // Software Guide : BeginCodeSnippet - filter->Update(); + try + { + filter->Update(); + } + catch (itk::ExceptionObject& err) + { + std::cerr << "ExceptionObject caught !" << std::endl; + std::cerr << err << std::endl; + return -1; + } // Software Guide : EndCodeSnippet writer->SetFileName(argv[2]); diff --git a/Examples/Markov/MarkovRestorationExample.cxx b/Examples/Markov/MarkovRestorationExample.cxx index 3821d1999eab7d2a34b13a4d5a55f9b9011ad6bf..1886ec468e2ced70bbb228c690340e409a27125f 100644 --- a/Examples/Markov/MarkovRestorationExample.cxx +++ b/Examples/Markov/MarkovRestorationExample.cxx @@ -223,7 +223,16 @@ int main(int argc, char* argv[]) writer->SetInput(rescaleFilter->GetOutput()); - writer->Update(); + try + { + writer->Update(); + } + catch (itk::ExceptionObject& err) + { + std::cerr << "ExceptionObject caught !" << std::endl; + std::cerr << err << std::endl; + return -1; + } // Software Guide : EndCodeSnippet // Software Guide : BeginLatex diff --git a/Modules/Adapters/GdalAdapters/include/otbOGRVersionProxy.h b/Modules/Adapters/GdalAdapters/include/otbOGRVersionProxy.h index 140520a3b6a4f618d4ce576e25bca948778f233d..87f19d40d22d1ec89798d916549b634ed1310d33 100644 --- a/Modules/Adapters/GdalAdapters/include/otbOGRVersionProxy.h +++ b/Modules/Adapters/GdalAdapters/include/otbOGRVersionProxy.h @@ -23,6 +23,16 @@ #include "otbConfigure.h" #include "itkMacro.h" +#if defined(_MSC_VER) +#pragma warning ( push ) +#pragma warning ( disable: 4251 ) +#include "ogr_core.h" // OGR enums +#pragma warning ( pop ) +#else +#include "ogr_core.h" // OGR enums +#endif + + #ifdef OTB_USE_GDAL_20 class GDALDataset; class GDALDriver; @@ -40,6 +50,12 @@ namespace ogr namespace version_proxy { +/** +* With Gdal >= 2.0, this function will test equality between type and +* OFTInteger64 enum. Otherwise, it returns false. +*/ +OTBGdalAdapters_EXPORT bool IsOFTInteger64(OGRFieldType type); + /** * This namespace holds proxy functions hiding interface changes in gdal 2.0 * diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRVersionProxy1x.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRVersionProxy1x.cxx index 8a21d09882a99b96a0c098b5a46181970f9f1717..b81eb37f2675a530fdcbf3a62dd2bb29f5f8c1f5 100644 --- a/Modules/Adapters/GdalAdapters/src/otbOGRVersionProxy1x.cxx +++ b/Modules/Adapters/GdalAdapters/src/otbOGRVersionProxy1x.cxx @@ -17,6 +17,8 @@ =========================================================================*/ #include "otbOGRVersionProxy.h" +#include "itkMacro.h" + #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshadow" @@ -33,6 +35,12 @@ namespace ogr namespace version_proxy { +OTBGdalAdapters_EXPORT bool IsOFTInteger64(OGRFieldType itkNotUsed(type)) +{ + return false; +} + + GDALDatasetType * Open(const char * filename, bool readOnly) { return OGRSFDriverRegistrar::Open(filename,!readOnly); diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRVersionProxy2x.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRVersionProxy2x.cxx index 81d0ff82b9753dc66673b38872fb0b63165473c3..1872586038f3c16511a7487faf1173260f2d59ee 100644 --- a/Modules/Adapters/GdalAdapters/src/otbOGRVersionProxy2x.cxx +++ b/Modules/Adapters/GdalAdapters/src/otbOGRVersionProxy2x.cxx @@ -34,6 +34,11 @@ namespace ogr namespace version_proxy { +OTBGdalAdapters_EXPORT bool IsOFTInteger64(OGRFieldType type) +{ + return type == OFTInteger64; +} + GDALDatasetType * Open(const char * filename, bool readOnly) { return (GDALDatasetType *)GDALOpenEx(filename, (readOnly? GDAL_OF_READONLY : GDAL_OF_UPDATE) | GDAL_OF_VECTOR,NULL,NULL,NULL); diff --git a/Modules/Adapters/QtAdapters/src/otbQtAdapters.cxx b/Modules/Adapters/QtAdapters/src/otbQtAdapters.cxx index b36d66cff678d575dc0c20d6270a33ee1000ce3a..d665845923c78ac923baab163183389ee7c8ef14 100644 --- a/Modules/Adapters/QtAdapters/src/otbQtAdapters.cxx +++ b/Modules/Adapters/QtAdapters/src/otbQtAdapters.cxx @@ -66,13 +66,18 @@ GetExistingDirectory( QWidget * p, const QString& dir, QFileDialog::Options options ) { + QString dialogCaption(caption.isEmpty() + ? QObject::tr( "Select directory..." ) + : caption); + QString dialogDir(dir.isEmpty() + ? RecentDirectory + : dir); + QString path( QFileDialog::getExistingDirectory( p, - caption.isEmpty() - ? QObject::tr( "Select directory..." ) - : caption, - dir.isEmpty() ? RecentDirectory : dir, + dialogCaption, + dialogDir, options ) ); @@ -95,13 +100,18 @@ GetOpenFileName( QWidget * p, QString* selectedFilter, QFileDialog::Options options ) { + QString dialogCaption(caption.isEmpty() + ? QObject::tr( "Open file..." ) + : caption); + QString dialogDir(dir.isEmpty() + ? RecentDirectory + : dir); + QString filename( QFileDialog::getOpenFileName( p, - caption.isEmpty() - ? QObject::tr( "Open file..." ) - : caption, - dir.isEmpty() ? RecentDirectory : dir, + dialogCaption, + dialogDir, filter, selectedFilter, options @@ -124,13 +134,18 @@ GetOpenFileNames( QWidget * p, QString * selectedFilter, QFileDialog::Options options ) { + QString dialogCaption(caption.isEmpty() + ? QObject::tr( "Open file..." ) + : caption); + QString dialogDir(dir.isEmpty() + ? RecentDirectory + : dir); + QStringList filenames( QFileDialog::getOpenFileNames( p, - caption.isEmpty() - ? QObject::tr( "Open file..." ) - : caption, - dir.isEmpty() ? RecentDirectory : dir, + dialogCaption, + dialogDir, filter, selectedFilter, options @@ -153,13 +168,18 @@ GetSaveFileName( QWidget * p, QString * selectedFilter, QFileDialog::Options options ) { + QString dialogCaption(caption.isEmpty() + ? QObject::tr( "Save file..." ) + : caption); + QString dialogDir(dir.isEmpty() + ? RecentDirectory + : dir); + QString filename( QFileDialog::getSaveFileName( p, - caption.isEmpty() - ? QObject::tr( "Save file..." ) - : caption, - dir.isEmpty() ? RecentDirectory : dir, + dialogCaption, + dialogDir, filter, selectedFilter, options diff --git a/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx b/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx index f3205381dd9ef5e2cdb6b8e466a8e1f8ad99d39f..240e55dfb4bbe9ba285ad5311313ac1d42fddfa3 100644 --- a/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx +++ b/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx @@ -30,6 +30,11 @@ namespace otb { namespace Wrapper { +/** Utility function to negate std::isalnum */ +bool IsNotAlphaNum(char c) + { + return !std::isalnum(c); + } class ComputeConfusionMatrix : public Application { @@ -108,12 +113,10 @@ private: AddParameter(ParameterType_InputFilename,"ref.vector.in","Input reference vector data"); SetParameterDescription("ref.vector.in", "Input vector data of the ground truth"); - AddParameter(ParameterType_String,"ref.vector.field","Field name"); + AddParameter(ParameterType_ListView,"ref.vector.field","Field name"); SetParameterDescription("ref.vector.field","Field name containing the label values"); - SetParameterString("ref.vector.field","Class"); - MandatoryOff("ref.vector.field"); - DisableParameter("ref.vector.field"); - + SetListViewSingleSelectionMode("ref.vector.field",true); + AddParameter(ParameterType_Int,"nodatalabel","Value for nodata pixels"); SetParameterDescription("nodatalabel", "Label for the NoData class. Such input pixels will be discarded from the " "ground truth and from the input classification map. By default, 'nodatalabel = 0'."); @@ -134,7 +137,32 @@ private: void DoUpdateParameters() ITK_OVERRIDE { - // Nothing to do here : all parameters are independent + if ( HasValue("ref.vector.in") ) + { + std::string vectorFile = GetParameterString("ref.vector.in"); + ogr::DataSource::Pointer ogrDS = + ogr::DataSource::New(vectorFile, ogr::DataSource::Modes::Read); + ogr::Layer layer = ogrDS->GetLayer(0); + ogr::Feature feature = layer.ogr().GetNextFeature(); + + ClearChoices("ref.vector.field"); + + for(int iField=0; iField<feature.ogr().GetFieldCount(); iField++) + { + std::string key, item = feature.ogr().GetFieldDefnRef(iField)->GetNameRef(); + key = item; + std::string::iterator end = std::remove_if(key.begin(),key.end(),IsNotAlphaNum); + std::transform(key.begin(), end, key.begin(), tolower); + + OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType(); + + if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType)) + { + std::string tmpKey="ref.vector.field."+key.substr(0, end - key.begin()); + AddChoice(tmpKey,item); + } + } + } } std::string LogConfusionMatrix(MapOfClassesType* mapOfClasses, ConfusionMatrixType* matrix) @@ -228,8 +256,18 @@ private: else { ogrRef = otb::ogr::DataSource::New(GetParameterString("ref.vector.in"), otb::ogr::DataSource::Modes::Read); - field = this->GetParameterString("ref.vector.field"); + // Get field name + std::vector<int> selectedCFieldIdx = GetSelectedItems("ref.vector.field"); + + if(selectedCFieldIdx.empty()) + { + otbAppLogFATAL(<<"No field has been selected for data labelling!"); + } + + std::vector<std::string> cFieldNames = GetChoiceNames("ref.vector.field"); + field = cFieldNames[selectedCFieldIdx.front()]; + rasterizeReference->AddOGRDataSource(ogrRef); rasterizeReference->SetOutputParametersFromImage(input); rasterizeReference->SetBackgroundValue(nodata); diff --git a/Modules/Applications/AppClassification/app/otbComputeImagesStatistics.cxx b/Modules/Applications/AppClassification/app/otbComputeImagesStatistics.cxx index b3e2a04b5ebe9ce9647f0e0c46979080971e0b4d..3de87d84bdb2d36261bedc3f441b3ff388efb4a3 100644 --- a/Modules/Applications/AppClassification/app/otbComputeImagesStatistics.cxx +++ b/Modules/Applications/AppClassification/app/otbComputeImagesStatistics.cxx @@ -86,44 +86,39 @@ private: // Samples typedef double ValueType; typedef itk::VariableLengthVector<ValueType> MeasurementType; + typedef itk::VariableSizeMatrix<ValueType> MatrixValueType; - unsigned int nbSamples = 0; unsigned int nbBands = 0; + FloatVectorImageListType* imageList = GetParameterImageList("il"); + FloatVectorImageListType::InternalContainerSizeType nbImages = imageList->Size(); + + // Initialization, all image have same size and number of band/component + FloatVectorImageType* firstImage = imageList->GetNthElement(0); + nbBands = firstImage->GetNumberOfComponentsPerPixel(); + // Build a Measurement Vector of mean - MeasurementType mean; + MatrixValueType mean(nbBands, static_cast<unsigned int>(nbImages)); + mean.Fill(itk::NumericTraits<MatrixValueType::ValueType>::Zero); - // Build a MeasurementVector of variance - MeasurementType variance; + // Build a Measurement Matrix of variance + MatrixValueType variance(nbBands, static_cast<unsigned int>(nbImages)); + variance.Fill(itk::NumericTraits<MatrixValueType::ValueType>::Zero); - FloatVectorImageListType* imageList = GetParameterImageList("il"); + // Build a Measurement Matrix of nbSamples + MatrixValueType nbSamples(nbBands, static_cast<unsigned int>(nbImages)); + nbSamples.Fill(itk::NumericTraits<MatrixValueType::ValueType>::Zero); //Iterate over all input images - for (unsigned int imageId = 0; imageId < imageList->Size(); ++imageId) + for (unsigned int imageId = 0; imageId < nbImages; ++imageId) { FloatVectorImageType* image = imageList->GetNthElement(imageId); - - if (nbBands == 0) - { - nbBands = image->GetNumberOfComponentsPerPixel(); - } - else if (nbBands != image->GetNumberOfComponentsPerPixel()) + if (nbBands != image->GetNumberOfComponentsPerPixel()) { itkExceptionMacro(<< "The image #" << imageId + 1 << " has " << image->GetNumberOfComponentsPerPixel() << " bands, while the image #1 has " << nbBands ); } - FloatVectorImageType::SizeType size = image->GetLargestPossibleRegion().GetSize(); - - //Set the measurement vectors size if it's the first iteration - if (imageId == 0) - { - mean.SetSize(nbBands); - mean.Fill(0.); - variance.SetSize(nbBands); - variance.Fill(0.); - } - // Compute Statistics of each VectorImage StreamingStatisticsVImageFilterType::Pointer statsEstimator = StreamingStatisticsVImageFilterType::New(); std::ostringstream processName; @@ -131,41 +126,88 @@ private: AddProcess(statsEstimator->GetStreamer(), processName.str().c_str()); statsEstimator->SetInput(image); statsEstimator->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); - if( HasValue( "bv" )==true ) + + if( HasValue( "bv" ) ) { statsEstimator->SetIgnoreUserDefinedValue(true); statsEstimator->SetUserIgnoredValue(GetParameterFloat("bv")); } statsEstimator->Update(); - mean += statsEstimator->GetMean(); - for (unsigned int itBand = 0; itBand < nbBands; itBand++) + + MeasurementType nbRelevantPixels = statsEstimator->GetNbRelevantPixels(); + MeasurementType meanPerBand = statsEstimator->GetMean(); + + for(unsigned int itBand = 0; itBand < nbBands; itBand++) + { + mean(itBand, imageId) = meanPerBand[itBand]; + variance(itBand, imageId) = (statsEstimator->GetCovariance())( itBand, itBand ); + nbSamples(itBand, imageId) = nbRelevantPixels[itBand]; + } + } + + // Compute total mean and pooled variation for each band of the image list + MeasurementType totalSamplesPerBand; + totalSamplesPerBand.SetSize(nbBands); + totalSamplesPerBand.Fill(itk::NumericTraits<MeasurementType::ValueType>::Zero); + + MeasurementType totalMeanPerBand; + totalMeanPerBand.SetSize(nbBands); + totalMeanPerBand.Fill(itk::NumericTraits<MeasurementType::ValueType>::Zero); + + MeasurementType totalVariancePerBand; + totalVariancePerBand.SetSize(nbBands); + totalVariancePerBand.Fill(itk::NumericTraits<MeasurementType::ValueType>::Zero); + + for (unsigned int imageId = 0; imageId < nbImages; ++imageId) + { + for(unsigned int itBand = 0; itBand < nbBands; itBand++) { - variance[itBand] += (size[0] * size[1] - 1) * (statsEstimator->GetCovariance())(itBand, itBand); + MeasurementType::ValueType nbSample = nbSamples(itBand, imageId); + totalSamplesPerBand[itBand] += nbSample; + totalMeanPerBand[itBand] += mean(itBand, imageId) * nbSample; + totalVariancePerBand[itBand] += variance(itBand, imageId) * (nbSample - 1); } - //Increment nbSamples - nbSamples += size[0] * size[1]; } - //Divide by the number of input images to get the mean over all layers - mean /= imageList->Size(); - //Apply the pooled variance formula - variance /= (nbSamples - imageList->Size()); + // Check 0 division + for(unsigned int itBand = 0; itBand < nbBands; itBand++) + { + MeasurementType::ValueType nbSample = totalSamplesPerBand[itBand]; + + if ( nbSample > nbImages ) + { + totalVariancePerBand[itBand] /= (nbSample - nbImages); + } + else + { + totalVariancePerBand[itBand] = itk::NumericTraits<ValueType>::Zero; + } + + if ( nbSample != 0 ) + { + totalMeanPerBand[itBand] /= nbSample; + } + else + { + totalMeanPerBand[itBand] = itk::NumericTraits<ValueType>::Zero; + } + } MeasurementType stddev; stddev.SetSize(nbBands); - stddev.Fill(0.); - for (unsigned int i = 0; i < variance.GetSize(); ++i) + stddev.Fill(itk::NumericTraits<MeasurementType::ValueType>::Zero); + for (unsigned int i = 0; i < totalVariancePerBand.GetSize(); ++i) { - stddev[i] = vcl_sqrt(variance[i]); + stddev[i] = vcl_sqrt(totalVariancePerBand[i]); } - if( HasValue( "out" )==true ) + if( HasValue( "out" ) ) { // Write the Statistics via the statistic writer typedef otb::StatisticsXMLFileWriter<MeasurementType> StatisticsWriter; StatisticsWriter::Pointer writer = StatisticsWriter::New(); writer->SetFileName(GetParameterString("out")); - writer->AddInput("mean", mean); + writer->AddInput("mean", totalMeanPerBand); writer->AddInput("stddev", stddev); writer->Update(); } diff --git a/Modules/Applications/AppClassification/app/otbDSFuzzyModelEstimation.cxx b/Modules/Applications/AppClassification/app/otbDSFuzzyModelEstimation.cxx index dd9d347a1fc42ecfc0a190384dfeaa1b321e6b25..29a2b45989846859f26c236788f2d11d6fbf3b1c 100644 --- a/Modules/Applications/AppClassification/app/otbDSFuzzyModelEstimation.cxx +++ b/Modules/Applications/AppClassification/app/otbDSFuzzyModelEstimation.cxx @@ -140,12 +140,12 @@ private: AddParameter(ParameterType_String, "cri", "Criterion"); SetParameterDescription("cri", "Dempster Shafer criterion (by default (belief+plausibility)/2)"); MandatoryOff("cri"); - SetParameterString("cri","((Belief + Plausibility)/2.)"); + SetParameterString("cri","((Belief + Plausibility)/2.)", false); AddParameter(ParameterType_Float,"wgt","Weighting"); SetParameterDescription("wgt","Coefficient between 0 and 1 to promote undetection or false detections (default 0.5)"); MandatoryOff("wgt"); - SetParameterFloat("wgt", 0.5); + SetParameterFloat("wgt",0.5, false); AddParameter(ParameterType_InputFilename,"initmod","initialization model"); SetParameterDescription("initmod","Initialization model (xml file) to be used. If the xml initialization model is set, the descriptor list is not used (specified using the option -desclist)"); @@ -154,12 +154,12 @@ private: AddParameter(ParameterType_StringList, "desclist","Descriptor list"); SetParameterDescription("desclist","List of the descriptors to be used in the model (must be specified to perform an automatic initialization)"); MandatoryOff("desclist"); - SetParameterString("desclist",""); + SetParameterString("desclist","", false); AddParameter(ParameterType_Int,"maxnbit","Maximum number of iterations"); MandatoryOff("maxnbit"); SetParameterDescription("maxnbit","Maximum number of optimizer iteration (default 200)"); - SetParameterInt("maxnbit", 200); + SetParameterInt("maxnbit",200, false); AddParameter(ParameterType_Empty,"optobs","Optimizer Observer"); SetParameterDescription("optobs","Activate the optimizer observer"); diff --git a/Modules/Applications/AppClassification/app/otbKMeansClassification.cxx b/Modules/Applications/AppClassification/app/otbKMeansClassification.cxx index e713cda0a8d193fb7231dba8cdb5c7c850b26c28..d511384c0e95e99a36c662b5344f36180b6b0527 100644 --- a/Modules/Applications/AppClassification/app/otbKMeansClassification.cxx +++ b/Modules/Applications/AppClassification/app/otbKMeansClassification.cxx @@ -175,8 +175,9 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); - AddDocTag(Tags::Segmentation); AddDocTag(Tags::Learning); + AddDocTag(Tags::Segmentation); + AddParameter(ParameterType_InputImage, "in", "Input Image"); SetParameterDescription("in", "Input image to classify."); AddParameter(ParameterType_OutputImage, "out", "Output Image"); @@ -244,7 +245,7 @@ private: { otbAppLogWARNING("The available RAM is too small to process this sample size of " << GetParameterInt("ts") << " pixels. The sample size will be reduced to " << maxPixNb << " pixels." << std::endl); - this->SetParameterInt("ts", maxPixNb); + this->SetParameterInt("ts",maxPixNb, false); } this->SetMaximumParameterIntValue("ts", maxPixNb); diff --git a/Modules/Applications/AppClassification/app/otbMultiImageSamplingRate.cxx b/Modules/Applications/AppClassification/app/otbMultiImageSamplingRate.cxx index 826af62fd982777cabdc7be8944a1a9fb9c26314..8bbd60510cf0938116c462e59fbab50c5bed8f42 100644 --- a/Modules/Applications/AppClassification/app/otbMultiImageSamplingRate.cxx +++ b/Modules/Applications/AppClassification/app/otbMultiImageSamplingRate.cxx @@ -161,7 +161,7 @@ private: SetParameterDescription("strategy.all","Take all samples"); // Default strategy : smallest - SetParameterString("strategy","smallest"); + SetParameterString("strategy","smallest", false); AddParameter(ParameterType_Choice, "mim", "Multi-Image Mode"); @@ -253,8 +253,15 @@ private: m_CalculatorList->SetNbOfSamplesAllClasses(countList, partitionMode); } break; - // percent + // smallest class case 2: + { + otbAppLogINFO("Sampling strategy : fit the number of samples based on the smallest class"); + m_CalculatorList->SetMinimumNbOfSamplesByClass(partitionMode); + } + break; + // percent + case 3: { std::vector<itksys::String> parts = itksys::SystemTools::SplitString(this->GetParameterString("strategy.percent.p"),' '); std::vector<double> percentList; @@ -283,7 +290,7 @@ private: break; // total - case 3: + case 4: { std::vector<itksys::String> parts = itksys::SystemTools::SplitString(this->GetParameterString("strategy.total.v"),' '); std::vector<unsigned long> totalList; @@ -305,14 +312,6 @@ private: m_CalculatorList->SetTotalNumberOfSamples(totalList, partitionMode); } break; - - // smallest class - case 4: - { - otbAppLogINFO("Sampling strategy : fit the number of samples based on the smallest class"); - m_CalculatorList->SetMinimumNbOfSamplesByClass(partitionMode); - } - break; // all samples case 5: { diff --git a/Modules/Applications/AppClassification/app/otbOGRLayerClassifier.cxx b/Modules/Applications/AppClassification/app/otbOGRLayerClassifier.cxx index b1161dddd7a2fd9e8bd66bf930f299aa7ca29e46..6ec4a448ed8d868649e12e5b838f26044e6deec8 100644 --- a/Modules/Applications/AppClassification/app/otbOGRLayerClassifier.cxx +++ b/Modules/Applications/AppClassification/app/otbOGRLayerClassifier.cxx @@ -78,7 +78,7 @@ private: AddParameter(ParameterType_String,"cfield","Field containing the predicted class."); SetParameterDescription("cfield","Field containing the predicted class"); - SetParameterString("cfield","predicted"); + SetParameterString("cfield","predicted", false); // Doc example parameter settings SetDocExampleParameterValue("inshp", "vectorData.shp"); diff --git a/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx b/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx index a6167febed174d998276e97b23f8e8994a6f2d40..d2272b5e07e58e2c4ee487e897d963200a02e8c9 100644 --- a/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx +++ b/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx @@ -22,12 +22,19 @@ #include "otbStatisticsXMLFileWriter.h" #include "otbGeometriesProjectionFilter.h" #include "otbGeometriesSet.h" +#include "otbWrapperElevationParametersHandler.h" namespace otb { namespace Wrapper { +/** Utility function to negate std::isalnum */ +bool IsNotAlphaNum(char c) + { + return !std::isalnum(c); + } + class PolygonClassStatistics : public Application { public: @@ -95,16 +102,17 @@ private: AddParameter(ParameterType_OutputFilename, "out", "Output Statistics"); SetParameterDescription("out","Output file to store statistics (XML format)"); - AddParameter(ParameterType_String, "field", "Field Name"); + AddParameter(ParameterType_ListView, "field", "Field Name"); SetParameterDescription("field","Name of the field carrying the class name in the input vectors."); - MandatoryOff("field"); - SetParameterString("field", "class"); + SetListViewSingleSelectionMode("field",true); AddParameter(ParameterType_Int, "layer", "Layer Index"); SetParameterDescription("layer", "Layer index to read in the input vector file."); MandatoryOff("layer"); SetDefaultParameterInt("layer",0); - + + ElevationParametersHandler::AddElevationParameters(this, "elev"); + AddRAMParameter(); // Doc example parameter settings @@ -116,14 +124,51 @@ private: void DoUpdateParameters() ITK_OVERRIDE { - // Nothing to do + if ( HasValue("vec") ) + { + std::string vectorFile = GetParameterString("vec"); + ogr::DataSource::Pointer ogrDS = + ogr::DataSource::New(vectorFile, ogr::DataSource::Modes::Read); + ogr::Layer layer = ogrDS->GetLayer(this->GetParameterInt("layer")); + ogr::Feature feature = layer.ogr().GetNextFeature(); + + ClearChoices("field"); + + for(int iField=0; iField<feature.ogr().GetFieldCount(); iField++) + { + std::string key, item = feature.ogr().GetFieldDefnRef(iField)->GetNameRef(); + key = item; + std::string::iterator end = std::remove_if(key.begin(),key.end(),IsNotAlphaNum); + std::transform(key.begin(), end, key.begin(), tolower); + + OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType(); + + if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType)) + { + std::string tmpKey="field."+key.substr(0, end - key.begin()); + AddChoice(tmpKey,item); + } + } + } } void DoExecute() ITK_OVERRIDE { otb::ogr::DataSource::Pointer vectors = otb::ogr::DataSource::New(this->GetParameterString("vec")); - std::string fieldName = this->GetParameterString("field"); + + // Retrieve the field name + std::vector<int> selectedCFieldIdx = GetSelectedItems("field"); + + if(selectedCFieldIdx.empty()) + { + otbAppLogFATAL(<<"No field has been selected for data labelling!"); + } + + std::vector<std::string> cFieldNames = GetChoiceNames("field"); + std::string fieldName = cFieldNames[selectedCFieldIdx.front()]; + + otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev"); // Reproject geometries FloatVectorImageType::Pointer inputImg = this->GetParameterImage("in"); diff --git a/Modules/Applications/AppClassification/app/otbSOMClassification.cxx b/Modules/Applications/AppClassification/app/otbSOMClassification.cxx index d7f90750fc158ea06ccab2de176fdca0290c1f46..64a288751037c38e20026396fb45b489f0ed3ba1 100644 --- a/Modules/Applications/AppClassification/app/otbSOMClassification.cxx +++ b/Modules/Applications/AppClassification/app/otbSOMClassification.cxx @@ -85,8 +85,8 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); + AddDocTag(Tags::Learning); AddDocTag(Tags::Segmentation); - AddDocTag(Tags::Learning); AddParameter(ParameterType_InputImage, "in", "InputImage"); SetParameterDescription("in", "Input image to classify."); diff --git a/Modules/Applications/AppClassification/app/otbSampleExtraction.cxx b/Modules/Applications/AppClassification/app/otbSampleExtraction.cxx index f1cc0f910231585c8b829e65c58e43200f852014..0eb1e3a8a9a60c18a3ed3a6a79fbdb44f3b9e40f 100644 --- a/Modules/Applications/AppClassification/app/otbSampleExtraction.cxx +++ b/Modules/Applications/AppClassification/app/otbSampleExtraction.cxx @@ -24,6 +24,11 @@ namespace otb { namespace Wrapper { +/** Utility function to negate std::isalnum */ +bool IsNotAlphaNum(char c) + { + return !std::isalnum(c); + } class SampleExtraction : public Application { @@ -81,7 +86,7 @@ private: AddParameter(ParameterType_String, "outfield.prefix.name", "Output field prefix"); SetParameterDescription("outfield.prefix.name","Prefix used to form the field names that" "will contain the extracted values."); - SetParameterString("outfield.prefix.name", "value_"); + SetParameterString("outfield.prefix.name", "value_", false); AddChoice("outfield.list","Use the given name list"); SetParameterDescription("outfield.list","Use the given name list"); @@ -89,12 +94,10 @@ private: AddParameter(ParameterType_StringList, "outfield.list.names", "Output field names"); SetParameterDescription("outfield.list.names","Full list of output field names."); - AddParameter(ParameterType_String, "field", "Field Name"); - SetParameterDescription("field","Name of the field carrying the class" - "name in the input vectors. This field is copied to output."); - MandatoryOff("field"); - SetParameterString("field", "class"); - + AddParameter(ParameterType_ListView, "field", "Field Name"); + SetParameterDescription("field","Name of the field carrying the class name in the input vectors."); + SetListViewSingleSelectionMode("field",true); + AddParameter(ParameterType_Int, "layer", "Layer Index"); SetParameterDescription("layer", "Layer index to read in the input vector file."); MandatoryOff("layer"); @@ -113,7 +116,32 @@ private: void DoUpdateParameters() { - // Nothing to do + if ( HasValue("vec") ) + { + std::string vectorFile = GetParameterString("vec"); + ogr::DataSource::Pointer ogrDS = + ogr::DataSource::New(vectorFile, ogr::DataSource::Modes::Read); + ogr::Layer layer = ogrDS->GetLayer(this->GetParameterInt("layer")); + ogr::Feature feature = layer.ogr().GetNextFeature(); + + ClearChoices("field"); + + for(int iField=0; iField<feature.ogr().GetFieldCount(); iField++) + { + std::string key, item = feature.ogr().GetFieldDefnRef(iField)->GetNameRef(); + key = item; + std::string::iterator end = std::remove_if(key.begin(),key.end(),IsNotAlphaNum); + std::transform(key.begin(), end, key.begin(), tolower); + + OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType(); + + if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType)) + { + std::string tmpKey="field."+key.substr(0, end - key.begin()); + AddChoice(tmpKey,item); + } + } + } } void DoExecute() @@ -134,6 +162,17 @@ private: output = vectors; } + // Retrieve the field name + std::vector<int> selectedCFieldIdx = GetSelectedItems("field"); + + if(selectedCFieldIdx.empty()) + { + otbAppLogFATAL(<<"No field has been selected for data labelling!"); + } + + std::vector<std::string> cFieldNames = GetChoiceNames("field"); + std::string fieldName = cFieldNames[selectedCFieldIdx.front()]; + std::vector<std::string> nameList; std::string namePrefix(""); if (this->GetParameterString("outfield").compare("prefix") == 0) @@ -155,7 +194,7 @@ private: filter->SetLayerIndex(this->GetParameterInt("layer")); filter->SetSamplePositions(vectors); filter->SetOutputSamples(output); - filter->SetClassFieldName(this->GetParameterString("field")); + filter->SetClassFieldName(fieldName); filter->SetOutputFieldPrefix(namePrefix); filter->SetOutputFieldNames(nameList); filter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); diff --git a/Modules/Applications/AppClassification/app/otbSampleSelection.cxx b/Modules/Applications/AppClassification/app/otbSampleSelection.cxx index c4472b33800360f56578cfcfc40fe842e61d12d1..81b2b33f021a01753d7a7703abe050ba4c51790e 100644 --- a/Modules/Applications/AppClassification/app/otbSampleSelection.cxx +++ b/Modules/Applications/AppClassification/app/otbSampleSelection.cxx @@ -23,12 +23,19 @@ #include "otbRandomSampler.h" #include "otbGeometriesProjectionFilter.h" #include "otbGeometriesSet.h" +#include "otbWrapperElevationParametersHandler.h" namespace otb { namespace Wrapper { +/** Utility function to negate std::isalnum */ +bool IsNotAlphaNum(char c) + { + return !std::isalnum(c); + } + class SampleSelection : public Application { public: @@ -66,8 +73,6 @@ public: private: SampleSelection() { - m_Periodic = PeriodicSamplerType::New(); - m_Random = RandomSamplerType::New(); m_ReaderStat = XMLReaderType::New(); m_RateCalculator = RateCalculatorType::New(); } @@ -192,18 +197,19 @@ private: SetParameterDescription("strategy.all","Take all samples"); // Default strategy : smallest - SetParameterString("strategy","smallest"); + SetParameterString("strategy","smallest", false); - AddParameter(ParameterType_String, "field", "Field Name"); + AddParameter(ParameterType_ListView, "field", "Field Name"); SetParameterDescription("field","Name of the field carrying the class name in the input vectors."); - MandatoryOff("field"); - SetParameterString("field", "class"); + SetListViewSingleSelectionMode("field",true); AddParameter(ParameterType_Int, "layer", "Layer Index"); SetParameterDescription("layer", "Layer index to read in the input vector file."); MandatoryOff("layer"); SetDefaultParameterInt("layer",0); + ElevationParametersHandler::AddElevationParameters(this, "elev"); + AddRAMParameter(); AddRANDParameter(); @@ -218,18 +224,51 @@ private: void DoUpdateParameters() { + if ( HasValue("vec") ) + { + std::string vectorFile = GetParameterString("vec"); + ogr::DataSource::Pointer ogrDS = + ogr::DataSource::New(vectorFile, ogr::DataSource::Modes::Read); + ogr::Layer layer = ogrDS->GetLayer(this->GetParameterInt("layer")); + ogr::Feature feature = layer.ogr().GetNextFeature(); + + ClearChoices("field"); + + for(int iField=0; iField<feature.ogr().GetFieldCount(); iField++) + { + std::string key, item = feature.ogr().GetFieldDefnRef(iField)->GetNameRef(); + key = item; + std::string::iterator end = std::remove_if(key.begin(),key.end(),IsNotAlphaNum); + std::transform(key.begin(), end, key.begin(), tolower); + + OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType(); + + if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType)) + { + std::string tmpKey="field."+key.substr(0, end - key.begin()); + AddChoice(tmpKey,item); + } + } + } } void DoExecute() { // Clear state m_RateCalculator->ClearRates(); - m_Periodic->GetFilter()->ClearOutputs(); - m_Random->GetFilter()->ClearOutputs(); - // Setup ram - m_Periodic->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); - m_Random->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); + otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev"); + + // Get field name + std::vector<int> selectedCFieldIdx = GetSelectedItems("field"); + + if(selectedCFieldIdx.empty()) + { + otbAppLogFATAL(<<"No field has been selected for data labelling!"); + } + + std::vector<std::string> cFieldNames = GetChoiceNames("field"); + std::string fieldName = cFieldNames[selectedCFieldIdx.front()]; m_ReaderStat->SetFileName(this->GetParameterString("instats")); ClassCountMapType classCount = m_ReaderStat->GetStatisticMapByName<ClassCountMapType>("samplesPerClass"); @@ -368,37 +407,41 @@ private: PeriodicSamplerType::SamplerParameterType param; param.Offset = 0; param.MaxJitter = this->GetParameterInt("sampler.periodic.jitter"); - - m_Periodic->SetInput(this->GetParameterImage("in")); - m_Periodic->SetOGRData(reprojVector); - m_Periodic->SetOutputPositionContainerAndRates(outputSamples, rates); - m_Periodic->SetFieldName(this->GetParameterString("field")); - m_Periodic->SetLayerIndex(this->GetParameterInt("layer")); - m_Periodic->SetSamplerParameters(param); + param.MaxBufferSize = 100000000UL; + PeriodicSamplerType::Pointer periodicFilt = PeriodicSamplerType::New(); + periodicFilt->SetInput(this->GetParameterImage("in")); + periodicFilt->SetOGRData(reprojVector); + periodicFilt->SetOutputPositionContainerAndRates(outputSamples, rates); + periodicFilt->SetFieldName(fieldName); + periodicFilt->SetLayerIndex(this->GetParameterInt("layer")); + periodicFilt->SetSamplerParameters(param); if (IsParameterEnabled("mask") && HasValue("mask")) { - m_Periodic->SetMask(this->GetParameterImage<UInt8ImageType>("mask")); + periodicFilt->SetMask(this->GetParameterImage<UInt8ImageType>("mask")); } - m_Periodic->GetStreamer()->SetAutomaticTiledStreaming(this->GetParameterInt("ram")); - AddProcess(m_Periodic->GetStreamer(),"Selecting positions with periodic sampler..."); - m_Periodic->Update(); + periodicFilt->GetStreamer()->SetAutomaticTiledStreaming(this->GetParameterInt("ram")); + AddProcess(periodicFilt->GetStreamer(),"Selecting positions with periodic sampler..."); + periodicFilt->Update(); } break; // random case 1: { - m_Random->SetInput(this->GetParameterImage("in")); - m_Random->SetOGRData(reprojVector); - m_Random->SetOutputPositionContainerAndRates(outputSamples, rates); - m_Random->SetFieldName(this->GetParameterString("field")); - m_Random->SetLayerIndex(this->GetParameterInt("layer")); + RandomSamplerType::Pointer randomFilt = RandomSamplerType::New(); + randomFilt->SetInput(this->GetParameterImage("in")); + randomFilt->SetOGRData(reprojVector); + randomFilt->SetOutputPositionContainerAndRates(outputSamples, rates); + randomFilt->SetFieldName(fieldName); + randomFilt->SetLayerIndex(this->GetParameterInt("layer")); if (IsParameterEnabled("mask") && HasValue("mask")) { - m_Random->SetMask(this->GetParameterImage<UInt8ImageType>("mask")); + randomFilt->SetMask(this->GetParameterImage<UInt8ImageType>("mask")); } - m_Random->GetStreamer()->SetAutomaticTiledStreaming(this->GetParameterInt("ram")); - AddProcess(m_Random->GetStreamer(),"Selecting positions with random sampler..."); - m_Random->Update(); + randomFilt->GetStreamer()->SetAutomaticTiledStreaming(this->GetParameterInt("ram")); + AddProcess(randomFilt->GetStreamer(),"Selecting positions with random sampler..."); + randomFilt->Update(); + + randomFilt = RandomSamplerType::New(); } break; default: @@ -408,10 +451,6 @@ private: } RateCalculatorType::Pointer m_RateCalculator; - - PeriodicSamplerType::Pointer m_Periodic; - RandomSamplerType::Pointer m_Random; - XMLReaderType::Pointer m_ReaderStat; }; diff --git a/Modules/Applications/AppClassification/app/otbTrainImagesClassifier.cxx b/Modules/Applications/AppClassification/app/otbTrainImagesClassifier.cxx index 932454f0b5ebe89bd84c9367b6c582b9cd3c0970..5433dcf170b2d8110b488267033bf87bd2ef9628 100644 --- a/Modules/Applications/AppClassification/app/otbTrainImagesClassifier.cxx +++ b/Modules/Applications/AppClassification/app/otbTrainImagesClassifier.cxx @@ -14,94 +14,68 @@ PURPOSE. See the above copyright notices for more information. =========================================================================*/ -#include "otbLearningApplicationBase.h" +#include "otbWrapperCompositeApplication.h" #include "otbWrapperApplicationFactory.h" -#include "otbListSampleGenerator.h" - -// Statistic XML Reader -#include "otbStatisticsXMLFileReader.h" - -// Validation -#include "otbConfusionMatrixCalculator.h" - -#include "itkTimeProbe.h" -#include "otbStandardFilterWatcher.h" - -// Normalize the samples -#include "otbShiftScaleSampleListFilter.h" - -// List sample concatenation -#include "otbConcatenateSampleListFilter.h" - -// Balancing ListSample -#include "otbListSampleToBalancedListSampleFilter.h" - -// VectorData projection filter - -// Extract a ROI of the vectordata -#include "otbVectorDataIntoImageProjectionFilter.h" - -// Elevation handler -#include "otbWrapperElevationParametersHandler.h" +#include "otbOGRDataToSamplePositionFilter.h" +#include "otbSamplingRateCalculator.h" namespace otb { namespace Wrapper { -class TrainImagesClassifier: public LearningApplicationBase<float,int> +class TrainImagesClassifier: public CompositeApplication { public: /** Standard class typedefs. */ typedef TrainImagesClassifier Self; - typedef LearningApplicationBase<float,int> Superclass; + typedef CompositeApplication Superclass; typedef itk::SmartPointer<Self> Pointer; typedef itk::SmartPointer<const Self> ConstPointer; /** Standard macro */ itkNewMacro(Self) - itkTypeMacro(TrainImagesClassifier, otb::Wrapper::LearningApplicationBase) - - typedef Superclass::SampleType SampleType; - typedef Superclass::ListSampleType ListSampleType; - typedef Superclass::TargetSampleType TargetSampleType; - typedef Superclass::TargetListSampleType TargetListSampleType; + itkTypeMacro(TrainImagesClassifier, otb::Wrapper::CompositeApplication) - typedef Superclass::SampleImageType SampleImageType; - typedef SampleImageType::PixelType PixelType; + /** filters typedefs*/ + typedef otb::OGRDataToSamplePositionFilter< + FloatVectorImageType, + UInt8ImageType, + otb::PeriodicSampler> PeriodicSamplerType; - // SampleList manipulation - typedef otb::ListSampleGenerator<SampleImageType, VectorDataType> ListSampleGeneratorType; - - typedef otb::Statistics::ConcatenateSampleListFilter<ListSampleType> ConcatenateListSampleFilterType; - typedef otb::Statistics::ConcatenateSampleListFilter<TargetListSampleType> ConcatenateLabelListSampleFilterType; - - // Statistic XML file Reader - typedef otb::StatisticsXMLFileReader<SampleType> StatisticsReader; - - // Enhance List Sample typedef otb::Statistics::ListSampleToBalancedListSampleFilter<ListSampleType, LabelListSampleType> BalancingListSampleFilterType; - typedef otb::Statistics::ShiftScaleSampleListFilter<ListSampleType, ListSampleType> ShiftScaleFilterType; - - // Estimate performance on validation sample - typedef otb::ConfusionMatrixCalculator<TargetListSampleType, TargetListSampleType> ConfusionMatrixCalculatorType; - typedef ConfusionMatrixCalculatorType::ConfusionMatrixType ConfusionMatrixType; - typedef ConfusionMatrixCalculatorType::MapOfIndicesType MapOfIndicesType; - typedef ConfusionMatrixCalculatorType::ClassLabelType ClassLabelType; - - // VectorData projection filter - typedef otb::VectorDataProjectionFilter<VectorDataType, VectorDataType> VectorDataProjectionFilterType; - - // Extract ROI - typedef otb::VectorDataIntoImageProjectionFilter<VectorDataType, SampleImageType> VectorDataReprojectionType; + typedef otb::SamplingRateCalculator::MapRateType MapRateType; protected: - //using Superclass::AddParameter; - //friend void InitSVMParams(TrainImagesClassifier & app); private: +bool RemoveFile(std::string &filePath) +{ + bool res = true; + if(itksys::SystemTools::FileExists(filePath.c_str())) + { + size_t posExt = filePath.rfind('.'); + if (posExt != std::string::npos && + filePath.compare(posExt,std::string::npos,".shp") == 0) + { + std::string shxPath = filePath.substr(0,posExt) + std::string(".shx"); + std::string dbfPath = filePath.substr(0,posExt) + std::string(".dbf"); + std::string prjPath = filePath.substr(0,posExt) + std::string(".prj"); + RemoveFile(shxPath); + RemoveFile(dbfPath); + RemoveFile(prjPath); + } + res = itksys::SystemTools::RemoveFile(filePath.c_str()); + if (!res) + { + otbAppLogINFO(<<"Unable to remove file "<<filePath); + } + } + return res; +} + void DoInit() ITK_OVERRIDE { SetName("TrainImagesClassifier"); @@ -126,62 +100,99 @@ void DoInit() ITK_OVERRIDE SetDocAuthors("OTB-Team"); SetDocSeeAlso("OpenCV documentation for machine learning http://docs.opencv.org/modules/ml/doc/ml.html "); + AddDocTag(Tags::Learning); + + ClearApplications(); + AddApplication("PolygonClassStatistics", "polystat","Polygon analysis"); + AddApplication("MultiImageSamplingRate", "rates", "Sampling rates"); + AddApplication("SampleSelection", "select", "Sample selection"); + AddApplication("SampleExtraction","extraction", "Sample extraction"); + AddApplication("TrainVectorClassifier", "training", "Model training"); + //Group IO AddParameter(ParameterType_Group, "io", "Input and output data"); SetParameterDescription("io", "This group of parameters allows setting input and output data."); + AddParameter(ParameterType_InputImageList, "io.il", "Input Image List"); SetParameterDescription("io.il", "A list of input images."); AddParameter(ParameterType_InputVectorDataList, "io.vd", "Input Vector Data List"); SetParameterDescription("io.vd", "A list of vector data to select the training samples."); - AddParameter(ParameterType_InputFilename, "io.imstat", "Input XML image statistics file"); - MandatoryOff("io.imstat"); - SetParameterDescription("io.imstat", - "Input XML file containing the mean and the standard deviation of the input images."); - AddParameter(ParameterType_OutputFilename, "io.confmatout", "Output confusion matrix"); - SetParameterDescription("io.confmatout", "Output file containing the confusion matrix (.csv format)."); - MandatoryOff("io.confmatout"); - AddParameter(ParameterType_OutputFilename, "io.out", "Output model"); - SetParameterDescription("io.out", "Output file containing the model estimated (.txt format)."); - - // Elevation - ElevationParametersHandler::AddElevationParameters(this, "elev"); - - //Group Sample list + + AddParameter(ParameterType_InputVectorDataList, "io.valid", "Validation Vector Data List"); + SetParameterDescription("io.valid", "A list of vector data to select the training samples."); + MandatoryOff("io.valid"); + + ShareParameter("io.imstat","training.io.stats"); + ShareParameter("io.confmatout","training.io.confmatout"); + ShareParameter("io.out","training.io.out"); + + ShareParameter("elev","polystat.elev"); + + // Sampling settings AddParameter(ParameterType_Group, "sample", "Training and validation samples parameters"); SetParameterDescription("sample", - "This group of parameters allows you to set training and validation sample lists parameters."); - + "This group of parameters allows you to set training and validation sample lists parameters."); AddParameter(ParameterType_Int, "sample.mt", "Maximum training sample size per class"); - //MandatoryOff("mt"); SetDefaultParameterInt("sample.mt", 1000); - SetParameterDescription("sample.mt", "Maximum size per class (in pixels) of the training sample list (default = 1000) (no limit = -1). If equal to -1, then the maximal size of the available training sample list per class will be equal to the surface area of the smallest class multiplied by the training sample ratio."); + SetParameterDescription("sample.mt", "Maximum size per class (in pixels) of " + "the training sample list (default = 1000) (no limit = -1). If equal to -1," + " then the maximal size of the available training sample list per class " + "will be equal to the surface area of the smallest class multiplied by the" + " training sample ratio."); AddParameter(ParameterType_Int, "sample.mv", "Maximum validation sample size per class"); - // MandatoryOff("mv"); SetDefaultParameterInt("sample.mv", 1000); - SetParameterDescription("sample.mv", "Maximum size per class (in pixels) of the validation sample list (default = 1000) (no limit = -1). If equal to -1, then the maximal size of the available validation sample list per class will be equal to the surface area of the smallest class multiplied by the validation sample ratio."); - + SetParameterDescription("sample.mv", "Maximum size per class (in pixels) of " + "the validation sample list (default = 1000) (no limit = -1). If equal to -1," + " then the maximal size of the available validation sample list per class " + "will be equal to the surface area of the smallest class multiplied by the " + "validation sample ratio."); AddParameter(ParameterType_Int, "sample.bm", "Bound sample number by minimum"); SetDefaultParameterInt("sample.bm", 1); - SetParameterDescription("sample.bm", "Bound the number of samples for each class by the number of available samples by the smaller class. Proportions between training and validation are respected. Default is true (=1)."); + SetParameterDescription("sample.bm", "Bound the number of samples for each " + "class by the number of available samples by the smaller class. Proportions " + "between training and validation are respected. Default is true (=1)."); + AddParameter(ParameterType_Float, "sample.vtr", "Training and validation sample ratio"); + SetParameterDescription("sample.vtr", + "Ratio between training and validation samples (0.0 = all training, 1.0 = " + "all validation) (default = 0.5)."); + SetParameterFloat("sample.vtr",0.5, false); + SetMaximumParameterFloatValue("sample.vtr",1.0); + SetMinimumParameterFloatValue("sample.vtr",0.0); + ShareParameter("sample.vfn","polystat.field"); - AddParameter(ParameterType_Empty, "sample.edg", "On edge pixel inclusion"); - SetParameterDescription("sample.edg", - "Takes pixels on polygon edge into consideration when building training and validation samples."); - MandatoryOff("sample.edg"); + // hide sampling parameters + //ShareParameter("sample.strategy","rates.strategy"); + //ShareParameter("sample.mim","rates.mim"); - AddParameter(ParameterType_Float, "sample.vtr", "Training and validation sample ratio"); - SetParameterDescription("sample.vtr", - "Ratio between training and validation samples (0.0 = all training, 1.0 = all validation) (default = 0.5)."); - SetParameterFloat("sample.vtr", 0.5); + // Classifier settings + ShareParameter("classifier","training.classifier"); - AddParameter(ParameterType_String, "sample.vfn", "Name of the discrimination field"); - SetParameterDescription("sample.vfn", "Name of the field used to discriminate class labels in the input vector data files."); - SetParameterString("sample.vfn", "Class"); + ShareParameter("rand","training.rand"); - Superclass::DoInit(); + // Synchronization between applications + Connect("select.field", "polystat.field"); + Connect("select.layer", "polystat.layer"); + Connect("select.elev", "polystat.elev"); + + Connect("extraction.in", "select.in"); + Connect("extraction.vec", "select.out"); + Connect("extraction.field", "polystat.field"); + Connect("extraction.layer", "polystat.layer"); + + Connect("training.cfield", "polystat.field"); + + ShareParameter("ram","polystat.ram"); + Connect("select.ram", "polystat.ram"); + Connect("extraction.ram", "polystat.ram"); + + Connect("select.rand", "training.rand"); + + AddParameter(ParameterType_Empty,"cleanup","Temporary files cleaning"); + EnableParameter("cleanup"); + SetParameterDescription("cleanup","If activated, the application will try to clean all temporary files it created"); + MandatoryOff("cleanup"); - AddRANDParameter(); // Doc example parameter settings SetDocExampleParameterValue("io.il", "QB_1_ortho.tif"); SetDocExampleParameterValue("io.vd", "VectorData_QB1.shp"); @@ -189,7 +200,6 @@ void DoInit() ITK_OVERRIDE SetDocExampleParameterValue("sample.mv", "100"); SetDocExampleParameterValue("sample.mt", "100"); SetDocExampleParameterValue("sample.vtr", "0.5"); - SetDocExampleParameterValue("sample.edg", "false"); SetDocExampleParameterValue("sample.vfn", "Class"); SetDocExampleParameterValue("classifier", "libsvm"); SetDocExampleParameterValue("classifier.libsvm.k", "linear"); @@ -201,396 +211,305 @@ void DoInit() ITK_OVERRIDE void DoUpdateParameters() ITK_OVERRIDE { - // Nothing to do here : all parameters are independent + if ( HasValue("io.vd") ) + { + std::vector<std::string> vectorFileList = GetParameterStringList("io.vd"); + GetInternalApplication("polystat")->SetParameterString("vec",vectorFileList[0], false); + UpdateInternalParameters("polystat"); + } } -void LogConfusionMatrix(ConfusionMatrixCalculatorType* confMatCalc) +void DoExecute() ITK_OVERRIDE { - ConfusionMatrixCalculatorType::ConfusionMatrixType matrix = confMatCalc->GetConfusionMatrix(); - - // Compute minimal width - size_t minwidth = 0; - - for (unsigned int i = 0; i < matrix.Rows(); i++) + FloatVectorImageListType* imageList = GetParameterImageList("io.il"); + std::vector<std::string> vectorFileList = GetParameterStringList("io.vd"); + unsigned int nbInputs = imageList->Size(); + if (nbInputs > vectorFileList.size()) { - for (unsigned int j = 0; j < matrix.Cols(); j++) - { - std::ostringstream os; - os << matrix(i, j); - size_t size = os.str().size(); - - if (size > minwidth) - { - minwidth = size; - } - } + otbAppLogFATAL("Missing input vector data files to match number of images ("<<nbInputs<<")."); } - MapOfIndicesType mapOfIndices = confMatCalc->GetMapOfIndices(); - - MapOfIndicesType::const_iterator it = mapOfIndices.begin(); - MapOfIndicesType::const_iterator end = mapOfIndices.end(); - - for (; it != end; ++it) + // check if validation vectors are given + std::vector<std::string> validationVectorFileList; + bool dedicatedValidation = false; + if (IsParameterEnabled("io.valid") && HasValue("io.valid")) { - std::ostringstream os; - os << "[" << it->second << "]"; - - size_t size = os.str().size(); - if (size > minwidth) + dedicatedValidation = true; + validationVectorFileList = GetParameterStringList("io.valid"); + if (nbInputs > validationVectorFileList.size()) { - minwidth = size; + otbAppLogFATAL("Missing validation vector data files to match number of images ("<<nbInputs<<")."); } } - // Generate matrix string, with 'minwidth' as size specifier - std::ostringstream os; - - // Header line - for (size_t i = 0; i < minwidth; ++i) - os << " "; - os << " "; - - it = mapOfIndices.begin(); - end = mapOfIndices.end(); - for (; it != end; ++it) + // Prepare temporary file names + std::string outModel(GetParameterString("io.out")); + std::vector<std::string> polyStatTrainOutputs; + std::vector<std::string> polyStatValidOutputs; + std::vector<std::string> ratesTrainOutputs; + std::vector<std::string> ratesValidOutputs; + std::vector<std::string> sampleOutputs; + std::vector<std::string> sampleTrainOutputs; + std::vector<std::string> sampleValidOutputs; + std::string rateTrainOut; + if (dedicatedValidation) { - os << "[" << it->second << "]" << " "; + rateTrainOut = outModel + "_ratesTrain.csv"; } - - os << std::endl; - - // Each line of confusion matrix - for (unsigned int i = 0; i < matrix.Rows(); i++) + else { - ConfusionMatrixCalculatorType::ClassLabelType label = mapOfIndices[i]; - os << "[" << std::setw(minwidth - 2) << label << "]" << " "; - for (unsigned int j = 0; j < matrix.Cols(); j++) - { - os << std::setw(minwidth) << matrix(i, j) << " "; - } - os << std::endl; + rateTrainOut = outModel + "_rates.csv"; } - - otbAppLogINFO("Confusion matrix (rows = reference labels, columns = produced labels):\n" << os.str()); -} - -void DoExecute() ITK_OVERRIDE -{ - //Create training and validation for list samples and label list samples - ConcatenateLabelListSampleFilterType::Pointer concatenateTrainingLabels = - ConcatenateLabelListSampleFilterType::New(); - ConcatenateListSampleFilterType::Pointer concatenateTrainingSamples = ConcatenateListSampleFilterType::New(); - ConcatenateLabelListSampleFilterType::Pointer concatenateValidationLabels = - ConcatenateLabelListSampleFilterType::New(); - ConcatenateListSampleFilterType::Pointer concatenateValidationSamples = ConcatenateListSampleFilterType::New(); - - SampleType meanMeasurementVector; - SampleType stddevMeasurementVector; - - // Setup the DEM Handler - otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this, "elev"); - - //-------------------------- - // Load measurements from images - unsigned int nbBands = 0; - //Iterate over all input images - - FloatVectorImageListType* imageList = GetParameterImageList("io.il"); - VectorDataListType* vectorDataList = GetParameterVectorDataList("io.vd"); - - vdreproj = VectorDataReprojectionType::New(); - - //Iterate over all input images - for (unsigned int imgIndex = 0; imgIndex < imageList->Size(); ++imgIndex) + std::string rateValidOut(outModel + "_ratesValid.csv"); + for (unsigned int i=0 ; i<nbInputs ; i++) { - std::ostringstream oss1, oss2; - oss1 << "Reproject polygons for image " << (imgIndex+1) << " ..."; - oss2 << "Extract samples from image " << (imgIndex+1) << " ..."; - - FloatVectorImageType::Pointer image = imageList->GetNthElement(imgIndex); - image->UpdateOutputInformation(); - - if (imgIndex == 0) + std::ostringstream oss; + oss <<i+1; + std::string strIndex(oss.str()); + if (dedicatedValidation) { - nbBands = image->GetNumberOfComponentsPerPixel(); + polyStatTrainOutputs.push_back(outModel + "_statsTrain_" + strIndex + ".xml"); + polyStatValidOutputs.push_back(outModel + "_statsValid_" + strIndex + ".xml"); + ratesTrainOutputs.push_back(outModel + "_ratesTrain_" + strIndex + ".csv"); + ratesValidOutputs.push_back(outModel + "_ratesValid_" + strIndex + ".csv"); + sampleOutputs.push_back(outModel + "_samplesTrain_" + strIndex + ".shp"); } - - // read the Vectordata - vdreproj->SetInputImage(image); - vdreproj->SetInput(vectorDataList->GetNthElement(imgIndex)); - vdreproj->SetUseOutputSpacingAndOriginFromImage(false); - - AddProcess(vdreproj, oss1.str()); - vdreproj->Update(); - - //Sample list generator - ListSampleGeneratorType::Pointer sampleGenerator = ListSampleGeneratorType::New(); - - sampleGenerator->SetInput(image); - sampleGenerator->SetInputVectorData(vdreproj->GetOutput()); - - sampleGenerator->SetClassKey(GetParameterString("sample.vfn")); - sampleGenerator->SetMaxTrainingSize(GetParameterInt("sample.mt")); - sampleGenerator->SetMaxValidationSize(GetParameterInt("sample.mv")); - sampleGenerator->SetValidationTrainingProportion(GetParameterFloat("sample.vtr")); - sampleGenerator->SetBoundByMin(GetParameterInt("sample.bm")!=0); - - // take pixel located on polygon edge into consideration - if (IsParameterEnabled("sample.edg")) + else { - sampleGenerator->SetPolygonEdgeInclusion(true); + polyStatTrainOutputs.push_back(outModel + "_stats_" + strIndex + ".xml"); + ratesTrainOutputs.push_back(outModel + "_rates_" + strIndex + ".csv"); + sampleOutputs.push_back(outModel + "_samples_" + strIndex + ".shp"); } - - AddProcess(sampleGenerator, oss2.str()); - sampleGenerator->Update(); - - TargetListSampleType::Pointer trainLabels = sampleGenerator->GetTrainingListLabel(); - ListSampleType::Pointer trainSamples = sampleGenerator->GetTrainingListSample(); - TargetListSampleType::Pointer validLabels = sampleGenerator->GetValidationListLabel(); - ListSampleType::Pointer validSamples = sampleGenerator->GetValidationListSample(); - - trainLabels->DisconnectPipeline(); - trainSamples->DisconnectPipeline(); - validLabels->DisconnectPipeline(); - validSamples->DisconnectPipeline(); - - //Concatenate training and validation samples from the image - concatenateTrainingLabels->AddInput(trainLabels); - concatenateTrainingSamples->AddInput(trainSamples); - concatenateValidationLabels->AddInput(validLabels); - concatenateValidationSamples->AddInput(validSamples); + sampleTrainOutputs.push_back(outModel + "_samplesTrain_" + strIndex + ".shp"); + sampleValidOutputs.push_back(outModel + "_samplesValid_" + strIndex + ".shp"); } - // Update - AddProcess(concatenateValidationLabels, "Concatenate samples ..."); - concatenateTrainingSamples->Update(); - concatenateTrainingLabels->Update(); - concatenateValidationSamples->Update(); - concatenateValidationLabels->Update(); - - if (concatenateTrainingSamples->GetOutput()->Size() == 0) + + // --------------------------------------------------------------------------- + // Polygons stats + for (unsigned int i=0 ; i<nbInputs ; i++) { - otbAppLogFATAL("No training samples, cannot perform SVM training."); + GetInternalApplication("polystat")->SetParameterInputImage("in",imageList->GetNthElement(i)); + GetInternalApplication("polystat")->SetParameterString("vec",vectorFileList[i], false); + GetInternalApplication("polystat")->SetParameterString("out",polyStatTrainOutputs[i], false); + ExecuteInternal("polystat"); + // analyse polygons given for validation + if (dedicatedValidation) + { + GetInternalApplication("polystat")->SetParameterString("vec",validationVectorFileList[i], false); + GetInternalApplication("polystat")->SetParameterString("out",polyStatValidOutputs[i], false); + ExecuteInternal("polystat"); + } } - if (concatenateValidationSamples->GetOutput()->Size() == 0) + // --------------------------------------------------------------------------- + // Compute sampling rates + GetInternalApplication("rates")->SetParameterString("mim","proportional", false); + double vtr = GetParameterFloat("sample.vtr"); + long mt = GetParameterInt("sample.mt"); + long mv = GetParameterInt("sample.mv"); + // compute final maximum training and final maximum validation + // By default take all samples (-1 means all samples) + long fmt = -1; + long fmv = -1; + if (GetParameterInt("sample.bm") == 0) { - otbAppLogWARNING("No validation samples."); + if (dedicatedValidation) + { + // fmt and fmv will be used separately + fmt = mt; + fmv = mv; + if (mt > -1 && mv <= -1 && vtr < 0.99999) + { + fmv = static_cast<long>((double) mt * vtr / (1.0 - vtr)); + } + if (mt <= -1 && mv > -1 && vtr > 0.00001) + { + fmt = static_cast<long>((double) mv * (1.0 - vtr) / vtr); + } + } + else + { + // only fmt will be used for both training and validation samples + // So we try to compute the total number of samples given input + // parameters mt, mv and vtr. + if (mt > -1 && mv > -1) + { + fmt = mt + mv; + } + if (mt > -1 && mv <= -1 && vtr < 0.99999) + { + fmt = static_cast<long>((double) mt / (1.0 - vtr)); + } + if (mt <= -1 && mv > -1 && vtr > 0.00001) + { + fmt = static_cast<long>((double) mv / vtr); + } + } } - if (IsParameterEnabled("io.imstat")) + // Sampling rates for training + GetInternalApplication("rates")->SetParameterStringList("il",polyStatTrainOutputs, false); + GetInternalApplication("rates")->SetParameterString("out",rateTrainOut, false); + if (GetParameterInt("sample.bm") != 0) { - StatisticsReader::Pointer statisticsReader = StatisticsReader::New(); - statisticsReader->SetFileName(GetParameterString("io.imstat")); - meanMeasurementVector = statisticsReader->GetStatisticVectorByName("mean"); - stddevMeasurementVector = statisticsReader->GetStatisticVectorByName("stddev"); + GetInternalApplication("rates")->SetParameterString("strategy","smallest", false); } else { - meanMeasurementVector.SetSize(nbBands); - meanMeasurementVector.Fill(0.); - stddevMeasurementVector.SetSize(nbBands); - stddevMeasurementVector.Fill(1.); + if (fmt > -1) + { + GetInternalApplication("rates")->SetParameterString("strategy","constant", false); + GetInternalApplication("rates")->SetParameterInt("strategy.constant.nb",fmt); + } + else + { + GetInternalApplication("rates")->SetParameterString("strategy","all", false); + } } - - // Shift scale the samples - ShiftScaleFilterType::Pointer trainingShiftScaleFilter = ShiftScaleFilterType::New(); - trainingShiftScaleFilter->SetInput(concatenateTrainingSamples->GetOutput()); - trainingShiftScaleFilter->SetShifts(meanMeasurementVector); - trainingShiftScaleFilter->SetScales(stddevMeasurementVector); - AddProcess(trainingShiftScaleFilter, "Normalize training samples ..."); - trainingShiftScaleFilter->Update(); - - ListSampleType::Pointer validationListSample=ListSampleType::New(); - - //Test if the validation test is empty - if ( concatenateValidationSamples->GetOutput()->Size() != 0 ) + ExecuteInternal("rates"); + // Sampling rates for validation + if (dedicatedValidation) { - ShiftScaleFilterType::Pointer validationShiftScaleFilter = ShiftScaleFilterType::New(); - validationShiftScaleFilter->SetInput(concatenateValidationSamples->GetOutput()); - validationShiftScaleFilter->SetShifts(meanMeasurementVector); - validationShiftScaleFilter->SetScales(stddevMeasurementVector); - AddProcess(validationShiftScaleFilter, "Normalize validation samples ..."); - validationShiftScaleFilter->Update(); - validationListSample = validationShiftScaleFilter->GetOutput(); + GetInternalApplication("rates")->SetParameterStringList("il",polyStatValidOutputs, false); + GetInternalApplication("rates")->SetParameterString("out",rateValidOut, false); + if (GetParameterInt("sample.bm") != 0) + { + GetInternalApplication("rates")->SetParameterString("strategy","smallest", false); + } + else + { + if (fmv > -1) + { + GetInternalApplication("rates")->SetParameterString("strategy","constant", false); + GetInternalApplication("rates")->SetParameterInt("strategy.constant.nb",fmv); + } + else + { + GetInternalApplication("rates")->SetParameterString("strategy","all", false); + } + } + ExecuteInternal("rates"); } - ListSampleType::Pointer listSample; - TargetListSampleType::Pointer labelListSample; - //-------------------------- - // Balancing training sample (if needed) - // if (IsParameterEnabled("sample.b")) - // { - // // Balance the list sample. - // otbAppLogINFO("Number of training samples before balancing: " << concatenateTrainingSamples->GetOutput()->Size()) - // BalancingListSampleFilterType::Pointer balancingFilter = BalancingListSampleFilterType::New(); - // balancingFilter->SetInput(trainingShiftScaleFilter->GetOutput()); - // balancingFilter->SetInputLabel(concatenateTrainingLabels->GetOutput()); - // balancingFilter->SetBalancingFactor(GetParameterInt("sample.b")); - // balancingFilter->Update(); - // listSample = balancingFilter->GetOutput(); - // labelListSample = balancingFilter->GetOutputLabelSampleList(); - // otbAppLogINFO("Number of samples after balancing: " << balancingFilter->GetOutput()->Size()); - - // } - // else - // { - listSample = trainingShiftScaleFilter->GetOutput(); - labelListSample = concatenateTrainingLabels->GetOutput(); - otbAppLogINFO("Number of training samples: " << concatenateTrainingSamples->GetOutput()->Size()); - // } - //-------------------------- - // Split the data set into training/validation set - ListSampleType::Pointer trainingListSample = listSample; - TargetListSampleType::Pointer trainingLabeledListSample = labelListSample; - - TargetListSampleType::Pointer validationLabeledListSample = concatenateValidationLabels->GetOutput(); - otbAppLogINFO("Size of training set: " << trainingListSample->Size()); - otbAppLogINFO("Size of validation set: " << validationListSample->Size()); - otbAppLogINFO("Size of labeled training set: " << trainingLabeledListSample->Size()); - otbAppLogINFO("Size of labeled validation set: " << validationLabeledListSample->Size()); - - //-------------------------- - // Estimate model - //-------------------------- - this->Train(trainingListSample,trainingLabeledListSample,GetParameterString("io.out")); - - //-------------------------- - // Performances estimation - //-------------------------- - TargetListSampleType::Pointer predictedList = TargetListSampleType::New(); - ListSampleType::Pointer performanceListSample=ListSampleType::New(); - TargetListSampleType::Pointer performanceLabeledListSample=TargetListSampleType::New(); - - //Test the input validation set size - if(validationLabeledListSample->Size() != 0) - { - performanceListSample = validationListSample; - performanceLabeledListSample = validationLabeledListSample; - } - else + // --------------------------------------------------------------------------- + // Select & extract samples + GetInternalApplication("select")->SetParameterString("sampler", "periodic", false); + GetInternalApplication("select")->SetParameterInt("sampler.periodic.jitter",50); + GetInternalApplication("select")->SetParameterString("strategy","byclass", false); + GetInternalApplication("extraction")->SetParameterString("outfield", "prefix", false); + GetInternalApplication("extraction")->SetParameterString("outfield.prefix.name","value_", false); + for (unsigned int i=0 ; i<nbInputs ; i++) { - otbAppLogWARNING("The validation set is empty. The performance estimation is done using the input training set in this case."); - performanceListSample = trainingListSample; - performanceLabeledListSample = trainingLabeledListSample; - } - - this->Classify(performanceListSample, predictedList, GetParameterString("io.out")); - - ConfusionMatrixCalculatorType::Pointer confMatCalc = ConfusionMatrixCalculatorType::New(); - - otbAppLogINFO("Predicted list size : " << predictedList->Size()); - otbAppLogINFO("ValidationLabeledListSample size : " << performanceLabeledListSample->Size()); - confMatCalc->SetReferenceLabels(performanceLabeledListSample); - confMatCalc->SetProducedLabels(predictedList); - confMatCalc->Compute(); - - otbAppLogINFO("training performances"); - LogConfusionMatrix(confMatCalc); - - for (unsigned int itClasses = 0; itClasses < confMatCalc->GetNumberOfClasses(); itClasses++) + GetInternalApplication("select")->SetParameterInputImage("in",imageList->GetNthElement(i)); + GetInternalApplication("select")->SetParameterString("vec",vectorFileList[i], false); + GetInternalApplication("select")->SetParameterString("out",sampleOutputs[i], false); + GetInternalApplication("select")->SetParameterString("instats",polyStatTrainOutputs[i], false); + GetInternalApplication("select")->SetParameterString("strategy.byclass.in",ratesTrainOutputs[i], false); + // select sample positions + ExecuteInternal("select"); + // extract sample descriptors + ExecuteInternal("extraction"); + + if (dedicatedValidation) { - ConfusionMatrixCalculatorType::ClassLabelType classLabel = confMatCalc->GetMapOfIndices()[itClasses]; - - otbAppLogINFO("Precision of class [" << classLabel << "] vs all: " << confMatCalc->GetPrecisions()[itClasses]); - otbAppLogINFO("Recall of class [" << classLabel << "] vs all: " << confMatCalc->GetRecalls()[itClasses]); - otbAppLogINFO( - "F-score of class [" << classLabel << "] vs all: " << confMatCalc->GetFScores()[itClasses] << "\n"); + GetInternalApplication("select")->SetParameterString("vec",validationVectorFileList[i], false); + GetInternalApplication("select")->SetParameterString("out",sampleValidOutputs[i], false); + GetInternalApplication("select")->SetParameterString("instats",polyStatValidOutputs[i], false); + GetInternalApplication("select")->SetParameterString("strategy.byclass.in",ratesValidOutputs[i], false); + // select sample positions + ExecuteInternal("select"); + // extract sample descriptors + ExecuteInternal("extraction"); } - otbAppLogINFO("Global performance, Kappa index: " << confMatCalc->GetKappaIndex()); - - - if (this->HasValue("io.confmatout")) + else { - // Writing the confusion matrix in the output .CSV file - - MapOfIndicesType::iterator itMapOfIndicesValid, itMapOfIndicesPred; - ClassLabelType labelValid = 0; - - ConfusionMatrixType confusionMatrix = confMatCalc->GetConfusionMatrix(); - MapOfIndicesType mapOfIndicesValid = confMatCalc->GetMapOfIndices(); - - unsigned int nbClassesPred = mapOfIndicesValid.size(); - - ///////////////////////////////////////////// - // Filling the 2 headers for the output file - const std::string commentValidStr = "#Reference labels (rows):"; - const std::string commentPredStr = "#Produced labels (columns):"; - const char separatorChar = ','; - std::ostringstream ossHeaderValidLabels, ossHeaderPredLabels; - - // Filling ossHeaderValidLabels and ossHeaderPredLabels for the output file - ossHeaderValidLabels << commentValidStr; - ossHeaderPredLabels << commentPredStr; - - itMapOfIndicesValid = mapOfIndicesValid.begin(); - - while (itMapOfIndicesValid != mapOfIndicesValid.end()) + // Split between training and validation + ogr::DataSource::Pointer source = ogr::DataSource::New(sampleOutputs[i], ogr::DataSource::Modes::Read); + ogr::DataSource::Pointer destTrain = ogr::DataSource::New(sampleTrainOutputs[i], ogr::DataSource::Modes::Overwrite); + ogr::DataSource::Pointer destValid = ogr::DataSource::New(sampleValidOutputs[i], ogr::DataSource::Modes::Overwrite); + // read sampling rates from ratesTrainOutputs[i] + SamplingRateCalculator::Pointer rateCalculator = SamplingRateCalculator::New(); + rateCalculator->Read(ratesTrainOutputs[i]); + // Compute sampling rates for train and valid + const MapRateType &inputRates = rateCalculator->GetRatesByClass(); + MapRateType trainRates; + MapRateType validRates; + otb::SamplingRateCalculator::TripletType tpt; + for (MapRateType::const_iterator it = inputRates.begin() ; + it != inputRates.end() ; + ++it) { - // labels labelValid of mapOfIndicesValid are already sorted in otbConfusionMatrixCalculator - labelValid = itMapOfIndicesValid->second; - - otbAppLogINFO("mapOfIndicesValid[" << itMapOfIndicesValid->first << "] = " << labelValid); - - ossHeaderValidLabels << labelValid; - ossHeaderPredLabels << labelValid; - - ++itMapOfIndicesValid; - - if (itMapOfIndicesValid != mapOfIndicesValid.end()) - { - ossHeaderValidLabels << separatorChar; - ossHeaderPredLabels << separatorChar; - } - else - { - ossHeaderValidLabels << std::endl; - ossHeaderPredLabels << std::endl; - } + unsigned long total = std::min(it->second.Required,it->second.Tot ); + unsigned long neededValid = static_cast<unsigned long>((double) total * vtr ); + unsigned long neededTrain = total - neededValid; + tpt.Tot = total; + tpt.Required = neededTrain; + tpt.Rate = (1.0 - vtr); + trainRates[it->first] = tpt; + tpt.Tot = neededValid; + tpt.Required = neededValid; + tpt.Rate = 1.0; + validRates[it->first] = tpt; } - std::ofstream outFile; - outFile.open(this->GetParameterString("io.confmatout").c_str()); - outFile << std::fixed; - outFile.precision(10); - - ///////////////////////////////////// - // Writing the 2 headers - outFile << ossHeaderValidLabels.str(); - outFile << ossHeaderPredLabels.str(); - ///////////////////////////////////// - - unsigned int indexLabelValid = 0, indexLabelPred = 0; - - for (itMapOfIndicesValid = mapOfIndicesValid.begin(); itMapOfIndicesValid != mapOfIndicesValid.end(); ++itMapOfIndicesValid) - { - indexLabelPred = 0; - - for (itMapOfIndicesPred = mapOfIndicesValid.begin(); itMapOfIndicesPred != mapOfIndicesValid.end(); ++itMapOfIndicesPred) - { - // Writing the confusion matrix (sorted in otbConfusionMatrixCalculator) in the output file - outFile << confusionMatrix(indexLabelValid, indexLabelPred); - if (indexLabelPred < (nbClassesPred - 1)) - { - outFile << separatorChar; - } - else - { - outFile << std::endl; - } - ++indexLabelPred; - } - - ++indexLabelValid; - } + // Use an otb::OGRDataToSamplePositionFilter with 2 outputs + PeriodicSamplerType::SamplerParameterType param; + param.Offset = 0; + param.MaxJitter = 0; + PeriodicSamplerType::Pointer splitter = PeriodicSamplerType::New(); + splitter->SetInput(imageList->GetNthElement(i)); + splitter->SetOGRData(source); + splitter->SetOutputPositionContainerAndRates(destTrain, trainRates, 0); + splitter->SetOutputPositionContainerAndRates(destValid, validRates, 1); + splitter->SetFieldName(this->GetParameterStringList("sample.vfn")[0]); + splitter->SetLayerIndex(0); + splitter->SetOriginFieldName(std::string("")); + splitter->SetSamplerParameters(param); + splitter->GetStreamer()->SetAutomaticTiledStreaming(this->GetParameterInt("ram")); + AddProcess(splitter->GetStreamer(),"Split samples between training and validation..."); + splitter->Update(); + } + } - outFile.close(); - } // END if (this->HasValue("io.confmatout")) + // --------------------------------------------------------------------------- + // Train model + GetInternalApplication("training")->SetParameterStringList("io.vd",sampleTrainOutputs, false); + GetInternalApplication("training")->SetParameterStringList("valid.vd",sampleValidOutputs, false); + UpdateInternalParameters("training"); + // set field names + FloatVectorImageType::Pointer image = imageList->GetNthElement(0); + unsigned int nbBands = image->GetNumberOfComponentsPerPixel(); + std::vector<std::string> selectedNames; + for (unsigned int i=0 ; i<nbBands ; i++) + { + std::ostringstream oss; + oss << i; + selectedNames.push_back("value_"+oss.str()); + } + GetInternalApplication("training")->SetParameterStringList("feat",selectedNames, false); + ExecuteInternal("training"); - // TODO: implement hyperplane distance classifier and performance validation (cf. object detection) ? + // cleanup + if(IsParameterEnabled("cleanup")) + { + otbAppLogINFO(<<"Final clean-up ..."); + for(unsigned int i=0 ; i<polyStatTrainOutputs.size() ; i++) + RemoveFile(polyStatTrainOutputs[i]); + for(unsigned int i=0 ; i<polyStatValidOutputs.size() ; i++) + RemoveFile(polyStatValidOutputs[i]); + for(unsigned int i=0 ; i<ratesTrainOutputs.size() ; i++) + RemoveFile(ratesTrainOutputs[i]); + for(unsigned int i=0 ; i<ratesValidOutputs.size() ; i++) + RemoveFile(ratesValidOutputs[i]); + for(unsigned int i=0 ; i<sampleOutputs.size() ; i++) + RemoveFile(sampleOutputs[i]); + for(unsigned int i=0 ; i<sampleTrainOutputs.size() ; i++) + RemoveFile(sampleTrainOutputs[i]); + for(unsigned int i=0 ; i<sampleValidOutputs.size() ; i++) + RemoveFile(sampleValidOutputs[i]); + } } - VectorDataReprojectionType::Pointer vdreproj; }; } // end namespace Wrapper diff --git a/Modules/Applications/AppClassification/app/otbTrainOGRLayersClassifier.cxx b/Modules/Applications/AppClassification/app/otbTrainOGRLayersClassifier.cxx index b461ac2a89f97fda7b2b2308d6e6f08ce5834964..0e4affaa6c4957b0c773af552d9756ce44339278 100644 --- a/Modules/Applications/AppClassification/app/otbTrainOGRLayersClassifier.cxx +++ b/Modules/Applications/AppClassification/app/otbTrainOGRLayersClassifier.cxx @@ -80,7 +80,7 @@ private: AddParameter(ParameterType_String,"cfield","Field containing the class id for supervision"); SetParameterDescription("cfield","Field containing the class id for supervision. Only geometries with this field available will be taken into account."); - SetParameterString("cfield","class"); + SetParameterString("cfield","class", false); // Doc example parameter settings SetDocExampleParameterValue("inshp", "vectorData.shp"); diff --git a/Modules/Applications/AppClassification/app/otbTrainRegression.cxx b/Modules/Applications/AppClassification/app/otbTrainRegression.cxx index 3039d44a0a053a5a84787683258069c16575b27c..335961cfce88ce3c259f1cb4f25be9d2b029c8ac 100644 --- a/Modules/Applications/AppClassification/app/otbTrainRegression.cxx +++ b/Modules/Applications/AppClassification/app/otbTrainRegression.cxx @@ -159,7 +159,7 @@ void DoInit() ITK_OVERRIDE AddParameter(ParameterType_Float, "sample.vtr", "Training and validation sample ratio"); SetParameterDescription("sample.vtr", "Ratio between training and validation samples (0.0 = all training, 1.0 = all validation) (default = 0.5)."); - SetParameterFloat("sample.vtr", 0.5); + SetParameterFloat("sample.vtr",0.5, false); Superclass::DoInit(); diff --git a/Modules/Applications/AppClassification/app/otbTrainVectorClassifier.cxx b/Modules/Applications/AppClassification/app/otbTrainVectorClassifier.cxx index 09edbc6cf385cb8397ca166d4c9394081e1f6019..fa5209552eb154aa1ef9aadee88cb54760b36722 100644 --- a/Modules/Applications/AppClassification/app/otbTrainVectorClassifier.cxx +++ b/Modules/Applications/AppClassification/app/otbTrainVectorClassifier.cxx @@ -109,11 +109,11 @@ private: AddParameter(ParameterType_ListView, "feat", "Field names for training features."); SetParameterDescription("feat","List of field names in the input vector data to be used as features for training."); - AddParameter(ParameterType_String,"cfield","Field containing the class id for supervision"); + AddParameter(ParameterType_ListView,"cfield","Field containing the class id for supervision"); SetParameterDescription("cfield","Field containing the class id for supervision. " "Only geometries with this field available will be taken into account."); - SetParameterString("cfield","class"); - + SetListViewSingleSelectionMode("cfield",true); + AddParameter(ParameterType_Int, "layer", "Layer Index"); SetParameterDescription("layer", "Index of the layer to use in the input vector file."); MandatoryOff("layer"); @@ -155,14 +155,27 @@ private: ogr::Feature feature = layer.ogr().GetNextFeature(); ClearChoices("feat"); + ClearChoices("cfield"); + for(int iField=0; iField<feature.ogr().GetFieldCount(); iField++) { std::string key, item = feature.ogr().GetFieldDefnRef(iField)->GetNameRef(); key = item; std::string::iterator end = std::remove_if(key.begin(),key.end(),IsNotAlphaNum); std::transform(key.begin(), end, key.begin(), tolower); - key="feat."+key.substr(0, end - key.begin()); - AddChoice(key,item); + + OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType(); + + if(fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType) || fieldType == OFTReal) + { + std::string tmpKey="feat."+key.substr(0, end - key.begin()); + AddChoice(tmpKey,item); + } + if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType)) + { + std::string tmpKey="cfield."+key.substr(0, end - key.begin()); + AddChoice(tmpKey,item); + } } } } @@ -248,25 +261,32 @@ void DoExecute() // Prepare selected field names (their position may change between two inputs) std::vector<int> selectedIdx = GetSelectedItems("feat"); + std::vector<int> selectedCFieldIdx = GetSelectedItems("cfield"); + + if(selectedIdx.empty()) + { + otbAppLogFATAL(<<"No features have been selected to train the classifier on!"); + } + + if(selectedCFieldIdx.empty()) + { + otbAppLogFATAL(<<"No field has been selected for data labelling!"); + } + const unsigned int nbFeatures = selectedIdx.size(); std::vector<std::string> fieldNames = GetChoiceNames("feat"); + std::vector<std::string> cFieldNames = GetChoiceNames("cfield"); std::vector<std::string> selectedNames(nbFeatures); for (unsigned int i=0 ; i<nbFeatures ; i++) { selectedNames[i] = fieldNames[selectedIdx[i]]; } + + std::string selectedCFieldName = cFieldNames[selectedCFieldIdx.front()]; + std::vector<int> featureFieldIndex(nbFeatures, -1); int cFieldIndex = -1; - // List of available fields - std::ostringstream oss; - for (unsigned int i=0 ; i<fieldNames.size() ; i++) - { - if (i) oss << ", "; - oss << fieldNames[i]; - } - std::string availableFields(oss.str()); - // Statistics for shift/scale MeasurementType meanMeasurementVector; MeasurementType stddevMeasurementVector; @@ -307,17 +327,17 @@ void DoExecute() // Check all needed fields are present : // - check class field - cFieldIndex = feature.ogr().GetFieldIndex(GetParameterString("cfield").c_str()); + cFieldIndex = feature.ogr().GetFieldIndex(selectedCFieldName.c_str()); if (cFieldIndex < 0) - otbAppLogFATAL("The field name for class label ("<<GetParameterString("cfield") - <<") has not been found in the input vector file! Choices are "<< availableFields); + otbAppLogFATAL("The field name for class label ("<<selectedCFieldName + <<") has not been found in the input vector file "<<vectorFileList[k]); // - check feature fields for (unsigned int i=0 ; i<nbFeatures ; i++) { featureFieldIndex[i] = feature.ogr().GetFieldIndex(selectedNames[i].c_str()); if (featureFieldIndex[i] < 0) otbAppLogFATAL("The field name for feature "<<selectedNames[i] - <<" has not been found in the input vector file! Choices are "<< availableFields); + <<" has not been found in the input vector file "<<vectorFileList[k]); } while(goesOn) @@ -381,17 +401,17 @@ void DoExecute() // Check all needed fields are present : // - check class field - cFieldIndex = feature.ogr().GetFieldIndex(GetParameterString("cfield").c_str()); + cFieldIndex = feature.ogr().GetFieldIndex(selectedCFieldName.c_str()); if (cFieldIndex < 0) - otbAppLogFATAL("The field name for class label ("<<GetParameterString("cfield") - <<") has not been found in the input vector file! Choices are "<< availableFields); + otbAppLogFATAL("The field name for class label ("<<selectedCFieldName + <<") has not been found in the validation vector file "<<validFileList[k]); // - check feature fields for (unsigned int i=0 ; i<nbFeatures ; i++) { featureFieldIndex[i] = feature.ogr().GetFieldIndex(selectedNames[i].c_str()); if (featureFieldIndex[i] < 0) otbAppLogFATAL("The field name for feature "<<selectedNames[i] - <<" has not been found in the input vector file! Choices are "<< availableFields); + <<" has not been found in the validation vector file "<<validFileList[k]); } while(goesOn) diff --git a/Modules/Applications/AppClassification/app/otbVectorDataDSValidation.cxx b/Modules/Applications/AppClassification/app/otbVectorDataDSValidation.cxx index c260e168195bc5b9e923b4ac34e48bec6a054a63..234b90e7677adcebd0259cba08d084b2d9e793d2 100644 --- a/Modules/Applications/AppClassification/app/otbVectorDataDSValidation.cxx +++ b/Modules/Applications/AppClassification/app/otbVectorDataDSValidation.cxx @@ -84,12 +84,12 @@ private: AddParameter(ParameterType_String, "cri", "Criterion"); SetParameterDescription("cri", "Dempster Shafer criterion (by default (belief+plausibility)/2)"); MandatoryOff("cri"); - SetParameterString("cri", "((Belief + Plausibility)/2.)"); + SetParameterString("cri", "((Belief + Plausibility)/2.)", false); AddParameter(ParameterType_Float, "thd", "Criterion threshold"); SetParameterDescription("thd", "Criterion threshold (default 0.5)"); MandatoryOff("thd"); - SetParameterFloat("thd", 0.5); + SetParameterFloat("thd",0.5, false); AddParameter(ParameterType_OutputVectorData, "out", "Output Vector Data"); SetParameterDescription("out", "Output VectorData containing only the validated samples"); diff --git a/Modules/Applications/AppClassification/include/otbTrainBoost.txx b/Modules/Applications/AppClassification/include/otbTrainBoost.txx index fbd99531a4eff13525b9db92ddad63643397bb2a..ea725cc28e52dfcbb1e25f4b77df859fac005792 100644 --- a/Modules/Applications/AppClassification/include/otbTrainBoost.txx +++ b/Modules/Applications/AppClassification/include/otbTrainBoost.txx @@ -39,22 +39,22 @@ namespace Wrapper AddChoice("classifier.boost.t.logit", "LogitBoost (technique producing good regression fits)"); AddChoice("classifier.boost.t.gentle", "Gentle AdaBoost (technique setting less weight on outlier data points " "and, for that reason, being often good with regression data)"); - SetParameterString("classifier.boost.t", "real"); + SetParameterString("classifier.boost.t", "real", false); SetParameterDescription("classifier.boost.t", "Type of Boosting algorithm."); //Do not expose SplitCriteria //WeakCount AddParameter(ParameterType_Int, "classifier.boost.w", "Weak count"); - SetParameterInt("classifier.boost.w", 100); + SetParameterInt("classifier.boost.w",100, false); SetParameterDescription("classifier.boost.w","The number of weak classifiers."); //WeightTrimRate AddParameter(ParameterType_Float, "classifier.boost.r", "Weight Trim Rate"); - SetParameterFloat("classifier.boost.r", 0.95); + SetParameterFloat("classifier.boost.r",0.95, false); SetParameterDescription("classifier.boost.r","A threshold between 0 and 1 used to save computational time. " "Samples with summary weight <= (1 - weight_trim_rate) do not participate in the next iteration of training. " "Set this parameter to 0 to turn off this functionality."); //MaxDepth : Not sure that this parameter has to be exposed. AddParameter(ParameterType_Int, "classifier.boost.m", "Maximum depth of the tree"); - SetParameterInt("classifier.boost.m", 1); + SetParameterInt("classifier.boost.m",1, false); SetParameterDescription("classifier.boost.m","Maximum depth of the tree."); } diff --git a/Modules/Applications/AppClassification/include/otbTrainDecisionTree.txx b/Modules/Applications/AppClassification/include/otbTrainDecisionTree.txx index 61cd1a34befbcf00aa70ea0703f3f43af3c81570..def7b605e537d51e73de0ab43dbd398d64032798 100644 --- a/Modules/Applications/AppClassification/include/otbTrainDecisionTree.txx +++ b/Modules/Applications/AppClassification/include/otbTrainDecisionTree.txx @@ -34,7 +34,7 @@ LearningApplicationBase<TInputValue,TOutputValue> "See complete documentation here \\url{http://docs.opencv.org/modules/ml/doc/decision_trees.html}."); //MaxDepth AddParameter(ParameterType_Int, "classifier.dt.max", "Maximum depth of the tree"); - SetParameterInt("classifier.dt.max", 65535); + SetParameterInt("classifier.dt.max",65535, false); SetParameterDescription( "classifier.dt.max", "The training algorithm attempts to split each node while its depth is smaller than the maximum " "possible depth of the tree. The actual depth may be smaller if the other termination criteria are met, and/or " @@ -42,13 +42,13 @@ LearningApplicationBase<TInputValue,TOutputValue> //MinSampleCount AddParameter(ParameterType_Int, "classifier.dt.min", "Minimum number of samples in each node"); - SetParameterInt("classifier.dt.min", 10); + SetParameterInt("classifier.dt.min",10, false); SetParameterDescription("classifier.dt.min", "If the number of samples in a node is smaller than this parameter, " "then this node will not be split."); //RegressionAccuracy AddParameter(ParameterType_Float, "classifier.dt.ra", "Termination criteria for regression tree"); - SetParameterFloat("classifier.dt.ra", 0.01); + SetParameterFloat("classifier.dt.ra",0.01, false); SetParameterDescription("classifier.dt.min", "If all absolute differences between an estimated value in a node " "and the values of the train samples in this node are smaller than this regression accuracy parameter, " "then the node will not be split."); @@ -60,14 +60,14 @@ LearningApplicationBase<TInputValue,TOutputValue> //MaxCategories AddParameter(ParameterType_Int, "classifier.dt.cat", "Cluster possible values of a categorical variable into K <= cat clusters to find a suboptimal split"); - SetParameterInt("classifier.dt.cat", 10); + SetParameterInt("classifier.dt.cat",10, false); SetParameterDescription( "classifier.dt.cat", "Cluster possible values of a categorical variable into K <= cat clusters to find a suboptimal split."); //CVFolds AddParameter(ParameterType_Int, "classifier.dt.f", "K-fold cross-validations"); - SetParameterInt("classifier.dt.f", 10); + SetParameterInt("classifier.dt.f",10, false); SetParameterDescription( "classifier.dt.f", "If cv_folds > 1, then it prunes a tree with K-fold cross-validation where K is equal to cv_folds."); diff --git a/Modules/Applications/AppClassification/include/otbTrainGradientBoostedTree.txx b/Modules/Applications/AppClassification/include/otbTrainGradientBoostedTree.txx index bcf5caa86181a84c546c264052bad32f2d8fd95f..d67f9643447686f4d8ee87e1143fc9a847d55b93 100644 --- a/Modules/Applications/AppClassification/include/otbTrainGradientBoostedTree.txx +++ b/Modules/Applications/AppClassification/include/otbTrainGradientBoostedTree.txx @@ -45,7 +45,7 @@ LearningApplicationBase<TInputValue,TOutputValue> //WeakCount AddParameter(ParameterType_Int, "classifier.gbt.w", "Number of boosting algorithm iterations"); - SetParameterInt("classifier.gbt.w", 200); + SetParameterInt("classifier.gbt.w",200, false); SetParameterDescription( "classifier.gbt.w", "Number \"w\" of boosting algorithm iterations, with w*K being the total number of trees in " @@ -53,20 +53,20 @@ LearningApplicationBase<TInputValue,TOutputValue> //Shrinkage AddParameter(ParameterType_Float, "classifier.gbt.s", "Regularization parameter"); - SetParameterFloat("classifier.gbt.s", 0.01); + SetParameterFloat("classifier.gbt.s",0.01, false); SetParameterDescription("classifier.gbt.s", "Regularization parameter."); //SubSamplePortion AddParameter(ParameterType_Float, "classifier.gbt.p", "Portion of the whole training set used for each algorithm iteration"); - SetParameterFloat("classifier.gbt.p", 0.8); + SetParameterFloat("classifier.gbt.p",0.8, false); SetParameterDescription( "classifier.gbt.p", "Portion of the whole training set used for each algorithm iteration. The subset is generated randomly."); //MaxDepth AddParameter(ParameterType_Int, "classifier.gbt.max", "Maximum depth of the tree"); - SetParameterInt("classifier.gbt.max", 3); + SetParameterInt("classifier.gbt.max",3, false); SetParameterDescription( "classifier.gbt.max", "The training algorithm attempts to split each node while its depth is smaller than the maximum " "possible depth of the tree. The actual depth may be smaller if the other termination criteria are met, and/or " diff --git a/Modules/Applications/AppClassification/include/otbTrainKNN.txx b/Modules/Applications/AppClassification/include/otbTrainKNN.txx index fdf10cdf283f1a5f22f3044aea335c844c16101c..6fba81fe4ea9d0604c5e0e3c19bcea876bfb76be 100644 --- a/Modules/Applications/AppClassification/include/otbTrainKNN.txx +++ b/Modules/Applications/AppClassification/include/otbTrainKNN.txx @@ -34,7 +34,7 @@ namespace Wrapper //K parameter AddParameter(ParameterType_Int, "classifier.knn.k", "Number of Neighbors"); - SetParameterInt("classifier.knn.k", 32); + SetParameterInt("classifier.knn.k",32, false); SetParameterDescription("classifier.knn.k","The number of neighbors to use."); if (this->m_RegressionFlag) diff --git a/Modules/Applications/AppClassification/include/otbTrainLibSVM.txx b/Modules/Applications/AppClassification/include/otbTrainLibSVM.txx index f89b7141566e3993f117990eaea5c7cb87f9438b..120b572fcee064bac28a14cce05526eb82862f2d 100644 --- a/Modules/Applications/AppClassification/include/otbTrainLibSVM.txx +++ b/Modules/Applications/AppClassification/include/otbTrainLibSVM.txx @@ -35,7 +35,7 @@ namespace Wrapper AddChoice("classifier.libsvm.k.rbf", "Gaussian radial basis function"); AddChoice("classifier.libsvm.k.poly", "Polynomial"); AddChoice("classifier.libsvm.k.sigmoid", "Sigmoid"); - SetParameterString("classifier.libsvm.k", "linear"); + SetParameterString("classifier.libsvm.k", "linear", false); SetParameterDescription("classifier.libsvm.k", "SVM Kernel Type."); AddParameter(ParameterType_Choice, "classifier.libsvm.m", "SVM Model Type"); SetParameterDescription("classifier.libsvm.m", "Type of SVM formulation."); @@ -43,17 +43,17 @@ namespace Wrapper { AddChoice("classifier.libsvm.m.epssvr", "Epsilon Support Vector Regression"); AddChoice("classifier.libsvm.m.nusvr", "Nu Support Vector Regression"); - SetParameterString("classifier.libsvm.m", "epssvr"); + SetParameterString("classifier.libsvm.m", "epssvr", false); } else { AddChoice("classifier.libsvm.m.csvc", "C support vector classification"); AddChoice("classifier.libsvm.m.nusvc", "Nu support vector classification"); AddChoice("classifier.libsvm.m.oneclass", "Distribution estimation (One Class SVM)"); - SetParameterString("classifier.libsvm.m", "csvc"); + SetParameterString("classifier.libsvm.m", "csvc", false); } AddParameter(ParameterType_Float, "classifier.libsvm.c", "Cost parameter C"); - SetParameterFloat("classifier.libsvm.c", 1.0); + SetParameterFloat("classifier.libsvm.c",1.0, false); SetParameterDescription( "classifier.libsvm.c", "SVM models have a cost parameter C (1 by default) to control the trade-off between training errors and forcing rigid margins."); @@ -67,9 +67,9 @@ namespace Wrapper if (this->m_RegressionFlag) { AddParameter(ParameterType_Float, "classifier.libsvm.eps", "Epsilon"); - SetParameterFloat("classifier.libsvm.eps", 1e-3); + SetParameterFloat("classifier.libsvm.eps",1e-3, false); AddParameter(ParameterType_Float, "classifier.libsvm.nu", "Nu"); - SetParameterFloat("classifier.libsvm.nu", 0.5); + SetParameterFloat("classifier.libsvm.nu",0.5, false); } } diff --git a/Modules/Applications/AppClassification/include/otbTrainNeuralNetwork.txx b/Modules/Applications/AppClassification/include/otbTrainNeuralNetwork.txx index ee7bf43d47c7e9f9b653208b8c7d611afc13c62e..8f9386a8d557b48a16f24df93edc5b943d062324 100644 --- a/Modules/Applications/AppClassification/include/otbTrainNeuralNetwork.txx +++ b/Modules/Applications/AppClassification/include/otbTrainNeuralNetwork.txx @@ -38,7 +38,7 @@ LearningApplicationBase<TInputValue,TOutputValue> AddParameter(ParameterType_Choice, "classifier.ann.t", "Train Method Type"); AddChoice("classifier.ann.t.reg", "RPROP algorithm"); AddChoice("classifier.ann.t.back", "Back-propagation algorithm"); - SetParameterString("classifier.ann.t", "reg"); + SetParameterString("classifier.ann.t", "reg", false); SetParameterDescription("classifier.ann.t", "Type of training method for the multilayer perceptron (MLP) neural network."); //LayerSizes @@ -56,25 +56,25 @@ LearningApplicationBase<TInputValue,TOutputValue> AddChoice("classifier.ann.f.ident", "Identity function"); AddChoice("classifier.ann.f.sig", "Symmetrical Sigmoid function"); AddChoice("classifier.ann.f.gau", "Gaussian function (Not completely supported)"); - SetParameterString("classifier.ann.f", "sig"); + SetParameterString("classifier.ann.f", "sig", false); SetParameterDescription("classifier.ann.f", "Neuron activation function."); //Alpha AddParameter(ParameterType_Float, "classifier.ann.a", "Alpha parameter of the activation function"); - SetParameterFloat("classifier.ann.a", 1.); + SetParameterFloat("classifier.ann.a",1., false); SetParameterDescription("classifier.ann.a", "Alpha parameter of the activation function (used only with sigmoid and gaussian functions)."); //Beta AddParameter(ParameterType_Float, "classifier.ann.b", "Beta parameter of the activation function"); - SetParameterFloat("classifier.ann.b", 1.); + SetParameterFloat("classifier.ann.b",1., false); SetParameterDescription("classifier.ann.b", "Beta parameter of the activation function (used only with sigmoid and gaussian functions)."); //BackPropDWScale AddParameter(ParameterType_Float, "classifier.ann.bpdw", "Strength of the weight gradient term in the BACKPROP method"); - SetParameterFloat("classifier.ann.bpdw", 0.1); + SetParameterFloat("classifier.ann.bpdw",0.1, false); SetParameterDescription( "classifier.ann.bpdw", "Strength of the weight gradient term in the BACKPROP method. The recommended value is about 0.1."); @@ -82,7 +82,7 @@ LearningApplicationBase<TInputValue,TOutputValue> //BackPropMomentScale AddParameter(ParameterType_Float, "classifier.ann.bpms", "Strength of the momentum term (the difference between weights on the 2 previous iterations)"); - SetParameterFloat("classifier.ann.bpms", 0.1); + SetParameterFloat("classifier.ann.bpms",0.1, false); SetParameterDescription( "classifier.ann.bpms", "Strength of the momentum term (the difference between weights on the 2 previous iterations). " @@ -92,12 +92,12 @@ LearningApplicationBase<TInputValue,TOutputValue> //RegPropDW0 AddParameter(ParameterType_Float, "classifier.ann.rdw", "Initial value Delta_0 of update-values Delta_{ij} in RPROP method"); - SetParameterFloat("classifier.ann.rdw", 0.1); + SetParameterFloat("classifier.ann.rdw",0.1, false); SetParameterDescription("classifier.ann.rdw", "Initial value Delta_0 of update-values Delta_{ij} in RPROP method (default = 0.1)."); //RegPropDWMin AddParameter(ParameterType_Float, "classifier.ann.rdwm", "Update-values lower limit Delta_{min} in RPROP method"); - SetParameterFloat("classifier.ann.rdwm", 1e-7); + SetParameterFloat("classifier.ann.rdwm",1e-7, false); SetParameterDescription( "classifier.ann.rdwm", "Update-values lower limit Delta_{min} in RPROP method. It must be positive (default = 1e-7)."); @@ -107,18 +107,18 @@ LearningApplicationBase<TInputValue,TOutputValue> AddChoice("classifier.ann.term.iter", "Maximum number of iterations"); AddChoice("classifier.ann.term.eps", "Epsilon"); AddChoice("classifier.ann.term.all", "Max. iterations + Epsilon"); - SetParameterString("classifier.ann.term", "all"); + SetParameterString("classifier.ann.term", "all", false); SetParameterDescription("classifier.ann.term", "Termination criteria."); //Epsilon AddParameter(ParameterType_Float, "classifier.ann.eps", "Epsilon value used in the Termination criteria"); - SetParameterFloat("classifier.ann.eps", 0.01); + SetParameterFloat("classifier.ann.eps",0.01, false); SetParameterDescription("classifier.ann.eps", "Epsilon value used in the Termination criteria."); //MaxIter AddParameter(ParameterType_Int, "classifier.ann.iter", "Maximum number of iterations used in the Termination criteria"); - SetParameterInt("classifier.ann.iter", 1000); + SetParameterInt("classifier.ann.iter",1000, false); SetParameterDescription("classifier.ann.iter", "Maximum number of iterations used in the Termination criteria."); } diff --git a/Modules/Applications/AppClassification/include/otbTrainRandomForests.txx b/Modules/Applications/AppClassification/include/otbTrainRandomForests.txx index 669b4562b6e955aaf34dd821675e3194d5b8f37b..7a507bb8f8d2bdbd4fabf4a9c01e3fc922c558c3 100644 --- a/Modules/Applications/AppClassification/include/otbTrainRandomForests.txx +++ b/Modules/Applications/AppClassification/include/otbTrainRandomForests.txx @@ -34,7 +34,7 @@ LearningApplicationBase<TInputValue,TOutputValue> "See complete documentation here \\url{http://docs.opencv.org/modules/ml/doc/random_trees.html}."); //MaxDepth AddParameter(ParameterType_Int, "classifier.rf.max", "Maximum depth of the tree"); - SetParameterInt("classifier.rf.max", 5); + SetParameterInt("classifier.rf.max",5, false); SetParameterDescription( "classifier.rf.max", "The depth of the tree. A low value will likely underfit and conversely a high value will likely overfit. " @@ -42,14 +42,14 @@ LearningApplicationBase<TInputValue,TOutputValue> //MinSampleCount AddParameter(ParameterType_Int, "classifier.rf.min", "Minimum number of samples in each node"); - SetParameterInt("classifier.rf.min", 10); + SetParameterInt("classifier.rf.min",10, false); SetParameterDescription( "classifier.rf.min", "If the number of samples in a node is smaller than this parameter, " "then the node will not be split. A reasonable value is a small percentage of the total data e.g. 1 percent."); //RegressionAccuracy AddParameter(ParameterType_Float, "classifier.rf.ra", "Termination Criteria for regression tree"); - SetParameterFloat("classifier.rf.ra", 0.); + SetParameterFloat("classifier.rf.ra",0., false); SetParameterDescription("classifier.rf.ra", "If all absolute differences between an estimated value in a node " "and the values of the train samples in this node are smaller than this regression accuracy parameter, " "then the node will not be split."); @@ -61,7 +61,7 @@ LearningApplicationBase<TInputValue,TOutputValue> //MaxNumberOfCategories AddParameter(ParameterType_Int, "classifier.rf.cat", "Cluster possible values of a categorical variable into K <= cat clusters to find a suboptimal split"); - SetParameterInt("classifier.rf.cat", 10); + SetParameterInt("classifier.rf.cat",10, false); SetParameterDescription( "classifier.rf.cat", "Cluster possible values of a categorical variable into K <= cat clusters to find a suboptimal split."); @@ -73,7 +73,7 @@ LearningApplicationBase<TInputValue,TOutputValue> //MaxNumberOfVariables AddParameter(ParameterType_Int, "classifier.rf.var", "Size of the randomly selected subset of features at each tree node"); - SetParameterInt("classifier.rf.var", 0); + SetParameterInt("classifier.rf.var",0, false); SetParameterDescription( "classifier.rf.var", "The size of the subset of features, randomly selected at each tree node, that are used to find the best split(s). " @@ -82,7 +82,7 @@ LearningApplicationBase<TInputValue,TOutputValue> //MaxNumberOfTrees AddParameter(ParameterType_Int, "classifier.rf.nbtrees", "Maximum number of trees in the forest"); - SetParameterInt("classifier.rf.nbtrees", 100); + SetParameterInt("classifier.rf.nbtrees",100, false); SetParameterDescription( "classifier.rf.nbtrees", "The maximum number of trees in the forest. Typically, the more trees you have, the better the accuracy. " @@ -92,7 +92,7 @@ LearningApplicationBase<TInputValue,TOutputValue> //ForestAccuracy AddParameter(ParameterType_Float, "classifier.rf.acc", "Sufficient accuracy (OOB error)"); - SetParameterFloat("classifier.rf.acc", 0.01); + SetParameterFloat("classifier.rf.acc",0.01, false); SetParameterDescription("classifier.rf.acc","Sufficient accuracy (OOB error)."); diff --git a/Modules/Applications/AppClassification/include/otbTrainSVM.txx b/Modules/Applications/AppClassification/include/otbTrainSVM.txx index d36c28dd052097b98a06bd7be44e163d5dc1cf38..2893b43e4b97304f902c5adf5a0328f042c7904e 100644 --- a/Modules/Applications/AppClassification/include/otbTrainSVM.txx +++ b/Modules/Applications/AppClassification/include/otbTrainSVM.txx @@ -37,35 +37,35 @@ namespace Wrapper { AddChoice("classifier.svm.m.epssvr", "Epsilon Support Vector Regression"); AddChoice("classifier.svm.m.nusvr", "Nu Support Vector Regression"); - SetParameterString("classifier.svm.m", "epssvr"); + SetParameterString("classifier.svm.m", "epssvr", false); } else { AddChoice("classifier.svm.m.csvc", "C support vector classification"); AddChoice("classifier.svm.m.nusvc", "Nu support vector classification"); AddChoice("classifier.svm.m.oneclass", "Distribution estimation (One Class SVM)"); - SetParameterString("classifier.svm.m", "csvc"); + SetParameterString("classifier.svm.m", "csvc", false); } AddParameter(ParameterType_Choice, "classifier.svm.k", "SVM Kernel Type"); AddChoice("classifier.svm.k.linear", "Linear"); AddChoice("classifier.svm.k.rbf", "Gaussian radial basis function"); AddChoice("classifier.svm.k.poly", "Polynomial"); AddChoice("classifier.svm.k.sigmoid", "Sigmoid"); - SetParameterString("classifier.svm.k", "linear"); + SetParameterString("classifier.svm.k", "linear", false); SetParameterDescription("classifier.svm.k", "SVM Kernel Type."); AddParameter(ParameterType_Float, "classifier.svm.c", "Cost parameter C"); - SetParameterFloat("classifier.svm.c", 1.0); + SetParameterFloat("classifier.svm.c",1.0, false); SetParameterDescription( "classifier.svm.c", "SVM models have a cost parameter C (1 by default) to control the trade-off between training errors and forcing rigid margins."); AddParameter(ParameterType_Float, "classifier.svm.nu", "Parameter nu of a SVM optimization problem (NU_SVC / ONE_CLASS)"); - SetParameterFloat("classifier.svm.nu", 0.0); + SetParameterFloat("classifier.svm.nu",0.0, false); SetParameterDescription("classifier.svm.nu", "Parameter nu of a SVM optimization problem."); if (this->m_RegressionFlag) { AddParameter(ParameterType_Float, "classifier.svm.p", "Parameter epsilon of a SVM optimization problem (EPS_SVR)"); - SetParameterFloat("classifier.svm.p", 1.0); + SetParameterFloat("classifier.svm.p",1.0, false); SetParameterDescription("classifier.svm.p", "Parameter epsilon of a SVM optimization problem (EPS_SVR)."); AddParameter(ParameterType_Choice, "classifier.svm.term", "Termination criteria"); @@ -75,22 +75,22 @@ namespace Wrapper AddChoice("classifier.svm.term.all", "Stops when either iteration or epsilon criteria is true"); AddParameter(ParameterType_Float, "classifier.svm.iter", "Maximum iteration"); - SetParameterFloat("classifier.svm.iter", 1000); + SetParameterFloat("classifier.svm.iter",1000, false); SetParameterDescription("classifier.svm.iter", "Maximum number of iterations (corresponds to the termination criteria 'iter')."); AddParameter(ParameterType_Float, "classifier.svm.eps", "Epsilon accuracy threshold"); - SetParameterFloat("classifier.svm.eps", FLT_EPSILON); + SetParameterFloat("classifier.svm.eps",FLT_EPSILON, false); SetParameterDescription("classifier.svm.eps", "Epsilon accuracy (corresponds to the termination criteria 'eps')."); } AddParameter(ParameterType_Float, "classifier.svm.coef0", "Parameter coef0 of a kernel function (POLY / SIGMOID)"); - SetParameterFloat("classifier.svm.coef0", 0.0); + SetParameterFloat("classifier.svm.coef0",0.0, false); SetParameterDescription("classifier.svm.coef0", "Parameter coef0 of a kernel function (POLY / SIGMOID)."); AddParameter(ParameterType_Float, "classifier.svm.gamma", "Parameter gamma of a kernel function (POLY / RBF / SIGMOID)"); - SetParameterFloat("classifier.svm.gamma", 1.0); + SetParameterFloat("classifier.svm.gamma",1.0, false); SetParameterDescription("classifier.svm.gamma", "Parameter gamma of a kernel function (POLY / RBF / SIGMOID)."); AddParameter(ParameterType_Float, "classifier.svm.degree", "Parameter degree of a kernel function (POLY)"); - SetParameterFloat("classifier.svm.degree", 1.0); + SetParameterFloat("classifier.svm.degree",1.0, false); SetParameterDescription("classifier.svm.degree", "Parameter degree of a kernel function (POLY)."); AddParameter(ParameterType_Empty, "classifier.svm.opt", "Parameters optimization"); MandatoryOff("classifier.svm.opt"); @@ -211,15 +211,15 @@ namespace Wrapper SVMClassifier->Save(modelPath); // Update the displayed parameters in the GUI after the training process, for further use of them - SetParameterFloat("classifier.svm.c", static_cast<float> (SVMClassifier->GetOutputC())); - SetParameterFloat("classifier.svm.nu", static_cast<float> (SVMClassifier->GetOutputNu())); + SetParameterFloat("classifier.svm.c",static_cast<float> (SVMClassifier->GetOutputC()), false); + SetParameterFloat("classifier.svm.nu",static_cast<float> (SVMClassifier->GetOutputNu()), false); if (this->m_RegressionFlag) { - SetParameterFloat("classifier.svm.p", static_cast<float> (SVMClassifier->GetOutputP())); + SetParameterFloat("classifier.svm.p",static_cast<float> (SVMClassifier->GetOutputP()), false); } - SetParameterFloat("classifier.svm.coef0", static_cast<float> (SVMClassifier->GetOutputCoef0())); - SetParameterFloat("classifier.svm.gamma", static_cast<float> (SVMClassifier->GetOutputGamma())); - SetParameterFloat("classifier.svm.degree", static_cast<float> (SVMClassifier->GetOutputDegree())); + SetParameterFloat("classifier.svm.coef0",static_cast<float> (SVMClassifier->GetOutputCoef0()), false); + SetParameterFloat("classifier.svm.gamma",static_cast<float> (SVMClassifier->GetOutputGamma()), false); + SetParameterFloat("classifier.svm.degree",static_cast<float> (SVMClassifier->GetOutputDegree()), false); } } //end namespace wrapper diff --git a/Modules/Applications/AppClassification/include/otbTrainSharkRandomForests.txx b/Modules/Applications/AppClassification/include/otbTrainSharkRandomForests.txx index c9b2d565695c708da557074076fadfcaa3a6c4cd..cf9705b3089884c39a4563b021893370d4facb2c 100644 --- a/Modules/Applications/AppClassification/include/otbTrainSharkRandomForests.txx +++ b/Modules/Applications/AppClassification/include/otbTrainSharkRandomForests.txx @@ -38,7 +38,7 @@ LearningApplicationBase<TInputValue,TOutputValue> //MaxNumberOfTrees AddParameter(ParameterType_Int, "classifier.sharkrf.nbtrees", "Maximum number of trees in the forest"); - SetParameterInt("classifier.sharkrf.nbtrees", 100); + SetParameterInt("classifier.sharkrf.nbtrees",100, false); SetParameterDescription( "classifier.sharkrf.nbtrees", "The maximum number of trees in the forest. Typically, the more trees you have, the better the accuracy. " @@ -48,7 +48,7 @@ LearningApplicationBase<TInputValue,TOutputValue> //NodeSize AddParameter(ParameterType_Int, "classifier.sharkrf.nodesize", "Min size of the node for a split"); - SetParameterInt("classifier.sharkrf.nodesize", 25); + SetParameterInt("classifier.sharkrf.nodesize",25, false); SetParameterDescription( "classifier.sharkrf.nodesize", "If the number of samples in a node is smaller than this parameter, " @@ -56,7 +56,7 @@ LearningApplicationBase<TInputValue,TOutputValue> //MTry AddParameter(ParameterType_Int, "classifier.sharkrf.mtry", "Number of features tested at each node"); - SetParameterInt("classifier.sharkrf.mtry", 0); + SetParameterInt("classifier.sharkrf.mtry",0, false); SetParameterDescription( "classifier.sharkrf.mtry", "The number of features (variables) which will be tested at each node in " @@ -66,7 +66,7 @@ LearningApplicationBase<TInputValue,TOutputValue> //OOB Ratio AddParameter(ParameterType_Float, "classifier.sharkrf.oobr", "Out of bound ratio"); - SetParameterFloat("classifier.sharkrf.oobr", 0.66); + SetParameterFloat("classifier.sharkrf.oobr",0.66, false); SetParameterDescription("classifier.sharkrf.oobr", "Set the fraction of the original training dataset to use as the out of bag sample." "A good default value is 0.66. "); diff --git a/Modules/Applications/AppClassification/test/CMakeLists.txt b/Modules/Applications/AppClassification/test/CMakeLists.txt index 451c17e6392e61a2d40bc2044b208ee4ba3f5c8f..aaa2f9cfe113a49279b2247b018b651f5ff05780 100644 --- a/Modules/Applications/AppClassification/test/CMakeLists.txt +++ b/Modules/Applications/AppClassification/test/CMakeLists.txt @@ -141,6 +141,7 @@ foreach(classifier ${classifierList}) -classifier ${lclassifier} ${${lclassifier}_parameters} -io.out ${TEMP}/${OUTMODELFILE} + -sample.vfn Class -rand 121212 VALID ${valid} @@ -162,6 +163,7 @@ foreach(classifier ${classifierList}) ${${lclassifier}_parameters} -io.out ${TEMP}/OutXML1_${OUTMODELFILE} -rand 121212 + -sample.vfn Class -outxml ${TEMP}/cl${classifier}_OutXML1.xml VALID ${valid} @@ -181,7 +183,7 @@ foreach(classifier ${classifierList}) -io.vd ${INPUTDATA}/Classification/VectorData_${${lclassifier}_input}QB1${vector_input_format} -io.imstat ${INPUTDATA}/Classification/clImageStatisticsQB1${stat_input_format} -io.out ${TEMP}/OutXML2_${OUTMODELFILE} - + -sample.vfn Class VALID ${valid} ) @@ -647,6 +649,7 @@ otb_test_application(NAME apTvClTrainSVMImagesClassifierQB1_allOpt_InXML -sample.mv 100 -sample.mt 100 -sample.vtr 0.5 + -sample.vfn Class -classifier.libsvm.opt true -rand 121212 -io.out ${TEMP}/clsvmModelQB1_allOpt_InXML.svm @@ -659,6 +662,7 @@ otb_test_application(NAME apTvClTrainSVMImagesClassifierQB1_OutXML OPTIONS -io.il ${INPUTDATA}/Classification/QB_1_ortho.tif -io.vd ${INPUTDATA}/Classification/VectorData_QB1.shp -io.imstat ${INPUTDATA}/Classification/clImageStatisticsQB1.xml + -sample.vfn Class -classifier libsvm -classifier.libsvm.opt true -io.out ${TEMP}/clsvmModelQB1_OutXML.svm @@ -677,6 +681,7 @@ otb_test_application(NAME apTvClTrainSVMImagesClassifierQB1_OutXML ${INPUTDATA}/Classification/VectorData_QB2.shp ${INPUTDATA}/Classification/VectorData_QB3.shp -io.imstat ${INPUTDATA}/Classification/clImageStatisticsQB123.xml + -sample.vfn Class -classifier libsvm -classifier.libsvm.opt true -io.out ${TEMP}/clsvmModelQB123.svm @@ -693,6 +698,7 @@ otb_test_application(NAME apTvClTrainSVMImagesClassifierQB1 -io.imstat ${INPUTDATA}/Classification/clImageStatisticsQB1.xml -classifier libsvm -classifier.libsvm.opt true + -sample.vfn Class -io.out ${TEMP}/clsvmModelQB1.svm -rand 121212 VALID ${ascii_comparison} @@ -708,6 +714,7 @@ otb_test_application(NAME apTvClTrainSVMImagesClassifierQB1 ${INPUTDATA}/Classification/VectorData_QB5.shp ${INPUTDATA}/Classification/VectorData_QB6.shp -io.imstat ${INPUTDATA}/Classification/clImageStatisticsQB456.xml + -sample.vfn Class -classifier libsvm -classifier.libsvm.opt true -io.out ${TEMP}/clsvmModelQB456.svm @@ -727,6 +734,7 @@ otb_test_application(NAME apTvClTrainSVMImagesClassifierQB1_allOpt -sample.mv 100 -sample.mt 100 -sample.vtr 0.5 + -sample.vfn Class -classifier.libsvm.opt true -rand 121212 -io.out ${TEMP}/clsvmModelQB1_allOpt.svm @@ -901,7 +909,7 @@ otb_test_application(NAME apTvClSampleExtraction APP SampleExtraction OPTIONS -in ${INPUTDATA}/Classification/QB_1_ortho.tif -vec ${INPUTDATA}/Classification/apTvClSampleSelectionOut.sqlite - -field Class + -field class -out ${TEMP}/apTvClSampleExtractionOut.sqlite VALID --compare-ogr ${NOTOL} ${OTBAPP_BASELINE_FILES}/apTvClSampleExtractionOut.sqlite diff --git a/Modules/Applications/AppDimensionalityReduction/app/otbDimensionalityReduction.cxx b/Modules/Applications/AppDimensionalityReduction/app/otbDimensionalityReduction.cxx index 2359b00bb607bffa6255433f345a1588c952e26a..18d951eeda4964327c5f97fbceb5fc3cb0bd94df 100644 --- a/Modules/Applications/AppDimensionalityReduction/app/otbDimensionalityReduction.cxx +++ b/Modules/Applications/AppDimensionalityReduction/app/otbDimensionalityReduction.cxx @@ -97,8 +97,8 @@ private: SetDocSeeAlso( "\"Kernel maximum autocorrelation factor and minimum noise fraction transformations,\" IEEE Transactions on Image Processing, vol. 20, no. 3, pp. 612-624, (2011)"); - AddDocTag(Tags::DimensionReduction); AddDocTag(Tags::Filter); + AddDocTag(Tags::DimensionReduction); AddParameter(ParameterType_InputImage, "in", "Input Image"); SetParameterDescription("in", "The input image to apply dimensionality reduction."); @@ -168,6 +168,8 @@ private: AddParameter(ParameterType_OutputFilename, "outmatrix", "Transformation matrix output (text format)"); SetParameterDescription("outmatrix", "Filename to store the transformation matrix (csv format)"); MandatoryOff("outmatrix"); + DisableParameter("outmatrix"); + AddRAMParameter(); @@ -189,7 +191,7 @@ private: unsigned int nbComp = static_cast<unsigned int> (GetParameterInt("nbcomp")); if (nbComp > nbComponents) { - SetParameterInt("nbcomp", nbComponents); + SetParameterInt("nbcomp",nbComponents, false); otbAppLogINFO( << "number of selected components can't exceed image dimension : "<<nbComponents ); } @@ -199,14 +201,14 @@ private: if (this->GetParameterString("outinv").size()!= 0) { otbAppLogWARNING(<<"This application only provides the forward transform for the MAF method."); - this->SetParameterString("outinv", ""); + this->SetParameterString("outinv", "", false); } this->DisableParameter("outinv"); if (this->GetParameterString("outmatrix").size()!= 0) { otbAppLogWARNING(<<"No transformation matrix available for MAF method."); - this->SetParameterString("outmatrix", ""); + this->SetParameterString("outmatrix", "", false); } this->DisableParameter("outmatrix"); @@ -218,7 +220,7 @@ private: unsigned int nbComp = static_cast<unsigned int> (GetParameterInt("nbcomp")); if ((nbComp != 0) && (nbComp != nbComponents)) { - SetParameterInt("nbcomp", nbComponents); + SetParameterInt("nbcomp",nbComponents, false); otbAppLogINFO( << "all components are kept when using MAF filter method."); } diff --git a/Modules/Applications/AppDomainTransform/CMakeLists.txt b/Modules/Applications/AppDomainTransform/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..67bc711e4a98cb05b8138dbc8da9ccb0ee460610 --- /dev/null +++ b/Modules/Applications/AppDomainTransform/CMakeLists.txt @@ -0,0 +1,2 @@ +project(OTBAppDomainTransform) +otb_module_impl() diff --git a/Modules/Applications/AppDomainTransform/app/CMakeLists.txt b/Modules/Applications/AppDomainTransform/app/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6837a6312608fed3480b2ea570d88ee9c47d3c5f --- /dev/null +++ b/Modules/Applications/AppDomainTransform/app/CMakeLists.txt @@ -0,0 +1,4 @@ +otb_create_application( + NAME DomainTransform + SOURCES otbDomainTransform.cxx + LINK_LIBRARIES ${${otb-module}_LIBRARIES}) diff --git a/Modules/Applications/AppDomainTransform/app/otbDomainTransform.cxx b/Modules/Applications/AppDomainTransform/app/otbDomainTransform.cxx new file mode 100644 index 0000000000000000000000000000000000000000..417861fa8d36762d7fa3405d02a1c70207bb59f8 --- /dev/null +++ b/Modules/Applications/AppDomainTransform/app/otbDomainTransform.cxx @@ -0,0 +1,425 @@ +/*========================================================================= + + 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. + + =========================================================================*/ + +#include "otbWrapperApplication.h" +#include "otbWrapperApplicationFactory.h" +#include "otbWaveletImageFilter.h" +#include "otbWaveletInverseImageFilter.h" +#include "otbWaveletGenerator.h" + +#include <itkConfigure.h> +#include <itkForwardFFTImageFilter.h> +#include <itkInverseFFTImageFilter.h> +#include <itkUnaryFunctorImageFilter.h> +#include <itkFFTShiftImageFilter.h> + +#include "otbComplexToVectorImageCastFilter.h" + +namespace otb +{ +namespace Wrapper +{ +template< class TInput, class TOutput> +class ToComplexPixel +{ +public: + ToComplexPixel ( ) { }; + + ~ToComplexPixel( ) { }; + + bool operator!=( const ToComplexPixel & ) const + { + return false; + } + bool operator==( const ToComplexPixel & other ) const + { + return !(*this != other); + } + inline TOutput operator( )( const TInput & A ) const + { + return TOutput( static_cast<typename TOutput::value_type> ( A[0] ), + static_cast<typename TOutput::value_type> ( A[1] ) ); + } +}; + +class DomainTransform : public Application +{ +public: + /** Standard class typedefs. */ + typedef DomainTransform Self; + typedef Application Superclass; + typedef itk::SmartPointer<Self> Pointer; + + typedef itk::SmartPointer<const Self> ConstPointer; + typedef float InputPixelType; + typedef float OutputPixelType; + + /** Standard macro */ + itkNewMacro(Self); + + itkTypeMacro(Self, otb::Application); + +private: + DomainTransform() {} + + ~DomainTransform() ITK_OVERRIDE + { + // This is a trick to make sure fftw will cleanup its threads when application + // shared lib is released. + #if defined(ITK_USE_FFTWF) + fftwf_cleanup_threads(); + fftwf_cleanup(); + #endif + #if defined(ITK_USE_FFTWD) + fftw_cleanup_threads(); + fftw_cleanup(); + #endif + } + + void DoInit() ITK_OVERRIDE + { + SetName("DomainTransform"); + SetDescription("Domain Transform application for wavelet and fourier"); + + // Documentation + SetDocName("DomainTransform"); + SetDocLongDescription("Domain Transform application for wavelet and fourier"); + SetDocLimitations("This application is not streamed, check your system resources when processing large images"); + SetDocAuthors("OTB-Team"); + SetDocSeeAlso("otbWaveletImageFilter, otbWaveletInverseImageFilter, otbWaveletTransform"); + AddDocTag(Tags::Filter); + + // Parameters + AddParameter(ParameterType_InputImage, "in", "Input Image"); + SetParameterDescription("in", "This will take an input image to be transformed" + " image. For FFT inverse transform, it expects a complex image as two-band" + " image in which first band represent real part and second band represent" + " imaginary part."); + + AddParameter(ParameterType_OutputImage, "out", "Output Image"); + SetParameterDescription("out", "This parameter holds the output file name to" + " which transformed image will be written. This has a slightly different" + " behaviour depending on transform type. \n For Wavelet, output is a" + " single band image for both forward and inverse transform. \n For FFT" + " forward transform, output is two band image where first band represents" + " real part and second band represents imaginary part of a complex image."); + + AddParameter(ParameterType_Choice, "mode", "Mode"); + SetParameterDescription("mode", "This parameter allows one to select between" + " fft(fourier) and wavelet"); + + AddChoice("mode.fft", "FFT transform"); + SetParameterDescription("mode.fft", "FFT transform"); + + AddParameter(ParameterType_Empty, "mode.fft.shift", "Shift fft transform"); + SetParameterDescription("mode.fft.shift", "Shift transform of fft filter"); + + AddChoice("mode.wavelet", "Wavelet"); + SetParameterDescription("mode.wavelet", "Wavelet transform"); + + AddParameter(ParameterType_Choice, "mode.wavelet.form", "Select wavelet form"); + AddChoice("mode.wavelet.form.haar", "HAAR"); + AddChoice("mode.wavelet.form.db4", "DAUBECHIES4"); + AddChoice("mode.wavelet.form.db6", "DAUBECHIES6"); + AddChoice("mode.wavelet.form.db8", "DAUBECHIES8"); + AddChoice("mode.wavelet.form.db12", "DAUBECHIES12"); + AddChoice("mode.wavelet.form.db20", "DAUBECHIES20"); + AddChoice("mode.wavelet.form.sb24", "SPLINE_BIORTHOGONAL_2_4"); + AddChoice("mode.wavelet.form.sb44", "SPLINE_BIORTHOGONAL_4_4"); + AddChoice("mode.wavelet.form.sym8", "SYMLET8"); + + // Default values for mode + SetParameterString("mode", "wavelet", false); + SetParameterString("mode.wavelet.form", "haar", false); + + AddParameter(ParameterType_Choice,"direction", "Direction"); + AddChoice("direction.forward", "Forward"); + AddChoice("direction.inverse", "Inverse"); + + AddParameter(ParameterType_Int,"mode.wavelet.nlevels","Number of decomposition levels"); + SetParameterDescription("mode.wavelet.nlevels","Number of decomposition levels"); + SetDefaultParameterInt("mode.wavelet.nlevels",2); + SetMinimumParameterIntValue("mode.wavelet.nlevels",2); + + AddRAMParameter(); + + SetDocExampleParameterValue("in", "input.tif"); + SetDocExampleParameterValue("mode.wavelet.form", "haar"); + SetDocExampleParameterValue("out", "output_wavelet_haar.tif"); + } + + void DoUpdateParameters() ITK_OVERRIDE + { + + } + + void DoExecute() ITK_OVERRIDE + { + int dir = GetParameterInt("direction"); + int mode = GetParameterInt("mode"); + + if( dir != 0 && dir != 1) + { + itkExceptionMacro(<< "-dir is '" + << dir << "'." + << "It must be either 'forward' or 'inverse'"); + } + + if( mode != 0 && mode != 1) + { + itkExceptionMacro( << "mode is '" + << mode << "'." + << "It must must be either 'fft' or 'wavelet'"); + } + + if ( mode == 1) + { + int wavelet_type = GetParameterInt("mode.wavelet.form"); + unsigned int nlevels = GetParameterInt("mode.wavelet.nlevels"); + switch (wavelet_type) + { + case 0: + { + DoWaveletTransform<otb::Wavelet::HAAR>(dir, nlevels); + break; + } + case 1: + { + DoWaveletTransform<otb::Wavelet::DB4>(dir, nlevels); + break; + } + case 2: + { + DoWaveletTransform<otb::Wavelet::DB4>(dir, nlevels); + break; + } + case 3: + { + DoWaveletTransform<otb::Wavelet::DB6>(dir, nlevels); + break; + } + case 4: + { + DoWaveletTransform<otb::Wavelet::DB8>(dir, nlevels); + break; + } + case 5: + { + DoWaveletTransform<otb::Wavelet::DB12>(dir, nlevels); + break; + } + case 6: + { + DoWaveletTransform<otb::Wavelet::DB20>(dir, nlevels); + break; + } + case 7: + { + DoWaveletTransform<otb::Wavelet::SPLINE_BIORTHOGONAL_2_4 >(dir, nlevels); + break; + } + case 8: + { + DoWaveletTransform<otb::Wavelet::SPLINE_BIORTHOGONAL_4_4>(dir, nlevels); + break; + } + case 9: + { + DoWaveletTransform<otb::Wavelet::SYMLET8>(dir, nlevels); + break; + } + default: + { + itkExceptionMacro( << "Invalid wavelet type: '" << wavelet_type << "'"); + break; + } + } + } + else + { + // fft ttransform + bool shift = IsParameterEnabled( "mode.fft.shift"); + typedef otb::Image< std::complex<OutputPixelType> > ComplexOutputImageType; + + if (dir == 0 ) + { + //forward fft + typedef otb::Image<InputPixelType> TInputImage; + typedef TInputImage::Pointer TInputImagePointer; + + //get input parameter as otb::Image<InputPixelType> + TInputImagePointer inImage = GetParameterImage<TInputImage>("in"); + + //typedef itk::::ForwardFFTImageFilter over otbImage< InputPixelType > + + typedef itk::ForwardFFTImageFilter < TInputImage, ComplexOutputImageType > FFTFilter; + FFTFilter::Pointer fwdFilter = FFTFilter::New(); + fwdFilter->SetInput( inImage ); + + + //typedef VectorImage for output of UnaryFunctorImageFilter + typedef otb::VectorImage<OutputPixelType> TOutputImage; + + typedef otb::ComplexToVectorImageCastFilter< + ComplexOutputImageType, + TOutputImage > ComplexToVectorImageCastFilter; + ComplexToVectorImageCastFilter::Pointer unaryFunctorImageFilter = ComplexToVectorImageCastFilter::New(); + + if( shift) + { + otbAppLogINFO( << "Applying Shift image filter" ); + typedef itk::FFTShiftImageFilter< + FFTFilter::OutputImageType, + FFTFilter::OutputImageType > FFTShiftFilterType; + + FFTShiftFilterType::Pointer + fftShiftFilter = FFTShiftFilterType::New(); + + fftShiftFilter->SetInput( fwdFilter->GetOutput() ); + fftShiftFilter->Update(); + unaryFunctorImageFilter->SetInput(fftShiftFilter->GetOutput() ); + } + else + { + unaryFunctorImageFilter->SetInput(fwdFilter->GetOutput()); + } + + unaryFunctorImageFilter->Update(); + + //set output image + SetParameterOutputImage<TOutputImage>("out", + unaryFunctorImageFilter->GetOutput()); + } + else + { + //inverse fft + typedef otb::VectorImage<InputPixelType> TInputImage; + typedef TInputImage::Pointer TInputImagePointer; + + TInputImagePointer inImage = GetParameterImage("in"); + + // typedef TComplexImage for InverseFFTImageFilter input + // This a image type of std::complex<InputPixelType> + typedef otb::Image< + std::complex<InputPixelType>, 2 > TComplexImage; + //typedef TOutputImage for InverseFFTImageFilter output + typedef otb::Image< OutputPixelType > TOutputImage; + + // a unary functor to convert vectorimage to complex image + typedef itk::UnaryFunctorImageFilter + <TInputImage, + TComplexImage, + ToComplexPixel + <TInputImage::PixelType, + TComplexImage::PixelType> > UnaryFunctorImageFilter; + + UnaryFunctorImageFilter::Pointer + unaryFunctorImageFilter = UnaryFunctorImageFilter::New(); + + if( shift) + { + typedef itk::FFTShiftImageFilter< + TInputImage, + TInputImage > FFTShiftFilterType; + + FFTShiftFilterType::Pointer + fftShiftFilter = FFTShiftFilterType::New(); + fftShiftFilter->SetInput( inImage ); + + fftShiftFilter->Update(); + + unaryFunctorImageFilter->SetInput(fftShiftFilter->GetOutput() ); + } + else + { + unaryFunctorImageFilter->SetInput(inImage); + } + + unaryFunctorImageFilter->Update(); + + //typedef itk::::InverseFFTImageFilter over TComplexImage + typedef itk::InverseFFTImageFilter + < TComplexImage, + TOutputImage > FFTFilter; + FFTFilter::Pointer invFilter = FFTFilter::New(); + invFilter->SetInput( unaryFunctorImageFilter->GetOutput() ); + invFilter->Update(); + + //set output image + SetParameterOutputImage<TOutputImage>("out", invFilter->GetOutput()); + } + } + } + + template<otb::Wavelet::Wavelet TWaveletOperator> + void DoWaveletTransform(const int dir, + const unsigned int nlevels, + const std::string inkey = "in", + const std::string outkey = "out") + { + typedef otb::Image< InputPixelType > TInputImage; + typedef otb::Image< OutputPixelType > TOutputImage; + typedef typename TInputImage::Pointer TInputImagePointer; + + TInputImagePointer inImage = GetParameterImage<TInputImage>(inkey); + + if( dir == 0) + { + typedef otb::WaveletImageFilter< + TInputImage, + TOutputImage, + TWaveletOperator> TWaveletImageFilter; + + typedef typename + TWaveletImageFilter::Pointer + TWaveletImageFilterPointer; + TWaveletImageFilterPointer waveletImageFilter = + TWaveletImageFilter::New(); + + waveletImageFilter->SetInput(inImage); + waveletImageFilter->SetNumberOfDecompositions(nlevels); + waveletImageFilter->Update(); + SetParameterOutputImage<TOutputImage>(outkey, waveletImageFilter->GetOutput() ); + } + else + { + typedef otb::WaveletInverseImageFilter< + TInputImage, + TOutputImage, + TWaveletOperator > TWaveletImageFilter; + + typedef typename + TWaveletImageFilter::Pointer + TWaveletImageFilterPointer; + + TWaveletImageFilterPointer waveletImageFilter = + TWaveletImageFilter::New(); + + waveletImageFilter->SetInput(inImage); + waveletImageFilter->SetNumberOfDecompositions(nlevels); + waveletImageFilter->Update(); + + SetParameterOutputImage<TOutputImage>( outkey, waveletImageFilter->GetOutput() ); + } + } +}; + +} // end of namespace Wrapper +} // end of namespace otb + +OTB_APPLICATION_EXPORT(otb::Wrapper::DomainTransform) diff --git a/Modules/Applications/AppDomainTransform/otb-module.cmake b/Modules/Applications/AppDomainTransform/otb-module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..7346a4367b9c898ce8a654a217cf05beaeb529df --- /dev/null +++ b/Modules/Applications/AppDomainTransform/otb-module.cmake @@ -0,0 +1,15 @@ +set(DOCUMENTATION "Application to perform Wavelet and Fourier transform. This application is not streamed") + +otb_module(OTBAppDomainTransform +DEPENDS + OTBWavelet + OTBApplicationEngine + + TEST_DEPENDS + OTBTestKernel + OTBCommandLine + + DESCRIPTION + "${DOCUMENTATION}" +) + diff --git a/Modules/Applications/AppDomainTransform/test/CMakeLists.txt b/Modules/Applications/AppDomainTransform/test/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..593cf6f458cd2fb143bc7d916a0288efcbc0446e --- /dev/null +++ b/Modules/Applications/AppDomainTransform/test/CMakeLists.txt @@ -0,0 +1,38 @@ +otb_module_test() +otb_test_application(NAME apTvDomainTransform_wav_db20_fwd + APP DomainTransform + OPTIONS -in ${INPUTDATA}/QB_Toulouse_Ortho_PAN.tif + -mode wavelet + -mode.wavelet.form db20 + -mode.wavelet.nlevels 2 + -direction forward + -out ${TEMP}/apTvDomainTransform_wav_db20_fwd.tif + ) + +otb_test_application(NAME apTvDomainTransform_wav_haar_inv + APP DomainTransform + OPTIONS -in ${INPUTDATA}/QB_Toulouse_Ortho_PAN.tif + -mode wavelet + -mode.wavelet.form haar + -direction inverse + -out ${TEMP}/apTvDomainTransform_wav_haar_inv.tif + ) + +otb_test_application(NAME apTvDomainTransform_fft_shift_fwd + APP DomainTransform + OPTIONS -in ${INPUTDATA}/QB_Toulouse_Ortho_PAN.tif + -mode fft + -mode.fft.shift true + -direction forward + -out ${TEMP}/apTvDomainTransform_fft_shift_fwd.tif + ) + + +otb_test_application(NAME apTvDomainTransform_fft_inv + APP DomainTransform + OPTIONS -in ${INPUTDATA}/QB_Toulouse_Ortho_PAN.tif + -mode fft + -direction inverse + -out ${TEMP}/apTvDomainTransform_fft_shift_inv.tif + ) + diff --git a/Modules/Applications/AppEdge/app/otbEdgeExtraction.cxx b/Modules/Applications/AppEdge/app/otbEdgeExtraction.cxx index 444749182f0b0c937d2e3a7ee6f36bd7df1c0097..b2a5d319961e072f219aa3be28531593f3ff6df0 100644 --- a/Modules/Applications/AppEdge/app/otbEdgeExtraction.cxx +++ b/Modules/Applications/AppEdge/app/otbEdgeExtraction.cxx @@ -70,8 +70,8 @@ SetDocLimitations("None"); SetDocAuthors("OTB-Team"); SetDocSeeAlso("otb class"); -AddDocTag("Edge"); AddDocTag(Tags::FeatureExtraction); +AddDocTag("Edge"); AddParameter(ParameterType_InputImage, "in", "Input Image"); SetParameterDescription("in", "The input image to compute the features on."); diff --git a/Modules/Applications/AppFiltering/app/otbDespeckle.cxx b/Modules/Applications/AppFiltering/app/otbDespeckle.cxx index 0fde206f26a6a2577acfb4fa32bf37dae162631b..79a62586c9fa84d658256001c2d36036ab92618f 100644 --- a/Modules/Applications/AppFiltering/app/otbDespeckle.cxx +++ b/Modules/Applications/AppFiltering/app/otbDespeckle.cxx @@ -63,8 +63,8 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); - AddDocTag(Tags::SAR); AddDocTag(Tags::Filter); + AddDocTag(Tags::SAR); AddParameter(ParameterType_InputImage, "in", "Input Image"); SetParameterDescription("in", "Input image."); diff --git a/Modules/Applications/AppFiltering/app/otbSmoothing.cxx b/Modules/Applications/AppFiltering/app/otbSmoothing.cxx index 18cd825f50212ee39e70be300824861e15503d23..14e6be72943071e6dc9f8d92299e70ec1209d98e 100644 --- a/Modules/Applications/AppFiltering/app/otbSmoothing.cxx +++ b/Modules/Applications/AppFiltering/app/otbSmoothing.cxx @@ -103,7 +103,7 @@ private: SetDefaultParameterInt("type.anidif.nbiter", 10); SetDefaultParameterInt("type.anidif.conductance", 1.); - SetParameterString("type", "anidif"); + SetParameterString("type", "anidif", false); // Doc example parameter settings SetExampleComment("Image smoothing using a mean filter.", 0); diff --git a/Modules/Applications/AppFusion/app/otbBundleToPerfectSensor.cxx b/Modules/Applications/AppFusion/app/otbBundleToPerfectSensor.cxx index 2f31cd6344d4c8a76db4436b4303e1aed42af98d..48d0c9c0a8f8cd3c133d07ab30ea367e95aaa088 100644 --- a/Modules/Applications/AppFusion/app/otbBundleToPerfectSensor.cxx +++ b/Modules/Applications/AppFusion/app/otbBundleToPerfectSensor.cxx @@ -16,25 +16,14 @@ =========================================================================*/ #include "otbWrapperApplicationFactory.h" +#include "otbWrapperCompositeApplication.h" -#include "otbMultiToMonoChannelExtractROI.h" -#include "otbGenericRSResampleImageFilter.h" -#include "otbGridResampleImageFilter.h" -#include "otbImportGeoInformationImageFilter.h" -#include "otbBCOInterpolateImageFunction.h" -#include "otbSimpleRcsPanSharpeningFusionImageFilter.h" -#include "itkFixedArray.h" - -// Elevation handler -#include "otbWrapperElevationParametersHandler.h" - -#include "otbPleiadesPToXSAffineTransformCalculator.h" namespace otb { namespace Wrapper { -class BundleToPerfectSensor : public Application +class BundleToPerfectSensor : public CompositeApplication { public: /** Standard class typedefs. */ @@ -46,7 +35,7 @@ public: /** Standard macro */ itkNewMacro(Self); - itkTypeMacro(BundleToPerfectSensor, otb::Application); + itkTypeMacro(BundleToPerfectSensor, otb::Wrapper::CompositeApplication); private: @@ -65,38 +54,27 @@ private: AddDocTag(Tags::Geometry); AddDocTag(Tags::Pansharpening); - AddParameter(ParameterType_InputImage, "inp", "Input PAN Image"); - SetParameterDescription("inp"," Input panchromatic image."); - AddParameter(ParameterType_InputImage, "inxs", "Input XS Image"); - SetParameterDescription("inxs"," Input XS image."); - - AddParameter(ParameterType_OutputImage, "out", "Output image"); - SetParameterDescription("out"," Output image."); - - // Elevation - ElevationParametersHandler::AddElevationParameters(this, "elev"); - - // Superposition mode - AddParameter(ParameterType_Choice,"mode", "Mode"); - SetParameterDescription("mode", "Superimposition mode"); - - AddChoice("mode.default", "Default mode"); - SetParameterDescription("mode.default", "Default superimposition mode : " - "uses any projection reference or sensor model found in the images"); - - AddChoice("mode.phr", "Pleiades mode"); - SetParameterDescription("mode.phr", "Pleiades superimposition mode, " - "designed for the case of a P+XS bundle in SENSOR geometry. It uses" - " a simple transform on the XS image : a scaling and a residual " - "translation."); + ClearApplications(); + AddApplication("Superimpose", "superimpose", "Reproject XS onto Pan"); + AddApplication("Pansharpening", "pansharp", "Fusion of XS and Pan"); + + ShareParameter("inp","superimpose.inr","Input PAN Image","Input panchromatic image."); + ShareParameter("inxs","superimpose.inm","Input XS Image","Input XS image."); + ShareParameter("out","pansharp.out"); + ShareParameter("elev","superimpose.elev"); + ShareParameter("mode","superimpose.mode"); + ShareParameter("lms","superimpose.lms", + "Spacing of the deformation field", + "Spacing of the deformation field. Default is 10 times the PAN image spacing."); + ShareParameter("fv","superimpose.fv"); + ShareParameter("ram","superimpose.ram"); + + Connect("pansharp.inp","superimpose.inr"); + Connect("pansharp.ram","superimpose.ram"); + + GetInternalApplication("superimpose")->SetParameterString("interpolator","bco", false); + GetInternalApplication("pansharp")->SetParameterString("method","rcs", false); - AddParameter(ParameterType_Float, "lms", "Spacing of the deformation field"); - SetParameterDescription("lms"," Spacing of the deformation field. Default is 10 times the PAN image spacing."); - - AddRAMParameter(); - - MandatoryOff("lms"); - // Doc example parameter settings SetDocExampleParameterValue("inp", "QB_Toulouse_Ortho_PAN.tif"); SetDocExampleParameterValue("inxs", "QB_Toulouse_Ortho_XS.tif"); @@ -106,150 +84,19 @@ private: void DoUpdateParameters() ITK_OVERRIDE { - if(!HasUserValue("mode") && HasValue("inp") && HasValue("inxs") && otb::PleiadesPToXSAffineTransformCalculator::CanCompute(GetParameterImage("inp"),GetParameterImage("inxs"))) - { - otbAppLogWARNING("Forcing PHR mode with PHR data. You need to add \"-mode default\" to force the default mode with PHR images."); - SetParameterString("mode","phr"); - } + UpdateInternalParameters("superimpose"); } void DoExecute() ITK_OVERRIDE { - FloatVectorImageType* panchroV = GetParameterImage("inp"); - FloatVectorImageType* xs = GetParameterImage("inxs"); - - if ( panchroV->GetNumberOfComponentsPerPixel() != 1 ) - { - itkExceptionMacro(<< "The panchromatic image must be a single channel image") - } - - // Transform the PAN image to otb::Image - typedef otb::Image<FloatVectorImageType::InternalPixelType> InternalImageType; - typedef otb::MultiToMonoChannelExtractROI<float,float> ExtractFilterType; - - ExtractFilterType::Pointer channelSelect = ExtractFilterType::New(); - m_Ref.push_back(channelSelect.GetPointer()); - channelSelect->SetChannel(1); - channelSelect->SetInput(panchroV); - channelSelect->UpdateOutputInformation(); - InternalImageType::Pointer panchro = channelSelect->GetOutput(); - - typedef otb::BCOInterpolateImageFunction<FloatVectorImageType> InterpolatorType; - typedef otb::GenericRSResampleImageFilter<FloatVectorImageType, FloatVectorImageType> ResamplerType; - typedef otb::GridResampleImageFilter<FloatVectorImageType, FloatVectorImageType> BasicResamplerType; - typedef otb::ImportGeoInformationImageFilter<FloatVectorImageType,InternalImageType> ImportGeoInformationFilterType; - typedef otb::SimpleRcsPanSharpeningFusionImageFilter<InternalImageType, FloatVectorImageType, FloatVectorImageType> FusionFilterType; + ExecuteInternal("superimpose"); - // Resample filter - ResamplerType::Pointer resampler = ResamplerType::New(); - m_Ref.push_back(resampler.GetPointer()); - - BasicResamplerType::Pointer basicResampler = BasicResamplerType::New(); - m_Ref.push_back(basicResampler.GetPointer()); - - ImportGeoInformationFilterType::Pointer geoImport = ImportGeoInformationFilterType::New(); - m_Ref.push_back(geoImport.GetPointer()); - - InterpolatorType::Pointer interpolator = InterpolatorType::New(); - resampler->SetInterpolator(interpolator); - basicResampler->SetInterpolator(interpolator); - - // Fusion filter - FusionFilterType::Pointer fusionFilter = FusionFilterType::New(); - m_Ref.push_back(fusionFilter.GetPointer()); - fusionFilter->SetPanInput(panchro); - - // Setup the DEM Handler - otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev"); - - // Set up output image information - FloatVectorImageType::SpacingType spacing = panchro->GetSpacing(); - FloatVectorImageType::IndexType start = panchro->GetLargestPossibleRegion().GetIndex(); - FloatVectorImageType::SizeType size = panchro->GetLargestPossibleRegion().GetSize(); - FloatVectorImageType::PointType origin = panchro->GetOrigin(); - - FloatVectorImageType::PixelType defaultValue; - itk::NumericTraits<FloatVectorImageType::PixelType>::SetLength(defaultValue, xs->GetNumberOfComponentsPerPixel()); + GetInternalApplication("pansharp")->SetParameterInputImage("inxs", + GetInternalApplication("superimpose")->GetParameterOutputImage("out")); - if(GetParameterString("mode") == "default") - { - otbAppLogINFO("Using the default mode"); - if(IsParameterEnabled("lms") && HasValue("lms")) - { - double defScalarSpacing = GetParameterFloat("lms"); - otbAppLogINFO(<< "Generating coarse deformation field (spacing="<<defScalarSpacing<<")" << std::endl); - FloatVectorImageType::SpacingType defSpacing; - - defSpacing[0] = defScalarSpacing; - defSpacing[1] = defScalarSpacing; - - resampler->SetDisplacementFieldSpacing(defSpacing); - } - else - { - FloatVectorImageType::SpacingType defSpacing; - defSpacing[0]=10*spacing[0]; - defSpacing[1]=10*spacing[1]; - resampler->SetDisplacementFieldSpacing(defSpacing); - } - - resampler->SetInput(xs); - resampler->SetOutputOrigin(origin); - resampler->SetOutputSpacing(spacing); - resampler->SetOutputSize(size); - resampler->SetOutputStartIndex(start); - resampler->SetOutputKeywordList(panchro->GetImageKeywordlist()); - resampler->SetOutputProjectionRef(panchro->GetProjectionRef()); - resampler->SetEdgePaddingValue(defaultValue); - fusionFilter->SetXsInput(resampler->GetOutput()); - } - else if(GetParameterString("mode")=="phr") - { - otbAppLogINFO("Using the PHR mode"); - - otb::PleiadesPToXSAffineTransformCalculator::TransformType::OffsetType offset - = otb::PleiadesPToXSAffineTransformCalculator::ComputeOffset(GetParameterImage("inp"), - GetParameterImage("inxs")); - - origin+=offset; - origin[0]=origin[0]/4; - origin[1]=origin[1]/4; - - basicResampler->SetOutputOrigin(origin); - basicResampler->SetInput(xs); - basicResampler->SetOutputOrigin(origin); - - FloatVectorImageType::SpacingType xsSpacing = GetParameterImage("inxs")->GetSpacing(); - xsSpacing*=0.25; - - basicResampler->SetOutputSpacing(xsSpacing); - basicResampler->SetOutputSize(size); - basicResampler->SetOutputStartIndex(start); - basicResampler->SetEdgePaddingValue(defaultValue); - - geoImport->SetInput(basicResampler->GetOutput()); - geoImport->SetSource(panchro); - - fusionFilter->SetXsInput(geoImport->GetOutput()); - - // Set the profRef & Keywordlist from Pan into the resampled XS image - basicResampler->UpdateOutputInformation(); - itk::MetaDataDictionary& dict = basicResampler->GetOutput()->GetMetaDataDictionary(); - itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey, - panchro->GetProjectionRef()); - itk::EncapsulateMetaData<ImageKeywordlist>(dict, MetaDataKey::OSSIMKeywordlistKey, - panchro->GetImageKeywordlist()); - } - else - { - otbAppLogWARNING("Unknown mode"); - } - - SetParameterOutputImage("out", fusionFilter->GetOutput()); + ExecuteInternal("pansharp"); } - std::vector<itk::ProcessObject::Pointer> m_Ref; - }; diff --git a/Modules/Applications/AppFusion/otb-module.cmake b/Modules/Applications/AppFusion/otb-module.cmake index 54fe75ccac06953703f04292cf71acadd3a4939c..e09047b0b4b7372b86c007a6b70532d6b6f4e691 100644 --- a/Modules/Applications/AppFusion/otb-module.cmake +++ b/Modules/Applications/AppFusion/otb-module.cmake @@ -10,6 +10,7 @@ otb_module(OTBAppFusion OTBInterpolation TEST_DEPENDS + OTBAppProjection OTBTestKernel OTBCommandLine diff --git a/Modules/Applications/AppHyperspectral/app/otbHyperspectralUnmixing.cxx b/Modules/Applications/AppHyperspectral/app/otbHyperspectralUnmixing.cxx index 50c8c11dcaa5b2ccf27a0d123d2db9dcb0b3c08f..403368ec40fcb2f466ec2938d4513ffed9847fc2 100644 --- a/Modules/Applications/AppHyperspectral/app/otbHyperspectralUnmixing.cxx +++ b/Modules/Applications/AppHyperspectral/app/otbHyperspectralUnmixing.cxx @@ -97,6 +97,7 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso("VertexComponentAnalysis"); + AddDocTag("Miscellaneous"); AddDocTag(Tags::Hyperspectral); AddParameter(ParameterType_InputImage, "in", "Input Image Filename"); @@ -125,7 +126,7 @@ private: AddChoice("ua.mdmdnmf", "MDMDNMF"); SetParameterDescription("ua.mdmdnmf", "Minimum Dispersion Constrained Non Negative Matrix Factorization"); - SetParameterString("ua", "ucls"); + SetParameterString("ua", "ucls", false); // Doc example parameter settings SetDocExampleParameterValue("in", "cupriteSubHsi.tif"); SetDocExampleParameterValue("ie", "cupriteEndmembers.tif"); diff --git a/Modules/Applications/AppHyperspectral/app/otbVertexComponentAnalysis.cxx b/Modules/Applications/AppHyperspectral/app/otbVertexComponentAnalysis.cxx index cc729585ce5ae1ec0a16af75048f930f15f12973..214c77f4e458bbec05dc6f855821bb12c541c73a 100644 --- a/Modules/Applications/AppHyperspectral/app/otbVertexComponentAnalysis.cxx +++ b/Modules/Applications/AppHyperspectral/app/otbVertexComponentAnalysis.cxx @@ -56,6 +56,7 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); + AddDocTag("Miscellaneous"); AddDocTag(Tags::Hyperspectral); AddDocTag(Tags::DimensionReduction); @@ -64,7 +65,7 @@ private: AddParameter(ParameterType_Int, "ne", "Number of endmembers"); SetParameterDescription("ne","The number of endmembers to extract from the data cube"); - SetParameterInt("ne", 1); + SetParameterInt("ne",1, false); MandatoryOn("ne"); AddParameter(ParameterType_OutputImage, "outendm", "Output Endmembers"); diff --git a/Modules/Applications/AppImageUtils/app/otbColorMapping.cxx b/Modules/Applications/AppImageUtils/app/otbColorMapping.cxx index d4968e35a4a331bb78ef6d169c39617bb91ca0ef..cd1d0c4e8911de9f5fe253a56b79ba93709dd549 100644 --- a/Modules/Applications/AppImageUtils/app/otbColorMapping.cxx +++ b/Modules/Applications/AppImageUtils/app/otbColorMapping.cxx @@ -265,10 +265,10 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso("ImageSVMClassifier"); - AddDocTag("Utilities"); AddDocTag(Tags::Manip); AddDocTag(Tags::Meta); AddDocTag(Tags::Learning); + AddDocTag("Utilities"); // Build lut map @@ -342,11 +342,11 @@ private: AddParameter(ParameterType_Float,"method.continuous.min","Mapping range lower value"); SetParameterDescription("method.continuous.min","Set the lower input value of the mapping range."); - SetParameterFloat("method.continuous.min", 0.); + SetParameterFloat("method.continuous.min",0., false); AddParameter(ParameterType_Float,"method.continuous.max","Mapping range higher value"); SetParameterDescription("method.continuous.max","Set the higher input value of the mapping range."); - SetParameterFloat("method.continuous.max", 255.); + SetParameterFloat("method.continuous.max",255., false); // Optimal LUT AddChoice("method.optimal","Compute an optimized look-up table"); @@ -355,7 +355,7 @@ private: "[color to label] Searching all the colors present in the image to compute a continuous label list"); AddParameter(ParameterType_Int,"method.optimal.background", "Background label"); SetParameterDescription("method.optimal.background","Value of the background label"); - SetParameterInt("method.optimal.background", 0); + SetParameterInt("method.optimal.background",0, false); SetMinimumParameterIntValue("method.optimal.background", 0); SetMaximumParameterIntValue("method.optimal.background", 255); @@ -367,18 +367,18 @@ private: AddParameter(ParameterType_Float, "method.image.nodatavalue", "NoData value"); SetParameterDescription("method.image.nodatavalue","NoData value for each channel of the support image, which will not be handled in the LUT estimation. If NOT checked, ALL the pixel values of the support image will be handled in the LUT estimation."); MandatoryOff("method.image.nodatavalue"); - SetParameterFloat("method.image.nodatavalue", 0); + SetParameterFloat("method.image.nodatavalue",0, false); DisableParameter("method.image.nodatavalue"); AddParameter(ParameterType_Int, "method.image.low", "lower quantile"); SetParameterDescription("method.image.low","lower quantile for image normalization"); MandatoryOff("method.image.low"); - SetParameterInt("method.image.low", 2); + SetParameterInt("method.image.low",2, false); SetMinimumParameterIntValue("method.image.low", 0); SetMaximumParameterIntValue("method.image.low", 100); AddParameter(ParameterType_Int, "method.image.up", "upper quantile"); SetParameterDescription("method.image.up","upper quantile for image normalization"); MandatoryOff("method.image.up"); - SetParameterInt("method.image.up", 2); + SetParameterInt("method.image.up",2, false); SetMinimumParameterIntValue("method.image.up", 0); SetMaximumParameterIntValue("method.image.up", 100); @@ -400,7 +400,7 @@ private: if (GetParameterInt("method")==1 || GetParameterInt("method")==3) { otbAppLogWARNING("Override method : use optimal"); - SetParameterInt("method", 2); + SetParameterInt("method",2, false); } } } diff --git a/Modules/Applications/AppImageUtils/app/otbCompareImages.cxx b/Modules/Applications/AppImageUtils/app/otbCompareImages.cxx index f08ac34ae20f07aa8847b34de459cf277746e158..b7d34b93bbb52d6b1733e1fbbba6fa9e94acac7a 100644 --- a/Modules/Applications/AppImageUtils/app/otbCompareImages.cxx +++ b/Modules/Applications/AppImageUtils/app/otbCompareImages.cxx @@ -58,7 +58,9 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso("BandMath application, ImageStatistics"); + AddDocTag("Miscellaneous"); AddDocTag("Statistics"); + AddDocTag(Tags::Manip); AddParameter(ParameterType_Group, "ref", "Reference image properties"); AddParameter(ParameterType_InputImage, "ref.in", "Reference image"); @@ -218,10 +220,10 @@ private: otbAppLogINFO( << "PSNR: " << m_CompareFilter->GetPSNR() ); otbAppLogINFO( << "Number of Pixel different: " << m_CompareFilter->GetDiffCount() ); - SetParameterFloat( "mse", m_CompareFilter->GetMSE() ); - SetParameterFloat( "mae", m_CompareFilter->GetMAE() ); - SetParameterFloat( "psnr", m_CompareFilter->GetPSNR() ); - SetParameterFloat( "count", m_CompareFilter->GetDiffCount() ); + SetParameterFloat( "mse",m_CompareFilter->GetMSE() , false); + SetParameterFloat( "mae",m_CompareFilter->GetMAE() , false); + SetParameterFloat( "psnr",m_CompareFilter->GetPSNR() , false); + SetParameterFloat( "count",m_CompareFilter->GetDiffCount() , false); } diff --git a/Modules/Applications/AppImageUtils/app/otbConvert.cxx b/Modules/Applications/AppImageUtils/app/otbConvert.cxx index 7f7d5651dc67b13dba29bed9d68bb99379c7e35a..085fe5db06158ac110424666d2100b4b32fbd546 100644 --- a/Modules/Applications/AppImageUtils/app/otbConvert.cxx +++ b/Modules/Applications/AppImageUtils/app/otbConvert.cxx @@ -86,9 +86,10 @@ private: SetDocLimitations("None"); SetDocAuthors("OTB-Team"); SetDocSeeAlso("Rescale"); + + AddDocTag(Tags::Manip); AddDocTag("Conversion"); AddDocTag("Image Dynamic"); - AddDocTag(Tags::Manip); AddParameter(ParameterType_InputImage, "in", "Input image"); SetParameterDescription("in", "Input image"); @@ -98,7 +99,7 @@ private: AddChoice("type.none", "None"); AddChoice("type.linear", "Linear"); AddChoice("type.log2", "Log2"); - SetParameterString("type", "none"); + SetParameterString("type", "none", false); AddParameter(ParameterType_Float,"type.linear.gamma","Gamma correction factor"); SetParameterDescription("type.linear.gamma","Gamma correction factor"); diff --git a/Modules/Applications/AppImageUtils/app/otbDownloadSRTMTiles.cxx b/Modules/Applications/AppImageUtils/app/otbDownloadSRTMTiles.cxx index b036c0f8071f6775d29f0ed00c1d61923c8e29cf..3ea74d4b77ef14152cd76b37b4345f7f5a64497e 100644 --- a/Modules/Applications/AppImageUtils/app/otbDownloadSRTMTiles.cxx +++ b/Modules/Applications/AppImageUtils/app/otbDownloadSRTMTiles.cxx @@ -103,8 +103,8 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); - AddDocTag("Utilities"); AddDocTag(Tags::Manip); + AddDocTag("Utilities"); AddParameter(ParameterType_InputImageList, "il", "Input images list"); SetParameterDescription("il", "The list of images on which you want to determine corresponding SRTM tiles."); diff --git a/Modules/Applications/AppImageUtils/app/otbExtractROI.cxx b/Modules/Applications/AppImageUtils/app/otbExtractROI.cxx index 8a3bc91d200271f629acfb2e5341a8bdb35c104a..4983ff4dc1f26bf7b00549e38b0f1049fe5fa83a 100644 --- a/Modules/Applications/AppImageUtils/app/otbExtractROI.cxx +++ b/Modules/Applications/AppImageUtils/app/otbExtractROI.cxx @@ -126,8 +126,8 @@ private: if (!HasUserValue("sizex") && !HasUserValue("sizey") ) { - SetParameterInt("sizex", largestRegion.GetSize()[0]); - SetParameterInt("sizey", largestRegion.GetSize()[1]); + SetParameterInt("sizex",largestRegion.GetSize()[0], false); + SetParameterInt("sizey",largestRegion.GetSize()[1], false); } unsigned int nbComponents = inImage->GetNumberOfComponentsPerPixel(); @@ -164,8 +164,8 @@ private: if(!this->CropRegionOfInterest()) { // Put the index of the ROI to origin and try to crop again - SetParameterInt("startx", 0); - SetParameterInt("starty", 0); + SetParameterInt("startx",0, false); + SetParameterInt("starty",0, false); this->CropRegionOfInterest(); } } @@ -209,10 +209,10 @@ private: { if (region.Crop(GetParameterImage("in")->GetLargestPossibleRegion())) { - SetParameterInt("sizex", region.GetSize(0)); - SetParameterInt("sizey", region.GetSize(1)); - SetParameterInt("startx", region.GetIndex(0)); - SetParameterInt("starty", region.GetIndex(1)); + SetParameterInt("sizex",region.GetSize(0), HasUserValue("sizex")); + SetParameterInt("sizey",region.GetSize(1), HasUserValue("sizey")); + SetParameterInt("startx",region.GetIndex(0), HasUserValue("startx")); + SetParameterInt("starty",region.GetIndex(1), HasUserValue("starty")); return true; } } diff --git a/Modules/Applications/AppImageUtils/app/otbManageNoData.cxx b/Modules/Applications/AppImageUtils/app/otbManageNoData.cxx index ba5231c409bc9e8f05fdda3caf5a8a5f6f122653..5611b960aa02194370a4d11d684e857b4f5c2742 100644 --- a/Modules/Applications/AppImageUtils/app/otbManageNoData.cxx +++ b/Modules/Applications/AppImageUtils/app/otbManageNoData.cxx @@ -64,10 +64,11 @@ private: SetDocLongDescription("This application has two modes. The first allows building a mask of no-data pixels from the no-data flags read from the image file. The second allows updating the change the no-data value of an image (pixels value and metadata). This last mode also allows replacing NaN in images with a proper no-data value. To do so, one should activate the NaN is no-data option."); SetDocLimitations("None"); SetDocAuthors("OTB-Team"); - SetDocSeeAlso("BanMath"); + SetDocSeeAlso("BandMath"); + + AddDocTag(Tags::Manip); AddDocTag("Conversion"); AddDocTag("Image Dynamic"); - AddDocTag(Tags::Manip); AddParameter(ParameterType_InputImage, "in", "Input image"); SetParameterDescription("in", "Input image"); @@ -108,7 +109,7 @@ private: SetParameterDescription("mode.apply.ndval","No Data value used according to the mask image"); SetDefaultParameterFloat("mode.apply.ndval", 0.0); - SetParameterString("mode","buildmask"); + SetParameterString("mode","buildmask", false); AddRAMParameter(); diff --git a/Modules/Applications/AppImageUtils/app/otbMultiResolutionPyramid.cxx b/Modules/Applications/AppImageUtils/app/otbMultiResolutionPyramid.cxx index 4e7ce61476dd258c9a6e024504536165a7fddd82..9fd36595d32b18c24f100056df4b94997375edb4 100644 --- a/Modules/Applications/AppImageUtils/app/otbMultiResolutionPyramid.cxx +++ b/Modules/Applications/AppImageUtils/app/otbMultiResolutionPyramid.cxx @@ -67,8 +67,8 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); + AddDocTag(Tags::Manip); AddDocTag("Conversion"); - AddDocTag(Tags::Manip); AddDocTag(Tags::Multi); AddDocTag("Util"); diff --git a/Modules/Applications/AppImageUtils/app/otbPixelValue.cxx b/Modules/Applications/AppImageUtils/app/otbPixelValue.cxx index 35a860d0d4473d1962879d4bb9951ac36a229025..ed170b21e63896ea5562165d5fe08bbf93444086 100644 --- a/Modules/Applications/AppImageUtils/app/otbPixelValue.cxx +++ b/Modules/Applications/AppImageUtils/app/otbPixelValue.cxx @@ -55,6 +55,7 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); + AddDocTag("Miscellaneous"); AddDocTag("Utilities"); AddDocTag("Coordinates"); AddDocTag("Raster"); @@ -146,7 +147,7 @@ private: std::ostringstream oss; oss << extractor->GetOutput()->GetPixel(id)<<std::endl; - SetParameterString("value", oss.str()); + SetParameterString("value", oss.str(), false); //Display image information in the dedicated logger otbAppLogINFO( << oss.str() ); diff --git a/Modules/Applications/AppImageUtils/app/otbQuicklook.cxx b/Modules/Applications/AppImageUtils/app/otbQuicklook.cxx index 7c3677041f526f47dbad77da25e6b96344ebdd3a..03d9ef4e2ac0d73c4533a20bc2aca1badc44d092 100644 --- a/Modules/Applications/AppImageUtils/app/otbQuicklook.cxx +++ b/Modules/Applications/AppImageUtils/app/otbQuicklook.cxx @@ -141,8 +141,8 @@ private: if (!HasUserValue("rsx") && !HasUserValue("rsy") ) { - SetParameterInt("rsx", largestRegion.GetSize()[0]); - SetParameterInt("rsy", largestRegion.GetSize()[1]); + SetParameterInt("rsx",largestRegion.GetSize()[0], false); + SetParameterInt("rsy",largestRegion.GetSize()[1], false); } // Put the limit of the index and the size relative the image @@ -163,8 +163,8 @@ private: if(!this->CropRegionOfInterest()) { // Put the index of the ROI to origin and try to crop again - SetParameterInt("rox", 0); - SetParameterInt("roy", 0); + SetParameterInt("rox",0, false); + SetParameterInt("roy",0, false); this->CropRegionOfInterest(); } } @@ -183,10 +183,10 @@ bool CropRegionOfInterest() { if (region.Crop(GetParameterImage("in")->GetLargestPossibleRegion())) { - SetParameterInt("rsx", region.GetSize(0)); - SetParameterInt("rsy", region.GetSize(1)); - SetParameterInt("rox", region.GetIndex(0)); - SetParameterInt("roy", region.GetIndex(1)); + SetParameterInt( "rsx", region.GetSize(0), HasUserValue("rsx") ); + SetParameterInt( "rsy", region.GetSize(1), HasUserValue("rsy") ); + SetParameterInt( "rox", region.GetIndex(0), HasUserValue("rox") ); + SetParameterInt( "roy", region.GetIndex(1), HasUserValue("roy") ); return true; } } diff --git a/Modules/Applications/AppImageUtils/app/otbReadImageInfo.cxx b/Modules/Applications/AppImageUtils/app/otbReadImageInfo.cxx index 0bb1633de361d4487fa1b0d834a6c512cc9f545e..8c78a284ec289951807ea4f064149b1cc6a1fde2 100644 --- a/Modules/Applications/AppImageUtils/app/otbReadImageInfo.cxx +++ b/Modules/Applications/AppImageUtils/app/otbReadImageInfo.cxx @@ -57,8 +57,8 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); - AddDocTag("Utilities"); AddDocTag(Tags::Manip); + AddDocTag("Utilities"); AddDocTag(Tags::Meta); AddParameter(ParameterType_InputImage, "in", "Input Image"); @@ -262,7 +262,7 @@ private: ImageMetadataInterfaceType::Pointer metadataInterface = ImageMetadataInterfaceFactory::CreateIMI(inImage->GetMetaDataDictionary()); //Get number of bands - SetParameterInt("numberbands", inImage->GetNumberOfComponentsPerPixel()); + SetParameterInt("numberbands",inImage->GetNumberOfComponentsPerPixel(), false); ossOutput << "\tNumber of bands : " << GetParameterInt("numberbands") << std::endl; std::vector<bool> noDataValueAvailable; bool ret = itk::ExposeMetaData<std::vector<bool> >(inImage->GetMetaDataDictionary(),MetaDataKey::NoDataValueAvailable,noDataValueAvailable); @@ -293,26 +293,26 @@ private: ossOutput<<std::endl; //Get image size - SetParameterInt("indexx", inImage->GetLargestPossibleRegion().GetIndex()[0]); - SetParameterInt("indexy", inImage->GetLargestPossibleRegion().GetIndex()[1]); + SetParameterInt("indexx",inImage->GetLargestPossibleRegion().GetIndex()[0], false); + SetParameterInt("indexy",inImage->GetLargestPossibleRegion().GetIndex()[1], false); ossOutput << "\tStart index : [" << GetParameterInt("indexx") << "," << GetParameterInt("indexy") << "]" << std::endl; //Get image size - SetParameterInt("sizex", inImage->GetLargestPossibleRegion().GetSize()[0]); - SetParameterInt("sizey", inImage->GetLargestPossibleRegion().GetSize()[1]); + SetParameterInt("sizex",inImage->GetLargestPossibleRegion().GetSize()[0], false); + SetParameterInt("sizey",inImage->GetLargestPossibleRegion().GetSize()[1], false); ossOutput << "\tSize : [" << GetParameterInt("sizex") << "," << GetParameterInt("sizey") << "]" << std::endl; //Get image origin - SetParameterFloat("originx", inImage->GetOrigin()[0]); - SetParameterFloat("originy", inImage->GetOrigin()[1]); + SetParameterFloat("originx",inImage->GetOrigin()[0], false); + SetParameterFloat("originy",inImage->GetOrigin()[1], false); ossOutput << "\tOrigin : [" << GetParameterFloat("originx") << "," << GetParameterFloat("originy") << "]" << std::endl; //Get image spacing - SetParameterFloat("spacingx", inImage->GetSpacing()[0]); - SetParameterFloat("spacingy", inImage->GetSpacing()[1]); + SetParameterFloat("spacingx",inImage->GetSpacing()[0], false); + SetParameterFloat("spacingy",inImage->GetSpacing()[1], false); ossOutput << "\tSpacing : [" << GetParameterFloat("spacingx") << "," << GetParameterFloat("spacingy") << "]" << std::endl; //Estimate ground spacing @@ -331,14 +331,14 @@ private: approxGroundSpacing = groundSpacing->EvaluateAtIndex(index); //Get image estimated ground spacing (in m) - SetParameterFloat("estimatedgroundspacingx", approxGroundSpacing[0]); - SetParameterFloat("estimatedgroundspacingy", approxGroundSpacing[1]); + SetParameterFloat("estimatedgroundspacingx",approxGroundSpacing[0], false); + SetParameterFloat("estimatedgroundspacingy",approxGroundSpacing[1], false); ossOutput << "\tEstimated ground spacing (in meters): [" << GetParameterFloat("estimatedgroundspacingx") << "," << GetParameterFloat("estimatedgroundspacingy") << "]" << std::endl; ossOutput << std::endl << "Image acquisition information:" << std::endl; - SetParameterString("sensor", metadataInterface->GetSensorID()); + SetParameterString("sensor", metadataInterface->GetSensorID(), false); ossOutput << "\tSensor : "; if (!GetParameterString("sensor").empty()) ossOutput << GetParameterString("sensor"); @@ -348,11 +348,11 @@ private: ossOutput << "\tImage identification number: "; if (metadataInterface->GetImageKeywordlist().HasKey("image_id")) { - SetParameterString("id", metadataInterface->GetImageKeywordlist().GetMetadataByKey("image_id")); + SetParameterString("id", metadataInterface->GetImageKeywordlist().GetMetadataByKey("image_id"), false); ossOutput << GetParameterString("id"); } ossOutput << std::endl; - SetParameterString("projectionref", metadataInterface->GetProjectionRef()); + SetParameterString("projectionref", metadataInterface->GetProjectionRef(), false); if (!GetParameterString("projectionref").empty()) ossOutput << "\tImage projection : " << GetParameterString("projectionref") << std::endl; @@ -376,7 +376,7 @@ private: osstime<<"0"; osstime<<metadataInterface->GetMinute(); osstime<<":00"; - SetParameterString("time", osstime.str()); + SetParameterString("time", osstime.str(), false); ossOutput << "\tAcquisition time : " << GetParameterString("time") << std::endl; } @@ -405,29 +405,29 @@ private: if( !coord2name->GetCountryName().empty() ) { - SetParameterString("country", coord2name->GetCountryName()); + SetParameterString("country", coord2name->GetCountryName(), false); ossOutput << "\tCountry : " << GetParameterString("country") << std::endl; } else - SetParameterString("country", "Not available"); + SetParameterString("country", "Not available", false); if( !coord2name->GetPlaceName().empty() ) { - SetParameterString("town", coord2name->GetPlaceName()); + SetParameterString("town", coord2name->GetPlaceName(), false); ossOutput << "\tTown : " << GetParameterString("town") << std::endl; } else - SetParameterString("town", "Not available"); + SetParameterString("town", "Not available", false); // Retrieve footprint - SetParameterFloat("ullat", ullat); - SetParameterFloat("ullon", ullon); - SetParameterFloat("urlat", urlat); - SetParameterFloat("urlon", urlon); - SetParameterFloat("lrlat", lrlat); - SetParameterFloat("lrlon", lrlon); - SetParameterFloat("lllat", lllat); - SetParameterFloat("lllon", lllon); + SetParameterFloat("ullat",ullat, false); + SetParameterFloat("ullon",ullon, false); + SetParameterFloat("urlat",urlat, false); + SetParameterFloat("urlon",urlon, false); + SetParameterFloat("lrlat",lrlat, false); + SetParameterFloat("lrlon",lrlon, false); + SetParameterFloat("lllat",lllat, false); + SetParameterFloat("lllon",lllon, false); ossOutput << std::endl << "Image footprint coordinates:" << std::endl; ossOutput << "\tUpper left corner (latitude, longitude) = [" << GetParameterFloat("ullat") << "," << GetParameterFloat("ullon") << "]" << std::endl; @@ -439,15 +439,15 @@ private: { } - SetParameterInt("rgb.r", metadataInterface->GetDefaultDisplay()[0]); - SetParameterInt("rgb.g", metadataInterface->GetDefaultDisplay()[1]); - SetParameterInt("rgb.b", metadataInterface->GetDefaultDisplay()[2]); + SetParameterInt("rgb.r",metadataInterface->GetDefaultDisplay()[0], false); + SetParameterInt("rgb.g",metadataInterface->GetDefaultDisplay()[1], false); + SetParameterInt("rgb.b",metadataInterface->GetDefaultDisplay()[2], false); ossOutput << std::endl << "Image default RGB composition:" << std::endl; ossOutput << "\t[R, G, B] = [" << GetParameterInt("rgb.r") << "," << GetParameterInt("rgb.g") << "," << GetParameterInt("rgb.b") << "]" << std::endl; - SetParameterInt("gcp.count", metadataInterface->GetGCPCount()); - SetParameterString("gcp.proj", metadataInterface->GetGCPProjection()); + SetParameterInt("gcp.count",metadataInterface->GetGCPCount(), false); + SetParameterString("gcp.proj", metadataInterface->GetGCPProjection(), false); ossOutput << std::endl << "Ground control points information:" << std::endl; ossOutput << "\tNumber of GCPs = " << GetParameterInt("gcp.count") << std::endl; @@ -476,16 +476,16 @@ private: ossOutput << "\t\tGround coordinates =" << gcp_geocoord.back() << std::endl; } - SetParameterStringList("gcp.ids", gcp_ids); - SetParameterStringList("gcp.imcoord", gcp_imcoord); - SetParameterStringList("gcp.geocoord", gcp_geocoord); - SetParameterStringList("gcp.info", gcp_infos); + SetParameterStringList("gcp.ids", gcp_ids, false); + SetParameterStringList("gcp.imcoord", gcp_imcoord, false); + SetParameterStringList("gcp.geocoord", gcp_geocoord, false); + SetParameterStringList("gcp.info", gcp_infos, false); if ( IsParameterEnabled("keywordlist") ) { std::ostringstream osskeywordlist; osskeywordlist<<metadataInterface->GetImageKeywordlist() << std::endl; - SetParameterString("keyword", osskeywordlist.str()); + SetParameterString("keyword", osskeywordlist.str(), false); ossOutput << std::endl << "Image OSSIM keywordlist (optional):" << std::endl; ossOutput << "\t" << GetParameterString("keyword") << std::endl; diff --git a/Modules/Applications/AppImageUtils/app/otbRescale.cxx b/Modules/Applications/AppImageUtils/app/otbRescale.cxx index ea109547cf8cba64d6e9775436ad18aafeb4d6f3..21ada14c85674bff0b3795578f7dc7c1ec619cfe 100644 --- a/Modules/Applications/AppImageUtils/app/otbRescale.cxx +++ b/Modules/Applications/AppImageUtils/app/otbRescale.cxx @@ -52,8 +52,9 @@ private: SetDescription("Rescale the image between two given values."); SetDocName("Rescale Image"); - SetDocLongDescription("This application scales the given image pixel intensity between two given values. " - "By default min (resp. max) value is set to 0 (resp. 255)."); + SetDocLongDescription("This application scales the given image pixel intensity between two given values.\n" + "By default min (resp. max) value is set to 0 (resp. 255).\n" + "Input minimum and maximum values is automatically computed for all image bands."); SetDocLimitations("None"); SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); @@ -109,6 +110,7 @@ private: m_RescaleFilter = RescaleImageFilterType::New(); m_RescaleFilter->SetInput( inImage ); + m_RescaleFilter->SetAutomaticInputMinMaxComputation(false); m_RescaleFilter->SetInputMinimum( m_MinMaxFilter->GetMinimum() ); m_RescaleFilter->SetInputMaximum( m_MinMaxFilter->GetMaximum() ); diff --git a/Modules/Applications/AppIndices/app/otbRadiometricIndices.cxx b/Modules/Applications/AppIndices/app/otbRadiometricIndices.cxx index 3c910f26e15995ebf50ba52d578572fa3791c709..3466d519131f521bc6fea30e7d30d2c66d1cf890 100644 --- a/Modules/Applications/AppIndices/app/otbRadiometricIndices.cxx +++ b/Modules/Applications/AppIndices/app/otbRadiometricIndices.cxx @@ -138,8 +138,8 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso("otbVegetationIndicesFunctor, otbWaterIndicesFunctor and otbSoilIndicesFunctor classes"); - AddDocTag("Radiometric Indices"); AddDocTag(Tags::FeatureExtraction); + AddDocTag("Radiometric Indices"); AddParameter(ParameterType_InputImage, "in", "Input Image"); SetParameterDescription("in", "Input image"); diff --git a/Modules/Applications/AppKMZ/app/otbKmzExport.cxx b/Modules/Applications/AppKMZ/app/otbKmzExport.cxx index e4156451bc87c17692475e0111599ff8c0ad355f..c0cc931a5854eae60ff9b9f67eb67131f0235963 100644 --- a/Modules/Applications/AppKMZ/app/otbKmzExport.cxx +++ b/Modules/Applications/AppKMZ/app/otbKmzExport.cxx @@ -53,6 +53,7 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso("Conversion"); + AddDocTag("Miscellaneous"); AddDocTag("KMZ"); AddDocTag("Export"); diff --git a/Modules/Applications/AppMathParser/app/otbBandMath.cxx b/Modules/Applications/AppMathParser/app/otbBandMath.cxx index 29e5f898c39539ee510b299c19eea558d8f64c48..48868b6c575ffb600ecf2ec9bb32e6d891bb27cd 100644 --- a/Modules/Applications/AppMathParser/app/otbBandMath.cxx +++ b/Modules/Applications/AppMathParser/app/otbBandMath.cxx @@ -66,7 +66,7 @@ private: SetDocLimitations("None"); SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); - AddDocTag("Util"); + AddDocTag("Miscellaneous"); AddParameter(ParameterType_InputImageList, "il", "Input image list"); SetParameterDescription("il", "Image list to perform computation on."); @@ -83,7 +83,7 @@ private: // Doc example parameter settings SetDocExampleParameterValue("il", "verySmallFSATSW_r.tif verySmallFSATSW_nir.tif verySmallFSATSW.tif"); SetDocExampleParameterValue("out", "apTvUtBandMathOutput.tif"); - SetDocExampleParameterValue("exp", "\"cos(im1b1) > cos(im2b1) ? im3b1 : im3b2 \""); + SetDocExampleParameterValue("exp", "\"cos(im1b1) > cos(im2b1) ? im3b1 : im3b2\""); } void DoUpdateParameters() ITK_OVERRIDE diff --git a/Modules/Applications/AppMathParserX/app/otbBandMathX.cxx b/Modules/Applications/AppMathParserX/app/otbBandMathX.cxx index 91d8c872e769092d9ddadfb584da319304e304c7..53884d3afa94e2455f1a94dc940e44949bff1168 100644 --- a/Modules/Applications/AppMathParserX/app/otbBandMathX.cxx +++ b/Modules/Applications/AppMathParserX/app/otbBandMathX.cxx @@ -141,7 +141,7 @@ private: "Separating expressions by semi-colons (; ) will concatenate their results into a unique multiband output image. "); SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); - AddDocTag("Util"); + AddDocTag("Miscellaneous"); AddParameter(ParameterType_InputImageList, "il", "Input image list"); SetParameterDescription("il", "Image list to perform computation on."); @@ -209,7 +209,7 @@ private: if (useContext) { // only set the first expression, 'ManyExpression' is disabled. - this->SetParameterString("exp",dummyFilter->GetExpression(0)); + this->SetParameterString("exp",dummyFilter->GetExpression(0), false); } } } diff --git a/Modules/Applications/AppMoments/app/otbLocalStatisticExtraction.cxx b/Modules/Applications/AppMoments/app/otbLocalStatisticExtraction.cxx index e60b4bb8e90a5212e4fe37f6a34845bd1d404547..ad4c0c43e81f09fe5402d068c63e2125353c5fe0 100644 --- a/Modules/Applications/AppMoments/app/otbLocalStatisticExtraction.cxx +++ b/Modules/Applications/AppMoments/app/otbLocalStatisticExtraction.cxx @@ -64,8 +64,8 @@ SetDocLimitations("None"); SetDocAuthors("OTB-Team"); SetDocSeeAlso("otbRadiometricMomentsImageFunction class"); -AddDocTag("Statistics"); AddDocTag(Tags::FeatureExtraction); +AddDocTag("Statistics"); AddParameter(ParameterType_InputImage, "in", "Input Image"); SetParameterDescription("in", "The input image to compute the features on."); diff --git a/Modules/Applications/AppMorphology/app/otbBinaryMorphologicalOperation.cxx b/Modules/Applications/AppMorphology/app/otbBinaryMorphologicalOperation.cxx index 9e5e121d5fd1a92cfc369c571f4300ee2f6f5b57..eeddd79f264e58edbc7b860b721520f759dac56f 100644 --- a/Modules/Applications/AppMorphology/app/otbBinaryMorphologicalOperation.cxx +++ b/Modules/Applications/AppMorphology/app/otbBinaryMorphologicalOperation.cxx @@ -85,8 +85,8 @@ SetDocLimitations("None"); SetDocAuthors("OTB-Team"); SetDocSeeAlso("itkBinaryDilateImageFilter, itkBinaryErodeImageFilter, itkBinaryMorphologicalOpeningImageFilter and itkBinaryMorphologicalClosingImageFilter classes"); -AddDocTag("MorphologicalOperations"); AddDocTag(Tags::FeatureExtraction); +AddDocTag("MorphologicalOperations"); AddParameter(ParameterType_InputImage, "in", "Input Image"); SetParameterDescription("in", "The input image to be filtered."); diff --git a/Modules/Applications/AppMorphology/app/otbGrayScaleMorphologicalOperation.cxx b/Modules/Applications/AppMorphology/app/otbGrayScaleMorphologicalOperation.cxx index ae025a22becff71995aff75d945151f80fe55103..bb816fc0b3c5d35f90cd490db57d3d1113994d3c 100644 --- a/Modules/Applications/AppMorphology/app/otbGrayScaleMorphologicalOperation.cxx +++ b/Modules/Applications/AppMorphology/app/otbGrayScaleMorphologicalOperation.cxx @@ -85,8 +85,8 @@ SetDocLimitations("None"); SetDocAuthors("OTB-Team"); SetDocSeeAlso("itkGrayscaleDilateImageFilter, itkGrayscaleErodeImageFilter, itkGrayscaleMorphologicalOpeningImageFilter and itkGrayscaleMorphologicalClosingImageFilter classes"); -AddDocTag("MorphologicalOperations"); AddDocTag(Tags::FeatureExtraction); +AddDocTag("MorphologicalOperations"); AddParameter(ParameterType_InputImage, "in", "Input Image"); SetParameterDescription("in", "The input image to be filtered."); diff --git a/Modules/Applications/AppOpticalCalibration/app/otbOpticalCalibration.cxx b/Modules/Applications/AppOpticalCalibration/app/otbOpticalCalibration.cxx index 10004ff35386d3add63f0cb6eef784ceacabac5a..52dd349396c57ebc48d03ae629ee5a13e8a5bfd9 100644 --- a/Modules/Applications/AppOpticalCalibration/app/otbOpticalCalibration.cxx +++ b/Modules/Applications/AppOpticalCalibration/app/otbOpticalCalibration.cxx @@ -194,7 +194,7 @@ private: AddChoice("level.toa", "Image to Top Of Atmosphere reflectance"); AddChoice("level.toatoim", "TOA reflectance to Image"); AddChoice("level.toc", "Image to Top Of Canopy reflectance (atmospheric corrections)"); - SetParameterString("level", "toa"); + SetParameterString("level", "toa", false); AddParameter(ParameterType_Empty, "milli", "Convert to milli reflectance"); SetParameterDescription("milli", "Flag to use milli-reflectance instead of reflectance.\n" @@ -424,21 +424,21 @@ private: ossOutput << "Acquisition Minute already set by user: no overload" <<std::endl; else { - SetParameterInt("acqui.minute", lImageMetadataInterface->GetMinute()); + SetParameterInt("acqui.minute",lImageMetadataInterface->GetMinute(), false); } if (HasUserValue("acqui.hour")) ossOutput << "Acquisition Hour already set by user: no overload" <<std::endl; else { - SetParameterInt("acqui.hour", lImageMetadataInterface->GetHour()); + SetParameterInt("acqui.hour",lImageMetadataInterface->GetHour(), false); } if (HasUserValue("acqui.day")) ossOutput << "Acquisition Day already set by user: no overload" <<std::endl; else { - SetParameterInt("acqui.day", lImageMetadataInterface->GetDay()); + SetParameterInt("acqui.day",lImageMetadataInterface->GetDay(), false); if (IsParameterEnabled("acqui.fluxnormcoeff")) DisableParameter("acqui.day"); } @@ -447,7 +447,7 @@ private: ossOutput << "Acquisition Month already set by user: no overload" <<std::endl; else { - SetParameterInt("acqui.month", lImageMetadataInterface->GetMonth()); + SetParameterInt("acqui.month",lImageMetadataInterface->GetMonth(), false); if (IsParameterEnabled("acqui.fluxnormcoeff")) DisableParameter("acqui.month"); } @@ -456,28 +456,28 @@ private: ossOutput << "Acquisition Year already set by user: no overload" <<std::endl; else { - SetParameterInt("acqui.year", lImageMetadataInterface->GetYear()); + SetParameterInt("acqui.year",lImageMetadataInterface->GetYear(), false); } if (HasUserValue("acqui.sun.elev")) ossOutput << "Acquisition Sun Elevation Angle already set by user: no overload" <<std::endl; else - SetParameterFloat("acqui.sun.elev", lImageMetadataInterface->GetSunElevation()); + SetParameterFloat("acqui.sun.elev",lImageMetadataInterface->GetSunElevation(), false); if (HasUserValue("acqui.sun.azim")) ossOutput << "Acquisition Sun Azimuth Angle already set by user: no overload" <<std::endl; else - SetParameterFloat("acqui.sun.azim", lImageMetadataInterface->GetSunAzimuth()); + SetParameterFloat("acqui.sun.azim",lImageMetadataInterface->GetSunAzimuth(), false); if (HasUserValue("acqui.view.elev")) ossOutput << "Acquisition Viewing Elevation Angle already set by user: no overload" <<std::endl; else - SetParameterFloat("acqui.view.elev", lImageMetadataInterface->GetSatElevation()); + SetParameterFloat("acqui.view.elev",lImageMetadataInterface->GetSatElevation(), false); if (HasUserValue("acqui.view.azim")) ossOutput << "Acquisition Viewing Azimuth Angle already set by user: no overload" <<std::endl; else - SetParameterFloat("acqui.view.azim", lImageMetadataInterface->GetSatAzimuth()); + SetParameterFloat("acqui.view.azim",lImageMetadataInterface->GetSatAzimuth(), false); // Set default value so that they are stored somewhere even if // they are overloaded by user values @@ -823,12 +823,14 @@ private: { otbAppLogWARNING("No relative spectral response found, using " "default response (constant between 0.3 and 1.0µm)"); - AcquiCorrectionParametersType::WavelengthSpectralBandVectorType spectralDummy; + AcquiCorrectionParametersType::WavelengthSpectralBandVectorType spectralDummy = + AcquiCorrectionParametersType::InternalWavelengthSpectralBandVectorType::New(); spectralDummy->Clear(); for (unsigned int i = 0; i < inImage->GetNumberOfComponentsPerPixel(); ++i) { spectralDummy->PushBack(FilterFunctionValues::New()); } + m_paramAcqui->SetWavelengthSpectralBand(spectralDummy); } // Aeronet file diff --git a/Modules/Applications/AppProjection/app/otbConvertCartoToGeoPoint.cxx b/Modules/Applications/AppProjection/app/otbConvertCartoToGeoPoint.cxx index 5dd1cdd05d63216aee50d9375bb5a01c31c397d0..819b035884da04e9caeffd2dad3f9f5673e06af9 100644 --- a/Modules/Applications/AppProjection/app/otbConvertCartoToGeoPoint.cxx +++ b/Modules/Applications/AppProjection/app/otbConvertCartoToGeoPoint.cxx @@ -59,8 +59,8 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); - AddDocTag(Tags::Coordinates); AddDocTag(Tags::Geometry); + AddDocTag(Tags::Coordinates); AddParameter(ParameterType_Group, "carto", "Input cartographic coordinates"); AddParameter(ParameterType_Float, "carto.x", "X cartographic coordinates"); @@ -117,8 +117,8 @@ private: otbAppLogINFO( << std::setprecision(10) << "Geographic Point (Long, Lat) : (" << geoPoint[0] << ", " << geoPoint[1] << ")" ); - SetParameterFloat( "long", geoPoint[0] ); - SetParameterFloat( "lat", geoPoint[1] ); + SetParameterFloat( "long",geoPoint[0] , false); + SetParameterFloat( "lat",geoPoint[1] , false); } }; diff --git a/Modules/Applications/AppProjection/app/otbConvertSensorToGeoPoint.cxx b/Modules/Applications/AppProjection/app/otbConvertSensorToGeoPoint.cxx index 3b3140b2b1c614000e4f4d193cc852e64974e4a0..be3f19a20f2c6524b8dd7e126103f4c3b60b3ceb 100644 --- a/Modules/Applications/AppProjection/app/otbConvertSensorToGeoPoint.cxx +++ b/Modules/Applications/AppProjection/app/otbConvertSensorToGeoPoint.cxx @@ -125,8 +125,8 @@ private: outputPoint = model->TransformPoint(point); // Set the value computed - SetParameterFloat("output.idx", outputPoint[0]); - SetParameterFloat("output.idy", outputPoint[1]); + SetParameterFloat("output.idx",outputPoint[0], false); + SetParameterFloat("output.idy",outputPoint[1], false); // Set the town and the neaerest city CoordinateToName::Pointer coord2name = CoordinateToName::New(); @@ -134,8 +134,8 @@ private: coord2name->SetLat(outputPoint[1]); coord2name->Evaluate(); - SetParameterString("output.town", coord2name->GetPlaceName()); - SetParameterString("output.country", coord2name->GetCountryName()); + SetParameterString("output.town", coord2name->GetPlaceName(), false); + SetParameterString("output.country", coord2name->GetCountryName(), false); } }; diff --git a/Modules/Applications/AppProjection/app/otbGenerateRPCSensorModel.cxx b/Modules/Applications/AppProjection/app/otbGenerateRPCSensorModel.cxx index be181ebb320b2b4fe0f97d48c0e836f42512e73d..f640e072e7441bc60430c89333640061364c7bae 100644 --- a/Modules/Applications/AppProjection/app/otbGenerateRPCSensorModel.cxx +++ b/Modules/Applications/AppProjection/app/otbGenerateRPCSensorModel.cxx @@ -60,7 +60,13 @@ private: SetDescription("Generate a RPC sensor model from a list of Ground Control Points."); SetDocName("Generate a RPC sensor model"); - SetDocLongDescription("This application generates a RPC sensor model from a list of Ground Control Points. At least 20 points are required for estimation wihtout elevation support, and 40 points for estimation with elevation support. Elevation support will be automatically deactivated if an insufficient amount of points is provided. The application can optionnaly output a file containing accuracy statistics for each point, and a vector file containing segments represening points residues. The map projection parameter allows defining a map projection in which the accuracy is evaluated."); + SetDocLongDescription( "This application generates a RPC sensor model from a list of Ground Control Points. " + "At least 20 points are required for estimation without elevation support, " + "and 40 points for estimation with elevation support. " + "Elevation support will be automatically deactivated if an insufficient amount of points is provided. " + "The application can optionally output a file containing accuracy statistics for each point," + " and a vector file containing segments representing points residues. " + "The map projection parameter allows defining a map projection in which the accuracy is evaluated." ); AddDocTag(Tags::Geometry); @@ -72,7 +78,7 @@ private: SetParameterDescription("outgeom","Geom file containing the generated RPC sensor model"); AddParameter(ParameterType_InputFilename,"inpoints","Input file containing tie points"); - SetParameterDescription("inpoints","Input file containing tie points. Points are stored in following format: col row lon lat. Line beginning with # are ignored."); + SetParameterDescription("inpoints","Input file containing tie points. Points are stored in following format: col row lon lat. Spaced by a space or tab character. Line beginning with # are ignored."); AddParameter(ParameterType_OutputFilename,"outstat","Output file containing output precision statistics"); SetParameterDescription("outstat","Output file containing the following info: ref_lon ref_lat elevation predicted_lon predicted_lat x_error_ref(meters) y_error_ref(meters) global_error_ref(meters) x_error(meters) y_error(meters) overall_error(meters)"); @@ -125,20 +131,8 @@ private: // Avoid commented lines or too short ones if (!line.empty() && line[0] != '#') { - // retrieve the x component - std::string::size_type pos = 0; - std::string::size_type nextpos = line.find_first_of("\t", pos); - x = atof(line.substr(pos, nextpos).c_str()); - pos = nextpos + 1; - nextpos = line.find_first_of("\t", pos); - y = atof(line.substr(pos, nextpos).c_str()); - pos = nextpos + 1; - nextpos = line.find_first_of("\t", pos); - lon = atof(line.substr(pos, nextpos).c_str()); - pos = nextpos + 1; - nextpos = line.find_first_of("\t", pos); - lat = atof(line.substr(pos, nextpos).c_str()); - + std::istringstream iss(line); + iss >> x >> y >> lon >> lat; z = otb::DEMHandler::Instance()->GetHeightAboveEllipsoid(lon,lat); otbAppLogINFO("Adding tie point x="<<x<<", y="<<y<<", z="<<z<<", lon="<<lon<<", lat="<<lat); diff --git a/Modules/Applications/AppProjection/app/otbGridBasedImageResampling.cxx b/Modules/Applications/AppProjection/app/otbGridBasedImageResampling.cxx index 5d782b3d17d1f5cfcf31613172cea5d2e42791c1..5a3286c4664ee2b0a87e17faa9b03fe604e62e54 100644 --- a/Modules/Applications/AppProjection/app/otbGridBasedImageResampling.cxx +++ b/Modules/Applications/AppProjection/app/otbGridBasedImageResampling.cxx @@ -170,7 +170,7 @@ private: AddParameter(ParameterType_Radius, "interpolator.bco.radius", "Radius for bicubic interpolation"); SetParameterDescription("interpolator.bco.radius","This parameter allows controlling the size of the bicubic interpolation filter. If the target pixel size is higher than the input pixel size, increasing this parameter will reduce aliasing artifacts."); SetDefaultParameterInt("interpolator.bco.radius", 2); - SetParameterString("interpolator","bco"); + SetParameterString("interpolator","bco", false); AddRAMParameter(); diff --git a/Modules/Applications/AppProjection/app/otbObtainUTMZoneFromGeoPoint.cxx b/Modules/Applications/AppProjection/app/otbObtainUTMZoneFromGeoPoint.cxx index e411fa356efded2277aa0a68015c988e456e5118..acfb9028faf1690c3f556225f45ec7ad6e04f188 100644 --- a/Modules/Applications/AppProjection/app/otbObtainUTMZoneFromGeoPoint.cxx +++ b/Modules/Applications/AppProjection/app/otbObtainUTMZoneFromGeoPoint.cxx @@ -61,6 +61,7 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); + AddDocTag("Miscellaneous"); AddDocTag(Tags::Coordinates); AddParameter(ParameterType_Float, "lat", "Latitude"); @@ -88,7 +89,7 @@ private: { int utmZone = otb::Utils::GetZoneFromGeoPoint(GetParameterFloat("lon"), GetParameterFloat("lat")); - SetParameterInt("utm", utmZone); + SetParameterInt("utm",utmZone, false); } }; diff --git a/Modules/Applications/AppProjection/app/otbOrthoRectification.cxx b/Modules/Applications/AppProjection/app/otbOrthoRectification.cxx index e94168465dba16134a52a42901156dc430521b67..4e0b6b56f56c8d40c5e68503e3f844e84c1ed9e9 100644 --- a/Modules/Applications/AppProjection/app/otbOrthoRectification.cxx +++ b/Modules/Applications/AppProjection/app/otbOrthoRectification.cxx @@ -235,6 +235,11 @@ private: { if (HasValue("io.in")) { + + // Clear and reset the DEM Handler + otb::DEMHandler::Instance()->ClearDEMs(); + otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev"); + // input image FloatVectorImageType::Pointer inImage = GetParameterImage("io.in"); @@ -263,28 +268,28 @@ private: // Fill the Gui with the computed parameters if (!HasUserValue("outputs.sizex")) - SetParameterInt("outputs.sizex", genericRSEstimator->GetOutputSize()[0]); + SetParameterInt("outputs.sizex",genericRSEstimator->GetOutputSize()[0], false); if (!HasUserValue("outputs.sizey")) - SetParameterInt("outputs.sizey", genericRSEstimator->GetOutputSize()[1]); + SetParameterInt("outputs.sizey",genericRSEstimator->GetOutputSize()[1], false); if (!HasUserValue("outputs.spacingx")) - SetParameterFloat("outputs.spacingx", genericRSEstimator->GetOutputSpacing()[0]); + SetParameterFloat("outputs.spacingx",genericRSEstimator->GetOutputSpacing()[0], false); if (!HasUserValue("outputs.spacingy")) - SetParameterFloat("outputs.spacingy", genericRSEstimator->GetOutputSpacing()[1]); + SetParameterFloat("outputs.spacingy",genericRSEstimator->GetOutputSpacing()[1], false); if (!HasUserValue("outputs.ulx")) - SetParameterFloat("outputs.ulx", genericRSEstimator->GetOutputOrigin()[0] - 0.5 * genericRSEstimator->GetOutputSpacing()[0]); + SetParameterFloat("outputs.ulx",genericRSEstimator->GetOutputOrigin()[0] - 0.5 * genericRSEstimator->GetOutputSpacing()[0], false); if (!HasUserValue("outputs.uly")) - SetParameterFloat("outputs.uly", genericRSEstimator->GetOutputOrigin()[1] - 0.5 * genericRSEstimator->GetOutputSpacing()[1]); + SetParameterFloat("outputs.uly",genericRSEstimator->GetOutputOrigin()[1] - 0.5 * genericRSEstimator->GetOutputSpacing()[1], false); if (!HasUserValue("outputs.lrx")) - SetParameterFloat("outputs.lrx", GetParameterFloat("outputs.ulx") + GetParameterFloat("outputs.spacingx") * static_cast<double>(GetParameterInt("outputs.sizex"))); + SetParameterFloat("outputs.lrx",GetParameterFloat("outputs.ulx") + GetParameterFloat("outputs.spacingx") * static_cast<double>(GetParameterInt("outputs.sizex")), false); if (!HasUserValue("outputs.lry")) - SetParameterFloat("outputs.lry", GetParameterFloat("outputs.uly") + GetParameterFloat("outputs.spacingy") * static_cast<double>(GetParameterInt("outputs.sizey"))); + SetParameterFloat("outputs.lry",GetParameterFloat("outputs.uly") + GetParameterFloat("outputs.spacingy") * static_cast<double>(GetParameterInt("outputs.sizey")), false); // Handle the spacing and size field following the mode // chose by the user @@ -325,8 +330,8 @@ private: MandatoryOff("outputs.ortho"); // Update lower right - SetParameterFloat("outputs.lrx", GetParameterFloat("outputs.ulx") + GetParameterFloat("outputs.spacingx") * static_cast<double>(GetParameterInt("outputs.sizex"))); - SetParameterFloat("outputs.lry", GetParameterFloat("outputs.uly") + GetParameterFloat("outputs.spacingy") * static_cast<double>(GetParameterInt("outputs.sizey"))); + SetParameterFloat("outputs.lrx",GetParameterFloat("outputs.ulx") + GetParameterFloat("outputs.spacingx") * static_cast<double>(GetParameterInt("outputs.sizex")), false); + SetParameterFloat("outputs.lry",GetParameterFloat("outputs.uly") + GetParameterFloat("outputs.spacingy") * static_cast<double>(GetParameterInt("outputs.sizey")), false); } break; case Mode_AutomaticSize: @@ -371,16 +376,16 @@ private: genericRSEstimator->Compute(); // Set the processed size relative to this forced spacing - SetParameterInt("outputs.sizex", genericRSEstimator->GetOutputSize()[0]); - SetParameterInt("outputs.sizey", genericRSEstimator->GetOutputSize()[1]); + SetParameterInt("outputs.sizex",genericRSEstimator->GetOutputSize()[0], false); + SetParameterInt("outputs.sizey",genericRSEstimator->GetOutputSize()[1], false); // Reset Origin to default - SetParameterFloat("outputs.ulx", genericRSEstimator->GetOutputOrigin()[0] - 0.5 * genericRSEstimator->GetOutputSpacing()[0]); - SetParameterFloat("outputs.uly", genericRSEstimator->GetOutputOrigin()[1] - 0.5 * genericRSEstimator->GetOutputSpacing()[1]); + SetParameterFloat("outputs.ulx",genericRSEstimator->GetOutputOrigin()[0] - 0.5 * genericRSEstimator->GetOutputSpacing()[0], false); + SetParameterFloat("outputs.uly",genericRSEstimator->GetOutputOrigin()[1] - 0.5 * genericRSEstimator->GetOutputSpacing()[1], false); // Update lower right - SetParameterFloat("outputs.lrx", GetParameterFloat("outputs.ulx") + GetParameterFloat("outputs.spacingx") * static_cast<double>(GetParameterInt("outputs.sizex"))); - SetParameterFloat("outputs.lry", GetParameterFloat("outputs.uly") + GetParameterFloat("outputs.spacingy") * static_cast<double>(GetParameterInt("outputs.sizey"))); + SetParameterFloat("outputs.lrx",GetParameterFloat("outputs.ulx") + GetParameterFloat("outputs.spacingx") * static_cast<double>(GetParameterInt("outputs.sizex")), false); + SetParameterFloat("outputs.lry",GetParameterFloat("outputs.uly") + GetParameterFloat("outputs.spacingy") * static_cast<double>(GetParameterInt("outputs.sizey")), false); } break; case Mode_AutomaticSpacing: @@ -425,16 +430,16 @@ private: genericRSEstimator->Compute(); // Set the processed spacing relative to this forced size - SetParameterFloat("outputs.spacingx", genericRSEstimator->GetOutputSpacing()[0]); - SetParameterFloat("outputs.spacingy", genericRSEstimator->GetOutputSpacing()[1]); + SetParameterFloat("outputs.spacingx",genericRSEstimator->GetOutputSpacing()[0], false); + SetParameterFloat("outputs.spacingy",genericRSEstimator->GetOutputSpacing()[1], false); // Reset Origin to default - SetParameterFloat("outputs.ulx", genericRSEstimator->GetOutputOrigin()[0] - 0.5 * genericRSEstimator->GetOutputSpacing()[0]); - SetParameterFloat("outputs.uly", genericRSEstimator->GetOutputOrigin()[1] - 0.5 * genericRSEstimator->GetOutputSpacing()[1]); + SetParameterFloat("outputs.ulx",genericRSEstimator->GetOutputOrigin()[0] - 0.5 * genericRSEstimator->GetOutputSpacing()[0], false); + SetParameterFloat("outputs.uly",genericRSEstimator->GetOutputOrigin()[1] - 0.5 * genericRSEstimator->GetOutputSpacing()[1], false); // Update lower right - SetParameterFloat("outputs.lrx", GetParameterFloat("outputs.ulx") + GetParameterFloat("outputs.spacingx") * static_cast<double>(GetParameterInt("outputs.sizex"))); - SetParameterFloat("outputs.lry", GetParameterFloat("outputs.uly") + GetParameterFloat("outputs.spacingy") * static_cast<double>(GetParameterInt("outputs.sizey"))); + SetParameterFloat("outputs.lrx",GetParameterFloat("outputs.ulx") + GetParameterFloat("outputs.spacingx") * static_cast<double>(GetParameterInt("outputs.sizex")), false); + SetParameterFloat("outputs.lry",GetParameterFloat("outputs.uly") + GetParameterFloat("outputs.spacingy") * static_cast<double>(GetParameterInt("outputs.sizey")), false); } break; @@ -478,9 +483,9 @@ private: // Set the processed size relative to this forced spacing if (vcl_abs(spacing[0]) > 0.0) - SetParameterInt("outputs.sizex", static_cast<int>(vcl_ceil((GetParameterFloat("outputs.lrx")-GetParameterFloat("outputs.ulx"))/spacing[0]))); + SetParameterInt("outputs.sizex",static_cast<int>(vcl_ceil((GetParameterFloat("outputs.lrx")-GetParameterFloat("outputs.ulx"))/spacing[0])), false); if (vcl_abs(spacing[1]) > 0.0) - SetParameterInt("outputs.sizey", static_cast<int>(vcl_ceil((GetParameterFloat("outputs.lry")-GetParameterFloat("outputs.uly"))/spacing[1]))); + SetParameterInt("outputs.sizey",static_cast<int>(vcl_ceil((GetParameterFloat("outputs.lry")-GetParameterFloat("outputs.uly"))/spacing[1])), false); } break; case Mode_OrthoFit: @@ -530,11 +535,11 @@ private: SetParameterInt("outputs.sizey",size[1]); SetParameterFloat("outputs.spacingx",spacing[0]); SetParameterFloat("outputs.spacingy",spacing[1]); - SetParameterFloat("outputs.ulx", orig[0] - 0.5 * spacing[0]); - SetParameterFloat("outputs.uly", orig[1] - 0.5 * spacing[1]); + SetParameterFloat("outputs.ulx",orig[0] - 0.5 * spacing[0], false); + SetParameterFloat("outputs.uly",orig[1] - 0.5 * spacing[1], false); // Update lower right - SetParameterFloat("outputs.lrx", GetParameterFloat("outputs.ulx") + GetParameterFloat("outputs.spacingx") * static_cast<double>(GetParameterInt("outputs.sizex"))); - SetParameterFloat("outputs.lry", GetParameterFloat("outputs.uly") + GetParameterFloat("outputs.spacingy") * static_cast<double>(GetParameterInt("outputs.sizey"))); + SetParameterFloat("outputs.lrx",GetParameterFloat("outputs.ulx") + GetParameterFloat("outputs.spacingx") * static_cast<double>(GetParameterInt("outputs.sizex")), false); + SetParameterFloat("outputs.lry",GetParameterFloat("outputs.uly") + GetParameterFloat("outputs.spacingy") * static_cast<double>(GetParameterInt("outputs.sizey")), false); } } break; @@ -580,11 +585,11 @@ private: // Use the smallest spacing (more precise grid) double optimalSpacing = std::min( vcl_abs(xgridspacing), vcl_abs(ygridspacing) ); otbAppLogINFO( "Setting grid spacing to " << optimalSpacing ); - SetParameterFloat("opt.gridspacing", optimalSpacing); + SetParameterFloat("opt.gridspacing",optimalSpacing, false); } else // if (m_OutputProjectionRef == otb::GeoInformationConversion::ToWKT(4326)) { - SetParameterFloat("opt.gridspacing", DefaultGridSpacingMeter); + SetParameterFloat("opt.gridspacing",DefaultGridSpacingMeter, false); } // if (m_OutputProjectionRef == otb::GeoInformationConversion::ToWKT(4326)) } // if (!HasUserValue("opt.gridspacing")) } // if (HasValue("io.in")) @@ -645,9 +650,6 @@ private: break; } - // Setup the DEM Handler - otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev"); - // If activated, generate RPC model if(IsParameterEnabled("opt.rpc")) { @@ -692,11 +694,16 @@ private: otbAppLogINFO("Using a deformation grid with a physical spacing of " << GetParameterFloat("opt.gridspacing")); + if ( GetParameterFloat( "opt.gridspacing" ) == 0 ) + { + otbAppLogFATAL( "opt.gridspacing must be different from 0 " ); + } + // Predict size of deformation grid - ResampleFilterType::SizeType deformationGridSize; - deformationGridSize[0] = static_cast<ResampleFilterType::SizeType::SizeValueType>(vcl_abs( + ResampleFilterType::SpacingType deformationGridSize; + deformationGridSize[0] = static_cast<ResampleFilterType::SpacingType::ValueType >(vcl_abs( GetParameterInt("outputs.sizex") * GetParameterFloat("outputs.spacingx") / GetParameterFloat("opt.gridspacing") )); - deformationGridSize[1] = static_cast<ResampleFilterType::SizeType::SizeValueType>(vcl_abs( + deformationGridSize[1] = static_cast<ResampleFilterType::SpacingType::ValueType>(vcl_abs( GetParameterInt("outputs.sizey") * GetParameterFloat("outputs.spacingy") / GetParameterFloat("opt.gridspacing") )); otbAppLogINFO("Using a deformation grid of size " << deformationGridSize); diff --git a/Modules/Applications/AppProjection/app/otbRigidTransformResample.cxx b/Modules/Applications/AppProjection/app/otbRigidTransformResample.cxx index 2bdaa251b37d3ba99b185017c235b16392022510..c3bd9e3df9b8055098256fa9d41573f68008c6e9 100644 --- a/Modules/Applications/AppProjection/app/otbRigidTransformResample.cxx +++ b/Modules/Applications/AppProjection/app/otbRigidTransformResample.cxx @@ -89,8 +89,8 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso("Translation"); + AddDocTag(Tags::Geometry); AddDocTag("Conversion"); - AddDocTag(Tags::Geometry); AddParameter(ParameterType_InputImage, "in", "Input image"); SetParameterDescription("in","The input image to translate."); @@ -156,7 +156,7 @@ private: AddParameter(ParameterType_Radius, "interpolator.bco.radius", "Radius for bicubic interpolation"); SetParameterDescription("interpolator.bco.radius","This parameter allows controlling the size of the bicubic interpolation filter. If the target pixel size is higher than the input pixel size, increasing this parameter will reduce aliasing artifacts."); SetDefaultParameterInt("interpolator.bco.radius", 2); - SetParameterString("interpolator","bco"); + SetParameterString("interpolator","bco", false); // RAM available AddRAMParameter("ram"); @@ -194,6 +194,7 @@ private: double> LinearInterpolationType; LinearInterpolationType::Pointer interpolator = LinearInterpolationType::New(); m_Resampler->SetInterpolator(interpolator); + m_GridResampler->SetInterpolator(interpolator); } break; case Interpolator_NNeighbor: @@ -202,6 +203,7 @@ private: double> NearestNeighborInterpolationType; NearestNeighborInterpolationType::Pointer interpolator = NearestNeighborInterpolationType::New(); m_Resampler->SetInterpolator(interpolator); + m_GridResampler->SetInterpolator(interpolator); } break; case Interpolator_BCO: @@ -210,6 +212,7 @@ private: BCOInterpolationType::Pointer interpolator = BCOInterpolationType::New(); interpolator->SetRadius(GetParameterInt("interpolator.bco.radius")); m_Resampler->SetInterpolator(interpolator); + m_GridResampler->SetInterpolator(interpolator); } break; } diff --git a/Modules/Applications/AppProjection/app/otbSuperimpose.cxx b/Modules/Applications/AppProjection/app/otbSuperimpose.cxx index 3293c3ad1f229e6af4ff39755c11f348e869038a..71cb75003eb0f48450e4f0f07c69888f3af49153 100644 --- a/Modules/Applications/AppProjection/app/otbSuperimpose.cxx +++ b/Modules/Applications/AppProjection/app/otbSuperimpose.cxx @@ -104,8 +104,14 @@ private: AddParameter(ParameterType_Float, "lms", "Spacing of the deformation field"); SetParameterDescription("lms","Generate a coarser deformation field with the given spacing"); SetDefaultParameterFloat("lms", 4.); + DisableParameter("lms"); MandatoryOff("lms"); + AddParameter(ParameterType_Float, "fv", "Fill Value"); + SetParameterDescription("fv","Fill value for area outside the reprojected image"); + SetDefaultParameterFloat("fv", 0.); + MandatoryOff("fv"); + AddParameter(ParameterType_OutputImage, "out", "Output image"); SetParameterDescription("out","Output reprojected image."); @@ -153,7 +159,7 @@ private: if(!HasUserValue("mode") && HasValue("inr") && HasValue("inm") && otb::PleiadesPToXSAffineTransformCalculator::CanCompute(GetParameterImage("inr"),GetParameterImage("inm"))) { otbAppLogWARNING("Forcing PHR mode with PHR data. You need to add \"-mode default\" to force the default mode with PHR images."); - SetParameterString("mode","phr"); + SetParameterString("mode","phr", false); } } @@ -210,24 +216,28 @@ private: FloatVectorImageType::PixelType defaultValue; itk::NumericTraits<FloatVectorImageType::PixelType>::SetLength(defaultValue, movingImage->GetNumberOfComponentsPerPixel()); + defaultValue.Fill(GetParameterFloat("fv")); - if(GetParameterString("mode")=="default") { + FloatVectorImageType::SpacingType defSpacing; if(IsParameterEnabled("lms")) { float defScalarSpacing = vcl_abs(GetParameterFloat("lms")); otbAppLogDEBUG("Generating coarse deformation field (spacing="<<defScalarSpacing<<")"); - FloatVectorImageType::SpacingType defSpacing; defSpacing[0] = defScalarSpacing; defSpacing[1] = defScalarSpacing; if (spacing[0]<0.0) defSpacing[0] *= -1.0; if (spacing[1]<0.0) defSpacing[1] *= -1.0; - - m_Resampler->SetDisplacementFieldSpacing(defSpacing); } + else + { + defSpacing[0]=10*spacing[0]; + defSpacing[1]=10*spacing[1]; + } + m_Resampler->SetDisplacementFieldSpacing(defSpacing); // Setup transform through projRef and Keywordlist m_Resampler->SetInputKeywordList(movingImage->GetImageKeywordlist()); diff --git a/Modules/Applications/AppProjection/app/otbVectorDataReprojection.cxx b/Modules/Applications/AppProjection/app/otbVectorDataReprojection.cxx index 3b4cdde5d15d15b881fcc301ad9233c25bf02c3a..5b0992eb3447048001e3db37770b9e91518da0fd 100644 --- a/Modules/Applications/AppProjection/app/otbVectorDataReprojection.cxx +++ b/Modules/Applications/AppProjection/app/otbVectorDataReprojection.cxx @@ -75,8 +75,8 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); - AddDocTag(Tags::Geometry); AddDocTag(Tags::Vector); + AddDocTag(Tags::Geometry); AddDocTag(Tags::Coordinates); // Set the parameters diff --git a/Modules/Applications/AppProjection/test/CMakeLists.txt b/Modules/Applications/AppProjection/test/CMakeLists.txt index bff04845b68deeb44c0924471b7d10066d522319..81eea8e987ac15269fb0677ce0b80dedadfc892f 100644 --- a/Modules/Applications/AppProjection/test/CMakeLists.txt +++ b/Modules/Applications/AppProjection/test/CMakeLists.txt @@ -320,6 +320,7 @@ otb_test_application(NAME apTvPrSuperimpose -inm ${INPUTDATA}/QB_Toulouse_Ortho_XS_ROI_170x230.tif -elev.dem ${INPUTDATA}/DEM/srtm_directory -out ${TEMP}/apTvPrSuperimpose.tif int16 + -lms 4.0 VALID --compare-image ${EPSILON_7} ${BASELINE}/apTvPrSuperimpose.tif ${TEMP}/apTvPrSuperimpose.tif) diff --git a/Modules/Applications/AppSARCalibration/test/CMakeLists.txt b/Modules/Applications/AppSARCalibration/test/CMakeLists.txt index 585c4d1e48dd3f1603123ce7ffcc7d5eb51c345b..dfceda5530c883a31d3b892e6d04ef673833a6b1 100644 --- a/Modules/Applications/AppSARCalibration/test/CMakeLists.txt +++ b/Modules/Applications/AppSARCalibration/test/CMakeLists.txt @@ -2,12 +2,22 @@ otb_module_test() #----------- SarRadiometricCalibration TESTS ---------------- otb_test_application(NAME apTvRaSarRadiometricCalibration_SENTINEL1 APP SARCalibration - OPTIONS -in ${INPUTDATA}/SENTINEL1_SLC_S6_1S_extract_300_300.tif?&geom=${INPUTDATA}/SENTINEL1_SLC_S6_1S_extract_300_300.geom + OPTIONS -in ${INPUTDATA}/SENTINEL1_SLC_S6_1S_extract_1200_1100_300_300.tiff?&geom=${INPUTDATA}/SENTINEL1_SLC_S6_1S_extract_1200_1100_300_300.geom -out ${TEMP}/apTvRaSarRadiometricCalibration_SENTINEL1.tif VALID --compare-image ${NOTOL} ${BASELINE}/raTvSarRadiometricCalibration_SENTINEL1.tif ${TEMP}/apTvRaSarRadiometricCalibration_SENTINEL1.tif ) +if(OTB_DATA_USE_LARGEINPUT) + otb_test_application(NAME apTvRaSarRadiometricCalibration_SENTINEL1_PRODUCT_INPUT + APP SARCalibration + OPTIONS -in LARGEINPUT{SENTINEL1/S1A_S6_SLC__1SSV_20150619T195043/measurement/s1a-s6-slc-vv-20150619t195043-20150619t195101-006447-00887d-001.tiff} + -out "${TEMP}/apTvRaSarRadiometricCalibration_SENTINEL1_PRODUCT_INPUT.tif?box=1200:1100:256:256" + VALID --compare-image ${NOTOL} + ${BASELINE}/raTvSarRadiometricCalibration_SENTINEL1_PRODUCT_INPUT.tif + ${TEMP}/apTvRaSarRadiometricCalibration_SENTINEL1_PRODUCT_INPUT.tif ) +endif() + otb_test_application(NAME apTvRaSarRadiometricCalibration_RADARSAT2 APP SARCalibration OPTIONS -in ${INPUTDATA}/RADARSAT2_ALTONA_300_300_VV.tif?&geom=${INPUTDATA}/RADARSAT2_ALTONA_300_300_VV.geom diff --git a/Modules/Applications/AppSegmentation/app/otbConnectedComponentSegmentation.cxx b/Modules/Applications/AppSegmentation/app/otbConnectedComponentSegmentation.cxx index 1c4e3073a7657abcd6bc73e0f45fc773d845308d..d6bf04c7cb804f08cb1da1a4d101b2526b9ff1c9 100644 --- a/Modules/Applications/AppSegmentation/app/otbConnectedComponentSegmentation.cxx +++ b/Modules/Applications/AppSegmentation/app/otbConnectedComponentSegmentation.cxx @@ -76,8 +76,8 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); - AddDocTag(Tags::Analysis); AddDocTag(Tags::Segmentation); + AddDocTag(Tags::Analysis); AddParameter(ParameterType_InputImage, "in", "Input Image"); SetParameterDescription("in", "The image to segment."); diff --git a/Modules/Applications/AppSegmentation/app/otbHooverCompareSegmentation.cxx b/Modules/Applications/AppSegmentation/app/otbHooverCompareSegmentation.cxx index d8224dbf51a08fa5b72f858ee1d2df1820e07da5..14fce9949dad4ae4fee9ac0615ad5d2cfefd3103 100644 --- a/Modules/Applications/AppSegmentation/app/otbHooverCompareSegmentation.cxx +++ b/Modules/Applications/AppSegmentation/app/otbHooverCompareSegmentation.cxx @@ -292,10 +292,10 @@ private: m_InstanceFilter->Update(); - SetParameterFloat("rc", m_InstanceFilter->GetMeanRC()); - SetParameterFloat("rf", m_InstanceFilter->GetMeanRF()); - SetParameterFloat("ra", m_InstanceFilter->GetMeanRA()); - SetParameterFloat("rm", m_InstanceFilter->GetMeanRM()); + SetParameterFloat("rc",m_InstanceFilter->GetMeanRC(), false); + SetParameterFloat("rf",m_InstanceFilter->GetMeanRF(), false); + SetParameterFloat("ra",m_InstanceFilter->GetMeanRA(), false); + SetParameterFloat("rm",m_InstanceFilter->GetMeanRM(), false); } ImageToLabelMapFilterType::Pointer m_GTFilter; diff --git a/Modules/Applications/AppSegmentation/app/otbMeanShiftSmoothing.cxx b/Modules/Applications/AppSegmentation/app/otbMeanShiftSmoothing.cxx index c69ec3f1475c44852e8165140fb040a7863ed28b..fc92d2c17e1e9ff19bceacae246f80a272916c75 100644 --- a/Modules/Applications/AppSegmentation/app/otbMeanShiftSmoothing.cxx +++ b/Modules/Applications/AppSegmentation/app/otbMeanShiftSmoothing.cxx @@ -101,7 +101,7 @@ private: AddParameter(ParameterType_Empty, "modesearch", "Mode search."); SetParameterDescription("modesearch", "If activated pixel iterative convergence is stopped if the path crosses an already converged pixel. Be careful, with this option, the result will slightly depend on thread number"); - EnableParameter("modesearch"); + DisableParameter("modesearch"); // Doc example parameter settings diff --git a/Modules/Applications/AppSegmentation/app/otbSegmentation.cxx b/Modules/Applications/AppSegmentation/app/otbSegmentation.cxx index 4234666c4972d80a1e609f29ae873bd38af6c9be..6454b130e6cca255631841921a0c8e7dc1ec2d5a 100644 --- a/Modules/Applications/AppSegmentation/app/otbSegmentation.cxx +++ b/Modules/Applications/AppSegmentation/app/otbSegmentation.cxx @@ -305,11 +305,11 @@ private: AddParameter(ParameterType_String, "mode.vector.layername", "Layer name"); SetParameterDescription("mode.vector.layername", "Name of the layer in the vector file or database (default is Layer)."); - SetParameterString("mode.vector.layername", "layer"); + SetParameterString("mode.vector.layername", "layer", false); AddParameter(ParameterType_String, "mode.vector.fieldname", "Geometry index field name"); SetParameterDescription("mode.vector.fieldname", "Name of the field holding the geometry index in the output vector file or database."); - SetParameterString("mode.vector.fieldname", "DN"); + SetParameterString("mode.vector.fieldname", "DN", false); AddParameter(ParameterType_Int, "mode.vector.tilesize", "Tiles size"); SetParameterDescription("mode.vector.tilesize", diff --git a/Modules/Applications/AppStereo/app/otbStereoFramework.cxx b/Modules/Applications/AppStereo/app/otbStereoFramework.cxx index 1b18dc5b89b6cece6460f3c72f7774f239cc873b..e4c4e030e286d1754169ce702b5b9e65fd1c8dac 100644 --- a/Modules/Applications/AppStereo/app/otbStereoFramework.cxx +++ b/Modules/Applications/AppStereo/app/otbStereoFramework.cxx @@ -346,7 +346,7 @@ private: SetParameterDescription("input.co","List of index of couples im image list. Couples must be separated by a comma. (index start at 0). for example : 0 1,1 2 will process a first couple composed of the first and the second image in image list, then the first and the third image\n. note that images are handled by pairs." " if left empty couples are created from input index i.e. a first couple will be composed of the first and second image, a second couple with third and fourth image etc. (in this case image list must be even)."); MandatoryOff("input.co"); - SetParameterString("input.co",""); + SetParameterString("input.co","", false); DisableParameter("input.co"); AddParameter(ParameterType_Int, "input.channel", "Image channel used for the block matching"); @@ -363,7 +363,7 @@ private: // // Build the Output Map Projection // for custom map projection MapProjectionParametersHandler::AddMapProjectionParameters(this, "map"); - SetParameterString("map","wgs"); + SetParameterString("map","wgs", false); AddParameter(ParameterType_Float, "output.res","Output resolution"); SetParameterDescription("output.res","Spatial sampling distance of the output elevation : the cell size (in m)"); diff --git a/Modules/Applications/AppTest/app/otbTestApplication.cxx b/Modules/Applications/AppTest/app/otbTestApplication.cxx index e1bfd325fcb581117af3f0282555b3f822300de8..314f244e7061e20f0140b756c69d2197a7b23e3f 100644 --- a/Modules/Applications/AppTest/app/otbTestApplication.cxx +++ b/Modules/Applications/AppTest/app/otbTestApplication.cxx @@ -87,8 +87,8 @@ private: MandatoryOff("il"); AddParameter(ParameterType_ListView, "cl", "Output Image channels"); - AddChoice("cl.choice1", "cl.choice1"); - AddChoice("cl.choice2", "cl.choice2"); + AddChoice("cl.choice1", "Choice1"); + AddChoice("cl.choice2", "Choice2"); MandatoryOff("cl"); AddParameter(ParameterType_ComplexInputImage, "cin", "Input Complex Image"); @@ -106,6 +106,9 @@ private: void DoExecute() ITK_OVERRIDE { + FloatVectorImageListType* imgList = GetParameterImageList("il"); + SetParameterOutputImage("outgroup.outputimage", imgList->GetNthElement(0)); + SetParameterComplexOutputImage("cout", GetParameterComplexImage("cin")); //std::cout << "TestApplication::DoExecute" << std::endl; } }; diff --git a/Modules/Applications/AppTest/test/CMakeLists.txt b/Modules/Applications/AppTest/test/CMakeLists.txt index e9dadfc3068d4b6b271aefbd0cee29ac5de11c04..ac83baa32c87ed5668d8771b47623689258e0f62 100644 --- a/Modules/Applications/AppTest/test/CMakeLists.txt +++ b/Modules/Applications/AppTest/test/CMakeLists.txt @@ -12,3 +12,26 @@ otb_module_target_label(otbAppTestTestDriver) otb_add_test(NAME apCheckDocumentation COMMAND otbAppTestTestDriver otbWrapperApplicationDocTest ${OTB_BINARY_DIR}/lib/otb/applications) + +otb_test_application(NAME apTvTestApplicationOutputXML_All + APP TestApplication + OPTIONS -boolean 1 + -int 2 + -float -0.7 + -string foo + -filename ${INPUTDATA}/letter.scale + -outfilename ${TEMP}/foo.txt + -directory ${INPUTDATA}/world_boundaries + -choice.choice1.floatchoice1 6.4e5 + -ingroup.integer 4 + -outgroup.outputimage ${TEMP}/foo.tif double + -il ${INPUTDATA}/anaglyphInput1.tif ${INPUTDATA}/anaglyphInput2.tif + -cl Choice2 + -cin ${INPUTDATA}/RADARSAT2_ALTONA_300_300_VV.tif + -cout ${TEMP}/fooCplx.tif + -outxml ${TEMP}/apTvTestApplicationOutputXML_All.xml + VALID --compare-ascii ${NOTOL} + ${OTBAPP_BASELINE_FILES}/apTvTestApplicationOutputXML_All.xml + ${TEMP}/apTvTestApplicationOutputXML_All.xml + --ignore-lines-with 8 letter.scale foo.txt world_boundaries foo.tif anaglyphInput1.tif anaglyphInput2.tif RADARSAT2_ALTONA_300_300_VV.tif <version> + ) diff --git a/Modules/Applications/AppTest/test/otbWrapperApplicationDocTests.cxx b/Modules/Applications/AppTest/test/otbWrapperApplicationDocTests.cxx index 1fbaf04a5943511a562c4b80e7874ee9d798126f..43939374ce3f32770f4b7c91ae8ca0e18ed9a901 100644 --- a/Modules/Applications/AppTest/test/otbWrapperApplicationDocTests.cxx +++ b/Modules/Applications/AppTest/test/otbWrapperApplicationDocTests.cxx @@ -145,6 +145,7 @@ int otbWrapperApplicationDocTest(int argc, char* argv[]) } } } + ApplicationRegistry::CleanRegistry(); if( !isOK ) return EXIT_FAILURE; diff --git a/Modules/Applications/AppTextures/app/otbHaralickTextureExtraction.cxx b/Modules/Applications/AppTextures/app/otbHaralickTextureExtraction.cxx index fa14c6dc8209bb748c16f62e55c7eeaef716db9b..e007a457fd6a215d6ba3c1ddcca89122f1d0a98e 100644 --- a/Modules/Applications/AppTextures/app/otbHaralickTextureExtraction.cxx +++ b/Modules/Applications/AppTextures/app/otbHaralickTextureExtraction.cxx @@ -76,8 +76,8 @@ SetDocLimitations("None"); SetDocAuthors("OTB-Team"); SetDocSeeAlso("otbScalarImageToTexturesFilter, otbScalarImageToAdvancedTexturesFilter and otbScalarImageToHigherOrderTexturesFilter classes"); -AddDocTag("Textures"); AddDocTag(Tags::FeatureExtraction); +AddDocTag("Textures"); AddParameter(ParameterType_InputImage, "in", "Input Image"); SetParameterDescription("in", "The input image to compute the features on."); @@ -87,6 +87,13 @@ SetParameterDescription("channel", "The selected channel index"); SetDefaultParameterInt("channel", 1); SetMinimumParameterIntValue("channel", 1); +AddParameter(ParameterType_Int, "step", "Computation step"); +SetParameterDescription("step", "Step (in pixels) to compute output texture values." + " The first computed pixel position is shifted by (step-1)/2 in both directions."); +SetDefaultParameterInt("step", 1); +SetMinimumParameterIntValue("step", 1); +MandatoryOff("step"); + AddRAMParameter(); AddParameter(ParameterType_Group, "parameters", "Texture feature parameters"); @@ -180,6 +187,12 @@ void DoExecute() ITK_OVERRIDE offset[0] = GetParameterInt("parameters.xoff"); offset[1] = GetParameterInt("parameters.yoff"); + RadiusType stepping; + stepping.Fill(GetParameterInt("step")); + + OffsetType stepOffset; + stepOffset.Fill((GetParameterInt("step") - 1) / 2); + m_ExtractorFilter = ExtractorFilterType::New(); m_ExtractorFilter->SetInput(inImage); m_ExtractorFilter->SetStartX(inImage->GetLargestPossibleRegion().GetIndex(0)); @@ -214,6 +227,8 @@ void DoExecute() ITK_OVERRIDE m_HarTexFilter->SetInputImageMinimum(GetParameterFloat("parameters.min")); m_HarTexFilter->SetInputImageMaximum(GetParameterFloat("parameters.max")); m_HarTexFilter->SetNumberOfBinsPerAxis(GetParameterInt("parameters.nbbin")); + m_HarTexFilter->SetSubsampleFactor(stepping); + m_HarTexFilter->SetSubsampleOffset(stepOffset); m_HarTexFilter->UpdateOutputInformation(); m_HarImageList->PushBack(m_HarTexFilter->GetEnergyOutput()); m_HarImageList->PushBack(m_HarTexFilter->GetEntropyOutput()); @@ -235,6 +250,8 @@ void DoExecute() ITK_OVERRIDE m_AdvTexFilter->SetInputImageMinimum(GetParameterFloat("parameters.min")); m_AdvTexFilter->SetInputImageMaximum(GetParameterFloat("parameters.max")); m_AdvTexFilter->SetNumberOfBinsPerAxis(GetParameterInt("parameters.nbbin")); + m_AdvTexFilter->SetSubsampleFactor(stepping); + m_AdvTexFilter->SetSubsampleOffset(stepOffset); m_AdvImageList->PushBack(m_AdvTexFilter->GetMeanOutput()); m_AdvImageList->PushBack(m_AdvTexFilter->GetVarianceOutput()); m_AdvImageList->PushBack(m_AdvTexFilter->GetDissimilarityOutput()); @@ -257,6 +274,8 @@ void DoExecute() ITK_OVERRIDE m_HigTexFilter->SetInputImageMinimum(GetParameterFloat("parameters.min")); m_HigTexFilter->SetInputImageMaximum(GetParameterFloat("parameters.max")); m_HigTexFilter->SetNumberOfBinsPerAxis(GetParameterInt("parameters.nbbin")); + m_HigTexFilter->SetSubsampleFactor(stepping); + m_HigTexFilter->SetSubsampleOffset(stepOffset); m_HigImageList->PushBack(m_HigTexFilter->GetShortRunEmphasisOutput()); m_HigImageList->PushBack(m_HigTexFilter->GetLongRunEmphasisOutput()); m_HigImageList->PushBack(m_HigTexFilter->GetGreyLevelNonuniformityOutput()); diff --git a/Modules/Applications/AppTextures/app/otbSFSTextureExtraction.cxx b/Modules/Applications/AppTextures/app/otbSFSTextureExtraction.cxx index 3fe88a9897dfc0b58ab64b9d378be0a45397a926..a415efc6de4c6ae79b103f5815bde9e8a6f939b2 100644 --- a/Modules/Applications/AppTextures/app/otbSFSTextureExtraction.cxx +++ b/Modules/Applications/AppTextures/app/otbSFSTextureExtraction.cxx @@ -67,8 +67,8 @@ SetDocLimitations("None"); SetDocAuthors("OTB-Team"); SetDocSeeAlso("otbSFSTexturesImageFilter class"); -AddDocTag("Textures"); AddDocTag(Tags::FeatureExtraction); +AddDocTag("Textures"); AddParameter(ParameterType_InputImage, "in", "Input Image"); SetParameterDescription("in", "The input image to compute the features on."); diff --git a/Modules/Applications/AppVectorDataTranslation/app/otbRasterization.cxx b/Modules/Applications/AppVectorDataTranslation/app/otbRasterization.cxx index 683a46b83422b4712005904939e2c95e3d4d35e5..1d3ebf78fa4aad74b62fb4389e843442c0cd774e 100644 --- a/Modules/Applications/AppVectorDataTranslation/app/otbRasterization.cxx +++ b/Modules/Applications/AppVectorDataTranslation/app/otbRasterization.cxx @@ -129,7 +129,7 @@ private: AddParameter(ParameterType_String,"mode.attribute.field","The attribute field to burn"); SetParameterDescription("mode.attribute.field","Name of the attribute field to burn"); - SetParameterString("mode.attribute.field","DN"); + SetParameterString("mode.attribute.field","DN", false); AddRAMParameter(); diff --git a/Modules/Applications/AppVectorUtils/app/otbOSMDownloader.cxx b/Modules/Applications/AppVectorUtils/app/otbOSMDownloader.cxx index 3ff6ee10d1ec3047b183c11877000d4891aa63ae..c50b4bf44e4c91ca0429748a432699c68b801718 100644 --- a/Modules/Applications/AppVectorUtils/app/otbOSMDownloader.cxx +++ b/Modules/Applications/AppVectorUtils/app/otbOSMDownloader.cxx @@ -58,7 +58,9 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso("Conversion"); + AddDocTag("Miscellaneous"); AddDocTag(Tags::Meta); + AddDocTag(Tags::Vector); AddParameter(ParameterType_OutputVectorData, "out", "Output vector data"); SetParameterDescription("out", "Generated output vector data path"); diff --git a/Modules/Applications/AppVectorUtils/app/otbVectorDataExtractROI.cxx b/Modules/Applications/AppVectorUtils/app/otbVectorDataExtractROI.cxx index 95e1ef3968fa18f09215ef0b1dccc9512d050627..44676f632befdd0bc4a43caef90fabac916f654a 100644 --- a/Modules/Applications/AppVectorUtils/app/otbVectorDataExtractROI.cxx +++ b/Modules/Applications/AppVectorUtils/app/otbVectorDataExtractROI.cxx @@ -77,6 +77,7 @@ private: SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); + AddDocTag(Tags::Vector); AddDocTag(Tags::Vector); AddParameter(ParameterType_Group,"io","Input and output data"); diff --git a/Modules/Core/ImageBase/test/CMakeLists.txt b/Modules/Core/ImageBase/test/CMakeLists.txt index 3d74d3d4230565e3486736f9b1a93ab23ae57ef7..1c9c2b3054130a455fc72f4f6190c18d0f3ee631 100644 --- a/Modules/Core/ImageBase/test/CMakeLists.txt +++ b/Modules/Core/ImageBase/test/CMakeLists.txt @@ -650,23 +650,6 @@ otb_add_test(NAME ioTvMultiChannelROI_p1_06_JPEG2000_2_TIF_res0 COMMAND otbIma ${TEMP}/ioExtractROI_JPEG2K_2_TIF_p1_06_OUT.tif ) -# Only do the following test if we are using the OTB Openjpeg driver, -# because gdal does not report jpeg2000 overview with size < 128 -# pixel, and will therefore interpolate. -if(OTB_USE_OPENJPEG) - -# Read an area inside one tile at resolution 4 (jpeg2000 conformance file with -# specific tile size at different resolution). -otb_add_test(NAME ioTvMultiChannelROI_p1_06_JPEG2000_2_TIF_res4 COMMAND otbImageBaseTestDriver - --compare-image ${EPSILON_9} ${BASELINE}/ioExtractROI_JPEG2K_2_TIF_p1_06_res4.tif - ${TEMP}/ioExtractROI_JPEG2K_2_TIF_p1_06_res4_OUT.tif - otbMultiChannelExtractROI - ${INPUTDATA}/jpeg2000_conf_p1_06.j2k?&resol=4 - ${TEMP}/ioExtractROI_JPEG2K_2_TIF_p1_06_res4_OUT.tif - ) - -endif() - # Read an area inside one tile at resolution 0 (quite similar coding parameter with pleiade # except it a lossless image with no quatization style). otb_add_test(NAME ioTvMultiChannelROI_lena_JPEG2000_2_TIF_res0 COMMAND otbImageBaseTestDriver diff --git a/Modules/Core/Interpolation/include/otbBCOInterpolateImageFunction.txx b/Modules/Core/Interpolation/include/otbBCOInterpolateImageFunction.txx index 89572aad83c63b515005883f223dc86d2d757b78..6f0fd2ad70165d7fb331a571fe456a33b33ea926 100644 --- a/Modules/Core/Interpolation/include/otbBCOInterpolateImageFunction.txx +++ b/Modules/Core/Interpolation/include/otbBCOInterpolateImageFunction.txx @@ -142,8 +142,6 @@ BCOInterpolateImageFunction<TInputImage, TCoordRep> IndexType baseIndex; IndexType neighIndex; - std::vector<RealType> lineRes(this->m_WinSize, 0.); - RealType value = itk::NumericTraits<RealType>::Zero; CoefContainerType BCOCoefX = this->EvaluateCoef(index[0]); @@ -157,6 +155,7 @@ BCOInterpolateImageFunction<TInputImage, TCoordRep> for(unsigned int i = 0; i < this->m_WinSize; ++i ) { + RealType lineRes = 0.; for(unsigned int j = 0; j < this->m_WinSize; ++j ) { // get neighbor index @@ -179,9 +178,9 @@ BCOInterpolateImageFunction<TInputImage, TCoordRep> { neighIndex[1] = this->m_StartIndex[1]; } - lineRes[i] += static_cast<RealType>( this->GetInputImage()->GetPixel( neighIndex ) ) * BCOCoefY[j]; + lineRes += static_cast<RealType>( this->GetInputImage()->GetPixel( neighIndex ) ) * BCOCoefY[j]; } - value += lineRes[i]*BCOCoefX[i]; + value += lineRes*BCOCoefX[i]; } @@ -211,14 +210,9 @@ BCOInterpolateImageFunction< otb::VectorImage<TPixel, VImageDimension> , TCoordR IndexType neighIndex; - - std::vector< std::vector<ScalarRealType> > lineRes ( this->m_WinSize, std::vector<ScalarRealType>( componentNumber, itk::NumericTraits<ScalarRealType>::Zero) ); - std::vector< ScalarRealType > value(componentNumber,itk::NumericTraits<ScalarRealType>::Zero); - - - OutputType output; - - output.SetSize(componentNumber); + std::vector<ScalarRealType> lineRes(componentNumber); + OutputType output(componentNumber); + output.Fill(itk::NumericTraits<ScalarRealType>::Zero); CoefContainerType BCOCoefX = this->EvaluateCoef(index[0]); CoefContainerType BCOCoefY = this->EvaluateCoef(index[1]); @@ -231,6 +225,7 @@ BCOInterpolateImageFunction< otb::VectorImage<TPixel, VImageDimension> , TCoordR for(unsigned int i = 0; i < this->m_WinSize; ++i ) { + std::fill(lineRes.begin(), lineRes.end(), itk::NumericTraits<ScalarRealType>::Zero); for(unsigned int j = 0; j < this->m_WinSize; ++j ) { // get neighbor index @@ -256,20 +251,15 @@ BCOInterpolateImageFunction< otb::VectorImage<TPixel, VImageDimension> , TCoordR const InputPixelType & pixel = this->GetInputImage()->GetPixel( neighIndex ); for( unsigned int k = 0; k<componentNumber; ++k) { - lineRes[i][k] += pixel.GetElement(k) * BCOCoefY[j]; + lineRes[k] += pixel.GetElement(k) * BCOCoefY[j]; } } for( unsigned int k = 0; k<componentNumber; ++k) { - value[k] += lineRes[i][k]*BCOCoefX[i]; + output[k] += lineRes[k]*BCOCoefX[i]; } } - for( unsigned int k = 0; k<componentNumber; ++k) - { - output.SetElement(k, value[k]); - } - return ( output ); } diff --git a/Modules/Core/Metadata/src/otbSentinel1ImageMetadataInterface.cxx b/Modules/Core/Metadata/src/otbSentinel1ImageMetadataInterface.cxx index 2a42ba1430cd4d71b81388037a8cfc80f0bee821..e00c1aa0cb4ea48ea6b4a74881f5a4e484f270af 100644 --- a/Modules/Core/Metadata/src/otbSentinel1ImageMetadataInterface.cxx +++ b/Modules/Core/Metadata/src/otbSentinel1ImageMetadataInterface.cxx @@ -94,9 +94,9 @@ Sentinel1ImageMetadataInterface otbMsgDevMacro(<<"calibration.startTime: "<<std::setprecision(16) << firstLineTime); otbMsgDevMacro(<<"calibration.stopTime : "<<std::setprecision(16) << lastLineTime); - const std::string supportDataPrefix = "support_data."; //make && use GetBandPrefix(subSwath, polarisation) + //const std::string supportDataPrefix = "support_data."; //make && use GetBandPrefix(subSwath, polarisation) - const int numOfLines = Utils::LexicalCast<int>(imageKeywordlist.GetMetadataByKey(supportDataPrefix + "number_lines"), supportDataPrefix + "number_lines(int)"); + const int numOfLines = Utils::LexicalCast<int>(imageKeywordlist.GetMetadataByKey("number_lines"), "number_lines(int)"); otbMsgDevMacro(<<"numOfLines : " << numOfLines); const int count = Utils::LexicalCast<int>(imageKeywordlist.GetMetadataByKey("calibration.count"), "calibration.count"); diff --git a/Modules/Core/Metadata/test/CMakeLists.txt b/Modules/Core/Metadata/test/CMakeLists.txt index 0217f7387745ff58527bb6c3a5c618e06e4e0345..dd74719a20306c81c292cd1be5e890afccfb3e58 100644 --- a/Modules/Core/Metadata/test/CMakeLists.txt +++ b/Modules/Core/Metadata/test/CMakeLists.txt @@ -385,7 +385,7 @@ otb_add_test(NAME ioTvSarCalibrationLookupDataTest_SENTINEL1 COMMAND otbMetadata --compare-ascii ${NOTOL} ${BASELINE_FILES}/ioTvSarCalibrationLookupDataTest_SENTINEL1.txt ${TEMP}/ioTvSarCalibrationLookupDataTest_SENTINEL1.txt otbSarCalibrationLookupDataTest - ${INPUTDATA}/SENTINEL1_SLC_S6_1S_extract_300_300.tif?&geom=${INPUTDATA}/SENTINEL1_SLC_S6_1S_extract_300_300.geom + ${INPUTDATA}/SENTINEL1_SLC_S6_1S_extract_1200_1100_300_300.tiff?&geom=${INPUTDATA}/SENTINEL1_SLC_S6_1S_extract_1200_1100_300_300.geom ${TEMP}/ioTvSarCalibrationLookupDataTest_SENTINEL1.txt ) diff --git a/Modules/Core/Transform/include/otbStreamingWarpImageFilter.h b/Modules/Core/Transform/include/otbStreamingWarpImageFilter.h index 813a4440bfebbf3b1dd0f2920cc013365a1c16a5..19435f45c38c0fbb3ef26fb2c124ab664990b68e 100644 --- a/Modules/Core/Transform/include/otbStreamingWarpImageFilter.h +++ b/Modules/Core/Transform/include/otbStreamingWarpImageFilter.h @@ -105,7 +105,7 @@ private: StreamingWarpImageFilter(const Self &); //purposely not implemented void operator =(const Self&); //purposely not implemented - // Assesment of the maximum displacement for streaming + // Assessment of the maximum displacement for streaming DisplacementValueType m_MaximumDisplacement; }; diff --git a/Modules/Detection/ObjectDetection/include/otbDescriptorsListSampleGenerator.txx b/Modules/Detection/ObjectDetection/include/otbDescriptorsListSampleGenerator.txx index 0f9b7b680ba817197df2e9791085bdc108d0bb9e..bccb8ec45ee827f3a0016597688c2b2586dd7fce 100644 --- a/Modules/Detection/ObjectDetection/include/otbDescriptorsListSampleGenerator.txx +++ b/Modules/Detection/ObjectDetection/include/otbDescriptorsListSampleGenerator.txx @@ -203,26 +203,22 @@ PersistentDescriptorsListSampleGenerator<TInputImage, TVectorData, TFunctionType labelListSample->SetMeasurementVectorSize(m_ThreadLabelListSample[0]->GetMeasurementVectorSize()); // Copy the first thread elements into lists - if( this->GetNumberOfThreads() > 1 ) + ListSampleType* threadListSample = m_ThreadListSample[0]; + LabelListSampleType* threadLabelListSample = m_ThreadLabelListSample[0]; + SamplesPositionType& threadSamplesPosition = m_ThreadSamplesPosition[0]; + for (unsigned int i = 0; i < threadListSample->Size(); ++i) { - ListSampleType* threadListSample = m_ThreadListSample[0]; - LabelListSampleType* threadLabelListSample = m_ThreadLabelListSample[0]; - SamplesPositionType& threadSamplesPosition = m_ThreadSamplesPosition[0]; - - for (unsigned int i = 0; i < threadListSample->Size(); ++i) - { - listSample->PushBack( threadListSample->GetMeasurementVector(i) ); - labelListSample->PushBack( threadLabelListSample->GetMeasurementVector(i) ); - samplesPosition.push_back( threadSamplesPosition[i] ); - } + listSample->PushBack( threadListSample->GetMeasurementVector(i) ); + labelListSample->PushBack( threadLabelListSample->GetMeasurementVector(i) ); + samplesPosition.push_back( threadSamplesPosition[i] ); } // Add the other thread element checking if the point dosn't already exist for (itk::ThreadIdType threadId = 1; threadId < this->GetNumberOfThreads(); ++threadId ) { - ListSampleType* threadListSample = m_ThreadListSample[threadId]; - LabelListSampleType* threadLabelListSample = m_ThreadLabelListSample[threadId]; - SamplesPositionType& threadSamplesPosition = m_ThreadSamplesPosition[threadId]; + threadListSample = m_ThreadListSample[threadId]; + threadLabelListSample = m_ThreadLabelListSample[threadId]; + threadSamplesPosition = m_ThreadSamplesPosition[threadId]; for (unsigned int i = 0; i < threadListSample->Size(); ++i) { diff --git a/Modules/Feature/Textures/include/otbScalarImageToAdvancedTexturesFilter.h b/Modules/Feature/Textures/include/otbScalarImageToAdvancedTexturesFilter.h index 456cf4aca4b25fae98cf8bfa0bbf7bfa3d390ff9..42c1a5f0739946ca6fbdf6e6717333bf1af3ded5 100644 --- a/Modules/Feature/Textures/include/otbScalarImageToAdvancedTexturesFilter.h +++ b/Modules/Feature/Textures/include/otbScalarImageToAdvancedTexturesFilter.h @@ -164,6 +164,18 @@ public: /** Get the input image maximum */ itkGetMacro(InputImageMaximum, InputPixelType); + /** Set the sub-sampling factor */ + itkSetMacro(SubsampleFactor, SizeType); + + /** Get the sub-sampling factor */ + itkGetMacro(SubsampleFactor, SizeType); + + /** Set the sub-sampling offset */ + itkSetMacro(SubsampleOffset, OffsetType); + + /** Get the sub-sampling offset */ + itkGetMacro(SubsampleOffset, OffsetType); + /** Get the mean output image */ OutputImageType * GetMeanOutput(); @@ -199,6 +211,8 @@ protected: ScalarImageToAdvancedTexturesFilter(); /** Destructor */ ~ScalarImageToAdvancedTexturesFilter() ITK_OVERRIDE; + /** Generate the output informations */ + void GenerateOutputInformation() ITK_OVERRIDE; /** Generate the input requested region */ void GenerateInputRequestedRegion() ITK_OVERRIDE; /** Before Parallel textures extraction */ @@ -231,6 +245,11 @@ private: /** Input image maximum */ InputPixelType m_InputImageMaximum; + /** Sub-sampling factor */ + SizeType m_SubsampleFactor; + + /** Sub-sampling offset */ + OffsetType m_SubsampleOffset; }; } // End namespace otb diff --git a/Modules/Feature/Textures/include/otbScalarImageToAdvancedTexturesFilter.txx b/Modules/Feature/Textures/include/otbScalarImageToAdvancedTexturesFilter.txx index e0463ab5c888f97a007d5ad62ba27d7a596dfbd1..80cf17d04104a6e9ee86abe698f36fd5b5dc8f5b 100644 --- a/Modules/Feature/Textures/include/otbScalarImageToAdvancedTexturesFilter.txx +++ b/Modules/Feature/Textures/include/otbScalarImageToAdvancedTexturesFilter.txx @@ -37,6 +37,8 @@ ScalarImageToAdvancedTexturesFilter<TInputImage, TOutputImage> , m_NumberOfBinsPerAxis(8) , m_InputImageMinimum(0) , m_InputImageMaximum(255) +, m_SubsampleFactor() +, m_SubsampleOffset() { // There are 10 outputs corresponding to the 9 textures indices this->SetNumberOfRequiredOutputs(10); @@ -52,6 +54,9 @@ ScalarImageToAdvancedTexturesFilter<TInputImage, TOutputImage> this->SetNthOutput(7, OutputImageType::New()); this->SetNthOutput(8, OutputImageType::New()); this->SetNthOutput(9, OutputImageType::New()); + + this->m_SubsampleFactor.Fill(1); + this->m_SubsampleOffset.Fill(0); } template <class TInputImage, class TOutputImage> @@ -188,6 +193,38 @@ ScalarImageToAdvancedTexturesFilter<TInputImage, TOutputImage> return static_cast<OutputImageType *>(this->GetOutput(9)); } +template <class TInputImage, class TOutputImage> +void +ScalarImageToAdvancedTexturesFilter<TInputImage, TOutputImage> +::GenerateOutputInformation() +{ + // First, call superclass implementation + Superclass::GenerateOutputInformation(); + + // Compute output size, origin & spacing + InputRegionType inputRegion = this->GetInput()->GetLargestPossibleRegion(); + OutputRegionType outputRegion; + outputRegion.SetIndex(0,0); + outputRegion.SetIndex(1,0); + outputRegion.SetSize(0, 1 + (inputRegion.GetSize(0) - 1 - m_SubsampleOffset[0]) / m_SubsampleFactor[0]); + outputRegion.SetSize(1, 1 + (inputRegion.GetSize(1) - 1 - m_SubsampleOffset[1]) / m_SubsampleFactor[1]); + + typename OutputImageType::SpacingType outSpacing = this->GetInput()->GetSpacing(); + outSpacing[0] *= m_SubsampleFactor[0]; + outSpacing[1] *= m_SubsampleFactor[1]; + + typename OutputImageType::PointType outOrigin; + this->GetInput()->TransformIndexToPhysicalPoint(inputRegion.GetIndex()+m_SubsampleOffset,outOrigin); + + for (unsigned int i=0 ; i<this->GetNumberOfOutputs() ; i++) + { + OutputImagePointerType outputPtr = this->GetOutput(i); + outputPtr->SetLargestPossibleRegion(outputRegion); + outputPtr->SetOrigin(outOrigin); + outputPtr->SetSpacing(outSpacing); + } +} + template <class TInputImage, class TOutputImage> void ScalarImageToAdvancedTexturesFilter<TInputImage, TOutputImage> @@ -209,12 +246,19 @@ ScalarImageToAdvancedTexturesFilter<TInputImage, TOutputImage> // We use only the first output since requested regions for all outputs are enforced to be equal // by the default GenerateOutputRequestedRegiont() implementation OutputRegionType outputRequestedRegion = outputPtr->GetRequestedRegion(); + InputRegionType inputLargest = inputPtr->GetLargestPossibleRegion(); typename OutputRegionType::IndexType outputIndex = outputRequestedRegion.GetIndex(); typename OutputRegionType::SizeType outputSize = outputRequestedRegion.GetSize(); typename InputRegionType::IndexType inputIndex; typename InputRegionType::SizeType inputSize; + // Convert index and size to full grid + outputIndex[0] = outputIndex[0] * m_SubsampleFactor[0] + m_SubsampleOffset[0] + inputLargest.GetIndex(0); + outputIndex[1] = outputIndex[1] * m_SubsampleFactor[1] + m_SubsampleOffset[1] + inputLargest.GetIndex(1); + outputSize[0] = 1 + (outputSize[0] - 1) * m_SubsampleFactor[0]; + outputSize[1] = 1 + (outputSize[1] - 1) * m_SubsampleFactor[1]; + // First, apply offset for (unsigned int dim = 0; dim < InputImageType::ImageDimension; ++dim) { @@ -311,6 +355,8 @@ ScalarImageToAdvancedTexturesFilter<TInputImage, TOutputImage> const unsigned int histSize = m_NumberOfBinsPerAxis; const long unsigned int twiceHistSize = 2 * m_NumberOfBinsPerAxis; + InputRegionType inputLargest = inputPtr->GetLargestPossibleRegion(); + // Set-up progress reporting itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); @@ -330,11 +376,16 @@ ScalarImageToAdvancedTexturesFilter<TInputImage, TOutputImage> typename InputRegionType::IndexType inputIndex; typename InputRegionType::SizeType inputSize; + // Convert index to full grid + typename OutputImageType::IndexType outIndex; + // First, create an window for neighborhood iterator based on m_Radius // For example, if xradius and yradius is 2. window size is 5x5 (2 * radius + 1). for (unsigned int dim = 0; dim < InputImageType::ImageDimension; ++dim) { - inputIndex[dim] = varianceIt.GetIndex()[dim] - m_Radius[dim]; + outIndex[dim] = varianceIt.GetIndex()[dim] * m_SubsampleFactor[dim] + + m_SubsampleOffset[dim] + inputLargest.GetIndex(dim); + inputIndex[dim] = outIndex[dim] - m_Radius[dim]; inputSize[dim] = 2 * m_Radius[dim] + 1; } diff --git a/Modules/Feature/Textures/include/otbScalarImageToHigherOrderTexturesFilter.h b/Modules/Feature/Textures/include/otbScalarImageToHigherOrderTexturesFilter.h index 4879c7565a03a992d317e22b03d9e7b25e3bd184..781d69f80b028c6477dc0c03b6f95a709d504865 100644 --- a/Modules/Feature/Textures/include/otbScalarImageToHigherOrderTexturesFilter.h +++ b/Modules/Feature/Textures/include/otbScalarImageToHigherOrderTexturesFilter.h @@ -148,6 +148,18 @@ public: itkSetMacro(FastCalculations, bool); itkBooleanMacro(FastCalculations); + /** Set the sub-sampling factor */ + itkSetMacro(SubsampleFactor, SizeType); + + /** Get the sub-sampling factor */ + itkGetMacro(SubsampleFactor, SizeType); + + /** Set the sub-sampling offset */ + itkSetMacro(SubsampleOffset, OffsetType); + + /** Get the sub-sampling offset */ + itkGetMacro(SubsampleOffset, OffsetType); + /** Get the Short Run Emphasis output image */ OutputImageType * GetShortRunEmphasisOutput(); @@ -186,6 +198,8 @@ protected: ScalarImageToHigherOrderTexturesFilter(); /** Destructor */ ~ScalarImageToHigherOrderTexturesFilter() ITK_OVERRIDE; + /** Generate the output informations */ + void GenerateOutputInformation() ITK_OVERRIDE; /** Generate the input requested region */ void GenerateInputRequestedRegion() ITK_OVERRIDE; /** Parallel textures extraction */ @@ -215,6 +229,12 @@ private: /** Fast calculation */ bool m_FastCalculations; + + /** Sub-sampling factor */ + SizeType m_SubsampleFactor; + + /** Sub-sampling offset */ + OffsetType m_SubsampleOffset; }; } // End namespace otb diff --git a/Modules/Feature/Textures/include/otbScalarImageToHigherOrderTexturesFilter.txx b/Modules/Feature/Textures/include/otbScalarImageToHigherOrderTexturesFilter.txx index 66d4a4b65a75403e3c66805807f7e0d475868452..fecb7ae6bbe4965cd2d7fc4f58e5f4e08d0900c9 100644 --- a/Modules/Feature/Textures/include/otbScalarImageToHigherOrderTexturesFilter.txx +++ b/Modules/Feature/Textures/include/otbScalarImageToHigherOrderTexturesFilter.txx @@ -32,7 +32,9 @@ ScalarImageToHigherOrderTexturesFilter<TInputImage, TOutputImage> m_NumberOfBinsPerAxis(8), m_InputImageMinimum(0), m_InputImageMaximum(255), - m_FastCalculations(false) + m_FastCalculations(false), + m_SubsampleFactor(), + m_SubsampleOffset() { // There are 11 outputs corresponding to the 8 textures indices this->SetNumberOfRequiredOutputs(10); @@ -71,6 +73,8 @@ ScalarImageToHigherOrderTexturesFilter<TInputImage, TOutputImage> } this->SetOffsets( offsets ); + this->m_SubsampleFactor.Fill(1); + this->m_SubsampleOffset.Fill(0); } template <class TInputImage, class TOutputImage> @@ -231,6 +235,38 @@ ScalarImageToHigherOrderTexturesFilter<TInputImage, TOutputImage> this->SetOffsets( offsetVector ); } +template <class TInputImage, class TOutputImage> +void +ScalarImageToHigherOrderTexturesFilter<TInputImage, TOutputImage> +::GenerateOutputInformation() +{ + // First, call superclass implementation + Superclass::GenerateOutputInformation(); + + // Compute output size, origin & spacing + InputRegionType inputRegion = this->GetInput()->GetLargestPossibleRegion(); + OutputRegionType outputRegion; + outputRegion.SetIndex(0,0); + outputRegion.SetIndex(1,0); + outputRegion.SetSize(0, 1 + (inputRegion.GetSize(0) - 1 - m_SubsampleOffset[0]) / m_SubsampleFactor[0]); + outputRegion.SetSize(1, 1 + (inputRegion.GetSize(1) - 1 - m_SubsampleOffset[1]) / m_SubsampleFactor[1]); + + typename OutputImageType::SpacingType outSpacing = this->GetInput()->GetSpacing(); + outSpacing[0] *= m_SubsampleFactor[0]; + outSpacing[1] *= m_SubsampleFactor[1]; + + typename OutputImageType::PointType outOrigin; + this->GetInput()->TransformIndexToPhysicalPoint(inputRegion.GetIndex()+m_SubsampleOffset,outOrigin); + + for (unsigned int i=0 ; i<this->GetNumberOfOutputs() ; i++) + { + OutputImagePointerType outputPtr = this->GetOutput(i); + outputPtr->SetLargestPossibleRegion(outputRegion); + outputPtr->SetOrigin(outOrigin); + outputPtr->SetSpacing(outSpacing); + } +} + template <class TInputImage, class TOutputImage> void ScalarImageToHigherOrderTexturesFilter<TInputImage, TOutputImage> @@ -252,7 +288,17 @@ ScalarImageToHigherOrderTexturesFilter<TInputImage, TOutputImage> // We use only the first output since requested regions for all outputs are enforced to be equal // by the default GenerateOutputRequestedRegiont() implementation OutputRegionType outputRequestedRegion = outputPtr->GetRequestedRegion(); - InputRegionType inputRequestedRegion = outputRequestedRegion; + typename OutputRegionType::IndexType outputIndex = outputRequestedRegion.GetIndex(); + typename OutputRegionType::SizeType outputSize = outputRequestedRegion.GetSize(); + InputRegionType inputLargest = inputPtr->GetLargestPossibleRegion(); + + // Convert index and size to full grid + outputIndex[0] = outputIndex[0] * m_SubsampleFactor[0] + m_SubsampleOffset[0] + inputLargest.GetIndex(0); + outputIndex[1] = outputIndex[1] * m_SubsampleFactor[1] + m_SubsampleOffset[1] + inputLargest.GetIndex(1); + outputSize[0] = 1 + (outputSize[0] - 1) * m_SubsampleFactor[0]; + outputSize[1] = 1 + (outputSize[1] - 1) * m_SubsampleFactor[1]; + + InputRegionType inputRequestedRegion(outputIndex,outputSize); // Apply the radius inputRequestedRegion.PadByRadius(m_Radius); @@ -297,6 +343,8 @@ ScalarImageToHigherOrderTexturesFilter<TInputImage, TOutputImage> inputPtr->TransformIndexToPhysicalPoint( outputImagesIterators[0].GetIndex() + m_Radius, bottomRightPoint ); double maxDistance = topLeftPoint.EuclideanDistanceTo(bottomRightPoint); + InputRegionType inputLargest = inputPtr->GetLargestPossibleRegion(); + // Set-up progress reporting itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); @@ -304,12 +352,17 @@ ScalarImageToHigherOrderTexturesFilter<TInputImage, TOutputImage> while ( !outputImagesIterators[0].IsAtEnd() ) { // Compute the region on which run-length matrix will be estimated - typename InputRegionType::IndexType inputIndex = outputImagesIterators[0].GetIndex() - m_Radius; + typename InputRegionType::IndexType inputIndex; typename InputRegionType::SizeType inputSize; - // First, apply offset + // Convert index to full grid + typename OutputImageType::IndexType outIndex; + for (unsigned int dim = 0; dim < InputImageType::ImageDimension; ++dim) { + outIndex[dim] = outputImagesIterators[0].GetIndex()[dim] * m_SubsampleFactor[dim] + + m_SubsampleOffset[dim] + inputLargest.GetIndex(dim); + inputIndex[dim] = outIndex[dim] - m_Radius[dim]; inputSize[dim] = 2 * m_Radius[dim] + 1; } diff --git a/Modules/Feature/Textures/include/otbScalarImageToTexturesFilter.h b/Modules/Feature/Textures/include/otbScalarImageToTexturesFilter.h index bb40e1766ccf609329504448ec1aae6174032434..a8387cd74d9fa32312b9f43c63c64f454dc2e7de 100644 --- a/Modules/Feature/Textures/include/otbScalarImageToTexturesFilter.h +++ b/Modules/Feature/Textures/include/otbScalarImageToTexturesFilter.h @@ -166,6 +166,18 @@ public: /** Get the input image maximum */ itkGetMacro(InputImageMaximum, InputPixelType); + /** Set the sub-sampling factor */ + itkSetMacro(SubsampleFactor, SizeType); + + /** Get the sub-sampling factor */ + itkGetMacro(SubsampleFactor, SizeType); + + /** Set the sub-sampling offset */ + itkSetMacro(SubsampleOffset, OffsetType); + + /** Get the sub-sampling offset */ + itkGetMacro(SubsampleOffset, OffsetType); + /** Get the energy output image */ OutputImageType * GetEnergyOutput(); @@ -195,6 +207,8 @@ protected: ScalarImageToTexturesFilter(); /** Destructor */ ~ScalarImageToTexturesFilter() ITK_OVERRIDE; + /** Generate the output informations */ + void GenerateOutputInformation() ITK_OVERRIDE; /** Generate the input requested region */ void GenerateInputRequestedRegion() ITK_OVERRIDE; /** Before Parallel textures extraction */ @@ -230,6 +244,11 @@ private: //TODO: should we use constexpr? only c++11 and problem for msvc inline double GetPixelValueTolerance() const {return 0.0001; } + /** Sub-sampling factor */ + SizeType m_SubsampleFactor; + + /** Sub-sampling offset */ + OffsetType m_SubsampleOffset; }; } // End namespace otb diff --git a/Modules/Feature/Textures/include/otbScalarImageToTexturesFilter.txx b/Modules/Feature/Textures/include/otbScalarImageToTexturesFilter.txx index c67e3a9ebfd3d6d9a46f3cfc9955914ffcaa97a5..be489347843888f73133163f852140abd721eabd 100644 --- a/Modules/Feature/Textures/include/otbScalarImageToTexturesFilter.txx +++ b/Modules/Feature/Textures/include/otbScalarImageToTexturesFilter.txx @@ -39,6 +39,8 @@ ScalarImageToTexturesFilter<TInputImage, TOutputImage> , m_NumberOfBinsPerAxis(8) , m_InputImageMinimum(0) , m_InputImageMaximum(255) +, m_SubsampleFactor() +, m_SubsampleOffset() { // There are 8 outputs corresponding to the 8 textures indices this->SetNumberOfRequiredOutputs(8); @@ -52,6 +54,9 @@ ScalarImageToTexturesFilter<TInputImage, TOutputImage> this->SetNthOutput(5, OutputImageType::New()); this->SetNthOutput(6, OutputImageType::New()); this->SetNthOutput(7, OutputImageType::New()); + + this->m_SubsampleFactor.Fill(1); + this->m_SubsampleOffset.Fill(0); } template <class TInputImage, class TOutputImage> @@ -163,6 +168,38 @@ ScalarImageToTexturesFilter<TInputImage, TOutputImage> return static_cast<OutputImageType *>(this->GetOutput(7)); } +template <class TInputImage, class TOutputImage> +void +ScalarImageToTexturesFilter<TInputImage, TOutputImage> +::GenerateOutputInformation() +{ + // First, call superclass implementation + Superclass::GenerateOutputInformation(); + + // Compute output size, origin & spacing + InputRegionType inputRegion = this->GetInput()->GetLargestPossibleRegion(); + OutputRegionType outputRegion; + outputRegion.SetIndex(0,0); + outputRegion.SetIndex(1,0); + outputRegion.SetSize(0, 1 + (inputRegion.GetSize(0) - 1 - m_SubsampleOffset[0]) / m_SubsampleFactor[0]); + outputRegion.SetSize(1, 1 + (inputRegion.GetSize(1) - 1 - m_SubsampleOffset[1]) / m_SubsampleFactor[1]); + + typename OutputImageType::SpacingType outSpacing = this->GetInput()->GetSpacing(); + outSpacing[0] *= m_SubsampleFactor[0]; + outSpacing[1] *= m_SubsampleFactor[1]; + + typename OutputImageType::PointType outOrigin; + this->GetInput()->TransformIndexToPhysicalPoint(inputRegion.GetIndex()+m_SubsampleOffset,outOrigin); + + for (unsigned int i=0 ; i<this->GetNumberOfOutputs() ; i++) + { + OutputImagePointerType outputPtr = this->GetOutput(i); + outputPtr->SetLargestPossibleRegion(outputRegion); + outputPtr->SetOrigin(outOrigin); + outputPtr->SetSpacing(outSpacing); + } +} + template <class TInputImage, class TOutputImage> void ScalarImageToTexturesFilter<TInputImage, TOutputImage> @@ -189,6 +226,13 @@ ScalarImageToTexturesFilter<TInputImage, TOutputImage> typename OutputRegionType::SizeType outputSize = outputRequestedRegion.GetSize(); typename InputRegionType::IndexType inputIndex; typename InputRegionType::SizeType inputSize; + InputRegionType inputLargest = inputPtr->GetLargestPossibleRegion(); + + // Convert index and size to full grid + outputIndex[0] = outputIndex[0] * m_SubsampleFactor[0] + m_SubsampleOffset[0] + inputLargest.GetIndex(0); + outputIndex[1] = outputIndex[1] * m_SubsampleFactor[1] + m_SubsampleOffset[1] + inputLargest.GetIndex(1); + outputSize[0] = 1 + (outputSize[0] - 1) * m_SubsampleFactor[0]; + outputSize[1] = 1 + (outputSize[1] - 1) * m_SubsampleFactor[1]; // First, apply offset for (unsigned int dim = 0; dim < InputImageType::ImageDimension; ++dim) @@ -278,6 +322,8 @@ ScalarImageToTexturesFilter<TInputImage, TOutputImage> const double log2 = vcl_log(2.0); + InputRegionType inputLargest = inputPtr->GetLargestPossibleRegion(); + // Set-up progress reporting itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); @@ -295,11 +341,15 @@ ScalarImageToTexturesFilter<TInputImage, TOutputImage> typename InputRegionType::IndexType inputIndex; typename InputRegionType::SizeType inputSize; + // Convert index to full grid + typename OutputImageType::IndexType outIndex; + // First, create an window for neighborhood iterator based on m_Radius // For example, if xradius and yradius is 2. window size is 5x5 (2 * radius + 1). for (unsigned int dim = 0; dim < InputImageType::ImageDimension; ++dim) { - inputIndex[dim] = energyIt.GetIndex()[dim] - m_Radius[dim]; + outIndex[dim] = energyIt.GetIndex()[dim] * m_SubsampleFactor[dim] + m_SubsampleOffset[dim] + inputLargest.GetIndex(dim); + inputIndex[dim] = outIndex[dim] - m_Radius[dim]; inputSize[dim] = 2 * m_Radius[dim] + 1; } diff --git a/Modules/Filtering/Convolution/include/otbOverlapSaveConvolutionImageFilter.txx b/Modules/Filtering/Convolution/include/otbOverlapSaveConvolutionImageFilter.txx index 8b3126aa4a90eda0bc73ce1503fc9dc26b855863..37355308e66c19c463d37699a83b9c29c719b5a1 100644 --- a/Modules/Filtering/Convolution/include/otbOverlapSaveConvolutionImageFilter.txx +++ b/Modules/Filtering/Convolution/include/otbOverlapSaveConvolutionImageFilter.txx @@ -186,6 +186,9 @@ OverlapSaveConvolutionImageFilter<TInputImage, TOutputImage, TBoundaryCondition> unsigned int leftskip = static_cast<unsigned int>(std::max(0L, inputIndex[0] - pieceIndex[0])); unsigned int topskip = pieceSize[0] * static_cast<unsigned int>(std::max(0L, inputIndex[1] - pieceIndex[1])); + // zero filling + memset(inputPiece,0,pieceNbOfPixel * sizeof(InputPixelType)); + // Filling the buffer with image values for (l = 0; l < inputSize[1]; ++l) { @@ -205,6 +208,9 @@ OverlapSaveConvolutionImageFilter<TInputImage, TOutputImage, TBoundaryCondition> filterPieceFFT, FFTW_MEASURE); + // zero filling + memset(resampledFilterPiece,0,pieceNbOfPixel * sizeof(InputPixelType)); + k = 0; // Filling the buffer with filter values for (j = 0; j < sizeOfFilter[1]; ++j) diff --git a/Modules/Filtering/ImageManipulation/include/otbStreamingShrinkImageFilter.h b/Modules/Filtering/ImageManipulation/include/otbStreamingShrinkImageFilter.h index 38d511a2ca3b9ab38c56529d1bc238af2aadbf14..51cef1b3d9c74b4054c2c8eb47ec99a40ba5cfc8 100644 --- a/Modules/Filtering/ImageManipulation/include/otbStreamingShrinkImageFilter.h +++ b/Modules/Filtering/ImageManipulation/include/otbStreamingShrinkImageFilter.h @@ -78,7 +78,6 @@ public: const RegionType& region) ITK_OVERRIDE; itkGetMacro(TileSizeAlignment, unsigned int); - itkSetMacro(TileSizeAlignment, unsigned int); itkGetMacro(TileDimension, unsigned int); @@ -246,6 +245,9 @@ private: /** The shrink factor */ unsigned int m_ShrinkFactor; + + /** The offset to get the cell center */ + IndexType m_Offset; }; // end of class PersistentStatisticsVectorImageFilter diff --git a/Modules/Filtering/ImageManipulation/include/otbStreamingShrinkImageFilter.txx b/Modules/Filtering/ImageManipulation/include/otbStreamingShrinkImageFilter.txx index d20cd23bb9b90f355a6ef6cc3ba573682ca82f9a..df3082cce1c204d7228c1a48c7a74d03da54956c 100644 --- a/Modules/Filtering/ImageManipulation/include/otbStreamingShrinkImageFilter.txx +++ b/Modules/Filtering/ImageManipulation/include/otbStreamingShrinkImageFilter.txx @@ -43,7 +43,7 @@ StreamingShrinkStreamingManager<TImage>::PrepareStreaming( itk::DataObject * inp { typedef otb::StreamingShrinkImageRegionSplitter TileSplitterType; TileSplitterType::Pointer splitter = TileSplitterType::New(); - splitter->SetTileSizeAlignment(m_ShrinkFactor); + splitter->SetShrinkFactor(m_ShrinkFactor); this->m_Splitter = splitter; unsigned long nbDivisions = this->EstimateOptimalNumberOfDivisions(input, region, 0); @@ -125,6 +125,9 @@ PersistentShrinkImageFilter<TInputImage, TOutputImage> inputSpacing = inputPtr->GetSpacing(); const typename InputImageType::SizeType& inputSize = inputPtr->GetLargestPossibleRegion().GetSize(); + const typename InputImageType::IndexType& inputIndex + = inputPtr->GetLargestPossibleRegion().GetIndex(); + typename InputImageType::IndexType startIndex; typename OutputImageType::SpacingType shrunkOutputSpacing; typename OutputImageType::RegionType shrunkOutputLargestPossibleRegion; @@ -134,12 +137,14 @@ PersistentShrinkImageFilter<TInputImage, TOutputImage> for (unsigned int i = 0; i < OutputImageType::ImageDimension; ++i) { + startIndex[i] = inputIndex[i] + (m_ShrinkFactor - 1) / 2; + if (m_ShrinkFactor > inputSize[i]) + startIndex[i] = inputIndex[i] + (inputSize[i] - 1) / 2; + m_Offset[i] = startIndex[i] % m_ShrinkFactor; shrunkOutputSpacing[i] = inputSpacing[i] * static_cast<double>(m_ShrinkFactor); shrunkOutputSize[i] = inputSize[i] > m_ShrinkFactor ? inputSize[i] / m_ShrinkFactor : 1; - shrunkOutputOrigin[i] = inputPtr->GetOrigin()[i] + inputSpacing[i] * - (static_cast<double>(inputPtr->GetLargestPossibleRegion().GetIndex(i)) - 0.5) - + shrunkOutputSpacing[i] * 0.5; + shrunkOutputOrigin[i] = inputPtr->GetOrigin()[i] + inputSpacing[i] * startIndex[i]; // we choose to output a region with a start index [0,0] // the origin is set accordingly @@ -184,12 +189,12 @@ PersistentShrinkImageFilter<TInputImage, TOutputImage> { const IndexType& inIndex = inIt.GetIndex(); // TODO the pixel value should be taken near the centre of the cell, not at the corners - if (inIndex[0] % m_ShrinkFactor == 0 - && inIndex[1] % m_ShrinkFactor == 0 ) + if ((inIndex[0] - m_Offset[0]) % m_ShrinkFactor == 0 + && (inIndex[1] - m_Offset[1]) % m_ShrinkFactor == 0 ) { IndexType shrunkIndex; - shrunkIndex[0] = inIndex[0] / m_ShrinkFactor; - shrunkIndex[1] = inIndex[1] / m_ShrinkFactor; + shrunkIndex[0] = (inIndex[0] - m_Offset[0]) / m_ShrinkFactor; + shrunkIndex[1] = (inIndex[1] - m_Offset[1]) / m_ShrinkFactor; if (m_ShrunkOutput->GetLargestPossibleRegion().IsInside(shrunkIndex)) m_ShrunkOutput->SetPixel(shrunkIndex, inIt.Get()); } diff --git a/Modules/Filtering/ImageManipulation/include/otbVectorRescaleIntensityImageFilter.h b/Modules/Filtering/ImageManipulation/include/otbVectorRescaleIntensityImageFilter.h index 150b4166c9043b87bd200e880f8726105a8fdf6e..f7e5aa53b0f7ea7ff03a13479ab594339b81c0b5 100644 --- a/Modules/Filtering/ImageManipulation/include/otbVectorRescaleIntensityImageFilter.h +++ b/Modules/Filtering/ImageManipulation/include/otbVectorRescaleIntensityImageFilter.h @@ -198,10 +198,15 @@ private: * * This filter rescales each band to match the [OutputMinimum, OutputMaximum] range. * In order to avoid odd values to alter the intensity extent, one can set a clamp percentage. + * The clamp percentage is set to 0.01 by default. * * Values lower than the first quantile of this percentage are set to the OutputMinimum. * Values upper than the last quantile of this percentage are set to the OutputMaximum. * + * This filter differ from itk::VectorRescaleIntensityImageFilter. + * Instead of setting only the OutputMaximumMagnitude, you can set the minimum and maximum values for the input and output images. + * There is also the possibilty to set a Gamma value and change the clamp percentage. + * * \ingroup IntensityImageFilters * \ingroup MultiThreaded * diff --git a/Modules/Filtering/ImageManipulation/src/otbStreamingShrinkImageFilter.cxx b/Modules/Filtering/ImageManipulation/src/otbStreamingShrinkImageFilter.cxx index e1e2064c29a8155856e442209a750553efdba5b9..dbbb0c7036835d77cbaf84123d880e888514f76e 100644 --- a/Modules/Filtering/ImageManipulation/src/otbStreamingShrinkImageFilter.cxx +++ b/Modules/Filtering/ImageManipulation/src/otbStreamingShrinkImageFilter.cxx @@ -27,23 +27,24 @@ StreamingShrinkImageRegionSplitter unsigned int theoricalNbPixelPerTile = region.GetNumberOfPixels() / requestedNumber; unsigned int theoricalTileDimension = static_cast<unsigned int> (vcl_sqrt(static_cast<double>(theoricalNbPixelPerTile)) ); - // Take the previous multiple of m_TileSizeAlignment (eventually generate more splits than requested) - m_TileDimension = theoricalTileDimension / m_TileSizeAlignment * m_TileSizeAlignment; + // Take the previous multiple of m_ShrinkFactor (eventually generate more splits than requested) + m_TileDimension = theoricalTileDimension / m_ShrinkFactor * m_ShrinkFactor; - // Minimal tile size is m_TileSizeAlignment * m_TileSizeAlignment - if (m_TileDimension < m_TileSizeAlignment) + // Minimal tile size is m_ShrinkFactor * m_ShrinkFactor + if (m_TileDimension < m_ShrinkFactor) { - otbMsgDevMacro(<< "Using the minimal tile size : " << m_TileSizeAlignment << " * " << m_TileSizeAlignment); - m_TileDimension = m_TileSizeAlignment; + otbMsgDevMacro(<< "Using the minimal tile size : " << m_ShrinkFactor << " * " << m_ShrinkFactor); + m_TileDimension = m_ShrinkFactor; } - // Use the computed tile size, and generate (m_TileDimension * 1) tiles const SizeType& regionSize = region.GetSize(); - m_SplitsPerDimension[0] = (regionSize[0] + m_TileDimension - 1) / m_TileDimension; - m_SplitsPerDimension[1] = regionSize[1] / m_TileSizeAlignment; + // Compute the alignment of the sampling grid + m_TileSizeAlignment = (m_ShrinkFactor - 1) / 2; + if (m_ShrinkFactor > regionSize[1]) m_TileSizeAlignment = (regionSize[1] - 1)/2; - if (m_SplitsPerDimension[1] == 0) - m_SplitsPerDimension[1] = 1; + // Use the computed tile size, and generate (m_TileDimension * 1) tiles + m_SplitsPerDimension[0] = (regionSize[0] + m_TileDimension - 1) / m_TileDimension; + m_SplitsPerDimension[1] = (regionSize[1] - m_TileSizeAlignment - 1) / m_ShrinkFactor + 1; unsigned int numPieces = 1; for (unsigned int j = 0; j < ImageDimension; ++j) @@ -82,7 +83,7 @@ StreamingShrinkImageRegionSplitter // Transform the split index to the actual coordinates splitRegion.SetIndex(0, region.GetIndex(0) + m_TileDimension * splitIndex[0]); - splitRegion.SetIndex(1, region.GetIndex(1) + m_TileSizeAlignment * splitIndex[1]); + splitRegion.SetIndex(1, region.GetIndex(1) + m_ShrinkFactor * splitIndex[1] + m_TileSizeAlignment); splitRegion.SetSize(0, m_TileDimension); splitRegion.SetSize(1, 1); @@ -98,6 +99,7 @@ StreamingShrinkImageRegionSplitter ::PrintSelf(std::ostream& os, itk::Indent indent) const { Superclass::PrintSelf(os, indent); + os << indent << "ShrinkFactor : " << m_ShrinkFactor << std::endl; os << indent << "SplitsPerDimension : " << m_SplitsPerDimension << std::endl; os << indent << "TileDimension : " << m_TileDimension << std::endl; os << indent << "TileSizeAlignment : " << m_TileSizeAlignment << std::endl; diff --git a/Modules/Filtering/MathParserX/include/otbParserX.h b/Modules/Filtering/MathParserX/include/otbParserX.h index eb58857f4cc4d1e1a15fb03f92443355efd1834b..55eecfa431adb46e1e6a67c03e6109b863bafe7f 100644 --- a/Modules/Filtering/MathParserX/include/otbParserX.h +++ b/Modules/Filtering/MathParserX/include/otbParserX.h @@ -24,8 +24,15 @@ #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wc++11-extensions" + +/* Apple's 3.6.0 based clang doesn't support -Winconsistent-missing-override */ +#if !defined(__apple_build_version__) || __apple_build_version__ >= 7000053 +#pragma clang diagnostic ignored "-Winconsistent-missing-override" +#endif + #include "mpParser.h" -#pragma GCC diagnostic pop +#pragma clang diagnostic pop + #else #include "mpParser.h" #endif diff --git a/Modules/Filtering/Smoothing/include/otbMeanShiftSmoothingImageFilter.txx b/Modules/Filtering/Smoothing/include/otbMeanShiftSmoothingImageFilter.txx index 50d39f72857d3ee05bd69be74d6e488b16295677..aa3dbe452d340d63e6113b8fda1f5b3fa05dc192 100644 --- a/Modules/Filtering/Smoothing/include/otbMeanShiftSmoothingImageFilter.txx +++ b/Modules/Filtering/Smoothing/include/otbMeanShiftSmoothingImageFilter.txx @@ -38,7 +38,7 @@ MeanShiftSmoothingImageFilter<TInputImage, TOutputImage, TKernel, TOutputIterati , m_NumberOfComponentsPerPixel(0) // , m_JointImage(0) // , m_ModeTable(0) - , m_ModeSearch(true) + , m_ModeSearch(false) , m_ThreadIdNumberOfBits(0) #if 0 , m_BucketOptimization(false) diff --git a/Modules/Filtering/Statistics/include/otbPeriodicSampler.h b/Modules/Filtering/Statistics/include/otbPeriodicSampler.h index 3940bcd796b022d9d9ff7d9dbff42bacd9255fc4..3cc91743e735c0302436c078a842f265d17184f0 100644 --- a/Modules/Filtering/Statistics/include/otbPeriodicSampler.h +++ b/Modules/Filtering/Statistics/include/otbPeriodicSampler.h @@ -51,6 +51,9 @@ public: /** Maximum jitter to introduce (0 means no jitter) */ unsigned long MaxJitter; + + /** Maximum buffer size for internal jitter values */ + unsigned long MaxBufferSize; bool operator!=(const struct Parameter & param) const; } ParameterType; @@ -109,6 +112,9 @@ private: /** Internal current offset value * (either fixed, or reset each time a sample is taken)*/ double m_OffsetValue; + + /** jitter offsets computed up to MaxBufferSize */ + std::vector<double> m_JitterValues; }; } // namespace otb diff --git a/Modules/Filtering/Statistics/include/otbStreamingStatisticsVectorImageFilter.h b/Modules/Filtering/Statistics/include/otbStreamingStatisticsVectorImageFilter.h index d3da80dceb3d65e08965727eec485e187c8da615..fcb3d0d4f03d0042601510569e8994a449b3c993 100644 --- a/Modules/Filtering/Statistics/include/otbStreamingStatisticsVectorImageFilter.h +++ b/Modules/Filtering/Statistics/include/otbStreamingStatisticsVectorImageFilter.h @@ -88,6 +88,7 @@ public: /** Type to use for computations. */ typedef itk::VariableSizeMatrix<PrecisionType> MatrixType; typedef itk::VariableLengthVector<PrecisionType> RealPixelType; + typedef itk::VariableLengthVector<unsigned long> CountType; /** Type of DataObjects used for outputs */ typedef itk::SimpleDataObjectDecorator<RealType> RealObjectType; @@ -95,6 +96,15 @@ public: typedef itk::SimpleDataObjectDecorator<PixelType> PixelObjectType; typedef itk::SimpleDataObjectDecorator<RealPixelType> RealPixelObjectType; typedef itk::SimpleDataObjectDecorator<MatrixType> MatrixObjectType; + typedef itk::SimpleDataObjectDecorator<CountType> CountObjectType; + + /** Return the number of relevant pixels **/ + CountType GetNbRelevantPixels() const + { + return this->GetNbRelevantPixelsOutput()->Get(); + } + CountObjectType* GetNbRelevantPixelsOutput(); + const CountObjectType* GetNbRelevantPixelsOutput() const; /** Return the computed Min */ PixelType GetMinimum() const @@ -300,6 +310,8 @@ public: typedef typename StatFilterType::RealPixelObjectType RealPixelObjectType; typedef typename StatFilterType::MatrixType MatrixType; typedef typename StatFilterType::MatrixObjectType MatrixObjectType; + typedef typename StatFilterType::CountType CountType; + typedef typename StatFilterType::CountObjectType CountObjectType; typedef typename StatFilterType::InternalPixelType InternalPixelType; @@ -313,6 +325,21 @@ public: return this->GetFilter()->GetInput(); } + /** Return the number of relevant pixels **/ + CountType GetNbRelevantPixels() const + { + return this->GetFilter()->GetNbRelevantPixelsOutput()->Get(); + } + CountObjectType* GetNbRelevantPixelsOutput() + { + return this->GetFilter()->GetNbRelevantPixelsOutput(); + } + const CountObjectType* GetNbRelevantPixelsOutput() const + { + return this->GetFilter()->GetNbRelevantPixelsOutput(); + } + + /** Return the computed Minimum. */ RealPixelType GetMinimum() const { @@ -383,7 +410,7 @@ public: return this->GetFilter()->GetCovarianceOutput(); } - /** Return the computed Covariance. */ + /** Return the computed Correlation. */ MatrixType GetCorrelation() const { return this->GetFilter()->GetCorrelationOutput()->Get(); @@ -425,7 +452,7 @@ public: return this->GetFilter()->GetComponentCovarianceOutput(); } - /** Return the computed Covariance. */ + /** Return the computed Correlation. */ RealType GetComponentCorrelation() const { return this->GetFilter()->GetComponentCorrelationOutput()->Get(); diff --git a/Modules/Filtering/Statistics/include/otbStreamingStatisticsVectorImageFilter.txx b/Modules/Filtering/Statistics/include/otbStreamingStatisticsVectorImageFilter.txx index c327cf3c1d59da9c4cf136ffa9f9afa3fe380329..3b2a0d9d9a67b4d71cb052ee1cb80d02d99a0604 100644 --- a/Modules/Filtering/Statistics/include/otbStreamingStatisticsVectorImageFilter.txx +++ b/Modules/Filtering/Statistics/include/otbStreamingStatisticsVectorImageFilter.txx @@ -43,7 +43,7 @@ PersistentStreamingStatisticsVectorImageFilter<TInputImage, TPrecision> // allocate the data objects for the outputs which are // just decorators around vector/matrix types - for (unsigned int i = 1; i < 10; ++i) + for (unsigned int i = 1; i < 11; ++i) { this->itk::ProcessObject::SetNthOutput(i, this->MakeOutput(i).GetPointer()); } @@ -83,6 +83,9 @@ PersistentStreamingStatisticsVectorImageFilter<TInputImage, TPrecision> // component mean, component covariance, component correlation return static_cast<itk::DataObject*>(RealObjectType::New().GetPointer()); break; + case 10: + // relevant pixel + return static_cast<itk::DataObject*>(CountObjectType::New().GetPointer()); default: // might as well make an image return static_cast<itk::DataObject*>(TInputImage::New().GetPointer()); @@ -90,6 +93,23 @@ PersistentStreamingStatisticsVectorImageFilter<TInputImage, TPrecision> } } +template<class TInputImage, class TPrecision> +typename PersistentStreamingStatisticsVectorImageFilter<TInputImage, TPrecision>::CountObjectType* +PersistentStreamingStatisticsVectorImageFilter<TInputImage, TPrecision> +::GetNbRelevantPixelsOutput() +{ + return static_cast<CountObjectType*>(this->itk::ProcessObject::GetOutput(10)); +} + +template<class TInputImage, class TPrecision> +const typename PersistentStreamingStatisticsVectorImageFilter<TInputImage, TPrecision>::CountObjectType* +PersistentStreamingStatisticsVectorImageFilter<TInputImage, TPrecision> +::GetNbRelevantPixelsOutput() const +{ + return static_cast<const CountObjectType*>(this->itk::ProcessObject::GetOutput(10)); +} + + template<class TInputImage, class TPrecision> typename PersistentStreamingStatisticsVectorImageFilter<TInputImage, TPrecision>::PixelObjectType* PersistentStreamingStatisticsVectorImageFilter<TInputImage, TPrecision> @@ -419,10 +439,15 @@ PersistentStreamingStatisticsVectorImageFilter<TInputImage, TPrecision> ); } - unsigned int nbRelevantPixels = + unsigned int nbRelevantPixel = nbPixels - (ignoredInfinitePixelCount + ignoredUserPixelCount); - if( nbRelevantPixels==0 ) + CountType nbRelevantPixels(numberOfComponent); + nbRelevantPixels.Fill(nbRelevantPixel); + + this->GetNbRelevantPixelsOutput()->Set(nbRelevantPixels); + + if( nbRelevantPixel==0 ) { itkExceptionMacro( "Statistics cannot be calculated with zero relevant pixels." @@ -438,15 +463,15 @@ PersistentStreamingStatisticsVectorImageFilter<TInputImage, TPrecision> if (m_EnableFirstOrderStats) { - this->GetComponentMeanOutput()->Set(streamFirstOrderComponentAccumulator / (nbRelevantPixels * numberOfComponent)); + this->GetComponentMeanOutput()->Set(streamFirstOrderComponentAccumulator / (nbRelevantPixel * numberOfComponent)); - this->GetMeanOutput()->Set(streamFirstOrderAccumulator / nbRelevantPixels); + this->GetMeanOutput()->Set(streamFirstOrderAccumulator / nbRelevantPixel); this->GetSumOutput()->Set(streamFirstOrderAccumulator); } if (m_EnableSecondOrderStats) { - MatrixType cor = streamSecondOrderAccumulator / nbRelevantPixels; + MatrixType cor = streamSecondOrderAccumulator / nbRelevantPixel; this->GetCorrelationOutput()->Set(cor); const RealPixelType& mean = this->GetMeanOutput()->Get(); @@ -454,18 +479,18 @@ PersistentStreamingStatisticsVectorImageFilter<TInputImage, TPrecision> double regul = 1.0; double regulComponent = 1.0; - if( m_UseUnbiasedEstimator && nbRelevantPixels>1 ) + if( m_UseUnbiasedEstimator && nbRelevantPixel>1 ) { regul = - static_cast< double >( nbRelevantPixels ) / - ( static_cast< double >( nbRelevantPixels ) - 1.0 ); + static_cast< double >( nbRelevantPixel ) / + ( static_cast< double >( nbRelevantPixel ) - 1.0 ); } - - if( m_UseUnbiasedEstimator && (nbRelevantPixels * numberOfComponent) > 1 ) + + if( m_UseUnbiasedEstimator && (nbRelevantPixel * numberOfComponent) > 1 ) { regulComponent = - static_cast< double >(nbRelevantPixels * numberOfComponent) / - ( static_cast< double >(nbRelevantPixels * numberOfComponent) - 1.0 ); + static_cast< double >(nbRelevantPixel * numberOfComponent) / + ( static_cast< double >(nbRelevantPixel * numberOfComponent) - 1.0 ); } MatrixType cov = cor; @@ -478,8 +503,8 @@ PersistentStreamingStatisticsVectorImageFilter<TInputImage, TPrecision> } this->GetCovarianceOutput()->Set(cov); - this->GetComponentMeanOutput()->Set(streamFirstOrderComponentAccumulator / (nbRelevantPixels * numberOfComponent)); - this->GetComponentCorrelationOutput()->Set(streamSecondOrderComponentAccumulator / (nbRelevantPixels * numberOfComponent)); + this->GetComponentMeanOutput()->Set(streamFirstOrderComponentAccumulator / (nbRelevantPixel * numberOfComponent)); + this->GetComponentCorrelationOutput()->Set(streamSecondOrderComponentAccumulator / (nbRelevantPixel * numberOfComponent)); this->GetComponentCovarianceOutput()->Set( regulComponent * (this->GetComponentCorrelation() - (this->GetComponentMean() * this->GetComponentMean()))); @@ -586,6 +611,7 @@ PersistentStreamingStatisticsVectorImageFilter<TImage, TPrecision> os << indent << "Mean: " << this->GetMeanOutput()->Get() << std::endl; os << indent << "Covariance: " << this->GetCovarianceOutput()->Get() << std::endl; os << indent << "Correlation: " << this->GetCorrelationOutput()->Get() << std::endl; + os << indent << "Relevant pixel: " << this->GetNbRelevantPixelsOutput()->Get() << std::endl; os << indent << "Component Mean: " << this->GetComponentMeanOutput()->Get() << std::endl; os << indent << "Component Covariance: " << this->GetComponentCovarianceOutput()->Get() << std::endl; os << indent << "Component Correlation: " << this->GetComponentCorrelationOutput()->Get() << std::endl; diff --git a/Modules/Filtering/Statistics/src/otbPeriodicSampler.cxx b/Modules/Filtering/Statistics/src/otbPeriodicSampler.cxx index ad4a6d88df1ed46ace6da5af59ac6f5d4b1894b5..1aba9367ffb3fe2c3e6ef2ab373c631a66fcbb82 100644 --- a/Modules/Filtering/Statistics/src/otbPeriodicSampler.cxx +++ b/Modules/Filtering/Statistics/src/otbPeriodicSampler.cxx @@ -27,7 +27,8 @@ bool PeriodicSampler::ParameterType::operator!=(const PeriodicSampler::ParameterType & param) const { return bool((Offset != param.Offset)|| - (MaxJitter != param.MaxJitter)); + (MaxJitter != param.MaxJitter) || + (MaxBufferSize != param.MaxBufferSize)); } void @@ -39,9 +40,20 @@ PeriodicSampler::Reset(void) if (m_JitterSize > 0.0) { // Using jitter : compute random offset value - m_OffsetValue = - itk::Statistics::MersenneTwisterRandomVariateGenerator::GetInstance() + m_JitterValues.resize(std::min(this->GetNeededElements(), this->m_Parameters.MaxBufferSize)); + for (unsigned long i=0UL ; i<m_JitterValues.size() ; i++) + { + m_JitterValues[i] = itk::Statistics::MersenneTwisterRandomVariateGenerator::GetInstance() ->GetUniformVariate(0.0,m_JitterSize); + } + if (m_JitterValues.empty()) + { + m_OffsetValue = 0.0; + } + else + { + m_OffsetValue = m_JitterValues[0]; + } } else { @@ -71,9 +83,7 @@ PeriodicSampler::TakeSample(void) if (m_JitterSize > 0.0) { // Using jitter : compute random offset value - m_OffsetValue = - itk::Statistics::MersenneTwisterRandomVariateGenerator::GetInstance() - ->GetUniformVariate(0.0,m_JitterSize); + m_OffsetValue = m_JitterValues[this->m_ChosenElements%m_JitterValues.size()]; } ret = true; } @@ -84,6 +94,7 @@ PeriodicSampler::PeriodicSampler() { this->m_Parameters.Offset = 0UL; this->m_Parameters.MaxJitter = 0UL; + this->m_Parameters.MaxBufferSize = 100000000UL; m_JitterSize = 0.0; m_OffsetValue = 0.0; } diff --git a/Modules/Filtering/Statistics/test/otbSamplerTest.cxx b/Modules/Filtering/Statistics/test/otbSamplerTest.cxx index d50684d5410abb2f28c4269cf66d6c1580a2e1ea..9d29cb5869bd8915e2832c1c060d57879119bcde 100644 --- a/Modules/Filtering/Statistics/test/otbSamplerTest.cxx +++ b/Modules/Filtering/Statistics/test/otbSamplerTest.cxx @@ -72,6 +72,7 @@ int otbPeriodicSamplerTest(int, char *[]) param.Offset = 0; param.MaxJitter = 10; + param.MaxBufferSize = 1000000UL; sampler->SetRate(0.2,50); sampler->SetParameters(param); std::string test2 = RunSampler<otb::PeriodicSampler>(sampler,50); diff --git a/Modules/Filtering/Wavelet/include/otbSubsampleImageFilter.h b/Modules/Filtering/Wavelet/include/otbSubsampleImageFilter.h index 93042076a9bcdecdc18d91177c05069a03970358..7b6414666690f457da39333505aa215061ca7873 100644 --- a/Modules/Filtering/Wavelet/include/otbSubsampleImageFilter.h +++ b/Modules/Filtering/Wavelet/include/otbSubsampleImageFilter.h @@ -102,7 +102,6 @@ protected: SubsampleImageFilter () { m_SubsampleFactor.Fill(1); - //this->SetNumberOfThreads(1); } ~SubsampleImageFilter() ITK_OVERRIDE {} diff --git a/Modules/Filtering/Wavelet/include/otbSubsampleImageFilter.txx b/Modules/Filtering/Wavelet/include/otbSubsampleImageFilter.txx index 1848cc66b5b054d97f353da298315bb2798e2191..7e9545261dcdb448a0ccf7cc8d9b4072f4890a54 100644 --- a/Modules/Filtering/Wavelet/include/otbSubsampleImageFilter.txx +++ b/Modules/Filtering/Wavelet/include/otbSubsampleImageFilter.txx @@ -83,7 +83,7 @@ SubsampleImageFilter<TInputImage, TOutputImage, TDirectionOfTransformation> { Superclass::CallCopyOutputRegionToInputRegion(destRegion, srcRegion); - if (static_cast<int>(DirectionOfTransformation) == Wavelet::INVERSE) + if (DirectionOfTransformation == Wavelet::INVERSE) { typename OutputImageRegionType::IndexType srcIndex = srcRegion.GetIndex(); typename OutputImageRegionType::SizeType srcSize = srcRegion.GetSize(); @@ -112,7 +112,7 @@ SubsampleImageFilter<TInputImage, TOutputImage, TDirectionOfTransformation> { Superclass::CallCopyInputRegionToOutputRegion(destRegion, srcRegion); - if (static_cast<int>(DirectionOfTransformation) == Wavelet::INVERSE) + if (DirectionOfTransformation == Wavelet::INVERSE) { typename InputImageRegionType::IndexType srcIndex = srcRegion.GetIndex(); typename InputImageRegionType::SizeType srcSize = srcRegion.GetSize(); @@ -161,8 +161,7 @@ SubsampleImageFilter<TInputImage, TOutputImage, TDirectionOfTransformation> SubsampledImageRegionConstIterator<InputImageType> inputIter (this->GetInput(), inputRegionForThread); - if (static_cast<int>(itkGetStaticConstMacro(DirectionOfTransformation)) - == static_cast<int>(Wavelet::FORWARD)) + if (DirectionOfTransformation == Wavelet::FORWARD) { inputIter.SetSubsampleFactor(GetSubsampleFactor()); inputIter.GoToBegin(); diff --git a/Modules/Filtering/Wavelet/include/otbWaveletFilterBank.h b/Modules/Filtering/Wavelet/include/otbWaveletFilterBank.h index 0089018a601933d6ced0181490a8a9581f627b9f..cc454f0faaf6dc3df0ebe1ac8beee74ba0cd62c3 100644 --- a/Modules/Filtering/Wavelet/include/otbWaveletFilterBank.h +++ b/Modules/Filtering/Wavelet/include/otbWaveletFilterBank.h @@ -399,6 +399,11 @@ protected: WaveletFilterBank(); ~WaveletFilterBank() ITK_OVERRIDE {} + void VerifyInputInformation() ITK_OVERRIDE + { + + } + /** GenerateOutputInformation * Set the size of the output image depending on the decimation factor * Copy information from the input image if existing. diff --git a/Modules/Filtering/Wavelet/include/otbWaveletFilterBank.txx b/Modules/Filtering/Wavelet/include/otbWaveletFilterBank.txx index 7753842f4bc8ed7eaa45035ed706543d8dee0f6c..7e7d238b937d6f4d6e118240425d75ea8792a34e 100644 --- a/Modules/Filtering/Wavelet/include/otbWaveletFilterBank.txx +++ b/Modules/Filtering/Wavelet/include/otbWaveletFilterBank.txx @@ -27,9 +27,6 @@ #include "itkPeriodicBoundaryCondition.h" -// FIXME -#define __myDebug__ 0 - namespace otb { /** @@ -54,7 +51,6 @@ WaveletFilterBank<TInputImage, TOutputImage, TWaveletOperator, Wavelet::FORWARD> m_UpSampleFilterFactor = 0; m_SubsampleImageFactor = 1; - //this->SetNumberOfThreads(1); } template <class TInputImage, class TOutputImage, class TWaveletOperator> @@ -66,11 +62,9 @@ WaveletFilterBank<TInputImage, TOutputImage, TWaveletOperator, Wavelet::FORWARD> if (GetSubsampleImageFactor() == 1) return; -#if __myDebug__ otbGenericMsgDebugMacro(<< " down sampling output regions by a factor of " << GetSubsampleImageFactor()); otbGenericMsgDebugMacro(<< "initial region " << this->GetInput()->GetLargestPossibleRegion().GetSize()[0] << "," << this->GetInput()->GetLargestPossibleRegion().GetSize()[1]); -#endif OutputImageRegionType newRegion; this->CallCopyInputRegionToOutputRegion(newRegion, this->GetInput()->GetLargestPossibleRegion()); @@ -80,9 +74,8 @@ WaveletFilterBank<TInputImage, TOutputImage, TWaveletOperator, Wavelet::FORWARD> this->GetOutput(i)->SetRegions(newRegion); } -#if __myDebug__ otbGenericMsgDebugMacro(<< "new region output " << newRegion.GetSize()[0] << "," << newRegion.GetSize()[1]); -#endif + } template <class TInputImage, class TOutputImage, class TWaveletOperator> @@ -185,12 +178,13 @@ WaveletFilterBank<TInputImage, TOutputImage, TWaveletOperator, Wavelet::FORWARD> this->CallCopyInputRegionToOutputRegion(InputImageDimension - 1 - direction, smallerRegion, largerRegion); - for (unsigned int i = 0; i < m_InternalImages[direction].size(); ++i) + const unsigned int d = InputImageDimension - 2 - direction; + for (unsigned int i = 0; i < m_InternalImages[d].size(); ++i) { - m_InternalImages[InputImageDimension - 2 - direction][i] = OutputImageType::New(); - m_InternalImages[InputImageDimension - 2 - direction][i]->SetRegions(smallerRegion); - m_InternalImages[InputImageDimension - 2 - direction][i]->Allocate(); - m_InternalImages[InputImageDimension - 2 - direction][i]->FillBuffer(0); + m_InternalImages[d][i] = OutputImageType::New(); + m_InternalImages[d][i]->SetRegions(smallerRegion); + m_InternalImages[d][i]->Allocate(); + m_InternalImages[d][i]->FillBuffer(0); } largerRegion = smallerRegion; @@ -642,21 +636,18 @@ WaveletFilterBank<TInputImage, TOutputImage, TWaveletOperator, Wavelet::INVERSE> } } -#if __myDebug__ otbGenericMsgDebugMacro(<< " up sampling output regions by a factor of " << GetSubsampleImageFactor()); otbGenericMsgDebugMacro(<< "initial region " << this->GetInput(0)->GetLargestPossibleRegion().GetSize()[0] << "," << this->GetInput(0)->GetLargestPossibleRegion().GetSize()[1]); -#endif OutputImageRegionType newRegion; this->CallCopyInputRegionToOutputRegion(newRegion, this->GetInput(0)->GetLargestPossibleRegion()); this->GetOutput()->SetRegions(newRegion); -#if __myDebug__ otbGenericMsgDebugMacro(<< "new region output " << newRegion.GetSize()[0] << "," << newRegion.GetSize()[1]); -#endif + } template <class TInputImage, class TOutputImage, class TWaveletOperator> @@ -1178,6 +1169,7 @@ WaveletFilterBank<TInputImage, TOutputImage, TWaveletOperator, Wavelet::INVERSE> typename FilterType::Pointer overSampledLowPass = FilterType::New(); overSampledLowPass->SetInput(cropedLowPass); overSampledLowPass->SetSubsampleFactor(delta); + overSampledLowPass->SetNumberOfThreads(1); overSampledLowPass->Update(); InputImagePointerType cropedHighPass = InputImageType::New(); @@ -1196,6 +1188,7 @@ WaveletFilterBank<TInputImage, TOutputImage, TWaveletOperator, Wavelet::INVERSE> typename FilterType::Pointer overSampledHighPass = FilterType::New(); overSampledHighPass->SetInput(cropedHighPass); overSampledHighPass->SetSubsampleFactor(delta); + overSampledHighPass->SetNumberOfThreads(1); overSampledHighPass->Update(); InnerProductType innerProduct; diff --git a/Modules/Filtering/Wavelet/include/otbWaveletImageFilter.h b/Modules/Filtering/Wavelet/include/otbWaveletImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..76ac1af497f60a866647e34d72d105556702e846 --- /dev/null +++ b/Modules/Filtering/Wavelet/include/otbWaveletImageFilter.h @@ -0,0 +1,112 @@ +/*========================================================================= + + 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 otbWaveletImageFilter_h +#define otbWaveletImageFilter_h + +#include "otbWaveletOperator.h" +#include "otbWaveletFilterBank.h" +#include "otbWaveletTransform.h" +#include "otbWaveletsBandsListToWaveletsSynopsisImageFilter.h" + +namespace otb { + +/** \class WaveletImageFilter + * \brief + * This filter performs wavelet forward transform. + * It takes three template arguments: Input, Output and WaveletOperator + * This filter is not streamed. + * + * \ingroup OTBWavelet + * \sa WaveletInverseImageFilter + * \sa WaveletsBandsListToWaveletsSynopsisImageFilter + * \sa WaveletGenerator + */ +template < class TInputImage, + class TOutputImage, + Wavelet::Wavelet TMotherWaveletOperator > +class WaveletImageFilter : + public itk::ImageToImageFilter< TInputImage, TOutputImage > +{ +public: + /** Standard class typedefs. */ + typedef TInputImage InputImageType; + typedef TOutputImage OutputImageType; + + itkStaticConstMacro( ImageDimension, unsigned int, InputImageType::ImageDimension ); + itkStaticConstMacro( MotherWaveletOperator, short, TMotherWaveletOperator ); + itkStaticConstMacro( DirectionOfTransformation, short, otb::Wavelet::FORWARD ); + + typedef WaveletImageFilter<InputImageType,OutputImageType, TMotherWaveletOperator> Self; + typedef itk::ImageToImageFilter<InputImageType, OutputImageType> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + typedef typename InputImageType::PixelType InputPixelType; + + typedef otb::WaveletOperator< TMotherWaveletOperator, otb::Wavelet::FORWARD, InputPixelType, ImageDimension > + WaveletOperatorType; + typedef otb::WaveletFilterBank< InputImageType, InputImageType, WaveletOperatorType, otb::Wavelet::FORWARD > + FilterBankType; + typedef otb::WaveletTransform< InputImageType, InputImageType, FilterBankType, otb::Wavelet::FORWARD > + WaveletTransformFilterType; + typedef typename WaveletTransformFilterType::Pointer + WaveletTransformFilterPointerType; + + typedef typename WaveletTransformFilterType::OutputImageListType + WaveletTransformFilterOutputImageListType; + typedef otb::WaveletsBandsListToWaveletsSynopsisImageFilter<WaveletTransformFilterOutputImageListType, OutputImageType> + WaveletBandsListToWaveletsSynopsisImageFilterType; + typedef typename WaveletBandsListToWaveletsSynopsisImageFilterType::Pointer + WaveletBandsListToWaveletsSynopsisImageFilterPointerType; + + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(WaveletImageFilter, ImageToImageFilter); + + itkGetMacro(NumberOfDecompositions,unsigned int); + itkSetMacro(NumberOfDecompositions,unsigned int); + +protected: + WaveletImageFilter(); + virtual ~WaveletImageFilter(); + + virtual void GenerateInputRequestedRegion(); + + virtual void GenerateData(); + + virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; + +private: + WaveletImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + WaveletTransformFilterPointerType m_WaveletTransform; + WaveletBandsListToWaveletsSynopsisImageFilterPointerType m_WaveletBandsListToWaveletsSynopsis; + unsigned int m_NumberOfDecompositions; +}; + +} + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbWaveletImageFilter.txx" +#endif + +#endif diff --git a/Modules/Filtering/Wavelet/include/otbWaveletImageFilter.txx b/Modules/Filtering/Wavelet/include/otbWaveletImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..290012331aae257df2117f189fa51f0b591b71dc --- /dev/null +++ b/Modules/Filtering/Wavelet/include/otbWaveletImageFilter.txx @@ -0,0 +1,95 @@ +/*========================================================================= + + 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 otbWaveletImageFilter_txx +#define otbWaveletImageFilter_txx + +#include "otbWaveletImageFilter.h" + +namespace otb +{ +/** Constructor */ +template <class TInputImage, class TOutputImage, Wavelet::Wavelet TMotherWaveletOperator> +WaveletImageFilter<TInputImage, TOutputImage, TMotherWaveletOperator> +::WaveletImageFilter() : m_NumberOfDecompositions(2) +{ + m_WaveletTransform = WaveletTransformFilterType::New(); + m_WaveletTransform->SetSubsampleImageFactor(2); + + m_WaveletBandsListToWaveletsSynopsis = WaveletBandsListToWaveletsSynopsisImageFilterType::New(); + m_WaveletBandsListToWaveletsSynopsis->SetInput( m_WaveletTransform->GetOutput() ); +} + +/** Destructor */ +template <class TInputImage, class TOutputImage, Wavelet::Wavelet TMotherWaveletOperator> +WaveletImageFilter<TInputImage, TOutputImage, TMotherWaveletOperator> +::~WaveletImageFilter() +{ +} + +/** + * GenerateInputRequestedRegion + */ +template <class TInputImage, class TOutputImage, Wavelet::Wavelet TMotherWaveletOperator> +void +WaveletImageFilter<TInputImage, TOutputImage, TMotherWaveletOperator> +::GenerateInputRequestedRegion(void) +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // get pointers to the inputs + typename InputImageType::Pointer input = + const_cast<InputImageType *> (this->GetInput()); + + if ( !input ) + { + return; + } + + input->SetRequestedRegionToLargestPossibleRegion(); +} + +/** + * Main computation method + */ +template <class TInputImage, class TOutputImage, Wavelet::Wavelet TMotherWaveletOperator> +void +WaveletImageFilter<TInputImage, TOutputImage, TMotherWaveletOperator> +::GenerateData() +{ + m_WaveletTransform->SetInput( this->GetInput() ); + m_WaveletTransform->SetNumberOfDecompositions( m_NumberOfDecompositions ); + m_WaveletBandsListToWaveletsSynopsis->GraftOutput( this->GetOutput() ); + m_WaveletBandsListToWaveletsSynopsis->Update(); + this->GraftOutput( m_WaveletBandsListToWaveletsSynopsis->GetOutput() ); +} + +/** + * PrintSelf Method + */ +template <class TInputImage, class TOutputImage, Wavelet::Wavelet TMotherWaveletOperator> +void +WaveletImageFilter<TInputImage, TOutputImage, TMotherWaveletOperator> +::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); +} + +} + +#endif diff --git a/Modules/Filtering/Wavelet/include/otbWaveletInverseImageFilter.h b/Modules/Filtering/Wavelet/include/otbWaveletInverseImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..16eb9d414ecf528fc4a412453d64865b8bc7f9ff --- /dev/null +++ b/Modules/Filtering/Wavelet/include/otbWaveletInverseImageFilter.h @@ -0,0 +1,113 @@ +/*========================================================================= + + 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 otbWaveletInverseImageFilter_h +#define otbWaveletInverseImageFilter_h + +#include "otbWaveletOperator.h" +#include "otbWaveletFilterBank.h" +#include "otbWaveletTransform.h" +#include "otbWaveletsSynopsisImageToWaveletsBandsListFilter.h" + +namespace otb { + +/** \class WaveletInverseImageFilter + * \brief + * This filter performs wavelet inverse transform. + * It takes three template arguments: Input, Output and WaveletOperator + * This filter is not streamed. + * \ingroup OTBWavelet + * \sa WaveletImageFilter + * \sa WaveletsSynopsisImageToWaveletsBandsListFilter + * \sa WaveletGenerator + */ +template < class TInputImage, + class TOutputImage, + Wavelet::Wavelet TMotherWaveletOperator > +class WaveletInverseImageFilter : + public itk::ImageToImageFilter< TInputImage, TOutputImage > +{ +public: + /** Standard class typedefs. */ + typedef TInputImage InputImageType; + typedef TOutputImage OutputImageType; + + itkStaticConstMacro( ImageDimension, unsigned int, InputImageType::ImageDimension ); + itkStaticConstMacro( MotherWaveletOperator, short, TMotherWaveletOperator ); + itkStaticConstMacro( DirectionOfTransformation, short , otb::Wavelet::FORWARD ); + + typedef WaveletInverseImageFilter<InputImageType,OutputImageType, TMotherWaveletOperator> Self; + typedef itk::ImageToImageFilter<InputImageType, OutputImageType> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + typedef typename InputImageType::PixelType InputPixelType; + typedef typename OutputImageType::PixelType OutputPixelType; + + typedef otb::WaveletOperator< TMotherWaveletOperator, otb::Wavelet::INVERSE, OutputPixelType, ImageDimension > + WaveletOperatorType; + typedef otb::WaveletFilterBank< OutputImageType, OutputImageType, WaveletOperatorType, otb::Wavelet::INVERSE > + FilterBankType; + typedef otb::WaveletTransform< OutputImageType, OutputImageType, FilterBankType, otb::Wavelet::INVERSE > + WaveletInverseTransformFilterType; + typedef typename WaveletInverseTransformFilterType::Pointer + WaveletInverseTransformFilterPointerType; + + typedef otb::WaveletsSynopsisImageToWaveletsBandsListFilter<InputImageType, typename WaveletInverseTransformFilterType::InputImageListType> + WaveletsSynopsisImageToWaveletsBandsListFilterType; + typedef typename WaveletsSynopsisImageToWaveletsBandsListFilterType::Pointer + WaveletsSynopsisImageToWaveletsBandsListFilterPointerType; + + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(WaveletInverseImageFilter, ImageToImageFilter); + + itkGetMacro(NumberOfDecompositions,unsigned int); + itkSetMacro(NumberOfDecompositions,unsigned int); + + /** If the filter is modified, the internal filters need to be modified too */ + virtual void Modified() const; + +protected: + WaveletInverseImageFilter(); + virtual ~WaveletInverseImageFilter(); + + virtual void GenerateInputRequestedRegion(); + + virtual void GenerateData(); + + virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; + +private: + WaveletInverseImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + WaveletsSynopsisImageToWaveletsBandsListFilterPointerType m_SynopsisImageToWaveletsBandsList; + WaveletInverseTransformFilterPointerType m_WaveletTransform; + unsigned int m_NumberOfDecompositions; +}; + +} + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbWaveletInverseImageFilter.txx" +#endif + +#endif diff --git a/Modules/Filtering/Wavelet/include/otbWaveletInverseImageFilter.txx b/Modules/Filtering/Wavelet/include/otbWaveletInverseImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..58ac44df317b0bb86475b370aa3dae5b9ef6214e --- /dev/null +++ b/Modules/Filtering/Wavelet/include/otbWaveletInverseImageFilter.txx @@ -0,0 +1,109 @@ +/*========================================================================= + + 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 __otbWaveletInverseImageFilter_txx +#define __otbWaveletInverseImageFilter_txx + +#include "otbWaveletInverseImageFilter.h" + +namespace otb +{ +/** Constructor */ +template <class TInputImage, class TOutputImage, Wavelet::Wavelet TMotherWaveletOperator> +WaveletInverseImageFilter<TInputImage, TOutputImage, TMotherWaveletOperator> +::WaveletInverseImageFilter() : m_NumberOfDecompositions(2) +{ + m_SynopsisImageToWaveletsBandsList = WaveletsSynopsisImageToWaveletsBandsListFilterType::New(); + m_SynopsisImageToWaveletsBandsList->SetDecimationRatio(2); + + m_WaveletTransform = WaveletInverseTransformFilterType::New(); + m_WaveletTransform->SetSubsampleImageFactor(2); + m_WaveletTransform->SetInput( m_SynopsisImageToWaveletsBandsList->GetOutput() ); + +} + +/** Destructor */ +template <class TInputImage, class TOutputImage, Wavelet::Wavelet TMotherWaveletOperator> +WaveletInverseImageFilter<TInputImage, TOutputImage, TMotherWaveletOperator> +::~WaveletInverseImageFilter() +{ +} + +/** Destructor */ +template <class TInputImage, class TOutputImage, Wavelet::Wavelet TMotherWaveletOperator> +void +WaveletInverseImageFilter<TInputImage, TOutputImage, TMotherWaveletOperator> +::Modified() const +{ + Superclass::Modified(); + m_SynopsisImageToWaveletsBandsList->Modified(); + m_WaveletTransform->Modified(); +} + +/** + * GenerateInputRequestedRegion + */ +template <class TInputImage, class TOutputImage, Wavelet::Wavelet TMotherWaveletOperator> +void +WaveletInverseImageFilter<TInputImage, TOutputImage, TMotherWaveletOperator> +::GenerateInputRequestedRegion(void) +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // get pointers to the inputs + typename InputImageType::Pointer input = + const_cast<InputImageType *> (this->GetInput()); + + if ( !input ) + { + return; + } + + input->SetRequestedRegionToLargestPossibleRegion(); +} + +/** + * Main computation method + */ +template <class TInputImage, class TOutputImage, Wavelet::Wavelet TMotherWaveletOperator> +void +WaveletInverseImageFilter<TInputImage, TOutputImage, TMotherWaveletOperator> +::GenerateData() +{ + m_SynopsisImageToWaveletsBandsList->SetInput( this->GetInput() ); + m_SynopsisImageToWaveletsBandsList->SetNumberOfLevels( m_NumberOfDecompositions ); + + m_WaveletTransform->GraftOutput( this->GetOutput() ); + m_WaveletTransform->Update(); + this->GraftOutput( m_WaveletTransform->GetOutput() ); +} + +/** + * PrintSelf Method + */ +template <class TInputImage, class TOutputImage, Wavelet::Wavelet TMotherWaveletOperator> +void +WaveletInverseImageFilter<TInputImage, TOutputImage, TMotherWaveletOperator> +::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); +} + +} + +#endif diff --git a/Modules/Filtering/Wavelet/include/otbWaveletsBandsListToWaveletsSynopsisImageFilter.h b/Modules/Filtering/Wavelet/include/otbWaveletsBandsListToWaveletsSynopsisImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..9e22f84968e16a1d48c02f674dc5e544e150be98 --- /dev/null +++ b/Modules/Filtering/Wavelet/include/otbWaveletsBandsListToWaveletsSynopsisImageFilter.h @@ -0,0 +1,103 @@ +/*========================================================================= + + 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 otbWaveletsBandsListToWaveletsSynopsisImageFilter_h +#define otbWaveletsBandsListToWaveletsSynopsisImageFilter_h + + +#include "otbImageListToImageFilter.h" + +namespace otb +{ + +/** \class WaveletsBandsListToWaveletsSynopsisImageFilter + * \brief Converts a list of wavelets bands to the traditional multi-resolution wavelets view + * + * The decimation ratio is taken into account. + * + * \ingroup OTBWavelet + * \sa WaveletsSynopsisImageToWaveletsBandsListFilter + */ + +template <class TImageList, class TImage> +class ITK_EXPORT WaveletsBandsListToWaveletsSynopsisImageFilter + : public ImageListToImageFilter<typename TImageList::ImageType, TImage> +{ +public: + /** Standard typedefs */ + typedef WaveletsBandsListToWaveletsSynopsisImageFilter Self; + typedef ImageListToImageFilter< + typename TImageList::ImageType,TImage> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Type macro */ + itkNewMacro(Self); + + /** Useful typedefs */ + typedef TImageList InputImageListType; + typedef typename InputImageListType::ImageType InputImageType; + typedef TImage OutputImageType; + typedef typename OutputImageType::RegionType RegionType; + + /** Creation through object factory macro */ + itkTypeMacro(WaveletsBandsListToWaveletsSynopsisImageFilter,ImageToImageListFilter); + + /** Set the decimation ratio */ + itkSetMacro(DecimationRatio,unsigned int); + + /** Get the decimation ratio */ + itkGetMacro(DecimationRatio,unsigned int); + +protected: + /** Main computation method */ + virtual void ThreadedGenerateData(const RegionType & outputRegionForThread, itk::ThreadIdType threadId); + + /** GenerateOutputInformation + * Set the number of bands of the output. + * Copy informations from the first image of the list if existing. + **/ + virtual void GenerateOutputInformation(void); + + /** + * GenerateInputRequestedRegion + * Set the requested region of each image in the list. + */ + virtual void GenerateInputRequestedRegion(void); + + /** Constructor */ + WaveletsBandsListToWaveletsSynopsisImageFilter(); + + /** Destructor */ + virtual ~WaveletsBandsListToWaveletsSynopsisImageFilter(); + + /**PrintSelf method */ + virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; + +private: + WaveletsBandsListToWaveletsSynopsisImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + /** The decimation ratio used in the decomposition */ + unsigned int m_DecimationRatio; +}; +}// End namespace otb +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbWaveletsBandsListToWaveletsSynopsisImageFilter.txx" +#endif + +#endif diff --git a/Modules/Filtering/Wavelet/include/otbWaveletsBandsListToWaveletsSynopsisImageFilter.txx b/Modules/Filtering/Wavelet/include/otbWaveletsBandsListToWaveletsSynopsisImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..ea21c6c2a968d5b698fa0c18d8dda09f5e12e7f5 --- /dev/null +++ b/Modules/Filtering/Wavelet/include/otbWaveletsBandsListToWaveletsSynopsisImageFilter.txx @@ -0,0 +1,222 @@ +/*========================================================================= + + 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 otbWaveletsBandsListToWaveletsSynopsisImageFilter_txx +#define otbWaveletsBandsListToWaveletsSynopsisImageFilter_txx + +#include "otbWaveletsBandsListToWaveletsSynopsisImageFilter.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionConstIterator.h" +#include "otbMacro.h" +#include "itkProgressReporter.h" + +namespace otb +{ +/** Constructor */ +template <class TImageList, class TImage> +WaveletsBandsListToWaveletsSynopsisImageFilter<TImageList,TImage> +::WaveletsBandsListToWaveletsSynopsisImageFilter() : m_DecimationRatio(2) +{} + +/** Destructor */ +template <class TImageList, class TImage> +WaveletsBandsListToWaveletsSynopsisImageFilter<TImageList,TImage> +::~WaveletsBandsListToWaveletsSynopsisImageFilter() +{} + +/** + * GenerateOutputInformation + */ +template <class TImageList, class TImage> +void +WaveletsBandsListToWaveletsSynopsisImageFilter<TImageList,TImage> +::GenerateOutputInformation(void) +{ + // We must set the size of the output image to be twice the size of the last image + // of the image list, which is the first band. + if(this->GetOutput()) + { + if (this->GetInput()->Size()>0) + { + // Retrieve the largest band + typename InputImageType::Pointer lastBand = this->GetInput()->Back(); + + // Retrieve the region of the largest band + RegionType largestBandRegion = lastBand->GetLargestPossibleRegion(); + + // Retrieve the size of the largest region + typename RegionType::SizeType outputSize = largestBandRegion.GetSize(); + + // Multiply this size by two + outputSize[0]*=m_DecimationRatio; + outputSize[1]*=m_DecimationRatio; + + // Build the output region + RegionType outputLargestRegion; + outputLargestRegion.SetSize(outputSize); + + // Copy information to the output image + this->GetOutput()->CopyInformation(lastBand); + this->GetOutput()->SetLargestPossibleRegion(outputLargestRegion); + + } + } +} +/** + * GenerateInputRequestedRegion + */ +template <class TImageList, class TImage> +void +WaveletsBandsListToWaveletsSynopsisImageFilter<TImageList,TImage> +::GenerateInputRequestedRegion(void) +{ + typename InputImageListType::Pointer inputPtr = this->GetInput(); + typename InputImageListType::ConstIterator inputListIt = inputPtr->Begin(); + while (inputListIt!=inputPtr->End()) + { + inputListIt.Get()->SetRequestedRegionToLargestPossibleRegion(); + ++inputListIt; + } +} + +/** + * Main computation method + */ +template <class TImageList, class TImage> +void +WaveletsBandsListToWaveletsSynopsisImageFilter<TImageList,TImage> +::ThreadedGenerateData(const RegionType & outputRegionForThread, + itk::ThreadIdType threadId) +{ + // Retrieve input and output pointers + typename InputImageListType::Pointer inputPtr = this->GetInput(); + typename OutputImageType::Pointer outputPtr = this->GetOutput(); + + // Set up progress reporting + itk::ProgressReporter progress(this, + threadId, + outputRegionForThread.GetNumberOfPixels()); + + // defines input and output iterators + typedef itk::ImageRegionConstIterator<InputImageType> InputIteratorType; + typedef itk::ImageRegionIterator<OutputImageType> OutputIteratorType; + + // Set up an iterator on the input wavelets band + typename InputImageListType::ConstIterator inputListIt = inputPtr->Begin(); + unsigned int bandIndex = 0; + + // Compute number of decomposition levels + unsigned int numberOfDecompositionLevels = (inputPtr->Size()-1)/3; + + // Retrieve the largest possible region size + typename RegionType::SizeType largestSize = outputPtr->GetLargestPossibleRegion().GetSize(); + + // Iterate on each band + for (;inputListIt!=inputPtr->End();++inputListIt,++bandIndex) + { + // Build a band offset + typename RegionType::OffsetType currentOffset; + currentOffset.Fill(0); + + // Initialise Current level + unsigned int currentLevel = 0; + unsigned int currentSubBand = 0; + + if(bandIndex > 0) + { + // Compute current level and sub band + currentLevel = 1 + (bandIndex-1)/3; + currentSubBand = (bandIndex-1)%3; + + // Compute potentiel offset in x and y + unsigned int offsetX = largestSize[0]/(unsigned int)vcl_pow((double)m_DecimationRatio,(double)1+numberOfDecompositionLevels-currentLevel); + unsigned int offsetY = largestSize[1]/(unsigned int)vcl_pow((double)m_DecimationRatio,(double)1+numberOfDecompositionLevels-currentLevel); + + // Compute final offset according to the subband index + if(currentSubBand == 0) + { + currentOffset[0]+=offsetX; + } + else if(currentSubBand == 1) + { + currentOffset[1]+=offsetY; + } + else + { + currentOffset[0]+=offsetX; + currentOffset[1]+=offsetY; + } + } + // Retrieve current band region + RegionType currentBandRegion = inputListIt.Get()->GetLargestPossibleRegion(); + + // Apply offset to get the current output region + RegionType currentOutputRegion = currentBandRegion; + typename RegionType::IndexType currentOutputIndex = currentBandRegion.GetIndex(); + currentOutputIndex+=currentOffset; + currentOutputRegion.SetIndex(currentOutputIndex); + + // Crop with the outputRegionForThread. If the crop fails, + // it means that currentOutputRegion is outside of outputRegionForThread, + // and in this case we skip to the next image in the list. + if(currentOutputRegion.Crop(outputRegionForThread)) + { + // Compute the corresponding input region + RegionType currentInputRegion = currentBandRegion; + currentOutputIndex = currentOutputRegion.GetIndex(); + typename RegionType::IndexType currentInputIndex = currentBandRegion.GetIndex(); + + for(unsigned int i = 0; i < InputImageType::ImageDimension;++i) + { + currentInputIndex[i]+=currentOutputIndex[i]; + currentInputIndex[i]-=currentOffset[i]; + } + currentInputRegion.SetSize(currentOutputRegion.GetSize()); + currentInputRegion.SetIndex(currentInputIndex); + + InputIteratorType inIt(inputListIt.Get(),currentInputRegion); + OutputIteratorType outIt(outputPtr,currentOutputRegion); + + // Go to begin + inIt.GoToBegin(); + outIt.GoToBegin(); + + // Copy pixels + while(!inIt.IsAtEnd() && !outIt.IsAtEnd()) + { + // Copy pixel value + outIt.Set(static_cast<typename OutputImageType::InternalPixelType>(inIt.Get())); + // Step forward + ++inIt; + ++outIt; + progress.CompletedPixel(); + } + } + } +} +/** + * PrintSelf Method + */ +template <class TImageType, class TImageList> +void +WaveletsBandsListToWaveletsSynopsisImageFilter<TImageType,TImageList> +::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); +} +} // End namespace otb +#endif diff --git a/Modules/Filtering/Wavelet/include/otbWaveletsSynopsisImageToWaveletsBandsListFilter.h b/Modules/Filtering/Wavelet/include/otbWaveletsSynopsisImageToWaveletsBandsListFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..8ad9a302b90c3e4049b671231192d9d951bc2db0 --- /dev/null +++ b/Modules/Filtering/Wavelet/include/otbWaveletsSynopsisImageToWaveletsBandsListFilter.h @@ -0,0 +1,122 @@ +/*========================================================================= + + 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 otbWaveletsSynopsisImageToWaveletsBandsListFilter_h +#define otbWaveletsSynopsisImageToWaveletsBandsListFilter_h + +#include "otbImageToImageListFilter.h" +#include "itkRegionOfInterestImageFilter.h" + + +namespace otb +{ + +/** \class WaveletsSynopsisImageToWaveletsBandsListFilter + * \brief This class convert the standard wavelets view to a list of bands. + * + * \ingroup OTBWavelet + * \sa WaveletsBandsListToWaveletsSynopsisImageFilter + */ + +template <class TImage, class TImageList> +class ITK_EXPORT WaveletsSynopsisImageToWaveletsBandsListFilter + : public ImageToImageListFilter<TImage,typename TImageList::ImageType> +{ +public: + /** Standard typedefs */ + typedef WaveletsSynopsisImageToWaveletsBandsListFilter Self; + typedef ImageToImageListFilter<TImage, + typename TImageList::ImageType> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Type macro */ + itkNewMacro(Self); + + /** Creation through object factory macro */ + itkTypeMacro(WaveletsSynopsisImageToWaveletsBandsListFilter,ImageToImageListFilter); + + /** Template parameters typedefs */ + typedef TImage InputImageType; + typedef typename InputImageType::RegionType RegionType; + typedef TImageList OutputImageListType; + typedef typename OutputImageListType::ImageType OutputImageType; + + typedef itk::RegionOfInterestImageFilter< + InputImageType, + InputImageType > ExtractFilterType; + + typedef typename ExtractFilterType::Pointer ExtractFilterPointerType; + + typedef std::vector<ExtractFilterPointerType> ExtractFilterVectorType; + + /** Set the number of levels */ + itkSetMacro(NumberOfLevels,unsigned int); + + /** Get the number of levels */ + itkGetMacro(NumberOfLevels,unsigned int); + + /** Set the decimation ratio */ + itkSetMacro(DecimationRatio,unsigned int); + + /** Get the decimation ratio */ + itkGetMacro(DecimationRatio,unsigned int); + + /** If the filter is modified, the extract list need to be regenerated */ + virtual void Modified() const; + +protected: + /** Constructor */ + WaveletsSynopsisImageToWaveletsBandsListFilter(); + + /** Destructor */ + virtual ~WaveletsSynopsisImageToWaveletsBandsListFilter(); + + /**PrintSelf method */ + virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; + + /** Generate the input requested region from the first element in the list. */ + virtual void GenerateInputRequestedRegion(void); + + /** Generate the output information by building the output list. */ + virtual void GenerateOutputInformation(void); + + /** Main computation method */ + virtual void GenerateData(void); + +private: + WaveletsSynopsisImageToWaveletsBandsListFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + /** The number of levels in the decomposition */ + unsigned int m_NumberOfLevels; + + /** The decimation ratio used in the decomposition */ + unsigned int m_DecimationRatio; + + /** The vector of extraction filters for each band */ + ExtractFilterVectorType m_ExtractFilters; + + /** True if extract list is up-to-date */ + mutable bool m_ExtractFiltersUpToDate; +}; +}// End namespace otb +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbWaveletsSynopsisImageToWaveletsBandsListFilter.txx" +#endif + +#endif diff --git a/Modules/Filtering/Wavelet/include/otbWaveletsSynopsisImageToWaveletsBandsListFilter.txx b/Modules/Filtering/Wavelet/include/otbWaveletsSynopsisImageToWaveletsBandsListFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..45de1a2c532aab00e33acf44a7b4816401c12c70 --- /dev/null +++ b/Modules/Filtering/Wavelet/include/otbWaveletsSynopsisImageToWaveletsBandsListFilter.txx @@ -0,0 +1,179 @@ +/*========================================================================= + + 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 otbWaveletsSynopsisImageToWaveletsBandsListFilter_txx +#define otbWaveletsSynopsisImageToWaveletsBandsListFilter_txx + +#include "otbWaveletsSynopsisImageToWaveletsBandsListFilter.h" + +namespace otb +{ +/** Constructor */ +template <class TImage, class TImageList> +WaveletsSynopsisImageToWaveletsBandsListFilter<TImage,TImageList> +::WaveletsSynopsisImageToWaveletsBandsListFilter() : m_NumberOfLevels(1), + m_DecimationRatio(2), + m_ExtractFilters(), + m_ExtractFiltersUpToDate(false) +{} + +/** Destructor */ +template <class TImage, class TImageList> +WaveletsSynopsisImageToWaveletsBandsListFilter<TImage,TImageList> +::~WaveletsSynopsisImageToWaveletsBandsListFilter() +{ + m_ExtractFilters.clear(); +} + +/** Modify overload */ +template <class TImage, class TImageList> +void +WaveletsSynopsisImageToWaveletsBandsListFilter<TImage,TImageList> +::Modified() const +{ + // Call superclass implementation + Superclass::Modified(); + m_ExtractFiltersUpToDate = false; +} + +/** Generate the input requested region from the first element in the list. */ +template <class TImage, class TImageList> +void +WaveletsSynopsisImageToWaveletsBandsListFilter<TImage,TImageList> +::GenerateOutputInformation(void) +{ + typename OutputImageListType::Pointer outputPtr = this->GetOutput(); + typename InputImageType::ConstPointer inputPtr = this->GetInput(); + + // Check if we need to regenerate the extract filters + if (inputPtr && !m_ExtractFiltersUpToDate) + { + // Retrieve image size + typename RegionType::SizeType largestSize = inputPtr->GetLargestPossibleRegion().GetSize(); + + // Compute the number of output images + unsigned int numberOfOutputImages = m_NumberOfLevels*3 + 1; + + // Clear the output image list + outputPtr->Clear(); + + // Clear the extract filter vector + m_ExtractFilters.clear(); + + // For each output image + for (unsigned int i=0;i<numberOfOutputImages;++i) + { + // Build the current extract filter + typename ExtractFilterType::Pointer currentExtract = ExtractFilterType::New(); + currentExtract->SetInput(inputPtr); + + // Add it to the filter list + m_ExtractFilters.push_back(currentExtract); + + // Add its output to the filter's output + outputPtr->PushBack(currentExtract->GetOutput()); + + // Build the corresponding region + RegionType currentRegion; + typename RegionType::IndexType currentIndex; + typename RegionType::SizeType currentSize; + currentIndex.Fill(0); + + // If this is not the first sub-band + if(i > 0) + { + // Compute current sub-band and level + unsigned int currentLevel = (i-1)/3; + unsigned int currentSubBand = (i-1)%3; + + unsigned int offsetX = largestSize[0]/(unsigned int)vcl_pow((double)m_DecimationRatio,(double)m_NumberOfLevels-currentLevel); + unsigned int offsetY = largestSize[1]/(unsigned int)vcl_pow((double)m_DecimationRatio,(double)m_NumberOfLevels-currentLevel); + + // Compute current size + currentSize[0] = offsetX; + currentSize[1] = offsetY; + + // Compute current index + if(currentSubBand == 0) + { + currentIndex[0]+= offsetX; + } + else if(currentSubBand == 1) + { + currentIndex[1]= offsetY; + } + else + { + currentIndex[0]= offsetX; + currentIndex[1]= offsetY; + } + } + else + { + // The coarsest scale size + currentSize[0] = largestSize[0]/(unsigned int)vcl_pow((double)m_DecimationRatio,(double)m_NumberOfLevels); + currentSize[1] = largestSize[1]/(unsigned int)vcl_pow((double)m_DecimationRatio,(double)m_NumberOfLevels); + } + // Build current region + currentRegion.SetIndex(currentIndex); + currentRegion.SetSize(currentSize); + //std::cout<<"Band: "<<i<<", region "<<currentRegion<<std::endl; + currentExtract->SetRegionOfInterest(currentRegion); + } + m_ExtractFiltersUpToDate = true; + } +} +/** Generate the output information by building the output list. */ +template <class TImage, class TImageList> +void +WaveletsSynopsisImageToWaveletsBandsListFilter<TImage,TImageList> +::GenerateInputRequestedRegion(void) +{ + typename InputImageType::Pointer inputPtr = this->GetInput(); + + if (inputPtr) + { + inputPtr->SetRequestedRegionToLargestPossibleRegion(); + } +} +/** + * Main computation method + */ +template <class TImage, class TImageList> +void +WaveletsSynopsisImageToWaveletsBandsListFilter<TImage,TImageList> +::GenerateData(void) +{ + // Update each extract fillter + for(typename ExtractFilterVectorType::iterator it = m_ExtractFilters.begin(); + it!=m_ExtractFilters.end();++it) + { + (*it)->Update(); + } +} +/** + * PrintSelf Method + */ +template <class TImage, class TImageList> +void +WaveletsSynopsisImageToWaveletsBandsListFilter<TImage,TImageList> +::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); +} +} // End namespace otb +#endif diff --git a/Modules/Filtering/Wavelet/test/CMakeLists.txt b/Modules/Filtering/Wavelet/test/CMakeLists.txt index e09d0c8e48ffea54f1fba01038175b636de7b919..f8c8023e5de7774d5707d296a2b854169716ab5e 100644 --- a/Modules/Filtering/Wavelet/test/CMakeLists.txt +++ b/Modules/Filtering/Wavelet/test/CMakeLists.txt @@ -15,6 +15,7 @@ otbWaveletFilterBank.cxx otbWaveletPacketTransformNew.cxx otbWaveletFilterBankNew.cxx otbWaveletOperatorNew.cxx +otbWaveletImageToImageFilter.cxx ) add_executable(otbWaveletTestDriver ${OTBWaveletTests}) @@ -572,3 +573,11 @@ otb_add_test(NAME msTuWaveletFilterBankNew COMMAND otbWaveletTestDriver otb_add_test(NAME msTuWaveletOperatorNew COMMAND otbWaveletTestDriver otbWaveletOperatorNew ) +otb_add_test(NAME msTvWaveletImageToImageFilter COMMAND otbWaveletTestDriver + --compare-image ${EPSILON_6} + ${INPUTDATA}/QB_Toulouse_Ortho_PAN.tif + ${TEMP}/msTvWaveletImageToImageFilterOut.tif + otbWaveletImageToImageFilter + ${INPUTDATA}/QB_Toulouse_Ortho_PAN.tif + ${TEMP}/msTvWaveletImageToImageFilterOut.tif + ) diff --git a/Modules/Filtering/Wavelet/test/otbWaveletImageToImageFilter.cxx b/Modules/Filtering/Wavelet/test/otbWaveletImageToImageFilter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..7a81db8bab9d9b5ce095ccad7737089e610fc7dc --- /dev/null +++ b/Modules/Filtering/Wavelet/test/otbWaveletImageToImageFilter.cxx @@ -0,0 +1,87 @@ +/*========================================================================= + + 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. + +=========================================================================*/ +/* +This test code will run a WaveletImageFilter on given input image. Output +from this filter is then fed to WaveletInverseImageFilter which does +the inverse transform. Hence output of inverse transform passed to +ImageFileWriter will result in the input image. + +Wavelet operator used is HAAR (otb::Wavelet::HAAR). +This filter works only in single-threaded setup +*/ + +#include "otbImage.h" +#include "otbImageFileReader.h" +#include "otbImageFileWriter.h" +#include "otbWaveletImageFilter.h" +#include "otbWaveletInverseImageFilter.h" + +int otbWaveletImageToImageFilter(int argc, char * argv[]) +{ + + const char * inputFileName = argv[1]; + const char * outputFileName = argv[argc-1]; + + /* Wavelet operator */ + const otb::Wavelet::Wavelet OperatorType = otb::Wavelet::HAAR; + + const int Dimension = 2; + typedef double PixelType; + typedef otb::Image<PixelType, Dimension> ImageType; + typedef otb::ImageFileReader<ImageType> ReaderType; + + + + typedef otb::WaveletImageFilter< + ImageType, + ImageType, + OperatorType> FwdFilterType; + + typedef otb::WaveletInverseImageFilter< + ImageType, + ImageType, + OperatorType> InvFilterType; + + typedef otb::ImageFileWriter<ImageType> WriterType; + + // itk::MultiThreader::SetGlobalMaximumNumberOfThreads( 1 ); + + /* Reading */ + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName(inputFileName); + + /* Forward Transformation */ + FwdFilterType::Pointer fwdFilter = FwdFilterType::New(); + + fwdFilter->SetInput(reader->GetOutput()); + fwdFilter->Update(); + + /* Inverse Transformation */ + + InvFilterType::Pointer invFilter = InvFilterType::New(); + + invFilter->SetInput(fwdFilter->GetOutput()); + invFilter->Update(); + + /* Writing output */ + WriterType::Pointer writer = WriterType::New(); + writer->SetFileName(outputFileName); + writer->SetInput(invFilter->GetOutput()); + writer->Update(); + + return EXIT_SUCCESS; +} diff --git a/Modules/Filtering/Wavelet/test/otbWaveletTestDriver.cxx b/Modules/Filtering/Wavelet/test/otbWaveletTestDriver.cxx index 532d5e7880926866964abe550f940c198b594eb6..60c07f794cfc141162783e429dc8849425b361ff 100644 --- a/Modules/Filtering/Wavelet/test/otbWaveletTestDriver.cxx +++ b/Modules/Filtering/Wavelet/test/otbWaveletTestDriver.cxx @@ -14,4 +14,5 @@ void RegisterTests() REGISTER_TEST(otbWaveletPacketTransformNew); REGISTER_TEST(otbWaveletFilterBankNew); REGISTER_TEST(otbWaveletOperatorNew); + REGISTER_TEST(otbWaveletImageToImageFilter); } diff --git a/Modules/Fusion/MajorityVoting/include/otbNeighborhoodMajorityVotingImageFilter.txx b/Modules/Fusion/MajorityVoting/include/otbNeighborhoodMajorityVotingImageFilter.txx index 9c4de263463dfb2ace173423bc4bc19dd5c05253..85785e1399880f4b103060d10040e4e69aaa665a 100644 --- a/Modules/Fusion/MajorityVoting/include/otbNeighborhoodMajorityVotingImageFilter.txx +++ b/Modules/Fusion/MajorityVoting/include/otbNeighborhoodMajorityVotingImageFilter.txx @@ -115,15 +115,25 @@ NeighborhoodMajorityVotingImageFilter<TInputImage, TOutputImage, histoNeigh[label] += 1; } } - HistoAsVectorType histoNeighVec(histoNeigh.begin(), histoNeigh.end()); - //Sort the 2 max elements to the beginning - std::nth_element(histoNeighVec.begin(), histoNeighVec.begin()+1, - histoNeighVec.end(), CompareHistoFequencies()); typename NeighborhoodMajorityVotingImageFilter<TInputImage, TOutputImage, TKernel>::HistoSummary result; - result.freqCenterLabel = histoNeigh[nit.GetCenterPixel()]; - result.majorityLabel = histoNeighVec[0].first; - result.majorityUnique = (histoNeighVec[0].second != histoNeighVec[1].second); + assert(!histoNeigh.empty()); + if (histoNeigh.size() == 1) + { + result.freqCenterLabel = histoNeigh.begin()->second; + result.majorityLabel = histoNeigh.begin()->first; + result.majorityUnique = true; + } + else + { + HistoAsVectorType histoNeighVec(histoNeigh.begin(), histoNeigh.end()); + //Sort the 2 max elements to the beginning + std::nth_element(histoNeighVec.begin(), histoNeighVec.begin()+1, + histoNeighVec.end(), CompareHistoFequencies()); + result.freqCenterLabel = histoNeigh[nit.GetCenterPixel()]; + result.majorityLabel = histoNeighVec[0].first; + result.majorityUnique = (histoNeighVec[0].second != histoNeighVec[1].second); + } return result; } diff --git a/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.h b/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.h index 25e1470de639d4b87a9a068e705dbc1281b31b13..822db14618dfa82479b480167892fc781b60b72d 100644 --- a/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.h +++ b/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.h @@ -110,8 +110,8 @@ private: * This functor applies the * \f[ \frac{XS}{\mathrm{Filtered}(PAN)}PAN \f] * operation. It is intended for internal use only. - * - * \ingroup OTBPanSharpening + * + * \ingroup OTBPanSharpening */ class FusionFunctor { @@ -142,6 +142,83 @@ private: } }; + + /** \class NoDataFusionFunctor + * This functor applies the following operation if there is no data : + * \f[ \frac{XS}{\mathrm{Filtered}(PAN)}PAN \f] + * It is intended for internal use only. + * + * \ingroup OTBPanSharpening + */ + class NoDataFusionFunctor + { + public: + // Implement the fusion as a three arguments operator + typename TOutputImageType::PixelType operator()(const typename TXsImageType::PixelType& xsPixel, + const TInternalPrecision& smoothPanchroPixel, + const typename TPanImageType::PixelType& sharpPanchroPixel) const + { + // Build output pixel + typename TOutputImageType::PixelType output(xsPixel.Size()); + + // Check for no data Pan value + if( m_NoDataValuePanAvailable && sharpPanchroPixel == m_NoDataValuePan ) + { + for ( unsigned int i = 0; i < xsPixel.Size(); ++i ) + { + output[i] = static_cast<typename TOutputImageType::InternalPixelType>( m_NoDataValuesXs[i] ); + } + return output; + } + + TInternalPrecision scale = 1.; + + if(vcl_abs(smoothPanchroPixel) > 1e-10) + { + scale = sharpPanchroPixel/smoothPanchroPixel; + } + + // Perform fusion for each band with appropriate casting + for(unsigned int i = 0; i < xsPixel.Size(); ++i) + { + output[i] = ( m_NoDataValuesXsAvailable[i] && (xsPixel[i] == m_NoDataValuesXs[i]) ) ? + static_cast<typename TOutputImageType::InternalPixelType>( xsPixel[i] ) : + static_cast<typename TOutputImageType::InternalPixelType>( xsPixel[i] * scale ); + } + // Returns the output pixel + return output; + } + + void SetNoDataValuePanAvailable(bool noDataAvailable) { + m_NoDataValuePanAvailable = noDataAvailable; + } + + void SetNoDataValuePan(typename TPanImageType::PixelType noDataValue) { + m_NoDataValuePan = noDataValue; + } + + void SetNoDataValuesXsAvailable(std::vector<bool> noDataValuesAvailable) { + m_NoDataValuesXsAvailable = noDataValuesAvailable; + } + + void SetNoDataValuesXs(std::vector<typename TXsImageType::InternalPixelType> noDataValues) { + m_NoDataValuesXs = noDataValues; + } + + + private: + /** No data flags and values for APN image */ + bool m_NoDataValuePanAvailable; + typename TPanImageType::InternalPixelType m_NoDataValuePan; + + /** No data flags and values for XS image */ + std::vector<bool> m_NoDataValuesXsAvailable; + std::vector<typename TXsImageType::InternalPixelType> m_NoDataValuesXs; + + + }; + + /** * Typedef of the TernaryFunctorImageFilter applying the fusion functor to * p, p_smooth and xs. @@ -152,6 +229,16 @@ private: TOutputImageType, FusionFunctor> FusionFilterType; + /** + * Typedef of the TernaryFunctorImageFilter applying the no data fusion functor to + * p, p_smooth and xs. + */ + typedef itk::TernaryFunctorImageFilter<TXsImageType, + InternalImageType, + TPanImageType, + TOutputImageType, + NoDataFusionFunctor> NoDataFusionFilterType; + /** Typedef of the convolution filter performing smoothing */ typedef otb::ConvolutionImageFilter <TPanImageType, @@ -160,10 +247,16 @@ private: TInternalPrecision> ConvolutionFilterType; /** Pointer to the internal convolution filter */ - typename ConvolutionFilterType::Pointer m_ConvolutionFilter; + typename ConvolutionFilterType::Pointer m_ConvolutionFilter; /** Pointer to the fusion filter */ - typename FusionFilterType::Pointer m_FusionFilter; + typename FusionFilterType::Pointer m_FusionFilter; + + /** Pointer to the fusion filter */ + typename NoDataFusionFilterType::Pointer m_NoDataFusionFilter; + + /** Boolean used for no data */ + bool m_UseNoData; /** Radius used for the smoothing filter */ RadiusType m_Radius; diff --git a/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.txx b/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.txx index 4ddbe4831764bef8a4b72abe65c251009b9f6670..f849204758ffaf98aad467666968dfe68080ab4d 100644 --- a/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.txx +++ b/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.txx @@ -32,6 +32,7 @@ SimpleRcsPanSharpeningFusionImageFilter { // Fix number of required inputs this->SetNumberOfRequiredInputs(2); + this->m_UseNoData = false; // Instantiate convolution filter m_ConvolutionFilter = ConvolutionFilterType::New(); @@ -42,15 +43,6 @@ SimpleRcsPanSharpeningFusionImageFilter m_Filter.SetSize(7 * 7); m_Filter.Fill(1); - // Instantiate fusion filter - m_FusionFilter = FusionFilterType::New(); - m_FusionFilter->SetInput2(m_ConvolutionFilter->GetOutput()); - - // Set-up progress reporting - m_ProgressAccumulator = itk::ProgressAccumulator::New(); - m_ProgressAccumulator->SetMiniPipelineFilter(this); - m_ProgressAccumulator->RegisterInternalFilter(m_ConvolutionFilter, 0.9); - m_ProgressAccumulator->RegisterInternalFilter(m_FusionFilter, 0.1); } template <class TPanImageType, class TXsImageType, class TOutputImageType, class TInternalPrecision> @@ -127,18 +119,89 @@ SimpleRcsPanSharpeningFusionImageFilter itkExceptionMacro(<< "SimpleRcsPanSharpeningFusionImageFilter: Wrong Pan/Xs size"); } - //Process the fusion + // Set-up progress reporting + m_ProgressAccumulator = itk::ProgressAccumulator::New(); + m_ProgressAccumulator->SetMiniPipelineFilter(this); + m_ProgressAccumulator->RegisterInternalFilter(m_ConvolutionFilter, 0.9); + m_ConvolutionFilter->SetInput(this->GetPanInput()); m_ConvolutionFilter->SetRadius(this->m_Radius); m_ConvolutionFilter->SetFilter(this->m_Filter); - m_FusionFilter->SetInput1(this->GetXsInput()); - m_FusionFilter->SetInput3(this->GetPanInput()); + typedef typename TPanImageType::InternalPixelType PanPixelType; + typedef typename TXsImageType::InternalPixelType XsPixelType; + + // Write no-data flags for Pan image + std::vector<bool> tmpNoDataValuePanAvailable; + std::vector<double> tmpNoDataValuePan; + bool noDataValuePanAvailable = false; + PanPixelType noDataValuePan = 0; + + bool retPan = itk::ExposeMetaData<std::vector<bool> >( this->GetPanInput()->GetMetaDataDictionary(), MetaDataKey::NoDataValueAvailable, tmpNoDataValuePanAvailable ); + retPan &= itk::ExposeMetaData<std::vector<double> >( this->GetPanInput()->GetMetaDataDictionary(), MetaDataKey::NoDataValue, tmpNoDataValuePan ); + + if(retPan && tmpNoDataValuePanAvailable.size() > 0 && tmpNoDataValuePan.size() > 0) + { + noDataValuePanAvailable = tmpNoDataValuePanAvailable[0] && retPan; + noDataValuePan = static_cast<PanPixelType>( tmpNoDataValuePan[0] ); + } + + + // Write no-data flags for Xs image + std::vector<bool> noDataValuesXsAvailable; + std::vector<double> tmpNoDataValuesXs; + std::vector<XsPixelType> noDataValuesXs; + + bool retXs = itk::ExposeMetaData<std::vector<bool> >( this->GetXsInput()->GetMetaDataDictionary(), MetaDataKey::NoDataValueAvailable, noDataValuesXsAvailable ); + retXs &= itk::ExposeMetaData<std::vector<double> >( this->GetXsInput()->GetMetaDataDictionary(), MetaDataKey::NoDataValue, tmpNoDataValuesXs ); + + // Check if noData is needed and update noDataValuesAvailable with return function value + if ( retPan || retXs ) + { + m_UseNoData = noDataValuePanAvailable; + for ( unsigned int i = 0; i < tmpNoDataValuesXs.size() && i < noDataValuesXsAvailable.size(); ++i ) + { + noDataValuesXs.push_back( static_cast<XsPixelType>(tmpNoDataValuesXs[i]) ); + m_UseNoData |= (noDataValuesXsAvailable[i] = (noDataValuesXsAvailable[i] && retXs)); + } + } + + // Instantiate fusion filter + if ( m_UseNoData ) + { + m_NoDataFusionFilter = NoDataFusionFilterType::New(); + m_ProgressAccumulator->RegisterInternalFilter( m_NoDataFusionFilter, 0.1 ); + + m_NoDataFusionFilter->SetInput2( m_ConvolutionFilter->GetOutput() ); + m_NoDataFusionFilter->GetFunctor().SetNoDataValuesXsAvailable( noDataValuesXsAvailable ); + m_NoDataFusionFilter->GetFunctor().SetNoDataValuePanAvailable( noDataValuePanAvailable ); + m_NoDataFusionFilter->GetFunctor().SetNoDataValuePan( noDataValuePan ); + m_NoDataFusionFilter->GetFunctor().SetNoDataValuesXs( noDataValuesXs ); + + m_NoDataFusionFilter->SetInput1( this->GetXsInput() ); + m_NoDataFusionFilter->SetInput2( m_ConvolutionFilter->GetOutput() ); + m_NoDataFusionFilter->SetInput3( this->GetPanInput() ); + + // Wire composite filter + m_NoDataFusionFilter->GraftOutput( this->GetOutput() ); + m_NoDataFusionFilter->Update(); + this->GraftOutput( m_NoDataFusionFilter->GetOutput() ); + } + else + { + m_FusionFilter = FusionFilterType::New(); + m_ProgressAccumulator->RegisterInternalFilter( m_FusionFilter, 0.1 ); + + m_FusionFilter->SetInput1( this->GetXsInput() ); + m_FusionFilter->SetInput2( m_ConvolutionFilter->GetOutput() ); + m_FusionFilter->SetInput3( this->GetPanInput() ); + + // Wire composite filter + m_FusionFilter->GraftOutput( this->GetOutput() ); + m_FusionFilter->Update(); + this->GraftOutput( m_FusionFilter->GetOutput() ); + } - // Wire composite filter - m_FusionFilter->GraftOutput(this->GetOutput()); - m_FusionFilter->Update(); - this->GraftOutput(m_FusionFilter->GetOutput()); } template <class TPanImageType, class TXsImageType, class TOutputImageType, class TInternalPrecision> diff --git a/Modules/IO/IOGDAL/src/otbGDALOverviewsBuilder.cxx b/Modules/IO/IOGDAL/src/otbGDALOverviewsBuilder.cxx index ecfdfcbeb1690a06cc0a0a513a53a83c2b7923bd..5e15ca437386840f76b958dc5242ba9a4f2d3dcf 100644 --- a/Modules/IO/IOGDAL/src/otbGDALOverviewsBuilder.cxx +++ b/Modules/IO/IOGDAL/src/otbGDALOverviewsBuilder.cxx @@ -200,7 +200,7 @@ GDALOverviewsBuilder unsigned int n = std::min( count, - CountResolutions( factor ) + CountResolutions( factor , 1) ); for( unsigned int i=0; i<n; ++i ) diff --git a/Modules/IO/IOJPEG2000/CMakeLists.txt b/Modules/IO/IOJPEG2000/CMakeLists.txt deleted file mode 100644 index 48427b642a6c589a2cc19a5a38c728b8d62a46df..0000000000000000000000000000000000000000 --- a/Modules/IO/IOJPEG2000/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -project(OTBIOJPEG2000) - -set(OTBIOJPEG2000_LIBRARIES OTBIOJPEG2000) -otb_module_impl() diff --git a/Modules/IO/IOJPEG2000/include/otbJPEG2000ImageIO.h b/Modules/IO/IOJPEG2000/include/otbJPEG2000ImageIO.h deleted file mode 100644 index 7ea055f5d16429797545003d3852833f8cae516b..0000000000000000000000000000000000000000 --- a/Modules/IO/IOJPEG2000/include/otbJPEG2000ImageIO.h +++ /dev/null @@ -1,175 +0,0 @@ -/*========================================================================= - - 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 otbJPEG2000ImageIO_h -#define otbJPEG2000ImageIO_h - -#include "otbImageIOBase.h" -#include "itkMultiThreader.h" - -#include <boost/shared_ptr.hpp> - -namespace otb -{ - -class JPEG2000InternalReader; -class JPEG2000TileCache; - -/** \class JPEG2000ImageIO - * - * \brief ImageIO object for reading and writing JPEG2000 format images - * - * The streaming (read and write) is implemented. - * - * \ingroup IOFilters - * - * - * \ingroup OTBIOJPEG2000 - */ -class ITK_EXPORT JPEG2000ImageIO : public otb::ImageIOBase -{ -public: - - /** Standard class typedefs. */ - typedef JPEG2000ImageIO Self; - typedef otb::ImageIOBase Superclass; - typedef itk::SmartPointer<Self> Pointer; - - /** Method for creation through the object factory. */ - itkNewMacro(Self); - - /** Run-time type information (and related methods). */ - itkTypeMacro(JPEG2000ImageIO, otb::ImageIOBase); - - /*-------- This part of the interface deals with reading data. ------ */ - - /** Determine the file type. Returns true if this ImageIO can read the - * file specified. */ - bool CanReadFile(const char*) ITK_OVERRIDE; - - /** Determine the file type. Returns true if the ImageIO can stream read the specified file */ - bool CanStreamRead() ITK_OVERRIDE - { - return true; - } - - /** Set the spacing and dimension information for the set filename. */ - void ReadImageInformation() ITK_OVERRIDE; - - /** Get description about overviews available into the file specified */ - std::vector<std::string> GetOverviewsInfo() ITK_OVERRIDE; - - /** Provide hist about the output container to deal with complex pixel - * type (Not used here) */ - void SetOutputImagePixelType( bool itkNotUsed(isComplexInternalPixelType), - bool itkNotUsed(isVectorImage)) ITK_OVERRIDE{} - - /** Get number of available overviews in the jpeg2000 file - * ( if return = 0 => no overviews available because only one resolution - * is encoded in the file) */ - unsigned int GetOverviewsCount() ITK_OVERRIDE; - - /** Reads the data from disk into the memory buffer provided. */ - void Read(void* buffer) ITK_OVERRIDE; - - /** Reads 3D data from multiple files assuming one slice per file. */ - virtual void ReadVolume(void* buffer); - - /*-------- This part of the interfaces deals with writing data. ----- */ - - /** Determine the file type. Returns true if this ImageIO can read the - * file specified. */ - bool CanWriteFile(const char*) ITK_OVERRIDE; - - /** Determine the file type. Returns true if the ImageIO can stream write the specified file */ - bool CanStreamWrite() ITK_OVERRIDE - { - return true; - } - - /** Writes the spacing and dimensions of the image. - * Assumes SetFileName has been called with a valid file name. */ - void WriteImageInformation() ITK_OVERRIDE; - - /** Writes the data to disk from the memory buffer provided. Make sure - * that the IORegion has been set properly. */ - void Write(const void* buffer) ITK_OVERRIDE; - - - /** Return the multithreader used by this class. */ - itk::MultiThreader * GetMultiThreader() - {return m_Threader; } - - itkSetMacro(ResolutionFactor, unsigned int); - itkGetMacro(ResolutionFactor, unsigned int); - - itkSetMacro(CacheSizeInByte, unsigned int); - itkGetMacro(CacheSizeInByte, unsigned int); - - - - -protected: - /** Constructor.*/ - JPEG2000ImageIO(); - /** Destructor.*/ - ~JPEG2000ImageIO() ITK_OVERRIDE; - - void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE; - - typedef std::vector<boost::shared_ptr<JPEG2000InternalReader> > ReaderVectorType; - - ReaderVectorType m_InternalReaders; - boost::shared_ptr<JPEG2000TileCache> m_TileCache; - -private: - JPEG2000ImageIO(const Self &); //purposely not implemented - void operator =(const Self&); //purposely not implemented - - /** Compute the tile index list from the GetRegion*/ - std::vector<unsigned int> ComputeTileList(); - - /** pixel nb of octets */ - unsigned int m_BytePerPixel; - - /** Resolution factor*/ - unsigned int m_ResolutionFactor; - - /** Size of the cache used to reduce number of decoding operations*/ - unsigned int m_CacheSizeInByte; - - /** Load data from a tile into the buffer. 2nd argument is a -* pointer to opj_image_t, hidden in void * to avoid forward declaration. */ - void LoadTileData(void * buffer, void * tile); - - /** Support processing data in multiple threads. Used by subclasses - * (e.g., ImageSource). */ - itk::MultiThreader::Pointer m_Threader; - int m_NumberOfThreads; - - /** Static function used as a "callback" by the MultiThreader. The threading - * library will call this routine for each thread, which will delegate the - * control to ThreadedGenerateData(). */ - static ITK_THREAD_RETURN_TYPE ThreaderCallback( void *arg ); - - /** Configure cache manager */ - void ConfigureCache(); -}; - -} // end namespace otb - -#endif // otbJPEG2000ImageIO_h diff --git a/Modules/IO/IOJPEG2000/include/otbJPEG2000ImageIOFactory.h b/Modules/IO/IOJPEG2000/include/otbJPEG2000ImageIOFactory.h deleted file mode 100644 index 5a284580c0697611272705c6bbd80e1e5b81bae5..0000000000000000000000000000000000000000 --- a/Modules/IO/IOJPEG2000/include/otbJPEG2000ImageIOFactory.h +++ /dev/null @@ -1,69 +0,0 @@ -/*========================================================================= - - 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 otbJPEG2000ImageIOFactory_h -#define otbJPEG2000ImageIOFactory_h - -#include "itkObjectFactoryBase.h" - -namespace otb -{ -/** \class JPEG2000ImageIOFactory - * \brief Create instances of JPEG2000ImageIO objects using an object factory. - * - * \ingroup OTBIOJPEG2000 - */ -class ITK_EXPORT JPEG2000ImageIOFactory : public itk::ObjectFactoryBase -{ -public: - /** Standard class typedefs. */ - typedef JPEG2000ImageIOFactory Self; - typedef itk::ObjectFactoryBase Superclass; - typedef itk::SmartPointer<Self> Pointer; - typedef itk::SmartPointer<const Self> ConstPointer; - - /** Class methods used to interface with the registered factories. */ - const char* GetITKSourceVersion(void) const ITK_OVERRIDE; - const char* GetDescription(void) const ITK_OVERRIDE; - - /** Method for class instantiation. */ - itkFactorylessNewMacro(Self); - static JPEG2000ImageIOFactory * FactoryNew() { return new JPEG2000ImageIOFactory; } - - /** Run-time type information (and related methods). */ - itkTypeMacro(JPEG2000ImageIOFactory, itk::ObjectFactoryBase); - - /** Register one factory of this type */ - static void RegisterOneFactory(void) - { - JPEG2000ImageIOFactory::Pointer JPEG2000Factory = JPEG2000ImageIOFactory::New(); - itk::ObjectFactoryBase::RegisterFactory(JPEG2000Factory); - } - -protected: - JPEG2000ImageIOFactory(); - ~JPEG2000ImageIOFactory() ITK_OVERRIDE; - -private: - JPEG2000ImageIOFactory(const Self &); //purposely not implemented - void operator =(const Self&); //purposely not implemented - -}; - -} // end namespace otb - -#endif diff --git a/Modules/IO/IOJPEG2000/otb-module.cmake b/Modules/IO/IOJPEG2000/otb-module.cmake deleted file mode 100644 index 50e4d018d17eeabccca10045c11bd643235cb102..0000000000000000000000000000000000000000 --- a/Modules/IO/IOJPEG2000/otb-module.cmake +++ /dev/null @@ -1,22 +0,0 @@ -set(DOCUMENTATION "This module contains features to read and write JPEG2000 -format images.") - -otb_module(OTBIOJPEG2000 - DEPENDS - OTBITK - OTBImageBase - OTBOSSIMAdapters - OTBCommon - OTBTinyXML - OTBOpenJPEG - OTBBoost - OTBGDAL - - TEST_DEPENDS - OTBTestKernel - OTBImageIO - OTBImageManipulation - - DESCRIPTION - "${DOCUMENTATION}" -) diff --git a/Modules/IO/IOJPEG2000/src/CMakeLists.txt b/Modules/IO/IOJPEG2000/src/CMakeLists.txt deleted file mode 100644 index 8bf3ff33627931b8d5b25c47e3aa8ae2cefa0111..0000000000000000000000000000000000000000 --- a/Modules/IO/IOJPEG2000/src/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -set(OTBIOJPEG2000_SRC - otbJPEG2000ImageIO.cxx - otbJPEG2000ImageIOFactory.cxx - ) - -add_library(OTBIOJPEG2000 ${OTBIOJPEG2000_SRC}) -target_link_libraries(OTBIOJPEG2000 - ${OTBTinyXML_LIBRARIES} - ${OTBImageBase_LIBRARIES} - ${OTBOSSIMAdapters_LIBRARIES} - ${OTBCommon_LIBRARIES} - ${OTBOpenJPEG_LIBRARIES} - ${OTBBoost_LIBRARIES} - ${OTBGDAL_LIBRARIES} - - ) - -otb_module_target(OTBIOJPEG2000) diff --git a/Modules/IO/IOJPEG2000/src/otbJPEG2000ImageIO.cxx b/Modules/IO/IOJPEG2000/src/otbJPEG2000ImageIO.cxx deleted file mode 100644 index e1d79be76d8f537d0885878e6a82d49802a54e98..0000000000000000000000000000000000000000 --- a/Modules/IO/IOJPEG2000/src/otbJPEG2000ImageIO.cxx +++ /dev/null @@ -1,1796 +0,0 @@ -/*========================================================================= - - 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. - -=========================================================================*/ -#include "otbJPEG2000ImageIO.h" - -#include <iomanip> -#include <iostream> - - -#include "otbMacro.h" -#include "itksys/SystemTools.hxx" -#include "itkTimeProbe.h" -#include "itkMetaDataObject.h" -#include "otbMetaDataKey.h" - -#include <deque> - -#include "otb_openjpeg.h" - -#include "gdal.h" -#include "gdaljp2metadata.h" -#include "cpl_string.h" -#include "ogr_spatialref.h" -#include "ogr_srs_api.h" - -#include "itksys/SystemTools.hxx" - -#include "otb_tinyxml.h" - -#include "itkMutexLock.h" -#include "itkMutexLockHolder.h" - -void OpjImageDestroy(opj_image_t * img) -{ - if(img) - { - opj_image_destroy(img); - } -} - -void OpjCodestreamDestroy(opj_codestream_info_v2_t * cstr) -{ - opj_destroy_cstr_info(&cstr); -} -#if defined(OTBOpenJPEG_VERSION_NUMBER) && OTBOpenJPEG_VERSION_NUMBER < 20100 -void FileDestroy(FILE * file) -{ - if(file) - { - fclose(file); - } -} -#endif -/** -Divide an integer by a power of 2 and round upwards -@return Returns a divided by 2^b -*/ -inline int int_ceildivpow2(int a, int b) { - return (a + (1 << b) - 1) >> b; -} - -inline unsigned int uint_ceildivpow2(unsigned int a, unsigned int b) { - return (a + (1 << b) - 1) >> b; -} - -/** - sample error debug callback expecting no client object -*/ -void error_callback(const char *msg, void *client_data) -{ - (void) msg; - (void) client_data; - otbMsgDevMacro(<< "OpenJPEG error: " << msg); -} -/** - sample warning debug callback expecting no client object -*/ -void warning_callback(const char *msg, void *client_data) -{ - (void) msg; - (void) client_data; - otbMsgDevMacro(<< "OpenJPEG warning: " << msg); -} -/** - sample debug callback expecting no client object -*/ -void info_callback(const char *msg, void *client_data) -{ - (void) msg; - (void) client_data; - otbMsgDevMacro(<< "OpenJPEG info: " << msg); -} - -namespace otb -{ - -/** Compute offsets needed to read the data from the tile decoded and - * offsets needed to write into the output buffer. - * - * Please note that this function uses a bare pointer instead of a - * shared one because it is called within LoadTileData, which hides - * the opj_image_t pointer between a void * for proper hiding of - * openjpeg API. - */ -void ComputeOffsets(opj_image_t * tile, - const itk::ImageIORegion & ioRegion, - unsigned int &l_width_src, - unsigned int &l_height_dest, - unsigned int &l_width_dest, - unsigned int &l_start_offset_dest, - unsigned int &l_start_offset_src); - -/************************************************************************/ -/* JPEG2000 metadata reader based on GDAL functionalities */ -/************************************************************************/ -class JPEG2000MetadataReader -{ -public: - JPEG2000MetadataReader(const char *filename ) - { - m_MetadataIsRead = false; - - if( m_JP2Metadata.ReadAndParse(filename) ) - { - m_MetadataIsRead = true; - } - - }; - - ~JPEG2000MetadataReader(){}; - - /** Get the geoTransform from file*/ - std::vector<double> GetGeoTransform(){ - std::vector<double> geoTransform; - for (unsigned int i = 0; i< 6; i++ ) - geoTransform.push_back(m_JP2Metadata.adfGeoTransform[i]); - return geoTransform; - }; - - /** Check if image in the file have a geoTransform*/ - bool HaveGeoTransform(){ - return static_cast<bool>(m_JP2Metadata.bHaveGeoTransform); - }; - - /** Get the nb of GCP from file*/ - int GetGCPCount(){ - return m_JP2Metadata.nGCPCount; - }; - - /** Get the GCPs from file*/ - std::vector<GDAL_GCP> GetGCPs(){ - std::vector<GDAL_GCP> gcps; - int nbGCP = m_JP2Metadata.nGCPCount; - for (int i = 0; i< nbGCP; i++ ) - gcps.push_back(m_JP2Metadata.pasGCPList[i]); - return gcps; - }; - - /** Get the projectionRef from file*/ - const char* GetProjectionRef() { - if (m_JP2Metadata.pszProjection) - return m_JP2Metadata.pszProjection; - else - return ITK_NULLPTR; - }; - - /** Get the GML box from file*/ - char** GetGMLMetadata() { - if (m_JP2Metadata.papszGMLMetadata) - return m_JP2Metadata.papszGMLMetadata; - else - return ITK_NULLPTR; - }; - - // Get the origin from GML box (use tinyxml to parse the GML box) - bool GetOriginFromGMLBox (std::vector<double> &origin); - - /** Check if the file has been correctly read*/ - bool m_MetadataIsRead; - -private: - /** GDAL structure where store metadata read from JP2 file*/ - GDALJP2Metadata m_JP2Metadata; - -}; - -bool JPEG2000MetadataReader::GetOriginFromGMLBox (std::vector<double> &origin) -{ - if (!m_MetadataIsRead) - return false; - - std::string gmlString = static_cast<std::string> (m_JP2Metadata.papszGMLMetadata[0]); - gmlString.erase(0,18); // We need to remove first part to create a true xml stream - otbMsgDevMacro( << "XML extract from GML box: " << gmlString ); - - TiXmlDocument doc; - doc.Parse(gmlString.c_str()); // Create xml doc from a string - - TiXmlHandle docHandle( &doc ); - TiXmlElement* originTag = docHandle.FirstChild( "gml:FeatureCollection" ) - .FirstChild( "gml:featureMember" ) - .FirstChild( "gml:FeatureCollection" ) - .FirstChild( "gml:featureMember" ) - .FirstChild( "gml:GridCoverage" ) - .FirstChild( "gml:gridDomain") - .FirstChild( "gml:Grid" ) - .FirstChild( "gml:limits" ) - .FirstChild( "gml:GridEnvelope" ) - .FirstChild( "gml:low").ToElement(); - if(originTag) - { - otbMsgDevMacro( << "\t Origin (" << originTag->Value() <<" tag)= "<< originTag->GetText()); - } - else - { - otbMsgDevMacro( << "Didn't find the GML element which indicate the origin!" ); - return false; - } - - std::vector<itksys::String> originValues; - originValues = itksys::SystemTools::SplitString(originTag->GetText(),' ', false); - - // Compute origin in GDAL convention (half pixel shift is applied later) - std::istringstream ss0 (originValues[0]); - std::istringstream ss1 (originValues[1]); - ss0 >> origin[1]; - ss1 >> origin[0]; - origin[0] += -1.0; - origin[1] += -1.0; - - otbMsgDevMacro( << "\t Origin from GML box: " << origin[0] << ", " << origin[1] ); - - return true; -} - - -/************************************************************************/ -/* JPEG2000 internal reader based on openjpeg */ -/************************************************************************/ -class JPEG2000InternalReader -{ -public: - JPEG2000InternalReader(); - - ~JPEG2000InternalReader() - { - this->Clean(); - } - - boost::shared_ptr<opj_image_t> DecodeTile(unsigned int tileIndex); - - const std::vector<unsigned int> & GetAvailableResolutions(){return this->m_AvailableResolutions; }; - - void Clean(); - - bool CanRead(); - - int Open(const char *filename, unsigned int resolution); - - bool m_IsOpen; - OPJ_CODEC_FORMAT m_CodecFormat; - - unsigned int m_Width; - unsigned int m_Height; - - unsigned int m_NbOfComponent; - - std::vector<unsigned int> m_XResolution; - std::vector<unsigned int> m_YResolution; - std::vector<unsigned int> m_Precision; - std::vector<int> m_Signed; - - unsigned int m_TileWidth; - unsigned int m_TileHeight; - unsigned int m_XNbOfTile; - unsigned int m_YNbOfTile; - - std::vector<unsigned int> m_AvailableResolutions; - - unsigned int m_ResolutionFactor; - -private: - std::string m_FileName; -#if defined(OTBOpenJPEG_VERSION_NUMBER) && OTBOpenJPEG_VERSION_NUMBER < 20100 - boost::shared_ptr<FILE> m_File; -#endif - int Initialize(); -}; - - -int JPEG2000InternalReader::Open(const char *filename, unsigned int resolution) -{ - this->Clean(); - - std::string str(filename); - this->m_FileName = str; - - // Open the file - if (this->m_FileName.empty()) - { - this->Clean(); - return 0; - } - -#if defined(OTBOpenJPEG_VERSION_NUMBER) && OTBOpenJPEG_VERSION_NUMBER < 20100 - this->m_File = boost::shared_ptr<FILE>(fopen(this->m_FileName.c_str(), "rb"),FileDestroy); - if (!this->m_File) - { - this->Clean(); - return 0; - } -#endif - - // Find the codec file format - - if (itksys::SystemTools::LowerCase(itksys::SystemTools::GetFilenameLastExtension(m_FileName)) == ".j2k") - { - this->m_CodecFormat = OPJ_CODEC_J2K; - } - else if (itksys::SystemTools::LowerCase(itksys::SystemTools::GetFilenameLastExtension(m_FileName)) == ".jp2" - || itksys::SystemTools::LowerCase(itksys::SystemTools::GetFilenameLastExtension(m_FileName)) == ".jpx") - { - this->m_CodecFormat = OPJ_CODEC_JP2; - } - else - { - this->Clean(); - return 0; - } - - this->m_ResolutionFactor = resolution; - - // Initialize the codec and the stream - if (!this->Initialize()) - { - this->Clean(); - return 0; - } - - this->m_IsOpen = true; - return 1; -} - -void JPEG2000InternalReader::Clean() -{ - this->m_FileName.clear(); -#if defined(OTBOpenJPEG_VERSION_NUMBER) && OTBOpenJPEG_VERSION_NUMBER < 20100 - this->m_File = boost::shared_ptr<FILE>(); -#endif - this->m_XResolution.clear(); - this->m_YResolution.clear(); - this->m_Precision.clear(); - this->m_Signed.clear(); - m_AvailableResolutions.clear(); - - this->m_Width = 0; - this->m_Height = 0; - this->m_NbOfComponent = 0; - this->m_TileWidth = 0; - this->m_TileHeight = 0; - this->m_XNbOfTile = 0; - this->m_YNbOfTile = 0; - - this->m_IsOpen = false; - this->m_CodecFormat = OPJ_CODEC_UNKNOWN; - this->m_ResolutionFactor=0; -} - -boost::shared_ptr<opj_image_t> JPEG2000InternalReader::DecodeTile(unsigned int tileIndex) -{ -#if defined(OTBOpenJPEG_VERSION_NUMBER) && OTBOpenJPEG_VERSION_NUMBER < 20100 - if (!this->m_File) - { - this->Clean(); - return boost::shared_ptr<opj_image_t>(); - } - - // Creating the file stream - boost::shared_ptr<opj_stream_t> stream = boost::shared_ptr<opj_stream_t>(opj_stream_create_default_file_stream(this->m_File.get(), true),opj_stream_destroy); - if (!stream) - { - this->Clean(); - return boost::shared_ptr<opj_image_t>(); - } -#else - if (this->m_FileName.empty()) - { - this->Clean(); - return boost::shared_ptr<opj_image_t>(); - } - - // Creating the file stream - boost::shared_ptr<opj_stream_t> stream = boost::shared_ptr<opj_stream_t>(opj_stream_create_default_file_stream(this->m_FileName.c_str(), true),opj_stream_destroy); - if (!stream) - { - this->Clean(); - return boost::shared_ptr<opj_image_t>(); - } -#endif - - // Creating the codec - boost::shared_ptr<opj_codec_t> codec = boost::shared_ptr<opj_codec_t>(opj_create_decompress(this->m_CodecFormat),opj_destroy_codec); - - if (!codec) - { - this->Clean(); - return boost::shared_ptr<opj_image_t>(); - } - - // Setting default parameters - opj_dparameters_t parameters; - opj_set_default_decoder_parameters(¶meters); - parameters.cp_reduce = static_cast<int>(this->m_ResolutionFactor); - - // Set default event mgr - // catch events using our callbacks and give a local context - opj_set_info_handler(codec.get(), info_callback,ITK_NULLPTR); - opj_set_warning_handler(codec.get(), warning_callback,ITK_NULLPTR); - opj_set_error_handler(codec.get(), error_callback,ITK_NULLPTR); - - // Setup the decoder decoding parameters using user parameters - if (!opj_setup_decoder(codec.get(), ¶meters)) - { - this->Clean(); - return boost::shared_ptr<opj_image_t>(); - } - - // Read the main header of the codestream and if necessary the JP2 - // boxes - opj_image_t * unsafeOpjImgPtr = ITK_NULLPTR; - - if (!opj_read_header(stream.get(), codec.get(),&unsafeOpjImgPtr)) - { - boost::shared_ptr<opj_image_t> image = boost::shared_ptr<opj_image_t>(unsafeOpjImgPtr,OpjImageDestroy); - this->Clean(); - return boost::shared_ptr<opj_image_t>(); - } - - boost::shared_ptr<opj_image_t> image = boost::shared_ptr<opj_image_t>(unsafeOpjImgPtr,OpjImageDestroy); - - if( opj_get_decoded_tile(codec.get(), stream.get(), image.get(), tileIndex)) - { - otbMsgDevMacro(<<"Tile "<<tileIndex<<" read from file"); - - return image; - } - else - { - this->Clean(); - return boost::shared_ptr<opj_image_t>(); - } -} - -JPEG2000InternalReader::JPEG2000InternalReader() -{ - this->Clean(); -} - -int JPEG2000InternalReader::Initialize() -{ -#if defined(OTBOpenJPEG_VERSION_NUMBER) && OTBOpenJPEG_VERSION_NUMBER < 20100 - if (this->m_File) - { - // Creating the file stream - boost::shared_ptr<opj_stream_t> stream = boost::shared_ptr<opj_stream_t>(opj_stream_create_default_file_stream(this->m_File.get(), true),opj_stream_destroy); - if (!stream) - { - std::cerr << "ERROR file stream creation" << std::endl; - this->Clean(); - return 0; - } -#else - if (!m_FileName.empty()) - { - // Creating the file stream - boost::shared_ptr<opj_stream_t> stream = boost::shared_ptr<opj_stream_t>(opj_stream_create_default_file_stream(this->m_FileName.c_str(), true),opj_stream_destroy); - if (!stream) - { - std::cerr << "ERROR file stream creation" << std::endl; - this->Clean(); - return 0; - } -#endif - // Creating the codec - boost::shared_ptr<opj_codec_t> codec = boost::shared_ptr<opj_codec_t>(opj_create_decompress(this->m_CodecFormat),opj_destroy_codec); - - if (!codec) - { - std::cerr << "ERROR codec creation" << std::endl ; - this->Clean(); - return 0; - } - - // Setting default parameters - opj_dparameters_t parameters; - opj_set_default_decoder_parameters(¶meters); - parameters.cp_reduce = static_cast<int>(this->m_ResolutionFactor); - - // Set default event mgr - // catch events using our callbacks and give a local context - opj_set_info_handler(codec.get(), info_callback,ITK_NULLPTR); - opj_set_warning_handler(codec.get(), warning_callback,ITK_NULLPTR); - opj_set_error_handler(codec.get(), error_callback,ITK_NULLPTR); - - // Setup the decoder decoding parameters using user parameters - if (!opj_setup_decoder(codec.get(), ¶meters)) - { - std::cerr << "ERROR setup decoder" << std::endl ; - this->Clean(); - return 0; - } - - // Read the main header of the codestream and if necessary the JP2 - // boxes - opj_image_t * unsafeOpjImgPtr = ITK_NULLPTR; - - if (!opj_read_header(stream.get(), codec.get(),&unsafeOpjImgPtr)) - { - std::cerr << "ERROR read header" << std::endl; - boost::shared_ptr<opj_image_t> image = boost::shared_ptr<opj_image_t>(unsafeOpjImgPtr,OpjImageDestroy); - this->Clean(); - return 0; - } - - boost::shared_ptr<opj_image_t> image = boost::shared_ptr<opj_image_t>(unsafeOpjImgPtr,OpjImageDestroy); - - // Get the codestream information - boost::shared_ptr<opj_codestream_info_v2> cstrInfo = boost::shared_ptr<opj_codestream_info_v2>(opj_get_cstr_info(codec.get()),OpjCodestreamDestroy); - - if (!cstrInfo) - { - std::cerr << "ERROR while get codestream info" << std::endl; - this->Clean(); - return 0; - } - - // We can now retrieve the main information of the image and the codestream - // (based on the first component and with no subsampling) - this->m_Width = image->comps->w; - this->m_Height = image->comps->h; - - otbMsgDevMacro(<< "JPEG2000InternalReader dimension (after reading header) = " << image->comps->w << " x " - << image->comps->w << " x " << image->comps->h ); - - this->m_TileHeight = cstrInfo->tdy; - this->m_TileWidth = cstrInfo->tdx; - this->m_XNbOfTile = cstrInfo->tw; - this->m_YNbOfTile = cstrInfo->th; - - this->m_NbOfComponent = image->numcomps; - - for (unsigned int itComp = 0; itComp < this->m_NbOfComponent; itComp++) - { - this->m_Precision.push_back( image->comps[itComp].prec); - this->m_Signed.push_back( image->comps[itComp].sgnd); - this->m_XResolution.push_back( image->comps[itComp].dx); - this->m_YResolution.push_back( image->comps[itComp].dy); - } - - // Warning: This value is based on the first component of the default tile parameters. - unsigned int numResAvailable = cstrInfo->m_default_tile_info.tccp_info[0].numresolutions; - m_AvailableResolutions.clear(); - for (unsigned int itRes = 0; itRes < numResAvailable; itRes++) - { - m_AvailableResolutions.push_back(itRes); - } - } - - return 1; -} - - -bool JPEG2000InternalReader::CanRead() - { - if (Initialize() && - ( this->m_Width > 0 ) && ( this->m_Height > 0 ) && - ( this->m_TileWidth > 0 ) && ( this->m_TileHeight > 0 ) && - ( this->m_XNbOfTile > 0 ) && ( this->m_YNbOfTile > 0 ) && - ( this->m_NbOfComponent > 0 ) ) - { - - // We manage only JPEG2000 file with characteristics which are equal between components - for(unsigned int itComp = 0; itComp < this->m_NbOfComponent - 1; itComp++) - { - if ( (this->m_Precision[itComp] != this->m_Precision[itComp+1]) && - (this->m_Signed[itComp] != this->m_Signed[itComp+1]) && - (this->m_XResolution[itComp] != this->m_XResolution[itComp+1]) && - (!this->m_XResolution[itComp]) && - (this->m_YResolution[itComp] != this->m_YResolution[itComp+1]) && - (!this->m_YResolution[itComp]) ) - { - return false; - } - } - return true; - } - else - { - std::cerr << this->m_Width << ", " - << this->m_Height << ", " - << this->m_TileWidth << ", " - << this->m_TileHeight << ", " - << this->m_XNbOfTile << ", " - << this->m_YNbOfTile<< ", " - << this->m_NbOfComponent - << std::endl ; - std::cout << "HERE1" << std::endl; - return false; - } - } - -/************************************************************************/ -/* Class to manage JPEG2000 tile cache system */ -/************************************************************************/ -class JPEG2000TileCache -{ -public: - JPEG2000TileCache(); - ~JPEG2000TileCache(); - - typedef std::pair<unsigned int, boost::shared_ptr<opj_image_t> > CachedTileType; - typedef std::deque<CachedTileType> TileCacheType; - - /** Get a tile in cache, return null if cache does not contain the - tile */ - boost::shared_ptr<opj_image_t> GetTile(unsigned int tileIndex); - - /** Register a new tile in cache */ - void AddTile(unsigned int tileIndex, boost::shared_ptr<opj_image_t> tileData); - - /** Remove the front tile */ - void RemoveOneTile(); - - /** Clear the cache */ - void Clear(); - - /** Initialize some parameters linked to the cache size in memory*/ - void Initialize(unsigned int originalWidthTile, unsigned int originalHeightTile, - unsigned int nbComponent, - unsigned int precision, - unsigned int resolution) - { - this->EstimateTileCacheSize(originalWidthTile, originalHeightTile, - nbComponent, - precision, - resolution); - m_CacheSizeInByte = m_CacheSizeInTiles * m_TileCacheSizeInByte; - m_IsReady = true; - }; - - /** Set the size of the cache with in terms of number of tiles */ - void SetCacheSizeInTiles(unsigned int nbOfTiles) - { - if (nbOfTiles > 0 && m_IsReady) - { - m_CacheSizeInTiles = nbOfTiles; - m_CacheSizeInByte = m_CacheSizeInTiles * m_TileCacheSizeInByte; - } - }; - - /** Get the size of the cache in terms of number of tiles */ - unsigned int GetCacheSizeInTiles() {return m_CacheSizeInTiles; }; - - /** Set the size of the cache with in terms of Bytes */ - void SetCacheSizeInByte(unsigned int sizeInByte) - { - if (sizeInByte > 0 && m_IsReady) - { - m_CacheSizeInByte = sizeInByte; - if (m_TileCacheSizeInByte) - m_CacheSizeInTiles = m_CacheSizeInByte / m_TileCacheSizeInByte; - else - m_CacheSizeInTiles = 0; - } - }; - - unsigned int GetCurrentNumberOfTileInCache() - { - return static_cast<unsigned int>(m_Cache.size()); - }; - -private: - TileCacheType m_Cache; - unsigned int m_CacheSizeInTiles; - unsigned int m_CacheSizeInByte; - unsigned int m_TileCacheSizeInByte; - bool m_IsReady; - - itk::SimpleMutexLock m_Mutex; - - /** Estimate the size of a tile in memory*/ - void EstimateTileCacheSize(unsigned int originalWidthTile, unsigned int originalHeightTile, - unsigned int nbComponent, - unsigned int precision, - unsigned int resolution); - -}; - -JPEG2000TileCache::JPEG2000TileCache() : m_Cache(), m_CacheSizeInTiles(4), m_CacheSizeInByte(0), m_TileCacheSizeInByte(0), m_IsReady(false) -{} - -JPEG2000TileCache::~JPEG2000TileCache() -{ - this->Clear(); -} - - -void JPEG2000TileCache::EstimateTileCacheSize(unsigned int originalWidthTile, unsigned int originalHeightTile, - unsigned int nbComponent, - unsigned int itkNotUsed(precision), - unsigned int resolution) -{ - this->m_TileCacheSizeInByte = originalWidthTile * originalHeightTile - * nbComponent - * sizeof(OPJ_INT32) - / vcl_pow(2, 2*static_cast<double>(resolution) ); - - if (!this->m_TileCacheSizeInByte) - { - otbMsgDevMacro( << "TileCacheSizeInByte is estimated at " << m_TileCacheSizeInByte - << " bytes so we don't used the cache"); - } - - otbMsgDevMacro( << "m_TileCacheSizeInByte = " << m_TileCacheSizeInByte ); -} - -void JPEG2000TileCache::Clear() -{ - m_Cache.clear(); -} - - -boost::shared_ptr<opj_image_t> JPEG2000TileCache::GetTile(unsigned int tileIndex) -{ - for(TileCacheType::iterator it = m_Cache.begin(); - it != m_Cache.end(); ++it) - { - if(it->first == tileIndex) - { - otbMsgDevMacro(<<"Tile "<<it->first<<" loaded from cache"); - return it->second; - } - } - return boost::shared_ptr<opj_image_t>(); -} - -void JPEG2000TileCache::RemoveOneTile() -{ - if(!m_Cache.empty()) - { - m_Cache.pop_front(); - } -} - -void JPEG2000TileCache::AddTile(unsigned int tileIndex, boost::shared_ptr<opj_image_t> tileData) -{ - // This helper class makes sure the Mutex is unlocked - // in the event an exception is thrown. - itk::MutexLockHolder<itk::SimpleMutexLock> mutexHolder(m_Mutex); - - if(!m_IsReady) - { - std::cerr<<(this)<<" Cache is not configured !"<<std::endl; - } - - for(TileCacheType::const_iterator it = m_Cache.begin(); - it != m_Cache.end(); ++it) - { - if(it->first == tileIndex) - { - return; - } - } - if(m_Cache.size() >= m_CacheSizeInTiles) - { - this->RemoveOneTile(); - } - m_Cache.push_back(CachedTileType(tileIndex, tileData)); -} - -/************************************************************************/ -/* JPEG2000ImageIO */ -/************************************************************************/ -JPEG2000ImageIO::JPEG2000ImageIO() -{ - // Initialize multi-threader - m_Threader = itk::MultiThreader::New(); - m_NumberOfThreads = m_Threader->GetNumberOfThreads(); - - for(int i = 0; i<m_NumberOfThreads; ++i) - { - m_InternalReaders.push_back(boost::shared_ptr<JPEG2000InternalReader>(new JPEG2000InternalReader)); - } - m_TileCache = boost::shared_ptr<JPEG2000TileCache>(new JPEG2000TileCache); - - // By default set number of dimensions to two. - this->SetNumberOfDimensions(2); - m_PixelType = SCALAR; - m_ComponentType = UCHAR; - - // Set default spacing to one - m_Spacing[0] = 1.0; - m_Spacing[1] = 1.0; - // Set default origin to zero - m_Origin[0] = 0.5; - m_Origin[1] = 0.5; - - m_BytePerPixel = 1; - m_ResolutionFactor = 0; // Full resolution by default - m_CacheSizeInByte = 0; // By default no cache -} - -JPEG2000ImageIO::~JPEG2000ImageIO() -{} - -bool JPEG2000ImageIO::CanReadFile(const char* filename) -{ - if (filename == ITK_NULLPTR) - { - itkDebugMacro(<< "No filename specified."); - return false; - } - - bool success = true; - - for(ReaderVectorType::iterator it = m_InternalReaders.begin(); - it != m_InternalReaders.end(); - ++it) - { - - if ( !(*it)->Open(filename, m_ResolutionFactor) ) - { - success = false; - } - } - - // If one of the readers fails, clean everything - if(!success) - { - for(ReaderVectorType::iterator it = m_InternalReaders.begin(); - it != m_InternalReaders.end(); - ++it) - { - (*it)->Clean(); - } - } - return success; -} - -// Used to print information about this object -void JPEG2000ImageIO::PrintSelf(std::ostream& os, itk::Indent indent) const -{ - Superclass::PrintSelf(os, indent); - os << indent << "Resolution Factor: " << m_ResolutionFactor << "\n"; -} - -// Read a 3D image not implemented yet -void JPEG2000ImageIO::ReadVolume(void*) -{ -} - -/** Internal structure used for passing image data into the threading library */ -struct ThreadStruct -{ - std::vector<boost::shared_ptr<JPEG2000InternalReader> > Readers; - std::vector<JPEG2000TileCache::CachedTileType> * Tiles; - JPEG2000ImageIO::Pointer IO; - boost::shared_ptr<JPEG2000TileCache> Cache; - void * Buffer; -}; - - -std::vector<std::string> JPEG2000ImageIO::GetOverviewsInfo() -{ - std::vector<std::string> desc; - int originalWidth = m_InternalReaders[0]->m_Width; - int originalHeight = m_InternalReaders[0]->m_Height; - - unsigned int lOverviewCount = this->GetOverviewsCount(); - - for (unsigned int i = 0; i < lOverviewCount; i++) - { - // For each resolution we will compute the tile dim and image dim - std::ostringstream oss; - - int w = int_ceildivpow2( originalWidth, i); - int h = int_ceildivpow2( originalHeight, i); - - int tw = int_ceildivpow2(m_InternalReaders[0]->m_TileWidth, i); - int th = int_ceildivpow2(m_InternalReaders[0]->m_TileHeight, i); - - oss << "Resolution: " << i << " (Image [w x h]: " << w << "x" << h << ", Tile [w x h]: " << tw << "x" << th << ")"; - - desc.push_back(oss.str()); - } - - return desc; -} - -unsigned int JPEG2000ImageIO::GetOverviewsCount() -{ - std::vector<unsigned int> tempResList = this->m_InternalReaders[0]->GetAvailableResolutions(); - - if (tempResList.empty()) - { - itkExceptionMacro(<< "Available resolutions in JPEG2000 is empty"); - } - - // count includes full resolution - return tempResList.size(); -} - -// Read image -void JPEG2000ImageIO::Read(void* buffer) -{ - itk::TimeProbe chrono; - chrono.Start(); - - // Check if conversion succeed - if (buffer == ITK_NULLPTR) - { - itkExceptionMacro(<< "JPEG2000ImageIO : Bad alloc"); - return; - } - - // Re-open the file if it was closed - bool open = true; - for(ReaderVectorType::iterator it = m_InternalReaders.begin(); - it != m_InternalReaders.end(); - ++it) - { - open = (*it)->m_IsOpen && open; - } - - if ( !open ) - { - if ( !this->CanReadFile( m_FileName.c_str() ) ) - { - itkExceptionMacro(<< "Cannot open file " << this->m_FileName << "!"); - return; - } - } - - if (m_ResolutionFactor >= this->m_InternalReaders[0]->m_AvailableResolutions.size()) - { - itkExceptionMacro(<< "Resolution not available in the file!"); - return; - } - - std::vector<unsigned int> tileList = this->ComputeTileList(); - if (tileList.empty()) - { - for(ReaderVectorType::iterator it = m_InternalReaders.begin(); - it != m_InternalReaders.end(); - ++it) - { - (*it)->Clean(); - } - itkExceptionMacro(<< " IORegion does not correspond to any tile!"); - } - - // Here we sort between tiles from cache and tiles to read - std::vector<JPEG2000TileCache::CachedTileType> cachedTiles; - std::vector<JPEG2000TileCache::CachedTileType> toReadTiles; - - for (std::vector<unsigned int>::iterator itTile = tileList.begin(); itTile < tileList.end(); ++itTile) - { - boost::shared_ptr<opj_image_t> currentImage(m_TileCache->GetTile(*itTile)); - - JPEG2000TileCache::CachedTileType currentTile = std::make_pair((*itTile), currentImage); - - if(!currentImage) - { - toReadTiles.push_back(currentTile); - } - else - { - cachedTiles.push_back(currentTile); - } - } - - // First, load tiles from cache - for (std::vector<JPEG2000TileCache::CachedTileType>::iterator itTile = cachedTiles.begin(); itTile < cachedTiles.end(); ++itTile) - { - this->LoadTileData(buffer, itTile->second.get()); - } - - // If we will read more tiles than the cache size, clear it - if(toReadTiles.size() > m_TileCache->GetCacheSizeInTiles()) - { - m_TileCache->Clear(); - } - // Else if there is not enough rooms from new tiles - else if(toReadTiles.size() > (m_TileCache->GetCacheSizeInTiles() - m_TileCache->GetCurrentNumberOfTileInCache())) - { - int nbTileToRemove = toReadTiles.size() - (m_TileCache->GetCacheSizeInTiles() - m_TileCache->GetCurrentNumberOfTileInCache()); - // Remove from cache as many tiles that will be read in this step - for (int itTileR = 0; itTileR < nbTileToRemove; ++itTileR) - { - m_TileCache->RemoveOneTile(); - } - } - - // Decode all tiles not in cache in parallel - if(!toReadTiles.empty()) - { - unsigned int nbThreads = itk::MultiThreader::GetGlobalDefaultNumberOfThreads(); - if (nbThreads > toReadTiles.size()) - { - nbThreads = toReadTiles.size(); - } - this->GetMultiThreader()->SetNumberOfThreads(nbThreads); - - // Set up the multithreaded processing - ThreadStruct str; - str.Readers = m_InternalReaders; - str.Tiles = &toReadTiles; - str.IO = this; - str.Cache = m_TileCache; - str.Buffer = buffer; - - // Set-up multi-threader - this->GetMultiThreader()->SetSingleMethod(this->ThreaderCallback, &str); - - // multithread the execution - this->GetMultiThreader()->SingleMethodExecute(); - } - - chrono.Stop(); - otbMsgDevMacro( << "JPEG2000ImageIO::Read took " << chrono.GetTotal() << " sec"); - - for(ReaderVectorType::iterator it = m_InternalReaders.begin(); - it != m_InternalReaders.end(); - ++it) - { - (*it)->Clean(); - } -} - -// The void * interface prevent us to propagate shared_ptr here -void JPEG2000ImageIO::LoadTileData(void * buffer, void * currentTile) -{ - opj_image_t * tile = static_cast<opj_image_t *>(currentTile); - - if(!tile) - { - itkExceptionMacro(<<"Tile needed but not loaded."); - } - - // Get nb. of lines and columns of the region to read - /* -Wunused-variable - int lNbLines = this->GetIORegion().GetSize()[1]; - */ - int lNbColumns = this->GetIORegion().GetSize()[0]; - /* -Wunused-variable - int lFirstLine = this->GetIORegion().GetIndex()[1]; // [1... ] - int lFirstColumn = this->GetIORegion().GetIndex()[0]; // [1... ] - */ - unsigned int lWidthSrc; // Width of the input pixel in nb of pixel - unsigned int lHeightDest; // Height of the area where write in nb of pixel - unsigned int lWidthDest; // Width of the area where write in nb of pixel - unsigned int lStartOffsetPxlDest; // Offset where begin to write the area in the otb buffer in nb of pixel - unsigned int lStartOffsetPxlSrc; // Offset where begin to write the area in the otb buffer in nb of pixel - - ComputeOffsets(tile, this->GetIORegion(), lWidthSrc, lHeightDest, lWidthDest, lStartOffsetPxlDest, lStartOffsetPxlSrc); - - switch (this->GetComponentType()) - { - case CHAR: - { - char *p = static_cast<char *> (buffer); - for (unsigned int j = 0; j < lHeightDest; ++j) - { - char* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents; - - for (unsigned int k = 0; k < lWidthDest; ++k) - { - for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++) - { - OPJ_INT32* data = tile->comps[itComp].data; - *(current_dst_line++) = static_cast<char> (data[lStartOffsetPxlSrc + k + j * lWidthSrc]); - } - } - } - } - break; - case UCHAR: - { - unsigned char *p = static_cast<unsigned char *> (buffer); - for (unsigned int j = 0; j < lHeightDest; ++j) - { - unsigned char* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents; - - for (unsigned int k = 0; k < lWidthDest; ++k) - { - for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++) - { - OPJ_INT32* data = tile->comps[itComp].data; - unsigned char component_val = data[lStartOffsetPxlSrc + k + j * lWidthSrc] & 0xff; - *(current_dst_line++) = static_cast<unsigned char> (component_val); - } - } - } - } - break; - case SHORT: - { - short *p = static_cast<short *> (buffer); - for (unsigned int j = 0; j < lHeightDest; ++j) - { - short* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents; - - for (unsigned int k = 0; k < lWidthDest; ++k) - { - for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++) - { - OPJ_INT32* data = tile->comps[itComp].data; - *(current_dst_line++) = static_cast<short> (data[lStartOffsetPxlSrc + k + j * lWidthSrc]); - } - } - } - } - break; - case USHORT: - { - unsigned short *p = static_cast<unsigned short *> (buffer); - for (unsigned int j = 0; j < lHeightDest; ++j) - { - unsigned short* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents; - - for (unsigned int k = 0; k < lWidthDest; ++k) - { - for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++) - { - OPJ_INT32* data = tile->comps[itComp].data; - *(current_dst_line++) = static_cast<unsigned short> (data[lStartOffsetPxlSrc + k + j * lWidthSrc] & 0xffff); - } - } - } - } - break; - case INT: - case UINT: - default: - itkGenericExceptionMacro(<< "This data type is not handled"); - break; - } -} - -ITK_THREAD_RETURN_TYPE JPEG2000ImageIO::ThreaderCallback( void *arg ) -{ - ThreadStruct *str; - unsigned int total, threadCount; - itk::ThreadIdType threadId; - - threadId = ((itk::MultiThreader::ThreadInfoStruct *)(arg))->ThreadID; - threadCount = ((itk::MultiThreader::ThreadInfoStruct *)(arg))->NumberOfThreads; - - str = (ThreadStruct *)(((itk::MultiThreader::ThreadInfoStruct *)(arg))->UserData); - - // Retrieve data - std::vector<boost::shared_ptr<JPEG2000InternalReader> > readers = str->Readers; - std::vector<JPEG2000TileCache::CachedTileType> * tiles = str->Tiles; - JPEG2000ImageIO::Pointer io = str->IO; - boost::shared_ptr<JPEG2000TileCache> cache = str->Cache; - void * buffer = str->Buffer; - - total = std::min((unsigned int)tiles->size(), threadCount); - - if(total == 0) - { - return ITK_THREAD_RETURN_VALUE; - } - - - unsigned int tilesPerThread = tiles->size()/total; - if(tilesPerThread == 0) - { - tilesPerThread = 1; - } - - for(unsigned int i = threadId * tilesPerThread; - i < tilesPerThread * (threadId+1); - ++i) - { - boost::shared_ptr<opj_image_t> currentTile = readers.at(threadId)->DecodeTile(tiles->at(i).first); - - // Check if tile is valid - if(!currentTile) - { - readers.at(threadId)->Clean(); - itkGenericExceptionMacro(" otbopenjpeg failed to decode the desired tile "<<tiles->at(i).first << "!"); - } - - otbMsgDevMacro(<< " Tile " << tiles->at(i).first << " decoded by thread "<<threadId); - - io->LoadTileData(buffer, currentTile.get()); - - if (cache->GetCacheSizeInTiles() != 0) - { - cache->AddTile(tiles->at(i).first, currentTile); - } - } - - unsigned int lastTile = threadCount*tilesPerThread + threadId; - - // TODO: check this last part - - if(lastTile < tiles->size()) - { - boost::shared_ptr<opj_image_t> currentTile = readers.at(threadId)->DecodeTile(tiles->at(lastTile).first); - - // Check if tile is valid - if(!currentTile) - { - readers.at(threadId)->Clean(); - itkGenericExceptionMacro(" otbopenjpeg failed to decode the desired tile "<<tiles->at(lastTile).first << "!"); - } - - otbMsgDevMacro(<< " Tile " <<tiles->at(lastTile).first << " decoded by thread "<<threadId); - - io->LoadTileData(buffer, currentTile.get()); - - if (cache->GetCacheSizeInTiles() != 0) - { - cache->AddTile(tiles->at(lastTile).first, currentTile); - } - } - - return ITK_THREAD_RETURN_VALUE; -} - -void JPEG2000ImageIO::ConfigureCache() -{ - itk::ExposeMetaData<unsigned int>(this->GetMetaDataDictionary(), - MetaDataKey::CacheSizeInBytes, - m_CacheSizeInByte); - - // Initialize some parameters of the tile cache - this->m_TileCache->Initialize(m_InternalReaders.front()->m_TileWidth, - m_InternalReaders.front()->m_TileHeight, - m_InternalReaders.front()->m_NbOfComponent, - m_BytePerPixel, - m_ResolutionFactor); - - // If available set the size of the cache - if (this->m_CacheSizeInByte) - this->m_TileCache->SetCacheSizeInByte(this->m_CacheSizeInByte); -} - -void JPEG2000ImageIO::ReadImageInformation() -{ - // Extract metadata - // In case the metadata are not set, the function silently returns, doing nothing - itk::ExposeMetaData<unsigned int>(this->GetMetaDataDictionary(), - MetaDataKey::ResolutionFactor, - m_ResolutionFactor); - - // Now initialize the itk dictionary - itk::MetaDataDictionary& dict = this->GetMetaDataDictionary(); - - JPEG2000MetadataReader lJP2MetadataReader(m_FileName.c_str()); - - if (lJP2MetadataReader.m_MetadataIsRead) - { - otbMsgDevMacro(<<"JPEG2000 file has metadata available!"); - - // reset the origin to [0,0] as in GDAL convention - m_Origin[0] = 0.0; - m_Origin[1] = 0.0; - - /* GEOTRANSFORM */ - if (lJP2MetadataReader.HaveGeoTransform()) - { - otbMsgDevMacro(<< "JPEG2000 file has a geotransform!"); - std::vector<double> geoTransform = lJP2MetadataReader.GetGeoTransform(); - - itk::EncapsulateMetaData<MetaDataKey::VectorType>(dict, MetaDataKey::GeoTransformKey, geoTransform); - - /*std::cout << "from gml box, geotransform: "; - for (int i = 0; i < 6; i++) - { - std::cout << geoTransform[i] << ", "; - } - std::cout << std::endl; */ - - // Retrieve origin and spacing from the geo transform - m_Spacing[0] = geoTransform[1]; - m_Spacing[1] = geoTransform[5]; - - if ( m_Spacing[0]== 0 || m_Spacing[1] == 0) - { - // Manage case where axis are not standard - if (geoTransform[2] != 0 && geoTransform[4] != 0 ) - { - m_Spacing[0] = geoTransform[2]; - m_Spacing[1] = geoTransform[4]; - } - else - { - otbWarningMacro(<< "JPEG2000 file has an incorrect geotransform (spacing = 0)!"); - m_Spacing[0] = 1; - m_Spacing[1] = 1; - } - } - // Geotransforms with a non-null rotation are not supported - // Beware : GDAL origin is at the corner of the top-left pixel - // whereas OTB/ITK origin is at the centre of the top-left pixel - // The origin is first stored in GDAL convention. The halft pixel - // shift is applied later (when the final spacing is known) - m_Origin[0] = geoTransform[0]; - m_Origin[1] = geoTransform[3]; - } - - /* GCPs */ - if (lJP2MetadataReader.GetGCPCount() > 0) - { - // No GCPprojRef return by GDALJP2metadata - std::string gcpProjectionKey = "UNKNOWN"; - itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::GCPProjectionKey, gcpProjectionKey); - - int nbGCPs = lJP2MetadataReader.GetGCPCount(); - otbMsgDevMacro(<< "JPEG2000 file has "<< nbGCPs << " GCPs!"); - itk::EncapsulateMetaData<int>(dict, MetaDataKey::GCPCountKey, nbGCPs); - - std::vector<GDAL_GCP> gcps = lJP2MetadataReader.GetGCPs(); - - std::string key; - for (int cpt = 0; cpt < nbGCPs; ++cpt) - { - GDAL_GCP currentGCP = gcps[cpt]; - OTB_GCP pOtbGCP; - pOtbGCP.m_Id = std::string(currentGCP.pszId); - pOtbGCP.m_Info = std::string(currentGCP.pszInfo); - pOtbGCP.m_GCPRow = currentGCP.dfGCPLine; - pOtbGCP.m_GCPCol = currentGCP.dfGCPPixel; - pOtbGCP.m_GCPX = currentGCP.dfGCPX; - pOtbGCP.m_GCPY = currentGCP.dfGCPY; - pOtbGCP.m_GCPZ = currentGCP.dfGCPZ; - - // Complete the key with the GCP number : GCP_i - std::ostringstream lStream; - lStream << MetaDataKey::GCPParametersKey << cpt; - key = lStream.str(); - - itk::EncapsulateMetaData<OTB_GCP>(dict, key, pOtbGCP); - } - } - - /* GMLMetadata*/ - char** papszGMLMetadata; - papszGMLMetadata = lJP2MetadataReader.GetGMLMetadata(); - if (CSLCount(papszGMLMetadata) > 0) - { - otbMsgDevMacro(<< "JPEG2000 file has GMLMetadata!"); - std::string key; - - for (int cpt = 0; papszGMLMetadata[cpt] != ITK_NULLPTR; ++cpt) - { - std::ostringstream lStream; - lStream << MetaDataKey::MetadataKey << cpt; - key = lStream.str(); - - itk::EncapsulateMetaData<std::string>(dict, key, static_cast<std::string> (papszGMLMetadata[cpt])); - otbMsgDevMacro( << static_cast<std::string>(papszGMLMetadata[cpt])); - } - } - - - /* ProjectionRef*/ - if (lJP2MetadataReader.GetProjectionRef() && !std::string(lJP2MetadataReader.GetProjectionRef()).empty() ) - { - OGRSpatialReferenceH pSR = OSRNewSpatialReference(ITK_NULLPTR); - - const char * pszProjection = ITK_NULLPTR; - pszProjection = lJP2MetadataReader.GetProjectionRef(); - - if (OSRImportFromWkt(pSR, (char **) (&pszProjection)) == OGRERR_NONE) - { - char * pszPrettyWkt = ITK_NULLPTR; - OSRExportToPrettyWkt(pSR, &pszPrettyWkt, FALSE); - - itk::EncapsulateMetaData<std::string> (dict, MetaDataKey::ProjectionRefKey, - static_cast<std::string>(pszPrettyWkt)); - - CPLFree(pszPrettyWkt); - } - else - { - itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey, - static_cast<std::string>(lJP2MetadataReader.GetProjectionRef())); - } - - if (pSR != ITK_NULLPTR) - { - OSRRelease(pSR); - pSR = ITK_NULLPTR; - } - } - else - { - otbMsgDevMacro( << "NO PROJECTION IN GML BOX => SENSOR MODEL " ); - m_Origin[0] = 0.0; m_Origin[1] = 0.0; - m_Spacing[0] = 1; m_Spacing[1] = 1; - - lJP2MetadataReader.GetOriginFromGMLBox(m_Origin); - } - - otbMsgDevMacro(<< "FROM GML box: " << "Origin: " << m_Origin[0] << ", " << m_Origin[1] - << " | Spacing: " << m_Spacing[0] << ", " << m_Spacing[1] ); - - } - else - { - otbMsgDevMacro( << "JPEG2000 file has NO metadata available!"); - m_Origin[0] = 0.0; - m_Origin[1] = 0.0; - m_Spacing[0] = 1.0; - m_Spacing[1] = 1.0; - } - - // Compute final spacing using the resolution factor - m_Spacing[0] *= vcl_pow(2.0, static_cast<double>(m_ResolutionFactor)); - m_Spacing[1] *= vcl_pow(2.0, static_cast<double>(m_ResolutionFactor)); - // Now that the spacing is known, apply the half-pixel shift - m_Origin[0] += 0.5*m_Spacing[0]; - m_Origin[1] += 0.5*m_Spacing[1]; - - // If the internal image was not open we open it. - // This is usually done when the user sets the ImageIO manually - if ( !m_InternalReaders.front()->m_IsOpen ) - { - if ( !this->CanReadFile( m_FileName.c_str() ) ) - { - itkExceptionMacro(<< "Cannot open file " << this->m_FileName << "!"); - return; - } - } - - // Check some internal parameters of the JPEG2000 file - if ( !this->m_InternalReaders.front()->CanRead()) - { - this->m_InternalReaders.front()->Clean(); - itkExceptionMacro(<< "Cannot read this file because some JPEG2000 parameters are not supported!"); - } - - // If one of the readers fails, clean everything - if(this->m_ResolutionFactor != 0) - { - for(ReaderVectorType::iterator it = m_InternalReaders.begin(); - it != m_InternalReaders.end(); - ++it) - { - (*it)->Clean(); - } - - bool success = true; - - for(ReaderVectorType::iterator it = m_InternalReaders.begin(); - it != m_InternalReaders.end(); - ++it) - { - - if ( !(*it)->Open( m_FileName.c_str(), this->m_ResolutionFactor ) ) - { - success = false; - } - (*it)->m_IsOpen = true; - } - - // If one of the readers fails, clean everything - if(!success) - { - for(ReaderVectorType::iterator it = m_InternalReaders.begin(); - it != m_InternalReaders.end(); - ++it) - { - (*it)->Clean(); - } - - itkExceptionMacro(<< "Cannot open this file with this resolution!"); - return; - } - } - - // Encapsulate tile hints for streaming - unsigned int tileHintX = m_InternalReaders.front()->m_TileWidth / static_cast<unsigned int>(vcl_pow(2.0, static_cast<int>(m_ResolutionFactor) )); - unsigned int tileHintY = m_InternalReaders.front()->m_TileHeight / static_cast<unsigned int>(vcl_pow(2.0, static_cast<int>(m_ResolutionFactor) )); - - itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::TileHintX, tileHintX); - itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::TileHintY, tileHintY); - - // If we have some spacing information we use it - // could be needed for other j2k image but not for pleiades - // if ( (m_InternalReaders.front()->m_XResolution.front() > 0) && (m_InternalReaders.front()->m_YResolution.front() > 0) ) - // { - // // We check previously that the X and Y resolution is equal between the components - // m_Spacing[0] *= m_InternalReaders.front()->m_XResolution[0]; - // m_Spacing[1] *= m_InternalReaders.front()->m_YResolution[0]; - // } - - m_Dimensions[0] = m_InternalReaders.front()->m_Width; - m_Dimensions[1] = m_InternalReaders.front()->m_Height; - - this->SetNumberOfDimensions(2); - - if (m_Dimensions[0] == 0 || m_Dimensions[1] == 0) - { - itkExceptionMacro(<< "Image size is null."); - } - - this->SetNumberOfComponents(m_InternalReaders.front()->m_NbOfComponent); - - // Automatically set the Type to Binary for JPEG2000 data - this->SetFileTypeToBinary(); - - // We check previously that these values are equal between all components - unsigned int precision = m_InternalReaders.front()->m_Precision[0]; - int isSigned = m_InternalReaders.front()->m_Signed[0]; - - if (precision <= 8) - { - m_BytePerPixel = 1; - if (isSigned) - { - SetComponentType(CHAR); - } - else - { - SetComponentType(UCHAR); - } - } - else if (precision <= 16) - { - m_BytePerPixel = 2; - if (isSigned) - { - SetComponentType(SHORT); - } - else - { - SetComponentType(USHORT); - } - } - else - { - m_BytePerPixel = 4; - if (isSigned) - { - SetComponentType(INT); - } - else - { - SetComponentType(UINT); - } - } - - if (this->GetNumberOfComponents() == 1) - { - this->SetPixelType(SCALAR); - } - else - { - this->SetPixelType(VECTOR); - } - - this->ConfigureCache(); - - otbMsgDebugMacro(<< "=========================="); - otbMsgDebugMacro(<< "ReadImageInformation: "); - otbMsgDebugMacro(<< "Tile size (WxH): " << m_InternalReaders.front()->m_TileWidth << " x " - << m_InternalReaders.front()->m_TileHeight); - otbMsgDebugMacro(<< "Number of tiles (Xdim x Ydim) : " << m_InternalReaders.front()->m_XNbOfTile - << " x " << m_InternalReaders.front()->m_YNbOfTile); - otbMsgDebugMacro(<< "Precision: " << precision); - otbMsgDebugMacro(<< "Signed: " << isSigned); - otbMsgDebugMacro(<< "Number of octet per value: " << m_BytePerPixel); - otbMsgDebugMacro(<< "=========================="); - - otbMsgDebugMacro(<< "Driver to read: JPEG2000"); - otbMsgDebugMacro(<< " Read file : " << m_FileName); - otbMsgDebugMacro(<< " Size : " << m_Dimensions[0] << "," << m_Dimensions[1]); - otbMsgDebugMacro(<< " ComponentType : " << this->GetComponentType()); - otbMsgDebugMacro(<< " NumberOfComponents : " << this->GetNumberOfComponents()); - otbMsgDebugMacro(<< " ComponentSize : " << this->GetComponentSize()); - otbMsgDebugMacro(<< " GetPixelSize : " << this->GetPixelSize()); -} - -// Compute the tile index list from the GetRegion -std::vector<unsigned int> JPEG2000ImageIO::ComputeTileList() -{ - std::vector<unsigned int> tileVector; - - // Get nb. of lines and columns of the region to decode - unsigned int startX = this->GetIORegion().GetIndex()[0]; - unsigned int endX = this->GetIORegion().GetIndex()[0] + this->GetIORegion().GetSize()[0]; - unsigned int startY = this->GetIORegion().GetIndex()[1]; - unsigned int endY = this->GetIORegion().GetIndex()[1] + this->GetIORegion().GetSize()[1]; - - // Compute index of tile recover by the decoded area - unsigned int tile_size_x = m_InternalReaders.front()->m_TileWidth; - unsigned int tile_size_y = m_InternalReaders.front()->m_TileHeight; - unsigned int width = m_Dimensions[0]; - unsigned int height = m_Dimensions[1]; - unsigned int nbOfTileX = m_InternalReaders.front()->m_XNbOfTile; - unsigned int nbOfTileY = m_InternalReaders.front()->m_YNbOfTile; - - unsigned int tilePosX0, tilePosX1; - unsigned int tilePosY0, tilePosY1; - - for (unsigned int itTileY = 0; itTileY < nbOfTileY; itTileY++) - { - tilePosY0 = uint_ceildivpow2( itTileY*tile_size_y, m_ResolutionFactor ); - tilePosY1 = std::min( uint_ceildivpow2( (itTileY+1)*tile_size_y, m_ResolutionFactor ), height ); - - for (unsigned int itTileX = 0; itTileX < nbOfTileX; itTileX++) - { - tilePosX0 = uint_ceildivpow2( itTileX*tile_size_x, m_ResolutionFactor ); - tilePosX1 = std::min( uint_ceildivpow2( (itTileX+1)*tile_size_x, m_ResolutionFactor ), width); - - if ( (tilePosX1 - tilePosX0) && (tilePosY1 - tilePosY0) && - (tilePosX1 > startX) && (tilePosX0 < endX ) && - (tilePosY1 > startY) && (tilePosY0 < endY ) ) - tileVector.push_back(itTileX + itTileY * nbOfTileX); - - } - } - - return tileVector; -} - -/** Compute the offsets in Pixel to move the input buffer from openjpeg - * to the corresponding area of the otb output buffer - * */ -void ComputeOffsets( opj_image_t * currentTile, - const itk::ImageIORegion & ioRegion, - unsigned int &l_width_src, // Width of the input pixel in nb of pixel - unsigned int &l_height_dest, // Height of the area where write in nb of pixel - unsigned int &l_width_dest, // Width of the area where write in nb of pixel - unsigned int &l_start_offset_dest, // Offset where begin to write the area in the otb buffer in nb of pixel - unsigned int &l_start_offset_src // Offset where begin to read the data in the openjpeg decoded data in nb of pixel - ) -{ - // Characteristics of the input buffer from openpjeg - unsigned int l_x0_src = int_ceildivpow2(currentTile->x0, currentTile->comps->factor); - unsigned int l_y0_src = int_ceildivpow2(currentTile->y0, currentTile->comps->factor); - unsigned int l_x1_src = int_ceildivpow2(currentTile->x1, currentTile->comps->factor); - unsigned int l_y1_src = int_ceildivpow2(currentTile->y1, currentTile->comps->factor); - - // Size of input buffer from openjpeg - l_width_src = l_x1_src - l_x0_src; - unsigned int l_height_src = l_y1_src - l_y0_src; - - // Characteristics of the otb region - unsigned int l_x0_dest = ioRegion.GetIndex()[0]; - unsigned int l_x1_dest = ioRegion.GetIndex()[0] + ioRegion.GetSize()[0]; - unsigned int l_y0_dest = ioRegion.GetIndex()[1]; - unsigned int l_y1_dest = ioRegion.GetIndex()[1] + ioRegion.GetSize()[1]; - - unsigned int l_start_x_dest, l_start_y_dest; - unsigned int l_offset_x0_src, l_offset_y0_src; - - /*-----*/ - /* Compute the origin (l_offset_x0_src, l_offset_y0_src ) - * of the input buffer (decoded tile) which will be move - * in the output buffer. - * Compute the area of the output buffer (l_start_x_dest, - * l_start_y_dest, l_width_dest, l_height_dest) which will be modified - * by this input area. - */ - - if (l_x0_dest < l_x0_src) - { - l_start_x_dest = l_x0_src - l_x0_dest; - l_offset_x0_src = 0; - - if (l_x1_dest >= l_x1_src) - { - l_width_dest = l_width_src; - } - else - { - l_width_dest = l_x1_dest - l_x0_src; - } - } - else - { - l_start_x_dest = 0; - l_offset_x0_src = l_x0_dest - l_x0_src; - - if (l_x1_dest >= l_x1_src) - { - l_width_dest = l_width_src - l_offset_x0_src; - } - else - { - l_width_dest = l_x1_dest - l_x0_dest; - } - } - - if (l_y0_dest < l_y0_src) - { - l_start_y_dest = l_y0_src - l_y0_dest; - l_offset_y0_src = 0; - - if (l_y1_dest >= l_y1_src) - { - l_height_dest = l_height_src; - } - else - { - l_height_dest = l_y1_dest - l_y0_src; - } - } - else - { - l_start_y_dest = 0; - l_offset_y0_src = l_y0_dest - l_y0_src; - - if (l_y1_dest >= l_y1_src) - { - l_height_dest = l_height_src - l_offset_y0_src; - } - else - { - l_height_dest = l_y1_dest - l_y0_dest; - } - } - /*-----*/ - - /* Compute the input buffer offset */ - l_start_offset_src = l_offset_x0_src + l_offset_y0_src * l_width_src; - - /* Compute the output buffer offset */ - l_start_offset_dest = l_start_x_dest + l_start_y_dest * (l_x1_dest - l_x0_dest); - - /* - std::cout << "SRC coordinates: l_start_x_src= " << l_x0_src << ", l_start_y_src= " << l_y0_src << ", l_width_src= " - << l_width_src << ", l_height_src= " << l_height_src << std::endl; - std::cout << "SRC tile offset: " << l_offset_x0_src << ", " << l_offset_y0_src << std::endl; - std::cout << "SRC buffer offset: " << l_start_offset_src << std::endl; - - std::cout << "DEST coordinates: l_start_x_dest= " << l_start_x_dest << ", l_start_y_dest= " << l_start_y_dest - << ", l_width_dest= " << l_width_dest << ", l_height_dest= " << l_height_dest << std::endl; - std::cout << "DEST start offset: " << l_start_offset_dest << std::endl; - */ -} - -// Not yet implemented -bool JPEG2000ImageIO::CanWriteFile(const char* /*filename*/) -{ - return false; -} - -// Not yet implemented -void JPEG2000ImageIO::Write(const void* /*buffer*/) -{ - -} - -void JPEG2000ImageIO::WriteImageInformation() -{ - if (m_FileName == "") - { - itkExceptionMacro(<< "A FileName must be specified."); - } - if (CanWriteFile(m_FileName.c_str()) == false) - { - itkExceptionMacro(<< "The file " << m_FileName.c_str() << " is not defined as a JPEG2000 file"); - } - - otbMsgDebugMacro(<< "Driver to write: JPEG2000"); - otbMsgDebugMacro(<< " Write file : " << m_FileName); - otbMsgDebugMacro(<< " Size : " << m_Dimensions[0] << "," << m_Dimensions[1]); - otbMsgDebugMacro(<< " ComponentType : " << this->GetComponentType()); - otbMsgDebugMacro(<< " NumberOfComponents : " << this->GetNumberOfComponents()); - otbMsgDebugMacro(<< " ComponentSize : " << this->GetComponentSize()); - otbMsgDebugMacro(<< " GetPixelSize : " << this->GetPixelSize()); - -} - -} // end namespace otb diff --git a/Modules/IO/IOJPEG2000/src/otbJPEG2000ImageIOFactory.cxx b/Modules/IO/IOJPEG2000/src/otbJPEG2000ImageIOFactory.cxx deleted file mode 100644 index 67f8a0309f33b3b841aadc52240c9c88abb6df08..0000000000000000000000000000000000000000 --- a/Modules/IO/IOJPEG2000/src/otbJPEG2000ImageIOFactory.cxx +++ /dev/null @@ -1,65 +0,0 @@ -/*========================================================================= - - 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. - -=========================================================================*/ -#include "otbJPEG2000ImageIOFactory.h" - -#include "itkCreateObjectFunction.h" -#include "otbJPEG2000ImageIO.h" -#include "itkVersion.h" - -namespace otb -{ - -JPEG2000ImageIOFactory::JPEG2000ImageIOFactory() -{ - this->RegisterOverride("otbImageIOBase", - "otbJPEG2000ImageIO", - "JPEG2000 Image IO", - 1, - itk::CreateObjectFunction<JPEG2000ImageIO>::New()); -} - -JPEG2000ImageIOFactory::~JPEG2000ImageIOFactory() -{ -} - -const char* -JPEG2000ImageIOFactory::GetITKSourceVersion(void) const -{ - return ITK_SOURCE_VERSION; -} - -const char* -JPEG2000ImageIOFactory::GetDescription() const -{ - return "JPEG2000 ImageIO Factory, allows the loading of JPEG2000 images into insight"; -} - -// Undocumented API used to register during static initialization. -// DO NOT CALL DIRECTLY. - -static bool JPEG2000ImageIOFactoryHasBeenRegistered; - -void JPEG2000ImageIOFactoryRegister__Private(void) -{ - if( ! JPEG2000ImageIOFactoryHasBeenRegistered ) - { - JPEG2000ImageIOFactoryHasBeenRegistered = true; - JPEG2000ImageIOFactory::RegisterOneFactory(); - } -} -} // end namespace otb diff --git a/Modules/IO/IOJPEG2000/test/CMakeLists.txt b/Modules/IO/IOJPEG2000/test/CMakeLists.txt deleted file mode 100644 index 63d8b80d808fb0b94a3d7b11281cb9e597b04d4a..0000000000000000000000000000000000000000 --- a/Modules/IO/IOJPEG2000/test/CMakeLists.txt +++ /dev/null @@ -1,80 +0,0 @@ -otb_module_test() - -set(OTBIOJPEG2000Tests -otbIOJPEG2000TestDriver.cxx -otbJPEG2000ImageIOTestCanWrite.cxx -otbJPEG2000ImageIOTestCanRead.cxx -otbGenerateClassicalQLWithJPEG2000.cxx -) - -add_executable(otbIOJPEG2000TestDriver ${OTBIOJPEG2000Tests}) -target_link_libraries(otbIOJPEG2000TestDriver ${OTBIOJPEG2000-Test_LIBRARIES}) -otb_module_target_label(otbIOJPEG2000TestDriver) - -# Tests Declaration - -otb_add_test(NAME ioTuJP2ImageIOCanRead COMMAND otbIOJPEG2000TestDriver - otbJPEG2000ImageIOTestCanRead - LARGEINPUT{JPEG2000/QB_multicomp.jpx} - ) - -otb_add_test(NAME ioTuJ2KImageIOCanRead COMMAND otbIOJPEG2000TestDriver - otbJPEG2000ImageIOTestCanRead - ${INPUTDATA}/bretagne.j2k - ) - -otb_add_test(NAME ioTvJPEG2000ImageIO_CacheSize_500 COMMAND otbIOJPEG2000TestDriver - --compare-image ${EPSILON_9} - ${BASELINE}/ioClassicalQLJPEG2K_bretagne.tif - ${TEMP}/ioClassicalQLJPEG2K_bretagne_500.tif - otbGenerateClassicalQLWithJPEG2000 - ${INPUTDATA}/bretagne.j2k - ${TEMP}/ioClassicalQLJPEG2K_bretagne_500.tif - 500) - -otb_add_test(NAME ioTvJPEG2000ImageIO_CacheSize_5000 COMMAND otbIOJPEG2000TestDriver - --compare-image ${EPSILON_9} - ${BASELINE}/ioClassicalQLJPEG2K_bretagne.tif - ${TEMP}/ioClassicalQLJPEG2K_bretagne_5000.tif - otbGenerateClassicalQLWithJPEG2000 - ${INPUTDATA}/bretagne.j2k - ${TEMP}/ioClassicalQLJPEG2K_bretagne_5000.tif - 5000) - -otb_add_test(NAME ioTvJPEG2000ImageIO_CacheSize_1000 COMMAND otbIOJPEG2000TestDriver - --compare-image ${EPSILON_9} - ${BASELINE}/ioClassicalQLJPEG2K_bretagne.tif - ${TEMP}/ioClassicalQLJPEG2K_bretagne_1000.tif - otbGenerateClassicalQLWithJPEG2000 - ${INPUTDATA}/bretagne.j2k - ${TEMP}/ioClassicalQLJPEG2K_bretagne_1000.tif - 1000) - -otb_add_test(NAME ioTvJPEG2000ImageIO_CacheSize_25000 COMMAND otbIOJPEG2000TestDriver - --compare-image ${EPSILON_9} - ${BASELINE}/ioClassicalQLJPEG2K_bretagne.tif - ${TEMP}/ioClassicalQLJPEG2K_bretagne_OUT.tif - otbGenerateClassicalQLWithJPEG2000 - ${INPUTDATA}/bretagne.j2k - ${TEMP}/ioClassicalQLJPEG2K_bretagne_OUT.tif) - -if(OTB_DATA_USE_LARGEINPUT) - set( GenericTestPHR_TESTNB 0) - -foreach( current_file ${GenericTestPHR_DATA_INPUTS} ) - list(GET GenericTestPHR_DATA_TYPES ${GenericTestPHR_TESTNB} current_type ) - math(EXPR GenericTestPHR_TESTNB "${GenericTestPHR_TESTNB} + 1") - string(REGEX MATCH "TIFF" PHR_TIFF_FILE ${current_type}) - - if(NOT PHR_TIFF_FILE) - # CanRead - otb_add_test(NAME ioTuJ2KImageIOCanRead_${current_type} COMMAND otbIOJPEG2000TestDriver - otbJPEG2000ImageIOTestCanRead - ${current_file} - ) - endif() - -endforeach() - -endif() - diff --git a/Modules/IO/IOJPEG2000/test/otbGenerateClassicalQLWithJPEG2000.cxx b/Modules/IO/IOJPEG2000/test/otbGenerateClassicalQLWithJPEG2000.cxx deleted file mode 100644 index 9b7e184faaa9dee264eeab061356555116dab5f1..0000000000000000000000000000000000000000 --- a/Modules/IO/IOJPEG2000/test/otbGenerateClassicalQLWithJPEG2000.cxx +++ /dev/null @@ -1,65 +0,0 @@ -/*========================================================================= - - 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. - -=========================================================================*/ -#include "otbImageFileReader.h" -#include "otbImageFileWriter.h" -#include "otbVectorImage.h" -#include "otbStreamingShrinkImageFilter.h" -#include "otbJPEG2000ImageIO.h" - -int otbGenerateClassicalQLWithJPEG2000(int argc, char * argv[]) -{ - char * inputFilename = argv[1]; - char * outputFilename = argv[2]; - unsigned int cacheSize = 0; - - if (argc == 4) - cacheSize = atoi(argv[3]) * 1000; - - const unsigned int Dimension = 2; - - typedef unsigned int PixelType; - typedef otb::VectorImage<PixelType, Dimension> ImageType; - typedef otb::ImageFileReader<ImageType> ReaderType; - typedef otb::ImageFileWriter<ImageType> WriterType; - typedef otb::StreamingShrinkImageFilter<ImageType, ImageType> ShrinkType; - - ReaderType::Pointer reader = ReaderType::New(); - ShrinkType::Pointer shrink = ShrinkType::New(); - WriterType::Pointer writer = WriterType::New(); - - reader->SetFileName(inputFilename); - - otb::JPEG2000ImageIO::Pointer imageIO = otb::JPEG2000ImageIO::New(); - reader->SetImageIO(imageIO); - - imageIO->SetCacheSizeInByte(cacheSize); - - reader->GenerateOutputInformation(); - - writer->SetFileName(outputFilename); - shrink->SetShrinkFactor(10); - - shrink->SetInput(reader->GetOutput()); - shrink->Update(); - - writer->SetInput(shrink->GetOutput()); - - writer->Update(); - - return EXIT_SUCCESS; -} diff --git a/Modules/IO/IOJPEG2000/test/otbIOJPEG2000TestDriver.cxx b/Modules/IO/IOJPEG2000/test/otbIOJPEG2000TestDriver.cxx deleted file mode 100644 index 81520918158cf26d42435cbac4722b4830521aa2..0000000000000000000000000000000000000000 --- a/Modules/IO/IOJPEG2000/test/otbIOJPEG2000TestDriver.cxx +++ /dev/null @@ -1,7 +0,0 @@ -#include "otbTestMain.h" -void RegisterTests() -{ - REGISTER_TEST(otbJPEG2000ImageIOTestCanWrite); - REGISTER_TEST(otbJPEG2000ImageIOTestCanRead); - REGISTER_TEST(otbGenerateClassicalQLWithJPEG2000); -} diff --git a/Modules/IO/IOJPEG2000/test/otbJPEG2000ImageIOTestCanRead.cxx b/Modules/IO/IOJPEG2000/test/otbJPEG2000ImageIOTestCanRead.cxx deleted file mode 100644 index 099407b17cb2f91405e39bd23f926ee62f639db6..0000000000000000000000000000000000000000 --- a/Modules/IO/IOJPEG2000/test/otbJPEG2000ImageIOTestCanRead.cxx +++ /dev/null @@ -1,36 +0,0 @@ -/*========================================================================= - - 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. - -=========================================================================*/ - - - -#include "otbJPEG2000ImageIO.h" -#include "itkMacro.h" -#include <iostream> - -int otbJPEG2000ImageIOTestCanRead(int itkNotUsed(argc), char* argv[]) -{ - otb::JPEG2000ImageIO::Pointer lJPEG2000ImageIO = otb::JPEG2000ImageIO::New(); - bool lCanRead = lJPEG2000ImageIO->CanReadFile(argv[1]); - if (lCanRead == false) - { - std::cerr << "Erreur otb::JPEG2000ImageIO : impossible to open the image file JPEG2000 " << argv[1] << "." << - std::endl; - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} diff --git a/Modules/IO/IOJPEG2000/test/otbJPEG2000ImageIOTestCanWrite.cxx b/Modules/IO/IOJPEG2000/test/otbJPEG2000ImageIOTestCanWrite.cxx deleted file mode 100644 index 35f51e8bf18c49cb7260c8d5d3f2982d04060f18..0000000000000000000000000000000000000000 --- a/Modules/IO/IOJPEG2000/test/otbJPEG2000ImageIOTestCanWrite.cxx +++ /dev/null @@ -1,37 +0,0 @@ -/*========================================================================= - - 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. - -=========================================================================*/ - - - -#include "otbJPEG2000ImageIO.h" -#include "itkMacro.h" -#include <iostream> - -int otbJPEG2000ImageIOTestCanWrite(int itkNotUsed(argc), char* argv[]) -{ - otb::JPEG2000ImageIO::Pointer lJPEG2000ImageIO = otb::JPEG2000ImageIO::New(); - bool lCanWrite = lJPEG2000ImageIO->CanWriteFile(argv[1]); - if (lCanWrite == false) - { - std::cerr << "Erreur otb::JPEG2000ImageIO : impossible to create the image file JPEG2000 " << argv[1] << "." << - std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/Modules/IO/ImageIO/include/otbImageFileReader.txx b/Modules/IO/ImageIO/include/otbImageFileReader.txx index 141f5f7f7d5a85d69c6f63bc69a0aec90e705831..e3db0c8507f0264c97d8f8c025da71118a9bbf8a 100644 --- a/Modules/IO/ImageIO/include/otbImageFileReader.txx +++ b/Modules/IO/ImageIO/include/otbImageFileReader.txx @@ -342,9 +342,6 @@ ImageFileReader<TOutputImage, ConvertPixelTraits> itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::ResolutionFactor, m_AdditionalNumber); } - // This value is used by JPEG2000ImageIO and not by the others ImageIO - itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::CacheSizeInBytes, 135000000); - // Got to allocate space for the image. Determine the characteristics of // the image. // diff --git a/Modules/IO/ImageIO/otb-module.cmake b/Modules/IO/ImageIO/otb-module.cmake index 8c0a036c839d715637db860d85708445e2313361..70df4300da2b6c482f97cf72b29f1d4a44686cca 100644 --- a/Modules/IO/ImageIO/otb-module.cmake +++ b/Modules/IO/ImageIO/otb-module.cmake @@ -20,9 +20,6 @@ otb_module(OTBImageIO OTBObjectList OTBStreaming - OPTIONAL_DEPENDS - OTBIOJPEG2000 - TEST_DEPENDS OTBStatistics OTBTestKernel diff --git a/Modules/IO/ImageIO/src/CMakeLists.txt b/Modules/IO/ImageIO/src/CMakeLists.txt index 96b6e61df93e09ba4a66024b646c2f3169573dd0..6c3889d4e4933d72f66878896cfa36388dcb8c68 100644 --- a/Modules/IO/ImageIO/src/CMakeLists.txt +++ b/Modules/IO/ImageIO/src/CMakeLists.txt @@ -6,7 +6,6 @@ add_library(OTBImageIO ${OTBImageIO_SRC}) target_link_libraries(OTBImageIO ${OTBIORAD_LIBRARIES} ${OTBIOONERA_LIBRARIES} - ${OTBIOJPEG2000_LIBRARIES} ${OTBIOLUM_LIBRARIES} ${OTBImageBase_LIBRARIES} ${OTBIOMW_LIBRARIES} diff --git a/Modules/IO/ImageIO/src/otbImageIOFactory.cxx b/Modules/IO/ImageIO/src/otbImageIOFactory.cxx index ab5701227068dae285da26bd6fab53277028548b..721e47228a43fe1960fbc8bec21822b9709242c3 100644 --- a/Modules/IO/ImageIO/src/otbImageIOFactory.cxx +++ b/Modules/IO/ImageIO/src/otbImageIOFactory.cxx @@ -31,10 +31,6 @@ #include "otbRADImageIOFactory.h" #include "otbMWImageIOFactory.h" -#ifdef OTB_USE_OPENJPEG -#include "otbJPEG2000ImageIOFactory.h" -#endif - #include "otbTileMapImageIOFactory.h" namespace otb @@ -100,9 +96,6 @@ ImageIOFactory::RegisterBuiltInFactories() itk::ObjectFactoryBase::RegisterFactory(RADImageIOFactory::New()); itk::ObjectFactoryBase::RegisterFactory(BSQImageIOFactory::New()); itk::ObjectFactoryBase::RegisterFactory(LUMImageIOFactory::New()); -#ifdef OTB_USE_OPENJPEG - itk::ObjectFactoryBase::RegisterFactory(JPEG2000ImageIOFactory::New()); -#endif itk::ObjectFactoryBase::RegisterFactory(TileMapImageIOFactory::New()); itk::ObjectFactoryBase::RegisterFactory(GDALImageIOFactory::New()); itk::ObjectFactoryBase::RegisterFactory(MWImageIOFactory::New()); diff --git a/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.h b/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.h index a654b79d75b633632c07d569ff3e8cf75cc0a3ff..c602f1276a7b1131ee07d70af5f192c35bee8073 100644 --- a/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.h +++ b/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.h @@ -148,8 +148,12 @@ private: /** Internal samplers*/ std::vector<SamplerMapType> m_Samplers; - /** Field name to store the FID of the geometry each sample comes from */ + /** Field name to store the FID of the geometry each sample comes from. + * When this name is empty, no FID is stored. */ std::string m_OriginFieldName; + + /** Flag to enable/disable origin FID in outputs */ + bool m_UseOriginField; }; /** diff --git a/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.txx b/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.txx index d2e6847e1f64bf95a19d6ba9c12d1023632c4fa2..d881897996d7f79e4dce1fddd4b2add79c04db6d 100644 --- a/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.txx +++ b/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.txx @@ -31,6 +31,7 @@ PersistentOGRDataToSamplePositionFilter<TInputImage,TMaskImage,TSampler> { this->SetNumberOfRequiredOutputs(2); m_OriginFieldName = std::string("originfid"); + m_UseOriginField = true; } template<class TInputImage, class TMaskImage, class TSampler> @@ -51,7 +52,11 @@ PersistentOGRDataToSamplePositionFilter<TInputImage,TMaskImage,TSampler> // Add an extra field for the original FID this->ClearAdditionalFields(); - this->CreateAdditionalField(this->GetOriginFieldName(),OFTInteger,12); + m_UseOriginField = (this->GetOriginFieldName().size() > 0); + if (m_UseOriginField) + { + this->CreateAdditionalField(this->GetOriginFieldName(),OFTInteger,12); + } // compute label mapping this->ComputeClassPartition(); @@ -179,7 +184,10 @@ PersistentOGRDataToSamplePositionFilter<TInputImage,TMaskImage,TSampler> ogr::Layer outputLayer = this->GetInMemoryOutput(threadid,i); ogr::Feature feat(outputLayer.GetLayerDefn()); feat.SetFrom(feature); - feat[this->GetOriginFieldName()].SetValue(static_cast<int>(feature.GetFID())); + if (m_UseOriginField) + { + feat[this->GetOriginFieldName()].SetValue(static_cast<int>(feature.GetFID())); + } feat.SetGeometry(&ogrTmpPoint); outputLayer.CreateFeature(feat); break; diff --git a/Modules/Learning/Sampling/src/otbSamplingRateCalculator.cxx b/Modules/Learning/Sampling/src/otbSamplingRateCalculator.cxx index f61ba32dc9bf642b34bfc2842e9da51938416d01..934e2d480ae6437846280be21c23aa476054a9b7 100644 --- a/Modules/Learning/Sampling/src/otbSamplingRateCalculator.cxx +++ b/Modules/Learning/Sampling/src/otbSamplingRateCalculator.cxx @@ -50,15 +50,23 @@ SamplingRateCalculator MapRateType::iterator it = m_RatesByClass.begin(); for (; it != m_RatesByClass.end() ; ++it) { - if (smallestNbofSamples > it->second.Tot) + if (it->second.Tot) { - smallestNbofSamples = it->second.Tot; + if (smallestNbofSamples > it->second.Tot) + { + smallestNbofSamples = it->second.Tot; + } + } + else + { + otbWarningMacro("Ignoring empty class " << it->first); } } - // Check if there is an empty class - if (smallestNbofSamples == 0UL) + // Check if there is at least one non-empty class + if (smallestNbofSamples == itk::NumericTraits<unsigned long>::max()) { - otbWarningMacro("There is an empty class, sample size is set to zero!"); + otbWarningMacro("There are only empty classes, sample size is set to zero!"); + smallestNbofSamples = 0UL; } this->SetNbOfSamplesAllClasses( smallestNbofSamples ); } @@ -70,7 +78,15 @@ SamplingRateCalculator MapRateType::iterator it = m_RatesByClass.begin(); for (; it != m_RatesByClass.end() ; ++it) { - it->second.Required = dRequiredNbSamples; + if (it->second.Tot) + { + it->second.Required = dRequiredNbSamples; + } + else + { + // ignore empty classes + it->second.Required = 0UL; + } this->UpdateRate(it->first); } } @@ -137,7 +153,7 @@ void SamplingRateCalculator // Then compute number of samples for each class for (it = m_RatesByClass.begin(); it != m_RatesByClass.end() ; ++it) { - double ratio = it->second.Tot / static_cast<double>(totalNumberOfSamplesAvailable); + double ratio = totalNumberOfSamplesAvailable != 0 ? it->second.Tot / static_cast<double>(totalNumberOfSamplesAvailable): 0; it->second.Required = static_cast<unsigned long>(0.5+ratio*value); this->UpdateRate(it->first); diff --git a/Modules/Learning/Sampling/src/otbSamplingRateCalculatorList.cxx b/Modules/Learning/Sampling/src/otbSamplingRateCalculatorList.cxx index 1ffe03a54cd51a35745ff5ec27b980146a4fb54c..56eca2cfaf0bc16f5449180f67ba31080aa16a99 100644 --- a/Modules/Learning/Sampling/src/otbSamplingRateCalculatorList.cxx +++ b/Modules/Learning/Sampling/src/otbSamplingRateCalculatorList.cxx @@ -372,19 +372,33 @@ SamplingRateCalculatorList total_nb_samples+=nb_samples[i]; } - - for (unsigned int i=0 ; i<this->Size() ; i++) - { + + const Superclass::InternalContainerSizeType sampleListSize = this->Size(); + for (unsigned int i=0 ; i<sampleListSize ; i++) + { + if (total_nb_samples != 0) + { this->GetNthElement(i)->SetTotalNumberOfSamples(vcl_floor(0.5+tot[0]*nb_samples[i]/static_cast<double>(total_nb_samples))); + } + else + { + this->GetNthElement(i)->SetTotalNumberOfSamples(0); + } } break; } case EQUAL: { + const Superclass::InternalContainerSizeType sampleListSize = this->Size(); - unsigned long total_by_image = static_cast<unsigned long>(vcl_floor(tot[0]/static_cast<double>(this->Size()))); - - for (unsigned int i=0 ; i<this->Size() ; i++) + unsigned long total_by_image = 0; + + if (sampleListSize != 0) + { + total_by_image = static_cast<unsigned long>(vcl_floor(tot[0]/static_cast<double>(sampleListSize))); + } + + for (unsigned int i=0 ; i<sampleListSize ; i++) { this->GetNthElement(i)->SetTotalNumberOfSamples(total_by_image); } diff --git a/Modules/Learning/Supervised/include/otbImageClassificationFilter.txx b/Modules/Learning/Supervised/include/otbImageClassificationFilter.txx index 899a5a25066ddb9d0d77a8dd5d687f1bcfc5caa8..54656b1948811c9685eaa01d729bc706ab15e98b 100644 --- a/Modules/Learning/Supervised/include/otbImageClassificationFilter.txx +++ b/Modules/Learning/Supervised/include/otbImageClassificationFilter.txx @@ -260,8 +260,7 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> typename TargetListSampleType::ConstIterator labIt = labels->Begin(); maskIt.GoToBegin(); - for (outIt.GoToBegin(); labIt!=labels->End() && !outIt.IsAtEnd(); - ++outIt) + for (outIt.GoToBegin(); !outIt.IsAtEnd(); ++outIt) { double confidenceIndex = 0.0; TargetValueType labelValue(m_DefaultLabel); @@ -270,7 +269,7 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> validPoint = maskIt.Get() > 0; ++maskIt; } - if (validPoint) + if (validPoint && labIt!=labels->End()) { labelValue = labIt.GetMeasurementVector()[0]; @@ -281,6 +280,10 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> ++labIt; } + else + { + labelValue = m_DefaultLabel; + } outIt.Set(labelValue); diff --git a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h index 458342b8c09fd1fbd4d76081bc04fbaa957da8f2..b362373e8eb7cad3aca821cbc219444f79b0b1d2 100644 --- a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h @@ -29,6 +29,9 @@ #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Woverloaded-virtual" #pragma GCC diagnostic ignored "-Wignored-qualifiers" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wcast-align" +#pragma GCC diagnostic ignored "-Wunknown-pragmas" #endif #include "shark/Algorithms/Trainers/RFTrainer.h" #if defined(__GNUC__) || defined(__clang__) diff --git a/Modules/Learning/Supervised/include/otbSharkUtils.h b/Modules/Learning/Supervised/include/otbSharkUtils.h index 6990bf72ce7d5ca80e1f4ce770428d8cb5227fd4..08165a114fdf73b67e463ec9e658aefe138932ce 100644 --- a/Modules/Learning/Supervised/include/otbSharkUtils.h +++ b/Modules/Learning/Supervised/include/otbSharkUtils.h @@ -19,6 +19,7 @@ #define otbSharkUtils_h #include "otb_shark.h" +#include "itkMacro.h" #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push diff --git a/Modules/MPI/MPIConfig/src/otbMPIConfig.cxx b/Modules/MPI/MPIConfig/src/otbMPIConfig.cxx index 49ffb07ffc0df21083f07115224fb862ab4aad06..c582dc322fd9a5e5866e67562b568f8d94e9b538 100644 --- a/Modules/MPI/MPIConfig/src/otbMPIConfig.cxx +++ b/Modules/MPI/MPIConfig/src/otbMPIConfig.cxx @@ -27,6 +27,7 @@ #if defined(__GNUC__) || defined(__clang__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-parameter" +# pragma GCC diagnostic ignored "-Wcast-align" #include <mpi.h> # pragma GCC diagnostic pop #else diff --git a/Modules/MPI/MPITiffWriter/include/otbSimpleParallelTiffWriter.h b/Modules/MPI/MPITiffWriter/include/otbSimpleParallelTiffWriter.h index 2f6c6f4fc462393bd445b02328240b436920e835..7a32268ef933d97a52d186a897bc4de99cfdf1d4 100644 --- a/Modules/MPI/MPITiffWriter/include/otbSimpleParallelTiffWriter.h +++ b/Modules/MPI/MPITiffWriter/include/otbSimpleParallelTiffWriter.h @@ -60,6 +60,7 @@ #if defined(__GNUC__) || defined(__clang__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-parameter" +# pragma GCC diagnostic ignored "-Wcast-align" #include "sptw.h" # pragma GCC diagnostic pop #else diff --git a/Modules/Remote/Mosaic.remote.cmake b/Modules/Remote/Mosaic.remote.cmake index 1989f99e313c74ee177e5b50b8faa3220d9baeb4..adfa72d32c7efb2f6171a63b2110352a0f141774 100644 --- a/Modules/Remote/Mosaic.remote.cmake +++ b/Modules/Remote/Mosaic.remote.cmake @@ -5,5 +5,5 @@ A more detailed description can be found on the project website: https://github.com/remicres/otb-mosaic " GIT_REPOSITORY https://github.com/remicres/otb-mosaic.git - GIT_TAG 9a8cdd63ed3bba500bb4ea3867abc38bce8be562 + GIT_TAG 516dfa7e7b91aa0263e495ee6b3878a03ced9173 ) diff --git a/Modules/Remote/otb-bv.remote.cmake b/Modules/Remote/otb-bv.remote.cmake index f699009f62157dc925cb290851f91d83bddc38f9..e760e4b739df0fdfb2ffba94d731f91aa8516b3d 100644 --- a/Modules/Remote/otb-bv.remote.cmake +++ b/Modules/Remote/otb-bv.remote.cmake @@ -5,5 +5,5 @@ A more detailed description can be found on the project website: http://tully.ups-tlse.fr/jordi/otb-bv " GIT_REPOSITORY http://tully.ups-tlse.fr/jordi/otb-bv.git - GIT_TAG master + GIT_TAG d13a3b3febe61c3c67777eac8261e07a6257a519 ) diff --git a/Modules/Remote/otbFFSforGMM.remote.cmake b/Modules/Remote/otbFFSforGMM.remote.cmake index 74c3752db8fd365fc23b06b388e9da57a7672aaf..f1806e1602e7a5b50cffc6205a7a7e406df5f090 100644 --- a/Modules/Remote/otbFFSforGMM.remote.cmake +++ b/Modules/Remote/otbFFSforGMM.remote.cmake @@ -1,9 +1,9 @@ #Contact: Adrien Lagrange <adrien.lagrange@irit.fr> -otb_fetch_module(OTBFastFeaturesSelection +otb_fetch_module(OTBFFSforGMM "This module implements a method to perform a fast forward feature selection using a Gaussian Mixture Model. A more detailed description can be found on the project website: https://github.com/Laadr/otbFFSforGMM " GIT_REPOSITORY https://github.com/Laadr/otbFFSforGMM.git - GIT_TAG master + GIT_TAG 78743f7d57de4acf913bf300cfbb93323a5c8ad3 ) diff --git a/Modules/Remote/phenotb.remote.cmake b/Modules/Remote/phenotb.remote.cmake index 3640ef3cfa99b6039f8f1010ab5ecb4daa8ffaa7..209b9682cfb29d206d17b2b35b245a2efade4964 100644 --- a/Modules/Remote/phenotb.remote.cmake +++ b/Modules/Remote/phenotb.remote.cmake @@ -7,5 +7,5 @@ A more detailed description can be found on the project website: http://tully.ups-tlse.fr/jordi/phenotb " GIT_REPOSITORY http://tully.ups-tlse.fr/jordi/phenotb.git - GIT_TAG master + GIT_TAG 17d69b1bc1f23041dafe265e320b46ffb20229b6 ) diff --git a/Modules/Remote/temporal-gapfilling.remote.cmake b/Modules/Remote/temporal-gapfilling.remote.cmake index b135cb29a30b790987240fd46d4b621878e23cd9..681ae6e773cbd3720115b9a90a31461cf1195b79 100644 --- a/Modules/Remote/temporal-gapfilling.remote.cmake +++ b/Modules/Remote/temporal-gapfilling.remote.cmake @@ -6,5 +6,5 @@ A more detailed description can be found on the project website: http://tully.ups-tlse.fr/jordi/temporalgapfilling " GIT_REPOSITORY http://tully.ups-tlse.fr/jordi/temporalgapfilling.git - GIT_TAG master + GIT_TAG 14c56cb73250861d8694effeba934cebde09424c ) diff --git a/Modules/ThirdParty/GDAL/otb-module-init.cmake b/Modules/ThirdParty/GDAL/otb-module-init.cmake index 1ed1ca6f83d5ce8cd576fb65ce803331229d8f3d..be7cfb790f2142caec54ebbf94af3bc3490fe11f 100644 --- a/Modules/ThirdParty/GDAL/otb-module-init.cmake +++ b/Modules/ThirdParty/GDAL/otb-module-init.cmake @@ -8,7 +8,7 @@ if(NOT GDAL_FOUND) endif() #Check if GDAL is compatible with OTB using a bunch of cmake try_run and try_compile. (Default value is ON.) -set(GDAL_CONFIG_CHECKING ON CACHE BOOL "Tests to check gdal config." FORCE) +set(GDAL_CONFIG_CHECKING ON CACHE BOOL "Tests to check gdal config.") mark_as_advanced(GDAL_CONFIG_CHECKING) if(NOT GDAL_CONFIG_CHECKING) @@ -23,6 +23,13 @@ if(NOT EXISTS ${TEMP}) FILE(MAKE_DIRECTORY ${TEMP}) endif() +set(GDAL_CONFIG_CHECKING OFF CACHE BOOL "Tests to check gdal config." FORCE) + +macro(error_message m) + message("Setting GDAL_CONFIG_CHECKING to ON. (all GDAL tests will run again)") + set(GDAL_CONFIG_CHECKING ON CACHE BOOL "Tests to check gdal config." FORCE) + message(FATAL_ERROR "${m}") +endmacro(error_message) #------------------- Helper Macro --------------------- macro(gdal_try_run msg_type var source_file) @@ -37,7 +44,7 @@ ARGS ${ARGN} ) if(NOT COMPILE_${var}) - message(FATAL_ERROR "Compiling Test ${var} - Failed \n + error_message("Compiling Test ${var} - Failed \n COMPILE_OUTPUT_${var}: '${COMPILE_OUTPUT_${var}}'") endif() if(RUN_${var}) @@ -47,7 +54,7 @@ if(RUN_${var}) if("${msg_type}" STREQUAL "STATUS") message(${msg_type} "Performing Test ${var} - Failed") else() - message(${msg_type} "Performing Test ${var} - Failed \n + error_message("Performing Test ${var} - Failed \n Exit status: '${RUN_${var}}' \n RUN_OUTPUT_${var}: '${RUN_OUTPUT_${var}}'") endif() @@ -75,7 +82,7 @@ if(EXISTS "${TEMP}/gdalVersion.txt") endif() set(GDAL_VERSION_STRING "${_GDAL_VERSION_STRING}" CACHE INTERNAL "" FORCE) else() - message(FATAL_ERROR "${TEMP}/gdalVersion.txt does not exist. Cannot continue.") + error_message( "${TEMP}/gdalVersion.txt does not exist. Cannot continue.") endif() #check OGR @@ -86,7 +93,7 @@ CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:PATH=${GDAL_INCLUDE_DIR}" "-w" "-DLINK_LIBRAR OUTPUT_VARIABLE COMPILE_OUTPUT_GDAL_HAS_OGR ) if(NOT COMPILE_GDAL_HAS_OGR) - message(FATAL_ERROR "Performing Test COMPILE_GDAL_HAS_OGR - Failed\n COMPILE_OUTPUT:${COMPILE_OUTPUT_GDAL_HAS_OGR}\n") + error_message("Performing Test COMPILE_GDAL_HAS_OGR - Failed\n COMPILE_OUTPUT:${COMPILE_OUTPUT_GDAL_HAS_OGR}\n") else() message(STATUS "Performing Test COMPILE_GDAL_HAS_OGR - Success") endif() @@ -143,8 +150,13 @@ gdal_try_run(STATUS GDAL_HAS_HDF4 gdalFormatsTest.c HDF4) #------------------- TESTS (END)--------------------- +set(RUN_GDAL_SYMBOLS_TEST TRUE) +if("${CMAKE_SYSTEM_NAME}" MATCHES "OpenBSD") + set(RUN_GDAL_SYMBOLS_TEST FALSE) +endif() + #FOR UNIX SYSTEMS ONLY -if(UNIX) +if(RUN_GDAL_SYMBOLS_TEST) # Prepare bash script configure_file(${CMAKE_SOURCE_DIR}/Modules/ThirdParty/GDAL/gdalTest.sh.in ${CMAKE_CURRENT_BINARY_DIR}/gdalTest.sh @ONLY) execute_process(COMMAND chmod u+x ${CMAKE_CURRENT_BINARY_DIR}/gdalTest.sh) @@ -159,4 +171,4 @@ elseif("${JPEG2000_DRIVER_USED}" STREQUAL "JPEG2000") unset(JPEG2000_DRIVER_USED) else() message(STATUS "GDAL driver used for JPEG2000 dataset is '${JPEG2000_DRIVER_USED}'") -endif() \ No newline at end of file +endif() diff --git a/Modules/ThirdParty/MuParserX/CMakeLists.txt b/Modules/ThirdParty/MuParserX/CMakeLists.txt index 7aa22a8c87a76e9ccf440a7fbf260f1fb17cba2f..1d7891da04fe06837ee5244e74c049c08acbce31 100644 --- a/Modules/ThirdParty/MuParserX/CMakeLists.txt +++ b/Modules/ThirdParty/MuParserX/CMakeLists.txt @@ -2,13 +2,5 @@ project(OTBMuParserX) set(OTBMuParserX_SYSTEM_INCLUDE_DIRS ${MUPARSERX_INCLUDE_DIRS}) set(OTBMuParserX_LIBRARIES "${MUPARSERX_LIBRARIES}") -set(OTBMuParserX_INCLUDE_DIRS ${OTBMuParserX_BINARY_DIR}/src) - -configure_file( src/mpCompat.h.in src/mpCompat.h ) otb_module_impl() - -install(FILES ${OTBMuParserX_BINARY_DIR}/src/mpCompat.h - DESTINATION ${OTBMuParserX_INSTALL_INCLUDE_DIR} - COMPONENT Development - ) diff --git a/Modules/ThirdParty/MuParserX/otb-module.cmake b/Modules/ThirdParty/MuParserX/otb-module.cmake index b44f57f995243ee642873079101e53a59f06bddb..46b52ad5c2c685e82927b9f21ce7076acfc7dcb1 100644 --- a/Modules/ThirdParty/MuParserX/otb-module.cmake +++ b/Modules/ThirdParty/MuParserX/otb-module.cmake @@ -10,3 +10,5 @@ otb_module(OTBMuParserX ) otb_module_activation_option("Enable MuParserX dependent modules" OFF) + +otb_module_requires_cxx11() diff --git a/Modules/ThirdParty/MuParserX/src/mpCompat.h.in b/Modules/ThirdParty/MuParserX/src/mpCompat.h.in deleted file mode 100644 index 7ac031c6b821a0719bb681b53a384d42a56daaeb..0000000000000000000000000000000000000000 --- a/Modules/ThirdParty/MuParserX/src/mpCompat.h.in +++ /dev/null @@ -1,46 +0,0 @@ -/*========================================================================= - - 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 MUP_COMPAT_H -#define MUP_COMPAT_H - -/* defined if OTB_CXX_HAS_UNIQUE_PTR cmake check is OK. */ -/* See CMake/OTBCheckCpp11Keywords.cmake for more details */ -#cmakedefine OTB_CXX_HAS_UNIQUE_PTR - -#ifndef OTB_CXX_HAS_UNIQUE_PTR -#define unique_ptr auto_ptr -#endif - -/* defined if OTB_CXX_HAS_OVERRIDE_SPECIFIER cmake check is OK. */ -/* See CMake/OTBCheckCpp11Keywords.cmake for more details */ -#cmakedefine OTB_CXX_HAS_OVERRIDE_SPECIFIER - -#ifndef OTB_CXX_HAS_OVERRIDE_SPECIFIER -#define override -#endif - -/* defined if OTB_CXX_HAS_NULLPTR cmake check is OK. */ -/* See CMake/OTBCheckCpp11Keywords.cmake for more details */ -#cmakedefine OTB_CXX_HAS_NULLPTR - -#ifndef OTB_CXX_HAS_NULLPTR -#define nullptr NULL -#endif - - -#endif //MUP_COMPAT_H diff --git a/Modules/ThirdParty/OpenGL/CMakeLists.txt b/Modules/ThirdParty/OpenGL/CMakeLists.txt index 229a923888aabf9f36c6ee8a7db0688c36e973c7..2f1a2c799ffb50f502cc7b5dc346ea2cc1cf33a4 100644 --- a/Modules/ThirdParty/OpenGL/CMakeLists.txt +++ b/Modules/ThirdParty/OpenGL/CMakeLists.txt @@ -2,6 +2,6 @@ project(OTBOpenGL) set(OTBOpenGL_THIRD_PARTY 1) set(OTBOpenGL_SYSTEM_INCLUDE_DIRS ${OPENGL_INCLUDE_DIR}) -set(OTBOpenGL_LIBRARIES ${OPENGL_LIBRARY}) +set(OTBOpenGL_LIBRARIES ${OPENGL_LIBRARIES}) otb_module_impl() diff --git a/Modules/ThirdParty/OpenGL/otb-module-init.cmake b/Modules/ThirdParty/OpenGL/otb-module-init.cmake index b3819dad16edeffe7e74c1ee3f54348af7715ac9..32cb2d0e985ec2d3bdc569b0c3d8e6012fb93112 100644 --- a/Modules/ThirdParty/OpenGL/otb-module-init.cmake +++ b/Modules/ThirdParty/OpenGL/otb-module-init.cmake @@ -1,7 +1,18 @@ #detection of OpenGL is apply is bit tricy as we deactivate #framework on OSX globally. see mantis #1193 if(APPLE) - set(OPENGL_FOUND FALSE) + set( OPENGL_FOUND FALSE ) + set( OPENGL_GLU_FOUND FALSE) + + set( OPENGL_INCLUDE_DIR) + set( OPENGL_LIBRARIES) + + find_path( + OPENGL_INCLUDE_DIR OpenGL/gl.h + PATHS "/System/Library/Frameworks/" + DOC "Include for OpenGL on OSX" + ) + find_library( OPENGL_gl_LIBRARY OpenGL PATHS "/System/Library/Frameworks/" @@ -14,44 +25,39 @@ if(APPLE) DOC "AGL lib for OSX" ) - find_path( - OPENGL_INCLUDE_DIR OpenGL/gl.h - PATHS "/System/Library/Frameworks/" - DOC "Include for OpenGL on OSX" - ) - - if(OPENGL_gl_LIBRARY) - set( OPENGL_LIBRARIES ${OPENGL_gl_LIBRARY} ${OPENGL_LIBRARIES}) - if(OPENGL_glu_LIBRARY) - set( OPENGL_GLU_FOUND "YES" ) - set( OPENGL_LIBRARIES ${OPENGL_glu_LIBRARY} ${OPENGL_LIBRARIES} ) - else() - set( OPENGL_GLU_FOUND "NO" ) - endif() - # This deprecated setting is for backward compatibility with CMake1.4 - set (OPENGL_LIBRARY ${OPENGL_LIBRARIES}) + if( OPENGL_gl_LIBRARY ) + set( OPENGL_LIBRARIES ${OPENGL_gl_LIBRARY}) + set( OPENGL_FOUND TRUE ) + endif() + if( OPENGL_glu_LIBRARY ) + set( OPENGL_GLU_FOUND TRUE) + set( OPENGL_LIBRARIES ${OPENGL_LIBRARIES} ${OPENGL_glu_LIBRARY} ) endif() - # This deprecated setting is for backward compatibility with CMake1.4 - set(OPENGL_INCLUDE_PATH ${OPENGL_INCLUDE_DIR}) mark_as_advanced( OPENGL_INCLUDE_DIR - OPENGL_LIBRARY + OPENGL_LIBRARIES OPENGL_glu_LIBRARY OPENGL_gl_LIBRARY ) - if(NOT OPENGL_LIBRARY OR NOT OPENGL_INCLUDE_DIR) - message(FATAL_ERROR "Cannot find OpenGL. Set OPENGL_INCLUDE_DIR and OPENGL_LIBRARY") - else() - message(STATUS "Found OpenGL framework: ${OPENGL_INCLUDE_DIR}") - endif() - - set(OPENGL_FOUND TRUE) else(APPLE) find_package(OpenGL REQUIRED) mark_as_advanced(OPENGL_INCLUDE_DIR) - mark_as_advanced(OPENGL_LIBRARY) - if(NOT OPENGL_FOUND) - message(FATAL_ERROR "Cannot find OpenGL. Set OPENGL_INCLUDE_DIR and OPENGL_LIBRARY") - endif() + mark_as_advanced(OPENGL_LIBRARIES) endif(APPLE) + + +if(NOT OPENGL_INCLUDE_DIR) + if(NOT WIN32) + message(FATAL_ERROR "Could not find OpenGL (missing: OPENGL_INCLUDE_DIR") + endif() +endif() + +if(NOT OPENGL_gl_LIBRARY) + message(FATAL_ERROR "Could not find OpenGL (missing: OPENGL_gl_LIBRARY") +endif() + +if(NOT OPENGL_glu_LIBRARY) + message(FATAL_ERROR "Could not find OpenGL (missing: OPENGL_glu_LIBRARY") +endif() + diff --git a/Modules/ThirdParty/OpenJPEG/CMakeLists.txt b/Modules/ThirdParty/OpenJPEG/CMakeLists.txt deleted file mode 100644 index 7dd8fd84e2948bbfd37cd99ef559002b07add130..0000000000000000000000000000000000000000 --- a/Modules/ThirdParty/OpenJPEG/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -project(OTBOpenJPEG) - - set(OTBOpenJPEG_SYSTEM_INCLUDE_DIRS ${OPENJPEG_INCLUDE_DIRS}) - set(OTBOpenJPEG_LIBRARIES "${OPENJPEG_LIBRARIES}") - set(OTBOpenJPEG_INCLUDE_DIRS ${OTBOpenJPEG_BINARY_DIR}/src) - set(OTBOpenJPEG_EXPORT_CODE_BUILD " -if(NOT OpenJPEG_FOUND) -find_package(OpenJPEG REQUIRED HINTS ${OpenJPEG_DIR}) -endif()") - set(OTBOpenJPEG_EXPORT_CODE_INSTALL ${OTBOpenJPEG_EXPORT_CODE_BUILD}) - - if(OpenJPEG_FOUND) - math(EXPR OTBOpenJPEG_VERSION_NUMBER - "((${OPENJPEG_MAJOR_VERSION})*100+${OPENJPEG_MINOR_VERSION})*100+${OPENJPEG_BUILD_VERSION}") - configure_file( src/otb_openjpeg.h.in src/otb_openjpeg.h ) - endif() - - message(STATUS "Found OpenJPEG : ${OPENJPEG_LIBRARIES} (version ${OPENJPEG_MAJOR_VERSION}.${OPENJPEG_MINOR_VERSION}.${OPENJPEG_BUILD_VERSION})") - message(STATUS "Caution : there could be a version conflict if ITK also contains an OpenJPEG version. " - "Depending on ITK version and enabled modules, the OpenJPEG headers can be " - "present in ITK include folder. Since the include order between modules is " - "deterministic, the OpenJPEG header from ITK may be included first. To avoid " - "version conflicts, try to use an ITK installed without GDCM nor ITKReview. " - "An alternative fix is to simply hide the header openjpeg.h in the ITK " - "include directory.") - - otb_module_impl() - -install(FILES ${OTBOpenJPEG_BINARY_DIR}/src/otb_openjpeg.h - DESTINATION ${OTBOpenJPEG_INSTALL_INCLUDE_DIR} - COMPONENT Development - ) diff --git a/Modules/ThirdParty/OpenJPEG/otb-module-init.cmake b/Modules/ThirdParty/OpenJPEG/otb-module-init.cmake deleted file mode 100644 index 07abcc5682c0f1e61adc908e90f3e59a9f3a001b..0000000000000000000000000000000000000000 --- a/Modules/ThirdParty/OpenJPEG/otb-module-init.cmake +++ /dev/null @@ -1,2 +0,0 @@ -find_package( OpenJPEG REQUIRED ) -mark_as_advanced( OpenJPEG_DIR ) diff --git a/Modules/ThirdParty/OpenJPEG/otb-module.cmake b/Modules/ThirdParty/OpenJPEG/otb-module.cmake deleted file mode 100644 index 7310e35f8cb930f3339658aeb51b4b3f9de99518..0000000000000000000000000000000000000000 --- a/Modules/ThirdParty/OpenJPEG/otb-module.cmake +++ /dev/null @@ -1,12 +0,0 @@ -set(DOCUMENTATION "This module imports OpenJPEG to the build system") - -otb_module(OTBOpenJPEG - DEPENDS - - TEST_DEPENDS - - DESCRIPTION - "${DOCUMENTATION}" -) - -otb_module_activation_option("Enable OpenJpeg dependent modules. Note that this may not be needed if your GDal has a JPEG2000 compatible driver (other than jasper)" OFF) diff --git a/Modules/ThirdParty/OpenJPEG/src/otb_openjpeg.h.in b/Modules/ThirdParty/OpenJPEG/src/otb_openjpeg.h.in deleted file mode 100644 index c99cf9af14652e0392fa7d2cb71e5488fcfd014a..0000000000000000000000000000000000000000 --- a/Modules/ThirdParty/OpenJPEG/src/otb_openjpeg.h.in +++ /dev/null @@ -1,29 +0,0 @@ -/*========================================================================= - - 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 otb_openjpeg_h -#define otb_openjpeg_h - -/* different API between 2.0 and 2.1 */ -#define OTBOpenJPEG_VERSION_NUMBER @OTBOpenJPEG_VERSION_NUMBER@ - -extern "C" -{ -#include "openjpeg.h" -} - -#endif diff --git a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSentinel1Model.cpp b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSentinel1Model.cpp index acfecf8f58ad57fb8222fea2d274b101b1e874ee..7925680ccbf553e00c90d2d14fee2abeff612555 100644 --- a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSentinel1Model.cpp +++ b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSentinel1Model.cpp @@ -235,20 +235,6 @@ namespace ossimplugins return false; } } - else - { - /* Keep this notify as WARN. code should not reach here. - If manifest.safe is not found then we are not loading a valid S1 dataset. - If the input is tiff or annotation xml, then also there must exists a - manifest.safe. However, we are forced to read only annotaion xml and - make ossimSentinel1Model out of it for the sake of - "ossimSentinel1ModelTest". This is not a very good idea to allow - reading a fake dataset. So user must be warned! - */ - ossimNotify(ossimNotifyLevel_WARN) - << MODULE - << " manifest.safe not found. but checking if xml file is valid" << "\n"; - } // -----[ Read product file ossimFilename xmlFileName = file; @@ -259,6 +245,12 @@ namespace ossimplugins const ossimFilename fileNameWihtoutExtension = file.fileNoExtension(); const ossimFilename path = file.path().path(); xmlFileName = ossimFilename(path+"/annotation/"+fileNameWihtoutExtension+".xml"); + + if (!xmlFileName.exists() && safeFile.empty()) + { + // this is just a plain tiff file without safe nor xml + return false; + } } if ( !xmlFileName.exists() || !this->readProduct(xmlFileName) ) @@ -279,6 +271,23 @@ namespace ossimplugins << " !xmlFileName.exists() || !this->readProduct(xmlFileName) fails \n"; return false; } + else + { + if ( safeFile.empty() ) + { + /* Keep this notify as WARN. code should not reach here. + If manifest.safe is not found then we are not loading a valid S1 dataset. + If the input is tiff or annotation xml, then also there must exists a + manifest.safe. However, we are forced to read only annotaion xml and + make ossimSentinel1Model out of it for the sake of + "ossimSentinel1ModelTest". This is not a very good idea to allow + reading a fake dataset. So user must be warned! + */ + ossimNotify(ossimNotifyLevel_WARN) + << MODULE + << " manifest.safe not found, but xml file is valid" << "\n"; + } + } if ( !this->initImageSize( theImageSize ) ) { diff --git a/Modules/ThirdParty/OssimPlugins/test/CMakeLists.txt b/Modules/ThirdParty/OssimPlugins/test/CMakeLists.txt index f56748017eee2013f22f64970274d01f668be413..a1e1cf79974dad455c07c9c0da70a68479174035 100644 --- a/Modules/ThirdParty/OssimPlugins/test/CMakeLists.txt +++ b/Modules/ThirdParty/OssimPlugins/test/CMakeLists.txt @@ -7,21 +7,21 @@ otb_module_test() if (Boost_UNIT_TEST_FRAMEWORK_FOUND) #this test is failing on osx due to a bug in AppleClang stdc++ (Luc Hermitte) if(NOT APPLE) - add_executable(ossimStringUtilitiesTest ossimStringUtilitiesTest.cpp) - target_link_libraries(ossimStringUtilitiesTest + add_executable(OTBossimStringUtilitiesTest ossimStringUtilitiesTest.cpp) + target_link_libraries(OTBossimStringUtilitiesTest otbossimplugins ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) - otb_module_target_label(ossimStringUtilitiesTest) - otb_add_test(NAME ossimStringUtilitiesTest COMMAND ossimStringUtilitiesTest ) + otb_module_target_label(OTBossimStringUtilitiesTest) + otb_add_test(NAME TuossimStringUtilitiesTest COMMAND OTBossimStringUtilitiesTest ) endif() - add_executable(ossimTimeUtilitiesTest ossimTimeUtilitiesTest.cpp) - target_link_libraries(ossimTimeUtilitiesTest + add_executable(OTBossimTimeUtilitiesTest ossimTimeUtilitiesTest.cpp) + target_link_libraries(OTBossimTimeUtilitiesTest # ${OTBOssim_LIBRARIES} otbossimplugins ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) - otb_module_target_label(ossimTimeUtilitiesTest) - otb_add_test(NAME ossimTimeUtilitiesTest COMMAND ossimTimeUtilitiesTest ) + otb_module_target_label(OTBossimTimeUtilitiesTest) + otb_add_test(NAME TuossimTimeUtilitiesTest COMMAND OTBossimTimeUtilitiesTest ) else() message(STATUS "Boost unit test framework not found, ossimStringUtilitiesTest and ossimTimeUtilitiesTest will be skipped.") endif() @@ -30,42 +30,42 @@ endif() # (requires google.benchmark) find_package(GBenchmark) if (GBENCHMARK_FOUND) - add_executable(ossimTimeUtilitiesBench ossimTimeUtilitiesBench.cpp) - include_directories(${GBENCHMARK_INCLUDE_DIRS}) - target_link_libraries(ossimTimeUtilitiesBench - otbossimplugins - ${GBENCHMARK_LIBRARIES}) - otb_module_target_label(ossimTimeUtilitiesBench) -else() - message(STATUS "Google.benchmark not found, ossimTimeUtilitiesBench will be skipped.") + add_executable(OTBossimTimeUtilitiesBench ossimTimeUtilitiesBench.cpp) + include_directories(${GBENCHMARK_INCLUDE_DIRS}) + target_link_libraries(OTBossimTimeUtilitiesBench + otbossimplugins + ${GBENCHMARK_LIBRARIES}) + otb_module_target_label(OTBossimTimeUtilitiesBench) +# else() +# Even if GBenchmark is found, test is not launched because it is not added to ctest endif() #===== Domain tests #Test executables -add_executable(ossimSarSensorModelTest ossimSarSensorModelTest.cpp) -target_link_libraries(ossimSarSensorModelTest otbossimplugins) -otb_module_target_label(ossimSarSensorModelTest) +add_executable(OTBossimSarSensorModelTest ossimSarSensorModelTest.cpp) +target_link_libraries(OTBossimSarSensorModelTest otbossimplugins) +otb_module_target_label(OTBossimSarSensorModelTest) # S1 -add_executable(ossimSentinel1ModelTest ossimSentinel1ModelTest.cpp) -target_link_libraries(ossimSentinel1ModelTest otbossimplugins) -otb_module_target_label(ossimSentinel1ModelTest) +add_executable(OTBossimSentinel1ModelTest ossimSentinel1ModelTest.cpp) +target_link_libraries(OTBossimSentinel1ModelTest otbossimplugins) +otb_module_target_label(OTBossimSentinel1ModelTest) # TSX (old) -add_executable(ossimTerraSarXSarSensorModelTest ossimTerraSarXSarSensorModelTest.cpp) -target_link_libraries(ossimTerraSarXSarSensorModelTest otbossimplugins) -otb_module_target_label(ossimTerraSarXSarSensorModelTest) +add_executable(OTBossimTerraSarXSarSensorModelTest ossimTerraSarXSarSensorModelTest.cpp) +target_link_libraries(OTBossimTerraSarXSarSensorModelTest otbossimplugins) +otb_module_target_label(OTBossimTerraSarXSarSensorModelTest) -otb_add_test(NAME ossimSarSensorModelTest COMMAND ossimSarSensorModelTest ) +otb_add_test(NAME TuossimSarSensorModelTest COMMAND OTBossimSarSensorModelTest ) #S1 tests file(GLOB s1_files ${INPUTDATA}/ossimPlugins/s1/*.xml) #Loop over all S1 annotation files foreach(entry ${s1_files}) get_filename_component(name ${entry} NAME_WE) - otb_add_test( NAME s1_inverse_${name} COMMAND ossimSentinel1ModelTest 1 ${entry}) - otb_add_test( NAME s1_forward_${name} COMMAND ossimSentinel1ModelTest 0 ${entry}) + otb_add_test( NAME s1_inverse_${name} COMMAND OTBossimSentinel1ModelTest 1 ${entry}) + otb_add_test( NAME s1_forward_${name} COMMAND OTBossimSentinel1ModelTest 0 ${entry}) endforeach() # #TSX tests diff --git a/Modules/ThirdParty/Shark/src/otb_shark.h.in b/Modules/ThirdParty/Shark/src/otb_shark.h.in index 3b5ea0997ef7b354f2e509923717b17f2afb9c88..c6c432e09b4ea52d44c513b5fb4d8405d8130805 100755 --- a/Modules/ThirdParty/Shark/src/otb_shark.h.in +++ b/Modules/ThirdParty/Shark/src/otb_shark.h.in @@ -33,7 +33,7 @@ #define BOOST_PARAMETER_MAX_ARITY 15 #define BOOST_FILESYSTEM_VERSION 3 -/* without having a compile defintion will give an linker error +/* without having a compile definition will give an linker error * when build otbapp_TrainImagesClassifier or this header test. * So define them depending on wheather you have static or shared * build of boost. diff --git a/Modules/ThirdParty/SiftFast/src/CMakeLists.txt b/Modules/ThirdParty/SiftFast/src/CMakeLists.txt index 56c63b1e54348d28e956941cfd14136f0c415612..ac8684974cde7330f5787f753b4e3b65865e7901 100644 --- a/Modules/ThirdParty/SiftFast/src/CMakeLists.txt +++ b/Modules/ThirdParty/SiftFast/src/CMakeLists.txt @@ -18,7 +18,7 @@ if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX ) if(IS_SIFTFAST_COMPILE) message(STATUS "Try to compile libsiftfast.cpp -- yes.") else() - message(STATUS "Try to compile libsiftfast.cpp -- no.") + message(STATUS "Try to compile libsiftfast.cpp -- no. OUTPUT_VARIABLE has ${OUTPUT}") try_compile(IS_SIFTFAST_COMPILE2 ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/test_try_compile_libsiftfast.cpp @@ -208,4 +208,4 @@ install(FILES otb_siftfast.h COMPONENT Development ) -otb_module_target( otbsiftfast NO_INSTALL ) \ No newline at end of file +otb_module_target( otbsiftfast NO_INSTALL ) diff --git a/Modules/ThirdParty/SiftFast/src/libsiftfast.cpp b/Modules/ThirdParty/SiftFast/src/libsiftfast.cpp index 631ab4e49ad25cc320706f70eb9ff7a340bd136c..3a31c09749234e48fb868f5a70d1c8e6ce4f9d3b 100644 --- a/Modules/ThirdParty/SiftFast/src/libsiftfast.cpp +++ b/Modules/ThirdParty/SiftFast/src/libsiftfast.cpp @@ -28,7 +28,9 @@ #include <map> #include <list> +#ifndef __OpenBSD__ #include <sys/timeb.h> // ftime(), struct timeb +#endif #ifndef _MSC_VER #include <sys/time.h> diff --git a/Modules/Visualization/Ice/include/otbGlView.h b/Modules/Visualization/Ice/include/otbGlView.h index a1aa852883560b332206c20798bea54acb0f8368..48c02d0333fa73ac3e6245e17df7e5655b788912 100644 --- a/Modules/Visualization/Ice/include/otbGlView.h +++ b/Modules/Visualization/Ice/include/otbGlView.h @@ -319,7 +319,6 @@ GlView if( actor.IsNull() ) return false; - // // Reference actor does not implement geo-interface. const otb::GeoInterface * geo = @@ -328,7 +327,8 @@ GlView if( geo==ITK_NULLPTR ) return false; - + const otb::GeoInterface::Spacing2 nativeReferenceSpacing = geo->GetSpacing(); + // // Compute transform origin. if( !geo->TransformFromViewport( center, vcenter, true ) ) @@ -390,13 +390,12 @@ GlView spacing[ 0 ] = vcl_sqrt( x[ 0 ] * x[ 0 ] + x[ 1 ] * x[ 1 ] ) / norm; spacing[ 1 ] = vcl_sqrt( y[ 0 ] * y[ 0 ] + y[ 1 ] * y[ 1 ] ) / norm; - // Sign of x-spacing is done by sign( x . (1, 0) ) which is sign( x[ 0 ] ) - // Sign of y-spacing is done by sign( y . (0, 1) ) which is sign[ y[ 1 ] ) - - if( x[ 0 ]<0.0 ) + // New spacing signs should match signs of the reference image spacing + + if( nativeReferenceSpacing[0]<0.0 ) spacing[ 0 ] = -spacing[ 0 ]; - if( y[ 1 ]<0.0 ) + if( nativeReferenceSpacing[1]<0.0 ) spacing[ 1 ] = -spacing[ 1 ]; // diff --git a/Modules/Visualization/Ice/include/otbStandardShader.h b/Modules/Visualization/Ice/include/otbStandardShader.h index 6077c36ee8de2f4c9a3558c83e136be9e3ccbb8a..e5755b592f80398021fb6e353d544b4aed45d7e1 100644 --- a/Modules/Visualization/Ice/include/otbStandardShader.h +++ b/Modules/Visualization/Ice/include/otbStandardShader.h @@ -33,7 +33,17 @@ typedef enum SHADER_ALPHA_GRID, SHADER_ALPHA_SLIDER, SHADER_SPECTRAL_ANGLE, - SHADER_GRADIENT + SHADER_GRADIENT, + SHADER_LUT_JET, + SHADER_LUT_LOCAL_JET, + SHADER_LUT_HOT, + SHADER_LUT_LOCAL_HOT, + SHADER_LUT_WINTER, + SHADER_LUT_LOCAL_WINTER, + SHADER_LUT_SUMMER, + SHADER_LUT_LOCAL_SUMMER, + SHADER_LUT_COOL, + SHADER_LUT_LOCAL_COOL } ShaderType; diff --git a/Modules/Visualization/Ice/src/otbGlImageActor.cxx b/Modules/Visualization/Ice/src/otbGlImageActor.cxx index f95da4257f877da2ca46469cbdbc9e5367340f84..530055e07ac6128893e542c183b5ceb957174d8c 100644 --- a/Modules/Visualization/Ice/src/otbGlImageActor.cxx +++ b/Modules/Visualization/Ice/src/otbGlImageActor.cxx @@ -873,13 +873,13 @@ GlImageActor #else index[ 0 ] = static_cast< IndexType::IndexValueType >( - ( physical[ 0 ] - m_Origin[ 0 ] ) / + ( physical[ 0 ] + 0.5 * m_Spacing[0] - m_Origin[ 0 ] ) / m_Spacing[ 0 ] ); index[ 1 ] = static_cast< IndexType::IndexValueType >( - ( physical[ 1 ]- m_Origin[ 1 ] ) / + ( physical[ 1 ] + 0.5 * m_Spacing[1] - m_Origin[ 1 ] ) / m_Spacing[ 1 ] ); diff --git a/Modules/Visualization/Ice/src/otbStandardShader.cxx b/Modules/Visualization/Ice/src/otbStandardShader.cxx index 66e4817f56f9e2bbb84c897e298f5cfcf6aa73b1..6fd2676d02b318b2c664a0995708c38ca59af9b7 100644 --- a/Modules/Visualization/Ice/src/otbStandardShader.cxx +++ b/Modules/Visualization/Ice/src/otbStandardShader.cxx @@ -85,7 +85,8 @@ std::string StandardShader::GetSource() const "uniform int shader_vertical_slider_flag;\n" \ "void main (void) {\n" \ "vec4 p = texture2D(src, gl_TexCoord[0].xy);\n" \ - "gl_FragColor = pow( clamp( ( p+shader_b ) * shader_a, 0.0, 1.0 ), shader_gamma );\n" \ + "vec4 colors = pow( clamp( ( p+shader_b ) * shader_a, 0.0, 1.0 ), shader_gamma );\n" \ + "gl_FragColor = colors;\n" \ "gl_FragColor[3] = clamp(shader_alpha,0.0,1.0);\n" \ "if(shader_use_no_data > 0 && vec3(p) == vec3(shader_no_data)){\n" \ "gl_FragColor[3] = 0.;\n" \ @@ -128,6 +129,141 @@ std::string StandardShader::GetSource() const "gl_FragColor[2] = tmp[2];\n" \ "gl_FragColor[3] = alpha;\n" \ "}\n" \ + "}\n" \ + "else if(shader_type == 7)\n" \ + "{\n" \ + "float color = colors[0];\n" \ + "vec3 mapped;\n" \ + "mapped[0] = -abs( 3.95 * (color - 0.7460)) + 1.5;\n" \ + "mapped[1] = -abs( 3.95 * (color - 0.492)) + 1.5;\n" \ + "mapped[2] = -abs( 3.95 * (color - 0.2385)) + 1.5;\n" \ + "mapped = clamp(mapped,0.0,1.0);\n" \ + "gl_FragColor[0] = mapped[0];\n" \ + "gl_FragColor[1] = mapped[1];\n" \ + "gl_FragColor[2] = mapped[2];\n" \ + "}\n" \ + "else if(shader_type == 8)\n" \ + "{\n" \ + "if(dist < shader_radius)\n" \ + "{\n" \ + "float color=clamp((p[0]-shader_current[0]+shader_localc_range)/(2.*shader_localc_range),0.0,1.0);\n" \ + "vec3 mapped;\n" \ + "mapped[0] = -abs( 3.95 * (color - 0.7460)) + 1.5;\n" \ + "mapped[1] = -abs( 3.95 * (color - 0.492)) + 1.5;\n" \ + "mapped[2] = -abs( 3.95 * (color - 0.2385)) + 1.5;\n" \ + "mapped = clamp(mapped,0.0,1.0);\n" \ + "gl_FragColor[0] = mapped[0];\n" \ + "gl_FragColor[1] = mapped[1];\n" \ + "gl_FragColor[2] = mapped[2];\n" \ + "}\n" \ + "}\n" \ + "else if(shader_type == 9)\n" \ + "{\n" \ + "float color = colors[0];\n" \ + "vec3 mapped;\n" \ + "mapped[0] = 63.0 / 26.0 * color - 1.0 / 13.0;\n" \ + "mapped[1] = 63.0 / 26.0 * color - 11.0 / 13.0;\n" \ + "mapped[2] = 4.5 * color - 3.5;\n" \ + "mapped = clamp(mapped,0.0,1.0);\n" \ + "gl_FragColor[0] = mapped[0];\n" \ + "gl_FragColor[1] = mapped[1];\n" \ + "gl_FragColor[2] = mapped[2];\n" \ + "}\n" \ + "else if(shader_type == 10)\n" \ + "{\n" \ + "if(dist < shader_radius)\n" \ + "{\n" \ + "float color=clamp((p[0]-shader_current[0]+shader_localc_range)/(2.*shader_localc_range),0.0,1.0);\n" \ + "vec3 mapped;\n" \ + "mapped[0] = 63.0 / 26.0 * color - 1.0 / 13.0;\n" \ + "mapped[1] = 63.0 / 26.0 * color - 11.0 / 13.0;\n" \ + "mapped[2] = 4.5 * color - 3.5;\n" \ + "mapped = clamp(mapped,0.0,1.0);\n" \ + "gl_FragColor[0] = mapped[0];\n" \ + "gl_FragColor[1] = mapped[1];\n" \ + "gl_FragColor[2] = mapped[2];\n" \ + "}\n" \ + "}\n" \ + "else if(shader_type == 11)\n" \ + "{\n" \ + "float color = colors[0];\n" \ + "vec3 mapped;\n" \ + "mapped[0] = 0.0;\n" \ + "mapped[1] = color;\n" \ + "mapped[2] = 1.0 - 0.5 * color;\n" \ + "mapped = clamp(mapped,0.0,1.0);\n" \ + "gl_FragColor[0] = mapped[0];\n" \ + "gl_FragColor[1] = mapped[1];\n" \ + "gl_FragColor[2] = mapped[2];\n" \ + "}\n" \ + "else if(shader_type == 12)\n" \ + "{\n" \ + "if(dist < shader_radius)\n" \ + "{\n" \ + "float color=clamp((p[0]-shader_current[0]+shader_localc_range)/(2.*shader_localc_range),0.0,1.0);\n" \ + "vec3 mapped;\n" \ + "mapped[0] = 0.0;\n" \ + "mapped[1] = color;\n" \ + "mapped[2] = 1.0 - 0.5 * color;\n" \ + "mapped = clamp(mapped,0.0,1.0);\n" \ + "gl_FragColor[0] = mapped[0];\n" \ + "gl_FragColor[1] = mapped[1];\n" \ + "gl_FragColor[2] = mapped[2];\n" \ + "}\n" \ + "}\n" \ + "else if(shader_type == 13)\n" \ + "{\n" \ + "float color = colors[0];\n" \ + "vec3 mapped;\n" \ + "mapped[0] = color;\n" \ + "mapped[1] = 0.5*color+0.5;\n" \ + "mapped[2] = 0.4;\n" \ + "mapped = clamp(mapped,0.0,1.0);\n" \ + "gl_FragColor[0] = mapped[0];\n" \ + "gl_FragColor[1] = mapped[1];\n" \ + "gl_FragColor[2] = mapped[2];\n" \ + "}\n" \ + "else if(shader_type == 14)\n" \ + "{\n" \ + "if(dist < shader_radius)\n" \ + "{\n" \ + "float color=clamp((p[0]-shader_current[0]+shader_localc_range)/(2.*shader_localc_range),0.0,1.0);\n" \ + "vec3 mapped;\n" \ + "mapped[0] = color;\n" \ + "mapped[1] = 0.5*color+0.5;\n" \ + "mapped[2] = 0.4;\n" \ + "mapped = clamp(mapped,0.0,1.0);\n" \ + "gl_FragColor[0] = mapped[0];\n" \ + "gl_FragColor[1] = mapped[1];\n" \ + "gl_FragColor[2] = mapped[2];\n" \ + "}\n" \ + "}\n" \ + "else if(shader_type == 15)\n" \ + "{\n" \ + "float color = colors[0];\n" \ + "vec3 mapped;\n" \ + "mapped[0] = color;\n" \ + "mapped[1] = 1.0-color;\n" \ + "mapped[2] = 1.0;\n" \ + "mapped = clamp(mapped,0.0,1.0);\n" \ + "gl_FragColor[0] = mapped[0];\n" \ + "gl_FragColor[1] = mapped[1];\n" \ + "gl_FragColor[2] = mapped[2];\n" \ + "}\n" \ + "else if(shader_type == 16)\n" \ + "{\n" \ + "if(dist < shader_radius)\n" \ + "{\n" \ + "float color=clamp((p[0]-shader_current[0]+shader_localc_range)/(2.*shader_localc_range),0.0,1.0);\n" \ + "vec3 mapped;\n" \ + "mapped[0] = color;\n" \ + "mapped[1] = 1.0-color;\n" \ + "mapped[2] = 1.0;\n" \ + "mapped = clamp(mapped,0.0,1.0);\n" \ + "gl_FragColor[0] = mapped[0];\n" \ + "gl_FragColor[1] = mapped[1];\n" \ + "gl_FragColor[2] = mapped[2];\n" \ + "}\n" \ "}\n"; if(isGLSLS140Available) diff --git a/Modules/Visualization/IceViewer/src/otbIceViewer.cxx b/Modules/Visualization/IceViewer/src/otbIceViewer.cxx index 873317ba10f0aba1a464955502ffe20f7f22daed..bfc39e6d5574a95374fd61f32c31a8736add1fec 100644 --- a/Modules/Visualization/IceViewer/src/otbIceViewer.cxx +++ b/Modules/Visualization/IceViewer/src/otbIceViewer.cxx @@ -468,6 +468,36 @@ void IceViewer::DrawHud() case SHADER_GRADIENT: oss<<" gradient"; break; + case SHADER_LUT_JET: + oss<<"Jet LUT"<<std::endl; + break; + case SHADER_LUT_LOCAL_JET: + oss<<"Local Jet LUT"<<std::endl; + break; + case SHADER_LUT_HOT: + oss<<"Hot LUT"<<std::endl; + break; + case SHADER_LUT_LOCAL_HOT: + oss<<"Local Hot LUT"<<std::endl; + break; + case SHADER_LUT_WINTER: + oss<<"Winter LUT"<<std::endl; + break; + case SHADER_LUT_LOCAL_WINTER: + oss<<"Local Winter LUT"<<std::endl; + break; + case SHADER_LUT_SUMMER: + oss<<"Summer LUT"<<std::endl; + break; + case SHADER_LUT_LOCAL_SUMMER: + oss<<"Local Summer LUT"<<std::endl; + break; + case SHADER_LUT_COOL: + oss<<"Cool LUT"<<std::endl; + break; + case SHADER_LUT_LOCAL_COOL: + oss<<"Local Cool LUT"<<std::endl; + break; } } diff --git a/Modules/Visualization/Mapla/src/mvdMaplaApplication.cxx b/Modules/Visualization/Mapla/src/mvdMaplaApplication.cxx index 4a1a871a2765d59d932c377223b97e22f0433a24..0096d801ee41af7a3797ec5ae8d5b74dfb7c7232 100644 --- a/Modules/Visualization/Mapla/src/mvdMaplaApplication.cxx +++ b/Modules/Visualization/Mapla/src/mvdMaplaApplication.cxx @@ -31,6 +31,7 @@ // // OTB includes (sorted by alphabetic order) +#include "otbWrapperApplicationRegistry.h" // // Monteverdi includes (sorted by alphabetic order) @@ -74,6 +75,7 @@ MaplaApplication MaplaApplication ::~MaplaApplication() { + otb::Wrapper::ApplicationRegistry::CleanRegistry(); } /*******************************************************************************/ diff --git a/Modules/Visualization/Monteverdi/include/mvdMainWindow.h b/Modules/Visualization/Monteverdi/include/mvdMainWindow.h index 80fa424606db26d016dc89db7b1d4ba2d1ab870c..5e5080fc4217ddf9b93a5e76dd6b00e7708cf8a0 100644 --- a/Modules/Visualization/Monteverdi/include/mvdMainWindow.h +++ b/Modules/Visualization/Monteverdi/include/mvdMainWindow.h @@ -126,7 +126,7 @@ public: /** */ - bool CheckGLCapabilities(); + bool CheckGLCapabilities( bool forceNoGLSL = false ); /** */ @@ -326,6 +326,10 @@ private: #endif // USE_PIXEL_DESCRIPTION + /** + */ + void SetGLSLEnabled( bool ); + // // I18nMainWindow methods. @@ -424,12 +428,21 @@ private: */ int m_GLSL140; + /** + */ + bool m_isGLSLAvailable : 1; + bool m_ForceNoGLSL : 1; + /*-[ PRIVATE SLOTS SECTION ]-----------------------------------------------*/ // // Private slots. private slots: + /** + */ + void on_action_GLSL_triggered( bool ); + /** * \brief Qt auto-connected slot which is called when Help/About * menu action is activated. diff --git a/Modules/Visualization/Monteverdi/src/CMakeLists.txt b/Modules/Visualization/Monteverdi/src/CMakeLists.txt index 85e016f6010b6734053bada692eec4f0b1ed0003..ab66fc6a2ce08e56d8a708d749c56edf10642506 100644 --- a/Modules/Visualization/Monteverdi/src/CMakeLists.txt +++ b/Modules/Visualization/Monteverdi/src/CMakeLists.txt @@ -72,6 +72,14 @@ add_executable( monteverdi ${Monteverdi_App_WIN32_RC_FILE} ${OTBMonteverdi_RESOURCES_RCC} ) + +# set monterverdi stack size to 10Mbytes on windows platform because +# the default size with visual compiler it is 1Mbyte +# which is to lower for us (thanks to 6S code). +if (WIN32) + set_linker_stack_size_flag( monteverdi 10000000 ) +endif() + target_link_libraries( monteverdi OTBMonteverdi ) diff --git a/Modules/Visualization/Monteverdi/src/main.cxx b/Modules/Visualization/Monteverdi/src/main.cxx index 170090bfd36a5f1f68cca0a0a304da55c3b30281..4a6d300a296d19a9ec3780ec46d33fc9208f6c72 100644 --- a/Modules/Visualization/Monteverdi/src/main.cxx +++ b/Modules/Visualization/Monteverdi/src/main.cxx @@ -58,17 +58,33 @@ enum ERROR_CODE ERROR_CODE_USAGE = -5, }; + +struct Flags +{ + Flags() : + loadOTBApplications( false ), + forceNoGLSL( false ) + { + } + + bool loadOTBApplications: 1; + bool forceNoGLSL: 1; +}; + + /*****************************************************************************/ /* FUNCTIONS DECLARATION */ +/*****************************************************************************/ /*****************************************************************************/ /* MAIN */ - +/*****************************************************************************/ int main( int argc, char* argv[] ) { QApplication qtApp( argc, argv ); + Flags flags; // // 0. Splash-screen. @@ -93,8 +109,9 @@ main( int argc, char* argv[] ) QCoreApplication::translate( PROJECT_NAME, "Usage: %1 [-h|--help] [-a|--applications] [<filename>...]\n" - " -h, --help display this help message.\n" + " -1, --no-glsl force OpenGL 1.x compatible rendering." " -a, --applications load OTB-applications from OTB_APPLICATIONS_PATH." + " -h, --help display this help message.\n" ) .arg( QFileInfo( argv[ 0 ] ).baseName() ) ) @@ -102,10 +119,24 @@ main( int argc, char* argv[] ) return ERROR_CODE_USAGE; } - else + + else if( it->compare( "-a" )==0 || + it->compare( "--applications" )==0 ) { - ++ it; + flags.loadOTBApplications = true; + + it = args.erase( it ); } + + else if(it->compare( "-1" )==0 || + it->compare( "--no-glsl" )==0 ) + { + flags.forceNoGLSL = true; + + it = args.erase( it ); + } + else + ++ it; } // @@ -163,48 +194,28 @@ main( int argc, char* argv[] ) // // 4. Check OpenGL capabilities - if( !mainWindow.CheckGLCapabilities() ) + if( !mainWindow.CheckGLCapabilities( flags.forceNoGLSL ) ) return ERROR_CODE_GL_VERSION; // - // 5. Parse command-line filenames. - args.pop_front(); - { - bool otbApplications = false; - - for( QStringList::iterator it( args.begin() ); - it!=args.end(); ) - if( it->compare( "-a" )==0 || - it->compare( "--applications" )==0 ) - { - if( !otbApplications ) - { + // 5. Load OTB-applications. + if( flags.loadOTBApplications ) #if USE_OTB_APPS - mainWindow.SetupOTBApplications(); + mainWindow.SetupOTBApplications(); #else // USE_OTB_APPS - qWarning() << "OTB-applications support is not included in this build."; + qWarning() << "OTB-applications support is not included in this build."; #endif // USE_OTB_APPS - it = args.erase( it ); - } - } - else - { - ++ it; - } - } + // + // 6. Load command-line filenames. + args.pop_front(); mainWindow.ImportImages( args ); - // // 6. Let's go: run the application and return exit code. int result = QCoreApplication::instance()->exec(); - /* - application->CloseDatabase(); - */ - // Coverity-14835 // { delete application; diff --git a/Modules/Visualization/Monteverdi/src/mvdApplication.cxx b/Modules/Visualization/Monteverdi/src/mvdApplication.cxx index e42c38f39ab21199b0e4e0d3346581fc1b9ea0b8..265818ade759b107718b230bb87b08208b113826 100644 --- a/Modules/Visualization/Monteverdi/src/mvdApplication.cxx +++ b/Modules/Visualization/Monteverdi/src/mvdApplication.cxx @@ -34,6 +34,7 @@ // // Monteverdi includes (sorted by alphabetic order) +#include "mvdMainWindow.h" #include "mvdStackedLayerModel.h" // @@ -41,6 +42,10 @@ # include "mvdOTBApplicationsModel.h" #endif +#if USE_OTB_APPS +#include "otbWrapperApplicationRegistry.h" +#endif + // // Class implementation. namespace mvd @@ -76,6 +81,9 @@ Application Application ::~Application() { +#if USE_OTB_APPS + otb::Wrapper::ApplicationRegistry::CleanRegistry(); +#endif } /*******************************************************************************/ diff --git a/Modules/Visualization/Monteverdi/src/mvdMainWindow.cxx b/Modules/Visualization/Monteverdi/src/mvdMainWindow.cxx index 5a93be01cdfce1284ac949083c4331ced9f0679c..263b69deb604af1f23f02e3cb6f359498357f5a1 100644 --- a/Modules/Visualization/Monteverdi/src/mvdMainWindow.cxx +++ b/Modules/Visualization/Monteverdi/src/mvdMainWindow.cxx @@ -139,7 +139,9 @@ MainWindow m_ShaderWidget( NULL ), m_FilenameDragAndDropEventFilter( NULL ), m_KeymapDialog( NULL ), - m_GLSL140( -2 ) + m_GLSL140( -2 ), + m_isGLSLAvailable( false ), + m_ForceNoGLSL( false ) { m_UI->setupUi( this ); @@ -171,7 +173,7 @@ MainWindow /*****************************************************************************/ bool MainWindow -::CheckGLCapabilities() +::CheckGLCapabilities( bool forceNoGLSL ) { assert( m_ImageView!=NULL ); assert( m_ImageView->GetRenderer()!=NULL ); @@ -182,35 +184,105 @@ MainWindow // m_ImageView->GetRenderer()==NULL ) // return false; - bool isGLSL = m_ImageView->GetRenderer()->CheckGLCapabilities( &m_GLSL140 ); + m_isGLSLAvailable = + m_ImageView->GetRenderer()->CheckGLCapabilities( &m_GLSL140 ); #if FORCE_NO_GLSL - m_ImageView->GetRenderer()->SetGLSLEnabled( false ); + qWarning() << "No-GLSL is always forced in this build!"; + + m_ForceNoGLSL = true; + +#else + m_ForceNoGLSL = forceNoGLSL; - isGLSL = false; #endif // FORCE_NO_GLSL - // MANTIS-1204 - // { + bool isGLSL = m_isGLSLAvailable && !m_ForceNoGLSL; + + { + assert( m_UI!=NULL ); + assert( m_UI->action_GLSL!=NULL ); + + bool isBlocked = m_UI->action_GLSL->blockSignals( true ); + + m_UI->action_GLSL->setEnabled( m_isGLSLAvailable ); + m_UI->action_GLSL->setChecked( isGLSL ); + + m_UI->action_GLSL->blockSignals( isBlocked ); + } + + SetGLSLEnabled( isGLSL ); + + return ( !m_isGLSLAvailable || m_ForceNoGLSL ) || m_isGLSLAvailable; +} + +/*****************************************************************************/ +void +MainWindow +::SetGLSLEnabled( bool enabled ) +{ // - // Forward GLSL state to quicklook view. - assert( GetQuicklookView()!=NULL ); - assert( GetQuicklookView()->GetRenderer()!=NULL ); + // Image view + { + assert( m_ImageView!=NULL ); - GetQuicklookView()->GetRenderer()->SetGLSLEnabled( isGLSL ); - // } + AbstractImageViewRenderer * renderer = m_ImageView->GetRenderer(); + + assert( renderer!=NULL ); + + if( renderer->SetGLSLEnabled( enabled )!=enabled ) + { + renderer->ClearScene( true ); + renderer->UpdateScene(); + + m_ImageView->updateGL(); + } + } + + { + ImageViewWidget * quicklookView = GetQuicklookView(); + assert( quicklookView!=NULL ); + + // MANTIS-1204 + // { + // + // Forward GLSL state to quicklook view. + assert( GetQuicklookView()->GetRenderer()!=NULL ); + + AbstractImageViewRenderer * renderer = quicklookView->GetRenderer(); + + assert( renderer!=NULL ); + + if( renderer->SetGLSLEnabled( enabled )!=enabled ) + { + renderer->ClearScene( true ); + renderer->UpdateScene(); + quicklookView->updateGL(); + } + // } + } + + // + // Shader widget assert( m_ShaderWidget!=NULL ); - m_ShaderWidget->SetGLSLEnabled( isGLSL ); + m_ShaderWidget->SetGLSLEnabled( enabled ); m_ShaderWidget->SetGLSL140Enabled( m_GLSL140>=0 ); + // + // Status bar widget. assert( m_StatusBarWidget!=NULL ); - m_StatusBarWidget->SetGLSLEnabled( isGLSL ); - + m_StatusBarWidget->SetGLSLEnabled( enabled ); - return true; + // + // Paint + // if( mustRefresh ) + // { + // m_ImageView->updateGL(); + // quicklookView->updateGL(); + // } } /*****************************************************************************/ @@ -470,7 +542,16 @@ MainWindow quicklookView, SLOT( OnApplyAllRequested() ) ); + + QObject::connect( + controller, + SIGNAL( ResetEffectsRequested() ), + // to: + m_ImageView, + SLOT( OnResetEffectsRequested() ) + ); } + } /*****************************************************************************/ @@ -1021,8 +1102,8 @@ MainWindow quicklookView->SetPickingEnabled( false ); quicklookView->SetPickingDefaultStatus( false ); - quicklookView->setMinimumSize( 64, 64 ); - quicklookView->setMaximumSize( 512, 512 ); + quicklookView->setMinimumSize( 32, 32 ); + quicklookView->setMaximumSize( 1024, 1024 ); quicklookView->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum ); return quicklookView; @@ -1636,6 +1717,16 @@ MainWindow /*****************************************************************************/ /* SLOTS */ +/*****************************************************************************/ +void +MainWindow +::on_action_GLSL_triggered( bool checked ) +{ + // qDebug() << this << "::on_action_GLSL_triggered(" << checked << ")"; + + SetGLSLEnabled( m_isGLSLAvailable && !m_ForceNoGLSL && checked ); +} + /*****************************************************************************/ void MainWindow @@ -1666,8 +1757,9 @@ MainWindow { // // Select filename. + QString caption(tr("Open file...")); ImportImages( - otb::GetOpenFileNames( this, tr( "Open file..." ) ) + otb::GetOpenFileNames( this, caption ) ); } diff --git a/Modules/Visualization/Monteverdi/src/mvdMainWindow.qrc b/Modules/Visualization/Monteverdi/src/mvdMainWindow.qrc index c4178f41819dabd3388f1c73daf46c7039fa1ce5..dfd8f7d2866727451fc5998de9f6515725cd9362 100644 --- a/Modules/Visualization/Monteverdi/src/mvdMainWindow.qrc +++ b/Modules/Visualization/Monteverdi/src/mvdMainWindow.qrc @@ -7,7 +7,7 @@ <file alias="action_LayerProjection_Icon">../../../../Utilities/Data/Icons/projection_24x24.png</file> <file alias="action_LayerUp_Icon">../../../../Utilities/Data/Icons/layer-up_24x24.png</file> <file alias="action_LayerBottom_Icon">../../../../Utilities/Data/Icons/layer-bottom_24x24.png</file> - <file alias="action_LayerDelete_Icon">../../../../Utilities/Data/Icons/layer-delete_24x24.png</file> + <file alias="action_LayerDelete_Icon">../../../../Utilities/Data/Icons/layer-delete.png</file> <file alias="action_LayerDown_Icon">../../../../Utilities/Data/Icons/layer-down_24x24.png</file> <file alias="action_LayerTop_Icon">../../../../Utilities/Data/Icons/layer-top_24x24.png</file> <file alias="action_ZoomFull_Icon">../../../../Utilities/Data/Icons/zoom-1to1.png</file> diff --git a/Modules/Visualization/Monteverdi/src/mvdMainWindow.ui b/Modules/Visualization/Monteverdi/src/mvdMainWindow.ui index 4e52db5f179facca6d05f5c12ec73e7c71e8290c..98628a1a63a5e01fb08c46e638946a6439d10644 100644 --- a/Modules/Visualization/Monteverdi/src/mvdMainWindow.ui +++ b/Modules/Visualization/Monteverdi/src/mvdMainWindow.ui @@ -51,7 +51,10 @@ <addaction name="action_ZoomExtent"/> <addaction name="action_ZoomLayer"/> <addaction name="separator"/> + <addaction name="action_GLSL"/> + <addaction name="separator"/> <addaction name="action_SaveScreenshot"/> + <addaction name="separator"/> </widget> <widget class="QMenu" name="menu_Edit"> <property name="title"> @@ -163,6 +166,9 @@ </property> </action> <action name="action_ZoomIn"> + <property name="checkable"> + <bool>true</bool> + </property> <property name="enabled"> <bool>false</bool> </property> @@ -271,6 +277,25 @@ <string>Ctrl+P</string> </property> </action> + <action name="actionOpenGL"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>OpenGL texture</string> + </property> + </action> + <action name="action_GLSL"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="text"> + <string>Use OpenGL Shading Language (GLSL)</string> + </property> + </action> </widget> <resources> <include location="mvdMainWindow.qrc"/> diff --git a/Modules/Visualization/MonteverdiCore/include/mvdCore.h b/Modules/Visualization/MonteverdiCore/include/mvdCore.h index d0e2582253a3d5d754d5d6feb6c456b716043e10..29561da2fbf742101692057d3028c99fdf9805b6 100644 --- a/Modules/Visualization/MonteverdiCore/include/mvdCore.h +++ b/Modules/Visualization/MonteverdiCore/include/mvdCore.h @@ -130,9 +130,19 @@ enum Effect EFFECT_LOCAL_CONTRAST, EFFECT_LOCAL_TRANSLUCENCY, EFFECT_NORMAL, - EFFECT_SPECTRAL_ANGLE, EFFECT_SWIPE_H, EFFECT_SWIPE_V, + EFFECT_SPECTRAL_ANGLE, + EFFECT_LUT_JET, + EFFECT_LUT_LOCAL_JET, + EFFECT_LUT_HOT, + EFFECT_LUT_LOCAL_HOT, + EFFECT_LUT_WINTER, + EFFECT_LUT_LOCAL_WINTER, + EFFECT_LUT_SUMMER, + EFFECT_LUT_LOCAL_SUMMER, + EFFECT_LUT_COOL, + EFFECT_LUT_LOCAL_COOL, // EFFECT_COUNT }; diff --git a/Modules/Visualization/MonteverdiCore/include/mvdImageSettings.h b/Modules/Visualization/MonteverdiCore/include/mvdImageSettings.h index 1281624b976d166bd117d1fc06ff69dae4a9fb6f..4323187fec5cf4e99d7e978d78dadda1dc8accf4 100644 --- a/Modules/Visualization/MonteverdiCore/include/mvdImageSettings.h +++ b/Modules/Visualization/MonteverdiCore/include/mvdImageSettings.h @@ -347,7 +347,12 @@ ImageSettings m_Effect==EFFECT_GRADIENT || m_Effect==EFFECT_LOCAL_CONTRAST || m_Effect==EFFECT_LOCAL_TRANSLUCENCY || - m_Effect==EFFECT_SPECTRAL_ANGLE; + m_Effect==EFFECT_SPECTRAL_ANGLE || + m_Effect==EFFECT_LUT_LOCAL_JET || + m_Effect==EFFECT_LUT_LOCAL_HOT || + m_Effect==EFFECT_LUT_LOCAL_WINTER || + m_Effect==EFFECT_LUT_LOCAL_SUMMER || + m_Effect==EFFECT_LUT_LOCAL_COOL; } /*****************************************************************************/ @@ -358,7 +363,12 @@ ImageSettings { return m_Effect==EFFECT_LOCAL_CONTRAST || - m_Effect==EFFECT_SPECTRAL_ANGLE; + m_Effect==EFFECT_SPECTRAL_ANGLE || + m_Effect==EFFECT_LUT_LOCAL_JET || + m_Effect==EFFECT_LUT_LOCAL_HOT || + m_Effect==EFFECT_LUT_LOCAL_WINTER || + m_Effect==EFFECT_LUT_LOCAL_SUMMER || + m_Effect==EFFECT_LUT_LOCAL_COOL; } /*****************************************************************************/ diff --git a/Modules/Visualization/MonteverdiCore/include/mvdTypes.h b/Modules/Visualization/MonteverdiCore/include/mvdTypes.h index e895260d3b1b4f797264cd6876ffe29b71613fe0..27fbc5a90ebd90e64a4129c61566f24ef443e76c 100644 --- a/Modules/Visualization/MonteverdiCore/include/mvdTypes.h +++ b/Modules/Visualization/MonteverdiCore/include/mvdTypes.h @@ -217,6 +217,7 @@ struct PixelInfo m_Point(), m_Index(), m_Pixel(), + m_Resolution (1), m_HasPoint( false ), m_HasIndex( false ), m_HasPixel( false ), diff --git a/Modules/Visualization/MonteverdiCore/include/mvdVectorImageSettings.h b/Modules/Visualization/MonteverdiCore/include/mvdVectorImageSettings.h index 8532f8a5705912ea2a9f70fbd52d65a630cd4753..478636b67fd5d2b86d8281d3a3bf5c010b26e404 100644 --- a/Modules/Visualization/MonteverdiCore/include/mvdVectorImageSettings.h +++ b/Modules/Visualization/MonteverdiCore/include/mvdVectorImageSettings.h @@ -550,6 +550,18 @@ VectorImageSettings { m_IsGrayscaleActivated = activated; + Effect effect = GetEffect(); + + if(activated + && effect == EFFECT_SPECTRAL_ANGLE) + { + SetEffect(EFFECT_NORMAL); + } + else if(!activated && effect >= EFFECT_LUT_LOCAL_JET) + { + SetEffect(EFFECT_NORMAL); + } + SetModified(); } diff --git a/Modules/Visualization/MonteverdiCore/src/mvdCore.cxx b/Modules/Visualization/MonteverdiCore/src/mvdCore.cxx index 041429170c1297f0019b4f6b9ac7053ef5239143..4995497710d75655340e4877e14c59dd9a53a745 100644 --- a/Modules/Visualization/MonteverdiCore/src/mvdCore.cxx +++ b/Modules/Visualization/MonteverdiCore/src/mvdCore.cxx @@ -87,9 +87,19 @@ EFFECT_NAMES[ EFFECT_COUNT ] = QT_TRANSLATE_NOOP( "mvd", "Local contrast" ), QT_TRANSLATE_NOOP( "mvd", "Local translucency" ), QT_TRANSLATE_NOOP( "mvd", "Normal" ), - QT_TRANSLATE_NOOP( "mvd", "Spectral angle" ), QT_TRANSLATE_NOOP( "mvd", "Swipe (horizontal)" ), QT_TRANSLATE_NOOP( "mvd", "Swipe (vertical)" ), + QT_TRANSLATE_NOOP( "mvd", "Spectral angle" ), + QT_TRANSLATE_NOOP( "mvd", "Lookup table (jet)" ), + QT_TRANSLATE_NOOP( "mvd", "Local lookup table (jet)" ), + QT_TRANSLATE_NOOP( "mvd", "Lookup table (hot)" ), + QT_TRANSLATE_NOOP( "mvd", "Local lookup table (hot)" ), + QT_TRANSLATE_NOOP( "mvd", "Lookup table (winter)" ), + QT_TRANSLATE_NOOP( "mvd", "Local lookup table (winter)" ), + QT_TRANSLATE_NOOP( "mvd", "Lookup table (summer)" ), + QT_TRANSLATE_NOOP( "mvd", "Local lookup table (summer)" ), + QT_TRANSLATE_NOOP( "mvd", "Lookup table (cool)" ), + QT_TRANSLATE_NOOP( "mvd", "Local lookup table (cool)" ) }; bool diff --git a/Modules/Visualization/MonteverdiCore/src/mvdI18nCoreApplication.cxx b/Modules/Visualization/MonteverdiCore/src/mvdI18nCoreApplication.cxx index da3a3c66329969ea7521ab64abcc2dbc0bf09da7..f3b45caa3fcae98b30765f2a64941cc1eab8a417 100644 --- a/Modules/Visualization/MonteverdiCore/src/mvdI18nCoreApplication.cxx +++ b/Modules/Visualization/MonteverdiCore/src/mvdI18nCoreApplication.cxx @@ -562,34 +562,33 @@ I18nCoreApplication // QTextCodec::setCodecForCStrings( QTextCodec::codecForName("System") ); - qWarning() + qDebug() << "Codec for C-strings:" << ( QTextCodec::codecForCStrings()!=NULL ? QTextCodec::codecForCStrings()->name() : "none" ); - qWarning() + qDebug() << "Codec for Locale:" << ( QTextCodec::codecForLocale()!=NULL ? QTextCodec::codecForLocale()->name() : "none" ); - qWarning() + qDebug() << "Codec for Tr:" << ( QTextCodec::codecForTr()!=NULL ? QTextCodec::codecForTr()->name() : "none" ); - // // 1. default UI language is english (no translation). QLocale sys_lc( QLocale::system() ); // Trace system locale. - qWarning() + qDebug() << "Language:" << QLocale::languageToString( sys_lc.language() ); - qWarning() + qDebug() << "Country:" << QLocale::countryToString( sys_lc.country() ); // Check system locale. diff --git a/Modules/Visualization/MonteverdiCore/src/mvdImageSettings.cxx b/Modules/Visualization/MonteverdiCore/src/mvdImageSettings.cxx index cc8253438f1a636842be6161357a886d1c5bcc94..3fef0af1eb9bf3bf903f9492b722483132e799c4 100644 --- a/Modules/Visualization/MonteverdiCore/src/mvdImageSettings.cxx +++ b/Modules/Visualization/MonteverdiCore/src/mvdImageSettings.cxx @@ -130,6 +130,31 @@ ImageSettings return m_Angle; break; + case EFFECT_LUT_LOCAL_JET: + // qDebug() << "Range:" << m_Range; + return m_Range; + break; + + case EFFECT_LUT_LOCAL_HOT: + // qDebug() << "Range:" << m_Range; + return m_Range; + break; + + case EFFECT_LUT_LOCAL_WINTER: + // qDebug() << "Range:" << m_Range; + return m_Range; + break; + + case EFFECT_LUT_LOCAL_SUMMER: + // qDebug() << "Range:" << m_Range; + return m_Range; + break; + + case EFFECT_LUT_LOCAL_COOL: + // qDebug() << "Range:" << m_Range; + return m_Range; + break; + default: break; } @@ -154,6 +179,31 @@ ImageSettings m_Angle = value; break; + case EFFECT_LUT_LOCAL_JET: + // qDebug() << "Range = " << value; + m_Range = value; + break; + + case EFFECT_LUT_LOCAL_HOT: + // qDebug() << "Range = " << value; + m_Range = value; + break; + + case EFFECT_LUT_LOCAL_WINTER: + // qDebug() << "Range = " << value; + m_Range = value; + break; + + case EFFECT_LUT_LOCAL_SUMMER: + // qDebug() << "Range = " << value; + m_Range = value; + break; + + case EFFECT_LUT_LOCAL_COOL: + // qDebug() << "Range = " << value; + m_Range = value; + break; + default: break; } diff --git a/Modules/Visualization/MonteverdiCore/src/mvdStackedLayerModel.cxx b/Modules/Visualization/MonteverdiCore/src/mvdStackedLayerModel.cxx index 95dd12f7068a7bd3fae173f1cbbd84976780ff2d..148aafbb79698b24b59ba47db37556efd4bd6855 100644 --- a/Modules/Visualization/MonteverdiCore/src/mvdStackedLayerModel.cxx +++ b/Modules/Visualization/MonteverdiCore/src/mvdStackedLayerModel.cxx @@ -41,6 +41,8 @@ // Monteverdi includes (sorted by alphabetic order) #include "mvdAbstractLayerModel.h" #include "mvdAlgorithm.h" +#include "mvdVectorImageModel.h" +#include "mvdCore.h" namespace mvd { @@ -251,7 +253,7 @@ StackedLayerModel ? m_Current : ( m_Current>0 ? m_Current - 1 - : StackedLayerModel::NIL_INDEX ); + : GetCount()>1 ? 0 : StackedLayerModel::NIL_INDEX ); // // Emit signals. @@ -285,7 +287,7 @@ StackedLayerModel ? m_Reference : ( m_Reference > 0 ? m_Reference - 1 - : StackedLayerModel::NIL_INDEX ), + : GetCount() > 0 ? 0 : StackedLayerModel::NIL_INDEX ), true ); diff --git a/Modules/Visualization/MonteverdiCore/src/mvdVectorImageModel.cxx b/Modules/Visualization/MonteverdiCore/src/mvdVectorImageModel.cxx index d891e8f687524d9f39a5d47d6aee028eade4c47b..98511d85480dd0b022c354a93a8cb0906fe41eff 100644 --- a/Modules/Visualization/MonteverdiCore/src/mvdVectorImageModel.cxx +++ b/Modules/Visualization/MonteverdiCore/src/mvdVectorImageModel.cxx @@ -212,7 +212,7 @@ VectorImageModel // TODO: this choice should be done by the user during the import of the file bool forceToCacheOvw = true; - qWarning() << tr( "The ImageIO used to read this file supports overviews." ); + qDebug() << tr( "The ImageIO used to read this file supports overviews." ); if( nbOfAvailableOvw>0 ) { @@ -223,7 +223,7 @@ VectorImageModel // TODO MSD: how to manage case of JPEG2000 with no overviews ? : wait GDAL support OpenJPEG ... // The current file don't have overviews available - qWarning() << tr( "The file doesn't have overviews." ); + qDebug() << tr( "The file doesn't have overviews." ); if( !forceToCacheOvw ) { diff --git a/Modules/Visualization/MonteverdiGui/CMakeLists.txt b/Modules/Visualization/MonteverdiGui/CMakeLists.txt index 73d8b00def4c69928e012d52803148695bebba76..d503daf285d81eac54f3688603ff6e8b9d2baab3 100644 --- a/Modules/Visualization/MonteverdiGui/CMakeLists.txt +++ b/Modules/Visualization/MonteverdiGui/CMakeLists.txt @@ -7,4 +7,45 @@ set( OTBMonteverdiGUI_INCLUDE_DIRS ${OTBMonteverdiGUI_BINARY_DIR}/src ) + +set(OTBMonteverdiGUI_DATA_DIR "${CMAKE_SOURCE_DIR}/Utilities/Data") + +if (UNIX AND NOT APPLE) + # ------------------------- + # Install icons + # following freedesktop recommandations + # http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html + + # The different icon sizes installed + # According to the specs, the 48x48 icon is mandatory, others are optional + set( icon_sizes 16 32 48 128 ) + foreach( icon_size ${icon_sizes} ) + install(FILES ${OTBMonteverdiGUI_DATA_DIR}/Icons/monteverdi-${icon_size}x${icon_size}.png + DESTINATION share/icons/hicolor/${icon_size}x${icon_size}/apps + RENAME monteverdi.png) + endforeach() + + # Fallback on "/usr/share/pixmaps" + # See http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#directory_layout + install(FILES ${OTBMonteverdiGUI_DATA_DIR}/Icons/monteverdi-32x32.png + DESTINATION share/pixmaps + RENAME monteverdi.png) + + install(FILES ${OTBMonteverdiGUI_DATA_DIR}/Icons/monteverdi-splash.png + DESTINATION share/pixmaps + RENAME monteverdi-splash.png) + + install(FILES ${OTBMonteverdiGUI_DATA_DIR}/Icons/monteverdi-32x32.xpm + DESTINATION share/pixmaps + RENAME monteverdi.xpm) + + # ------------------------- + # Install freedesktop entry + + configure_file(${OTBMonteverdiGUI_DATA_DIR}/monteverdi.desktop.in ${CMAKE_BINARY_DIR}/monteverdi.desktop) + install(FILES ${CMAKE_BINARY_DIR}/monteverdi.desktop + DESTINATION share/applications) + +endif() + otb_module_impl() diff --git a/Modules/Visualization/MonteverdiGui/include/mvdAbstractImageViewRenderer.h b/Modules/Visualization/MonteverdiGui/include/mvdAbstractImageViewRenderer.h index c2930c313a189aee676005b1f99461786156f89b..eb134a54cf085801af2270b074a0e23ae206a928 100644 --- a/Modules/Visualization/MonteverdiGui/include/mvdAbstractImageViewRenderer.h +++ b/Modules/Visualization/MonteverdiGui/include/mvdAbstractImageViewRenderer.h @@ -250,6 +250,7 @@ public: // public slots public slots: + inline void ClearScene( bool keepViewport = false ); inline void UpdateScene(); inline void RefreshScene(); @@ -280,7 +281,6 @@ protected: { } - // // Protected attributes. protected: @@ -292,7 +292,7 @@ protected: private: /** */ - // virtual void virtual_ClearScene() {}; + virtual void virtual_ClearScene( bool ) {}; /** */ virtual void virtual_PrepareScene() {}; @@ -456,6 +456,15 @@ AbstractImageViewRenderer return wasEnabled; } +/*****************************************************************************/ +inline +void +AbstractImageViewRenderer +::ClearScene( bool keepViewport ) +{ + virtual_ClearScene( keepViewport ); +} + /*****************************************************************************/ inline void diff --git a/Modules/Visualization/MonteverdiGui/include/mvdColorDynamicsWidget.h b/Modules/Visualization/MonteverdiGui/include/mvdColorDynamicsWidget.h index 3182a3ed839a5e3929f5c7679705d97fe368b3d0..fe9d894eb960c5876b52158eeb5cfa2e5d302b37 100644 --- a/Modules/Visualization/MonteverdiGui/include/mvdColorDynamicsWidget.h +++ b/Modules/Visualization/MonteverdiGui/include/mvdColorDynamicsWidget.h @@ -323,6 +323,8 @@ private slots: /** */ void on_gammaSlider_valueChanged( int gamma ); + + void on_gammaResetButton_clicked(); }; } // end namespace 'mvd'. diff --git a/Modules/Visualization/MonteverdiGui/include/mvdImageViewRenderer.h b/Modules/Visualization/MonteverdiGui/include/mvdImageViewRenderer.h index 4167861185250371a5a74ba0f3407859e58c392d..adfe94490d0347e9c81d433a894ff7f136171a99 100644 --- a/Modules/Visualization/MonteverdiGui/include/mvdImageViewRenderer.h +++ b/Modules/Visualization/MonteverdiGui/include/mvdImageViewRenderer.h @@ -269,6 +269,7 @@ private: // // AbstractImageViewRenderer overloads. + void virtual_ClearScene( bool ) ITK_OVERRIDE; void virtual_UpdateScene() ITK_OVERRIDE; void virtual_RefreshScene() ITK_OVERRIDE; diff --git a/Modules/Visualization/MonteverdiGui/include/mvdImageViewWidget.h b/Modules/Visualization/MonteverdiGui/include/mvdImageViewWidget.h index add78b1cda507501b4a1eea6a4a5f33dfe63e2fb..61c4022c36bbdf6ee97e2c9239286c48f0fe03ef 100644 --- a/Modules/Visualization/MonteverdiGui/include/mvdImageViewWidget.h +++ b/Modules/Visualization/MonteverdiGui/include/mvdImageViewWidget.h @@ -410,6 +410,7 @@ private slots: /** */ void OnApplyAllRequested(); + void OnResetEffectsRequested(); /** */ void OnSetReferenceRequested(); diff --git a/Modules/Visualization/MonteverdiGui/include/mvdImportImagesDialog.h b/Modules/Visualization/MonteverdiGui/include/mvdImportImagesDialog.h index e887e4ddbc4854992e56cbc57497b140d37faf6b..336adf0b8994422b692025e7fbe39a4e8c2f54fd 100644 --- a/Modules/Visualization/MonteverdiGui/include/mvdImportImagesDialog.h +++ b/Modules/Visualization/MonteverdiGui/include/mvdImportImagesDialog.h @@ -165,10 +165,6 @@ private: */ Ui::ImportImagesDialog * m_UI; - /** - */ - QPushButton * m_IgnoreButton; - /** */ GDALOverviewsBuilderVector m_GDALOverviewsBuilders; diff --git a/Modules/Visualization/MonteverdiGui/include/mvdLayerStackController.h b/Modules/Visualization/MonteverdiGui/include/mvdLayerStackController.h index 24b0cf5a7791a36fc0ad1ab25e1fc7dd47b5df57..e9dcfb77447eacfeeddec53335321351f13519c9 100644 --- a/Modules/Visualization/MonteverdiGui/include/mvdLayerStackController.h +++ b/Modules/Visualization/MonteverdiGui/include/mvdLayerStackController.h @@ -107,6 +107,7 @@ signals: /** */ void ApplyAllRequested(); + void ResetEffectsRequested(); /*-[ PROTECTED SECTION ]---------------------------------------------------*/ diff --git a/Modules/Visualization/MonteverdiGui/include/mvdLayerStackWidget.h b/Modules/Visualization/MonteverdiGui/include/mvdLayerStackWidget.h index ae0a08d1ecc2f1c519e2c8030b74564e07e2bb85..b38e962d5f4f259525c0888a50821c9d115954af 100644 --- a/Modules/Visualization/MonteverdiGui/include/mvdLayerStackWidget.h +++ b/Modules/Visualization/MonteverdiGui/include/mvdLayerStackWidget.h @@ -131,6 +131,8 @@ public: */ void SetReloadEnabled( bool ); + void SetResetEffectsEnabled( bool ); + /** */ void InstallEventFilter( QObject * filter ); @@ -188,6 +190,9 @@ signals: /** */ void ApplyButtonClicked(); + /** + */ + void ResetEffectsButtonClicked(); /** */ void CopyLayerRequested( const AbstractLayerModel * ); diff --git a/Modules/Visualization/MonteverdiGui/include/mvdShaderWidget.h b/Modules/Visualization/MonteverdiGui/include/mvdShaderWidget.h index 640131d74f778634e382588aca138f7e91f9d1ef..aae6425508f82d3e0fb2e709c22264bc0f779f0d 100644 --- a/Modules/Visualization/MonteverdiGui/include/mvdShaderWidget.h +++ b/Modules/Visualization/MonteverdiGui/include/mvdShaderWidget.h @@ -23,7 +23,7 @@ // Configuration include. //// Included at first position before any other ones. #include "ConfigureMonteverdi.h" - +#include "mvdImageSettings.h" /*****************************************************************************/ /* INCLUDE SECTION */ @@ -114,6 +114,8 @@ public: // Public SLOTS. public slots: + void GrayscaleActivated(bool status); + /*-[ SIGNALS SECTION ]-----------------------------------------------------*/ // @@ -137,6 +139,8 @@ protected: // Private methods. private: + void SetEffectVisible(const Effect & effect, bool visible); + /** */ void virtual_SetSettings( ImageSettings * ) ITK_OVERRIDE; diff --git a/Modules/Visualization/MonteverdiGui/src/CMakeLists.txt b/Modules/Visualization/MonteverdiGui/src/CMakeLists.txt index b61d29567f45f623bba298c9b47424a6f5664589..99b784c31cde245689d7ff2ed7f1e46aefaa256e 100644 --- a/Modules/Visualization/MonteverdiGui/src/CMakeLists.txt +++ b/Modules/Visualization/MonteverdiGui/src/CMakeLists.txt @@ -120,7 +120,7 @@ set( OTBMonteverdiGUI_FORMS ############################################################################# set( OTBMonteverdiGUI_RESOURCES - # mvdIcons.qrc + mvdIcons.qrc ) ############################################################################# diff --git a/Modules/Visualization/MonteverdiGui/src/mvdColorBandDynamicsWidget.ui b/Modules/Visualization/MonteverdiGui/src/mvdColorBandDynamicsWidget.ui index dd697ccb77c7f316937a185e2effa32c335876be..b7d6734aa9efc54de9199733340f24fa83b72ec7 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdColorBandDynamicsWidget.ui +++ b/Modules/Visualization/MonteverdiGui/src/mvdColorBandDynamicsWidget.ui @@ -343,7 +343,7 @@ </property> <property name="icon"> <iconset> - <normaloff>:/icons/Data/Icons/execute.png</normaloff>:/icons/Data/Icons/execute.png</iconset> + <normaloff>:/icons/Utilities/Data/Icons/execute.png</normaloff>:/icons/Utilities/Data/Icons/execute.png</iconset> </property> <property name="iconSize"> <size> diff --git a/Modules/Visualization/MonteverdiGui/src/mvdColorDynamicsWidget.cxx b/Modules/Visualization/MonteverdiGui/src/mvdColorDynamicsWidget.cxx index 4b3c384fb828d2cbbeabf33d552d3f7ac3d58f6f..0e0daa80227a1d5ccd49e004029d1a79ec0c5c30 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdColorDynamicsWidget.cxx +++ b/Modules/Visualization/MonteverdiGui/src/mvdColorDynamicsWidget.cxx @@ -454,4 +454,11 @@ ColorDynamicsWidget QToolTip::showText(mapToGlobal(m_UI->gammaSlider->pos()),tr("Gamma: ") % QString::number(GetGamma()) ); } +void +ColorDynamicsWidget +::on_gammaResetButton_clicked() +{ + this->SetGamma(1.0); +} + } // end namespace 'mvd' diff --git a/Modules/Visualization/MonteverdiGui/src/mvdColorDynamicsWidget.ui b/Modules/Visualization/MonteverdiGui/src/mvdColorDynamicsWidget.ui index be9da912997b37ba6f8daf33d82df399ee04060b..09afa39e08c0a41a75e033030780ec950226a15c 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdColorDynamicsWidget.ui +++ b/Modules/Visualization/MonteverdiGui/src/mvdColorDynamicsWidget.ui @@ -158,6 +158,17 @@ </property> </widget> </item> + <item> + <widget class="QToolButton" name="gammaResetButton"> + <property name="toolTip"> + <string>Reset value to 1.</string> + </property> + <property name="icon"> + <iconset resource="mvdIcons.qrc"> + <normaloff>:/Utilities/Data/Icons/view-refresh.png</normaloff>:/Utilities/Data/Icons/view-refresh.png</iconset> + </property> + </widget> + </item> </layout> </widget> </item> @@ -307,7 +318,9 @@ <tabstop>noDataLineEdit</tabstop> <tabstop>noDataButton</tabstop> </tabstops> - <resources/> + <resources> + <include location="mvdIcons.qrc"/> + </resources> <connections> <connection> <sender>noDataCheckBox</sender> diff --git a/Modules/Visualization/MonteverdiGui/src/mvdColorSetupWidget.ui b/Modules/Visualization/MonteverdiGui/src/mvdColorSetupWidget.ui index 2bed58e35869d5ea15ce46809c4af8628686766c..662283b0b3f3b00ec1d852cda018e8e7c209556a 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdColorSetupWidget.ui +++ b/Modules/Visualization/MonteverdiGui/src/mvdColorSetupWidget.ui @@ -11,7 +11,7 @@ </rect> </property> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> @@ -47,10 +47,13 @@ </item> <item row="0" column="0"> <layout class="QGridLayout" name="gridLayout"> + <property name="margin"> + <number>9</number> + </property> <property name="spacing"> <number>3</number> </property> - <item row="4" column="0"> + <item row="3" column="0"> <layout class="QHBoxLayout" name="wHorizontalLayout"> <property name="spacing"> <number>1</number> @@ -95,7 +98,7 @@ </item> </layout> </item> - <item row="4" column="1"> + <item row="3" column="1"> <widget class="QComboBox" name="wComboBox"> <property name="enabled"> <bool>false</bool> @@ -123,23 +126,7 @@ </item> </widget> </item> - <item row="0" column="1"> - <widget class="QLabel" name="fileComponentLabel"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string><html><head/><body><p align="center">Image bands<br/>↓</p></body></html></string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="1" column="0"> + <item row="0" column="0"> <layout class="QHBoxLayout" name="rHorizontalLayout"> <property name="spacing"> <number>1</number> @@ -178,7 +165,7 @@ </item> </layout> </item> - <item row="1" column="1"> + <item row="0" column="1"> <widget class="QComboBox" name="rComboBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> @@ -203,7 +190,7 @@ </item> </widget> </item> - <item row="2" column="0"> + <item row="1" column="0"> <layout class="QHBoxLayout" name="gHorizontalLayout"> <property name="spacing"> <number>1</number> @@ -242,7 +229,7 @@ </item> </layout> </item> - <item row="2" column="1"> + <item row="1" column="1"> <widget class="QComboBox" name="gComboBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> @@ -267,7 +254,7 @@ </item> </widget> </item> - <item row="3" column="0"> + <item row="2" column="0"> <layout class="QHBoxLayout" name="bHorizontalLayout"> <property name="spacing"> <number>1</number> @@ -306,7 +293,7 @@ </item> </layout> </item> - <item row="3" column="1"> + <item row="2" column="1"> <widget class="QComboBox" name="bComboBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> @@ -331,7 +318,7 @@ </item> </widget> </item> - <item row="4" column="2"> + <item row="3" column="2"> <widget class="QCheckBox" name="wCheckBox"> <property name="toolTip"> <string>Enable/disable gray-scale mode.</string> diff --git a/Modules/Visualization/MonteverdiGui/src/mvdHistogramWidget.ui b/Modules/Visualization/MonteverdiGui/src/mvdHistogramWidget.ui index b66d978f9682d5422665c04bd5ad3c5344c6e744..0ca487f4eb2eb0f7f1f8e12740f9150c033f06aa 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdHistogramWidget.ui +++ b/Modules/Visualization/MonteverdiGui/src/mvdHistogramWidget.ui @@ -100,7 +100,7 @@ <property name="minimumSize"> <size> <width>200</width> - <height>100</height> + <height>60</height> </size> </property> <property name="toolTip"> diff --git a/Modules/Visualization/MonteverdiGui/src/mvdI18nMainWindow.cxx b/Modules/Visualization/MonteverdiGui/src/mvdI18nMainWindow.cxx index 3aad4081bea5228e44199aff3a2febb3c60ab9a2..499e6a8bb1430b5e7f2d9992eb3639e3c51c522c 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdI18nMainWindow.cxx +++ b/Modules/Visualization/MonteverdiGui/src/mvdI18nMainWindow.cxx @@ -181,14 +181,23 @@ I18nMainWindow ::BuildGDALOverviews( const QStringList & filenames ) { ImportImagesDialog * importDialog = new ImportImagesDialog( filenames, this ); + // The import dialog should be deleted before leaving this function if( importDialog->GetEffectiveCount()<1 ) + { + delete importDialog; + importDialog = NULL; return true; + } int result = importDialog->exec(); if( result== QDialog::Rejected ) + { + delete importDialog; + importDialog = NULL; return false; + } if( result==QDialog::Accepted ) { @@ -205,6 +214,11 @@ I18nMainWindow Import( builder ); } + if (importDialog) + { + delete importDialog; + importDialog = NULL; + } return true; } diff --git a/Modules/Visualization/MonteverdiGui/src/mvdIcons.qrc b/Modules/Visualization/MonteverdiGui/src/mvdIcons.qrc index 835ed7133726a2cc2d89f0f6b2f5cba01b3c3314..71dcbd6cc583cd95802a97770cd23af425261822 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdIcons.qrc +++ b/Modules/Visualization/MonteverdiGui/src/mvdIcons.qrc @@ -3,5 +3,7 @@ <file>../../../../Utilities/Data/Icons/execute.png</file> <file>../../../../Utilities/Data/Icons/locked.png</file> <file>../../../../Utilities/Data/Icons/unlocked.png</file> + <file>../../../../Utilities/Data/Icons/view-refresh.png</file> + <file>../../../../Utilities/Data/Icons/edit-clear.png</file> </qresource> </RCC> diff --git a/Modules/Visualization/MonteverdiGui/src/mvdImageViewRenderer.cxx b/Modules/Visualization/MonteverdiGui/src/mvdImageViewRenderer.cxx index fa1d9366c3ef51412b175aadc24d2db47ae2d789..cc3cbf7af7187ce80886234eefd7cd4b21b5539d 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdImageViewRenderer.cxx +++ b/Modules/Visualization/MonteverdiGui/src/mvdImageViewRenderer.cxx @@ -789,6 +789,65 @@ ImageViewRenderer shader->SetVerticalSlider( true ); break; + case EFFECT_LUT_JET: + shader->SetShaderType(otb::SHADER_LUT_JET); + break; + + case EFFECT_LUT_LOCAL_JET: + shader->SetShaderType(otb::SHADER_LUT_LOCAL_JET); + shader->SetRadius( settings.GetSize() ); + shader->SetLocalContrastRange(settings.GetValue()); + + break; + + case EFFECT_LUT_HOT: + shader->SetShaderType(otb::SHADER_LUT_HOT); + break; + + case EFFECT_LUT_LOCAL_HOT: + shader->SetShaderType(otb::SHADER_LUT_LOCAL_HOT); + shader->SetRadius( settings.GetSize() ); + shader->SetLocalContrastRange(settings.GetValue()); + + break; + + case EFFECT_LUT_SUMMER: + shader->SetShaderType(otb::SHADER_LUT_SUMMER); + break; + + case EFFECT_LUT_LOCAL_SUMMER: + shader->SetShaderType(otb::SHADER_LUT_LOCAL_SUMMER); + shader->SetRadius( settings.GetSize() ); + shader->SetLocalContrastRange(settings.GetValue()); + + break; + + case EFFECT_LUT_WINTER: + shader->SetShaderType(otb::SHADER_LUT_WINTER); + break; + + case EFFECT_LUT_LOCAL_WINTER: + shader->SetShaderType(otb::SHADER_LUT_LOCAL_WINTER); + shader->SetRadius( settings.GetSize() ); + shader->SetLocalContrastRange(settings.GetValue()); + + break; + + case EFFECT_LUT_COOL: + shader->SetShaderType(otb::SHADER_LUT_COOL); + break; + + case EFFECT_LUT_LOCAL_COOL: + shader->SetShaderType(otb::SHADER_LUT_LOCAL_COOL); + shader->SetRadius( settings.GetSize() ); + shader->SetLocalContrastRange(settings.GetValue()); + + break; + + + + + default: assert( false && "Unhandled mvd::Effect value!" ); break; @@ -808,6 +867,34 @@ ImageViewRenderer m_GlView->SetRenderingOrder( stackedLayerModel->GetKeys(), false ); } + +/*******************************************************************************/ +void +ImageViewRenderer +::virtual_ClearScene( bool keepViewport ) +{ + // qDebug() << this << "::virtual_ClearScene()"; + + // Remove all actors. + m_GlView->ClearActors(); + + // Clear reference actor. + m_ReferencePair.second = otb::GlActor::Pointer(); + + // Nothing more if keep viewport is enabled. + if( keepViewport ) + return; + + // Clear reference layer. + m_ReferencePair.first = NULL; + + // + // MANTIS-1244: image-view not reset when layer-stack is cleared. + // { + emit ResetViewport(); + // } +} + /*******************************************************************************/ void ImageViewRenderer @@ -826,30 +913,23 @@ ImageViewRenderer if( stackedLayerModel==NULL || stackedLayerModel->IsEmpty() ) - { - m_GlView->ClearActors(); + ClearScene(); - // - // MANTIS-1244: image-view not reset when layer-stack is cleared. - // { - emit ResetViewport(); - // } - } else { { otb::GlView::StringVectorType keys( m_GlView->GetActorsKeys() ); for( otb::GlView::StringVectorType::const_iterator it( keys.begin() ); - it!=keys.end(); - ++it ) - if( !stackedLayerModel->Contains( *it ) ) - { - // qDebug() + it!=keys.end(); + ++it ) + if( !stackedLayerModel->Contains( *it ) ) + { + // qDebug() // << QString( "Removing image-actor '%1'..." ).arg( it->c_str() ); - m_GlView->RemoveActor( *it ); - } + m_GlView->RemoveActor( *it ); + } } @@ -904,8 +984,6 @@ ImageViewRenderer m_GlView->AddActor( glImageActor, it->first ); - // glImageActor->SetVisible( vectorImageModel->IsVisible() ); - // qDebug() << // QString( "Added image-actor '%1' from file '%2'" ) // .arg( FromStdString( it->first ) ) diff --git a/Modules/Visualization/MonteverdiGui/src/mvdImageViewWidget.cxx b/Modules/Visualization/MonteverdiGui/src/mvdImageViewWidget.cxx index 6acda526b30902f8559f7ad1215f5b9d88d81216..1afaf36d82892653ff8b36ca07d7921b3df7ccf3 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdImageViewWidget.cxx +++ b/Modules/Visualization/MonteverdiGui/src/mvdImageViewWidget.cxx @@ -335,8 +335,10 @@ ImageViewWidget ::Initialize( AbstractImageViewManipulator* manipulator, AbstractImageViewRenderer* renderer ) { +#if OTB_DEBUG // Test OpenGL. ListGlVersions(); +#endif // Accept drops setAcceptDrops( true ); @@ -1371,6 +1373,28 @@ ImageViewWidget } } +void ImageViewWidget +::OnResetEffectsRequested() +{ + StackedLayerModel * layerStack = m_Renderer->GetLayerStack(); + + for( StackedLayerModel::ConstIterator it( layerStack->Begin() ); + it!=layerStack->End(); + ++it ) + { + if( it->second->inherits( VectorImageModel::staticMetaObject.className() ) ) + { + VectorImageModel * imageModel = + qobject_cast< VectorImageModel * >( it->second ); + + VectorImageSettings & settings = imageModel->GetSettings(); + settings.SetEffect( EFFECT_NORMAL ); + } + } + + emit ModelUpdated(); +} + /******************************************************************************/ void ImageViewWidget diff --git a/Modules/Visualization/MonteverdiGui/src/mvdImportImagesDialog.cxx b/Modules/Visualization/MonteverdiGui/src/mvdImportImagesDialog.cxx index 73b848ba0e894d9d3c03a1887d53a654ea2fbadf..76614c96afe42b8193043a8d8cd58f450f061bdc 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdImportImagesDialog.cxx +++ b/Modules/Visualization/MonteverdiGui/src/mvdImportImagesDialog.cxx @@ -222,28 +222,39 @@ ImportImagesDialog I18nCoreApplication::SETTINGS_KEY_OVERVIEWS_SIZE ) ); - - count = - builder->CountResolutions( - 2, - value.isValid() - ? value.toInt() - : OVERVIEWS_SIZE_DEFAULT - ); + unsigned int threshold = + value.isValid() ? value.toInt() : OVERVIEWS_SIZE_DEFAULT; + + otb::GDALOverviewsBuilder::SizeVector ovrSizes; + builder->SetResolutionFactor(2); + // Count all resolution with minimum size 1 (the high requested count is + // clamped by the builder) + builder->ListResolutions(ovrSizes, 2, 9999); + // Count the number of levels with a least 1 size larger than the default size + for (unsigned int k=0 ; k<ovrSizes.size() ; k++) + { + if (std::max(ovrSizes[k][0],ovrSizes[k][1]) >= threshold) + count++; + else + break; + } } if( builder->GetOverviewsCount()>0 ) builder->SetBypassEnabled( true ); - else + else if (count>1) { flags |= Qt::ItemIsEnabled; - builder->SetBypassEnabled( count<=1 ); + builder->SetBypassEnabled( false ); ++ m_EffectiveCount; } + else + { + builder->SetBypassEnabled(true); + } - builder->SetResolutionFactor( 2 ); builder->SetNbResolutions( count ); builder->SetResamplingMethod( otb::GDAL_RESAMPLING_AVERAGE ); builder->SetCompressionMethod( otb::GDAL_COMPRESSION_NONE ); diff --git a/Modules/Visualization/MonteverdiGui/src/mvdLayerStackController.cxx b/Modules/Visualization/MonteverdiGui/src/mvdLayerStackController.cxx index f5fe47211f4a4aa9b3b5c2f7d899f7b36117385b..be683a5dc8cac82855e5bf7f4759f005e993f74c 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdLayerStackController.cxx +++ b/Modules/Visualization/MonteverdiGui/src/mvdLayerStackController.cxx @@ -220,6 +220,14 @@ LayerStackController this, SIGNAL( ApplyAllRequested() ) ); + + QObject::connect( + widget, + SIGNAL( ResetEffectsButtonClicked() ), + // to: + this, + SIGNAL( ResetEffectsRequested() ) + ); } /*******************************************************************************/ @@ -351,6 +359,14 @@ LayerStackController this, SIGNAL( ApplyAllRequested() ) ); + + QObject::disconnect( + widget, + SIGNAL( ResetEffectsButtonClicked() ), + // to: + this, + SIGNAL( ResetEffectsRequested() ) + ); } /*******************************************************************************/ @@ -389,6 +405,8 @@ LayerStackController widget->SetMoveEnabled( model->GetCount()>1 ); widget->SetApplyEnabled( model->GetCount()>1 ); + + widget->SetResetEffectsEnabled( !model->IsEmpty() ); } /*******************************************************************************/ diff --git a/Modules/Visualization/MonteverdiGui/src/mvdLayerStackItemModel.cxx b/Modules/Visualization/MonteverdiGui/src/mvdLayerStackItemModel.cxx index 83a0805f05abf8df079bddd923fd0b9dca66983b..fd626710b0d542a1f2348218a21a006bc49445c5 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdLayerStackItemModel.cxx +++ b/Modules/Visualization/MonteverdiGui/src/mvdLayerStackItemModel.cxx @@ -67,8 +67,8 @@ HEADERS[ LayerStackItemModel::COLUMN_COUNT ] = QT_TRANSLATE_NOOP( "mvd::LayerStackItemModel", "Res" ), QT_TRANSLATE_NOOP( "mvd::LayerStackItemModel", "Name" ), QT_TRANSLATE_NOOP( "mvd::LayerStackItemModel", "Effect" ), - QT_TRANSLATE_NOOP( "mvd::LayerStackItemModel", "I" ), - QT_TRANSLATE_NOOP( "mvd::LayerStackItemModel", "J" ), + QT_TRANSLATE_NOOP( "mvd::LayerStackItemModel", "Column" ), + QT_TRANSLATE_NOOP( "mvd::LayerStackItemModel", "Line" ), QT_TRANSLATE_NOOP( "mvd::LayerStackItemModel", "Red" ), QT_TRANSLATE_NOOP( "mvd::LayerStackItemModel", "Green" ), QT_TRANSLATE_NOOP( "mvd::LayerStackItemModel", "Blue" ), @@ -683,7 +683,8 @@ LayerStackItemModel // qDebug() // << this << "::index(" << row << "," << column << "," << parent << ")"; - assert( m_StackedLayerModel!=NULL ); + if (m_StackedLayerModel == NULL) + return QModelIndex(); // qDebug() // << "index:" << row << "," << column << "," << m_StackedLayerModel->At( row ); diff --git a/Modules/Visualization/MonteverdiGui/src/mvdLayerStackWidget.cxx b/Modules/Visualization/MonteverdiGui/src/mvdLayerStackWidget.cxx index c52a9fea19f5e326b5b14fd5dd399d54d81075d4..4e1e163f443c1692b291f3ef650f031d7862a47d 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdLayerStackWidget.cxx +++ b/Modules/Visualization/MonteverdiGui/src/mvdLayerStackWidget.cxx @@ -166,6 +166,14 @@ LayerStackWidget this, SIGNAL( ApplyButtonClicked() ) ); + + QObject::connect( + m_UI->resetEffectsButton, + SIGNAL( clicked() ), + // to: + this, + SIGNAL( ResetEffectsButtonClicked() ) + ); } /*******************************************************************************/ @@ -403,6 +411,18 @@ LayerStackWidget m_UI->reloadButton->setEnabled( enabled ); } +/*******************************************************************************/ +void +LayerStackWidget +::SetResetEffectsEnabled( bool enabled ) +{ + assert( m_UI!=NULL ); + + assert( m_UI->reloadButton!=NULL ); + + m_UI->resetEffectsButton->setEnabled( enabled ); +} + /*******************************************************************************/ /* SLOTS */ /*******************************************************************************/ diff --git a/Modules/Visualization/MonteverdiGui/src/mvdLayerStackWidget.ui b/Modules/Visualization/MonteverdiGui/src/mvdLayerStackWidget.ui index 3e769442f6ebe8436d66bc15d6310f253e7a24e9..96f5c15ebc7868902d2c32a573040f7ff93fdea3 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdLayerStackWidget.ui +++ b/Modules/Visualization/MonteverdiGui/src/mvdLayerStackWidget.ui @@ -56,7 +56,7 @@ <string/> </property> <property name="icon"> - <iconset resource="../../Application/Monteverdi/mvdMainWindow.qrc"> + <iconset> <normaloff>:/icons/action_LayerTop_Icon</normaloff>:/icons/action_LayerTop_Icon</iconset> </property> </widget> @@ -73,7 +73,7 @@ <string/> </property> <property name="icon"> - <iconset resource="../../Application/Monteverdi/mvdMainWindow.qrc"> + <iconset> <normaloff>:/icons/action_LayerUp_Icon</normaloff>:/icons/action_LayerUp_Icon</iconset> </property> </widget> @@ -90,7 +90,7 @@ <string/> </property> <property name="icon"> - <iconset resource="../../Application/Monteverdi/mvdMainWindow.qrc"> + <iconset> <normaloff>:/icons/action_LayerDown_Icon</normaloff>:/icons/action_LayerDown_Icon</iconset> </property> </widget> @@ -107,7 +107,7 @@ <string/> </property> <property name="icon"> - <iconset resource="../../Application/Monteverdi/mvdMainWindow.qrc"> + <iconset> <normaloff>:/icons/action_LayerBottom_Icon</normaloff>:/icons/action_LayerBottom_Icon</iconset> </property> </widget> @@ -124,7 +124,7 @@ <string/> </property> <property name="icon"> - <iconset resource="../../Application/Monteverdi/mvdMainWindow.qrc"> + <iconset> <normaloff>:/icons/action_LayerProjection_Icon</normaloff>:/icons/action_LayerProjection_Icon</iconset> </property> </widget> @@ -141,7 +141,7 @@ <string/> </property> <property name="icon"> - <iconset resource="../../Application/Monteverdi/mvdMainWindow.qrc"> + <iconset> <normaloff>:/icons/action_ApplyAll_Icon</normaloff>:/icons/action_ApplyAll_Icon</iconset> </property> </widget> @@ -158,7 +158,7 @@ <string/> </property> <property name="icon"> - <iconset resource="../../Application/Monteverdi/mvdMainWindow.qrc"> + <iconset> <normaloff>:/icons/action_Reload_Icon</normaloff>:/icons/action_Reload_Icon</iconset> </property> </widget> @@ -180,19 +180,16 @@ </spacer> </item> <item> - <widget class="QToolButton" name="deleteAllButton"> + <widget class="QToolButton" name="resetEffectsButton"> <property name="toolTip"> - <string>Delete all layers</string> - </property> - <property name="locale"> - <locale language="C" country="AnyCountry"/> + <string>Reset all layer effects to Normal</string> </property> <property name="text"> <string/> </property> <property name="icon"> - <iconset resource="../../Application/Monteverdi/mvdMainWindow.qrc"> - <normaloff>:/icons/action_LayerDeleteAll_Icon</normaloff>:/icons/action_LayerDeleteAll_Icon</iconset> + <iconset resource="mvdIcons.qrc"> + <normaloff>:/Utilities/Data/Icons/edit-clear.png</normaloff>:/Utilities/Data/Icons/edit-clear.png</iconset> </property> </widget> </item> @@ -208,17 +205,35 @@ <string/> </property> <property name="icon"> - <iconset resource="../../Application/Monteverdi/mvdMainWindow.qrc"> + <iconset> <normaloff>:/icons/action_LayerDelete_Icon</normaloff>:/icons/action_LayerDelete_Icon</iconset> </property> </widget> </item> + <item> + <widget class="QToolButton" name="deleteAllButton"> + <property name="toolTip"> + <string>Delete all layers</string> + </property> + <property name="locale"> + <locale language="C" country="AnyCountry"/> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>:/icons/action_LayerDeleteAll_Icon</normaloff>:/icons/action_LayerDeleteAll_Icon</iconset> + </property> + </widget> + </item> </layout> </item> </layout> </widget> <resources> <include location="../../Application/Monteverdi/mvdMainWindow.qrc"/> + <include location="mvdIcons.qrc"/> </resources> <connections/> </ui> diff --git a/Modules/Visualization/MonteverdiGui/src/mvdShaderWidget.cxx b/Modules/Visualization/MonteverdiGui/src/mvdShaderWidget.cxx index f7bfd139e7c2fefa0c4e54d8b393725544082f8d..706c6670690c105ec40ebb99e6c47e26e9bd21c5 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdShaderWidget.cxx +++ b/Modules/Visualization/MonteverdiGui/src/mvdShaderWidget.cxx @@ -40,8 +40,8 @@ // // Monteverdi includes (sorted by alphabetic order) #include "mvdAlgorithm.h" -#include "mvdImageSettings.h" #include "mvdGui.h" +#include "mvdVectorImageSettings.h" namespace mvd { @@ -117,18 +117,24 @@ ShaderWidget void ShaderWidget ::SetGLSL140Enabled( bool isGLSLEnabled ) +{ + SetEffectVisible(EFFECT_GRADIENT,isGLSLEnabled); +} + +void ShaderWidget +::SetEffectVisible(const Effect & effect, bool visible) { assert( qApp!=NULL ); int index = m_UI->effectComboBox->findText( - qApp->translate( "mvd", EFFECT_NAMES[ EFFECT_GRADIENT ] ) + qApp->translate( "mvd", EFFECT_NAMES[ effect ] ) ); - if( isGLSLEnabled ) + if( visible ) { if( index<0 ) - m_UI->effectComboBox->addItem( tr( "mvd", EFFECT_NAMES[ EFFECT_GRADIENT ] ) ); + m_UI->effectComboBox->addItem( qApp->translate( "mvd", EFFECT_NAMES[ effect ] ) ); } else if( index>=0 ) m_UI->effectComboBox->removeItem( index ); @@ -185,6 +191,14 @@ ShaderWidget ); m_UI->valueLineEdit->setCursorPosition( 0 ); } + + VectorImageSettings * vis = dynamic_cast<VectorImageSettings*>(settings); + + if(vis!=NULL) + { + GrayscaleActivated(vis->IsGrayscaleActivated()); + } + } /*******************************************************************************/ @@ -275,4 +289,21 @@ ShaderWidget emit SettingsChanged(); } + +void ShaderWidget +::GrayscaleActivated(bool status) +{ + SetEffectVisible(EFFECT_LUT_JET,status); + SetEffectVisible(EFFECT_LUT_LOCAL_JET,status); + SetEffectVisible(EFFECT_LUT_HOT,status); + SetEffectVisible(EFFECT_LUT_LOCAL_HOT,status); + SetEffectVisible(EFFECT_LUT_WINTER,status); + SetEffectVisible(EFFECT_LUT_LOCAL_WINTER,status); + SetEffectVisible(EFFECT_LUT_SUMMER,status); + SetEffectVisible(EFFECT_LUT_LOCAL_SUMMER,status); + SetEffectVisible(EFFECT_LUT_COOL,status); + SetEffectVisible(EFFECT_LUT_LOCAL_COOL,status); + SetEffectVisible(EFFECT_SPECTRAL_ANGLE,!status); +} + } // end namespace 'mvd' diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h index 3b97b246a9b1431de56ddf4b3483b6befad1d1e8..90d0a226651b8dbdbc39dd6707ddd7e89a53d5ea 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h @@ -24,6 +24,7 @@ #include "otbWrapperParameterGroup.h" #include "itkLogger.h" +#include "itkTimeProbe.h" #include "otbWrapperMacros.h" #include "otbWrapperInputImageParameter.h" #include "otbWrapperInputImageListParameter.h" @@ -124,9 +125,9 @@ public: ParameterGroup* GetParameterList(); /* Get the internal application parameter specified - * + * if the follow flag is on, the function returns the target of proxy parameters * WARNING: this method may disappear from the API */ - Parameter* GetParameterByKey(std::string parameter); + Parameter* GetParameterByKey(std::string parameter, bool follow=true); /* Get the internal application parameter specified * @@ -171,10 +172,6 @@ public: * or a value set externally by user */ bool HasValue(std::string paramKey) const; - /* Activate or deactivate the bool parameter - */ - void SetParameterEmpty(std::string paramKey, bool active); - /* Get active flag of parameter with key paramKey */ bool GetParameterEmpty(std::string paramKey); @@ -203,13 +200,6 @@ public: */ /* Set the Parameter value and Update the UserFlag. used by xml parameter */ - void SetParameterInt(std::string parameter, int value, bool hasUserValueFlag); - void SetParameterFloat(std::string parameter, float value, bool hasUserValueFlag); - void SetParameterString(std::string parameter, std::string value, bool hasUserValueFlag); - void SetParameterStringList(std::string parameter, std::vector<std::string> values, bool hasUserValueFlag); - void SetParameterEmpty(std::string parameter, bool value, bool hasUserValueFlag); - - bool IsApplicationReady(); /* Set an integer value * @@ -219,14 +209,48 @@ public: * \li ParameterType_Radius * \li ParameterType_Choice */ - void SetParameterInt(std::string parameter, int value); + void SetParameterInt(std::string parameter, int value, bool hasUserValueFlag = true); /* Set a floating value * * Can be called for types : * \li ParameterType_Float */ - void SetParameterFloat(std::string parameter, float value); + void SetParameterFloat(std::string parameter, float value, bool hasUserValueFlag = true); + + /* Set a string value + * + * Can be called for types : + * \li ParameterType_InputImageListParameter + * \li ParameterType_InputVectorDataListParameter + * \li ParameterType_InputFilenameListParameter + * \li ParameterType_StringList + */ + void SetParameterString(std::string parameter, std::string value, bool hasUserValueFlag = true); + + /* Set a string value + * + * Can be called for types : + * \li ParameterType_String + * \li ParameterType_InputFilename + * \li ParameterType_OutputFilename + * \li ParameterType_Directory + * \li ParameterType_Choice + * \li ParameterType_Float + * \li ParameterType_Int + * \li ParameterType_Radius + * \li ParameterType_InputImageParameter + * \li ParameterType_InputComplexImageParameter + * \li ParameterType_InputVectorDataParameter + * \li ParameterType_OutputImageParameter + * \li ParameterType_OutputVectorDataParameter + */ + void SetParameterStringList(std::string parameter, std::vector<std::string> values, bool hasUserValueFlag = true); + + void SetParameterEmpty(std::string parameter, bool value, bool hasUserValueFlag = true); + + bool IsApplicationReady(); + /* Set an default integer value, must used in the * DoInit when setting a value by default @@ -299,34 +323,15 @@ public: */ void SetMaximumParameterFloatValue(std::string parameter, float value); - /* Set a string value - * - * Can be called for types : - * \li ParameterType_String - * \li ParameterType_InputFilename - * \li ParameterType_OutputFilename - * \li ParameterType_Directory - * \li ParameterType_Choice - * \li ParameterType_Float - * \li ParameterType_Int - * \li ParameterType_Radius - * \li ParameterType_InputImageParameter - * \li ParameterType_InputComplexImageParameter - * \li ParameterType_InputVectorDataParameter - * \li ParameterType_OutputImageParameter - * \li ParameterType_OutputVectorDataParameter - */ - void SetParameterString(std::string parameter, std::string value); - /* Set a string value - * - * Can be called for types : - * \li ParameterType_InputImageListParameter - * \li ParameterType_InputVectorDataListParameter - * \li ParameterType_InputFilenameListParameter - * \li ParameterType_StringList + /** + * Enable single selection mode for list view if status in true + * (default is false). + * + * Can be called for types: + * \li ParameterType_ListView */ - void SetParameterStringList(std::string parameter, std::vector<std::string> value); + void SetListViewSingleSelectionMode(std::string parameter, bool status); /* Set an output image value * @@ -472,6 +477,34 @@ public: */ void SetNthParameterInputImageList(std::string parameter, const unsigned int &id, InputImageListParameter::ImageBaseType * img); +/** + * Add a value to a parameter list as a string + * + * Can be called for parameter types: + * \li ParameterType_InputImageList + * + * \in parameter The parameter key + * \in str The string + * \throw itk::Exception if parameter is not found or not an + * InputImageList parameter + */ + void AddParameterStringList(std::string parameter, const std::string & str); + + /** + * Set the nth value of a parameter list as a string. + * + * Can be called for parameter types: + * \li ParameterType_InputImageList + * + * \in parameter The parameter key + * \in id Position at which to set the ImageBase pointer + * \in str The string + * \throw itk::Exception if parameter is not found or not an + * InputImageList parameter or if id is out of bounds + */ + void SetNthParameterStringList(std::string parameter, const unsigned int &id, const std::string& str); + + /** * Clear all images from an InputImageList parameter. * @@ -737,6 +770,8 @@ public: m_IsInXMLParsed = false; } + double GetLastExecutionTiming() const; + protected: /** Constructor */ Application(); @@ -898,6 +933,9 @@ private: /** Tags that define the application (ex : segmentation, OBIA).*/ std::vector<std::string> m_DocTags; + /** Chrono to measure execution time */ + itk::TimeProbe m_Chrono; + //rashad:: controls adding of -xml parameter. set to true by default bool m_HaveInXML; bool m_HaveOutXML; diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperCompositeApplication.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperCompositeApplication.h new file mode 100644 index 0000000000000000000000000000000000000000..7c7bfa3ae3e05c144fdcd74dae3896bc7dcd6341 --- /dev/null +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperCompositeApplication.h @@ -0,0 +1,158 @@ +/*========================================================================= + + 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 otbWrapperCompositeApplication_h +#define otbWrapperCompositeApplication_h + +#include "otbWrapperApplication.h" +#include "itkStdStreamLogOutput.h" + +namespace otb +{ +namespace Wrapper +{ + +/** \class CompositeApplication + * \brief This class is a base class for composite applications + * + * This class allows to create & store internal applications with the same logic + * as parameters. You choose the application type to create, you choose an + * identifier (alphanumeric string), and you can give a short description. + * Later, you will refer to this application using the identifier. In the + * functions of this class, you can refer to parameters from internal + * applications by using their identifier as prefix. For instance, "app1.in" + * will refer to parameter "in" from internal application named "app1" + * (if such application exists, if not it will refer to a parameter of this + * composite application). + * + * \ingroup OTBApplicationEngine + */ +class OTBApplicationEngine_EXPORT CompositeApplication: public Application +{ +public: + /** Standard class typedefs. */ + typedef CompositeApplication Self; + typedef Application Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** RTTI support */ + itkTypeMacro(CompositeApplication, Application); + + /** Filters typedef */ + typedef itk::MemberCommand< Self > AddProcessCommandType; + + typedef struct + { + Application::Pointer App; + std::string Desc; + } InternalApplication; + + typedef std::map<std::string, InternalApplication> InternalAppContainer; + +protected: + /** Constructor */ + CompositeApplication(); + + /** Destructor */ + ~CompositeApplication() ITK_OVERRIDE; + + /** + * Callback function to retrieve the process watchers on internal filters + */ + void LinkWatchers(itk::Object * itkNotUsed(caller), const itk::EventObject & event); + + /** + * Method to instanciate and register a new internal application + * \param appType Type of the application to instanciate + * \param key Identifier associated to the created application + * \param desc Description of the internal application + */ + bool AddApplication(std::string appType, std::string key, std::string desc); + + /** + * Method to remove all internal applications. Application deriving from + * CompositeApplication should call this method at the beginning of their + * DoInit(). + */ + void ClearApplications(); + + /** + * Connect two existing parameters together. The first parameter will point to + * the second parameter. + */ + bool Connect(std::string fromKey, std::string toKey); + + /** + * Share a parameter between the composite application and an internal application + * The local parameter is created as a proxy to the internal parameter. + * \param localKey New parameter key in the composite application + * \param internalKey Key to the internal parameter to expose + * \param name Name for the local parameter, if empty the target's name is used + * \param desc Description for the local parameter, if empty the target's description is used + */ + bool ShareParameter(std::string localKey, + std::string internalKey, + std::string name = std::string(), + std::string desc = std::string()); + + /** + * Decode a key to extract potential prefix for internal applications + * If a valid prefix (corresponding to an internal app) is found: + * - prefix is removed from the input key which is altered. + * - the function returns a pointer to the internal application + * If no valid prefix is found, the input key is not modified, and the + * function returns 'this'. + */ + Application* DecodeKey(std::string &key); + + /** + * Get the internal application with the given identifier + */ + Application* GetInternalApplication(std::string id); + + /** + * Get the description of an internal application + */ + std::string GetInternalAppDescription(std::string id); + + /** + * Utility function to call Execute() on an internal app and get its output logs + */ + void ExecuteInternal(std::string key); + + /** + * Utility function to call UpdateParameters() on an internal app + */ + void UpdateInternalParameters(std::string key); + +private: + CompositeApplication(const CompositeApplication &); //purposely not implemented + void operator =(const CompositeApplication&); //purposely not implemented + + InternalAppContainer m_AppContainer; + + itk::StdStreamLogOutput::Pointer m_LogOutput; + + std::ostringstream m_Oss; + + AddProcessCommandType::Pointer m_AddProcessCommand; +}; + +} +} +#endif diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperListViewParameter.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperListViewParameter.h index 5423377f05acedca711c639389b2bcd15fb18571..15f46725ac115104b92eb930623e95550199bae8 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperListViewParameter.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperListViewParameter.h @@ -50,6 +50,10 @@ public: /** RTTI support */ itkTypeMacro(ListViewParameter, Parameter); + itkSetMacro(SingleSelection,bool); + itkGetMacro(SingleSelection,bool); + itkBooleanMacro(SingleSelection); + /** Add a value to the choice */ void AddChoice( std::string choicekey, std::string choiceName ); @@ -92,24 +96,10 @@ public: std::vector<int> GetSelectedItems() { - if( m_SelectedNames.size() != 0 ) - { - this->SetSelectedItemsByNames(); - } - else if( m_SelectedKeys.size() != 0 ) - { - this->SetSelectedItemsByKeys(); - } - return m_SelectedItems; } - void SetSelectedNames(std::vector<std::string> selectedNames) - { - m_SelectedNames = selectedNames; - m_SelectedItems.clear(); - m_SelectedKeys.clear(); - } + void SetSelectedNames(std::vector<std::string> selectedNames); std::vector<std::string> GetSelectedNames() { @@ -117,22 +107,21 @@ public: } - void SetSelectedKeys(std::vector<std::string> selectedKeys) - { - m_SelectedKeys = selectedKeys; - m_SelectedItems.clear(); - m_SelectedNames.clear(); - } + void SetSelectedKeys(std::vector<std::string> selectedKeys); std::vector<std::string> GetSelectedKeys() { return m_SelectedKeys; } - /** Set selected items using a lit of selected keys. */ - void SetSelectedItemsByKeys(); - /** Set selected items using a lit of selected names. */ - void SetSelectedItemsByNames(); + /** Set selected items using a lit of selected keys. + * OBSOLETE : this method is not needed anymore and does nothing. */ + void SetSelectedItemsByKeys(){} + + /** Set selected items using a lit of selected names. + * OBSOLETE : this method is not needed anymore and does nothing. */ + void SetSelectedItemsByNames(){} + void SetSelectedItems(std::vector<std::string> selectedItems) { std::vector<int> items; @@ -140,14 +129,22 @@ public: { items.push_back( atoi( selectedItems[i].c_str() ) ); } - m_SelectedItems = items; - m_SelectedNames.clear(); - m_SelectedKeys.clear(); + this->SetSelectedItems(items); } void SetSelectedItems(std::vector<int> selectedItems) { m_SelectedItems = selectedItems; + m_SelectedNames.clear(); + m_SelectedKeys.clear(); + // update selected names and keys + std::vector<std::string> names = this->GetChoiceNames(); + std::vector<std::string> keys = this->GetChoiceKeys(); + for (unsigned int i=0 ; i<m_SelectedItems.size() ; i++) + { + m_SelectedNames.push_back(names[m_SelectedItems[i]]); + m_SelectedKeys.push_back(keys[m_SelectedItems[i]]); + } } protected: @@ -171,6 +168,7 @@ protected: std::vector<int> m_SelectedItems; std::vector<std::string> m_SelectedKeys; std::vector<std::string> m_SelectedNames; + bool m_SingleSelection; private: ListViewParameter(const ListViewParameter &); //purposely not implemented diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputImageParameter.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputImageParameter.h index 25eedebf631ce507c6c6b603ba7cee8bf3322db1..b4a8102db2110217aac752add482e783babc5e84 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputImageParameter.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputImageParameter.h @@ -104,6 +104,8 @@ public: void InitializeWriters(); + std::string CheckFileName(bool fixMissingExtension = false); + protected: /** Constructor */ OutputImageParameter(); diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputProcessXMLParameter.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputProcessXMLParameter.h index 73fec0535a1256a116840a22a709050339302f0b..526e2274ec5a8f7110fb6c1fa8a715fa7c93dff3 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputProcessXMLParameter.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputProcessXMLParameter.h @@ -67,6 +67,8 @@ public: void Write(Application::Pointer application); + TiXmlElement* ParseApplication(Application::Pointer app); + protected: OutputProcessXMLParameter(); diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameterGroup.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameterGroup.h index fb395b439c68f70701676b16665fde8443032dd1..5aea541604912424fcec62ed5319ed33976d0162 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameterGroup.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameterGroup.h @@ -47,6 +47,10 @@ public: void AddParameter(Parameter::Pointer p); + /** Method to substitute a parameter in a group. + * The function returns true on success, false on failure */ + bool ReplaceParameter(std::string &key, Parameter::Pointer p); + /** Add a new choice value to an existing choice parameter */ void AddChoice(std::string paramKey, std::string paramName); @@ -61,9 +65,9 @@ public: * or the path to a choice value */ void AddParameter(ParameterType type, std::string paramKey, std::string paramName); - Parameter::Pointer GetParameterByIndex(unsigned int i); + Parameter::Pointer GetParameterByIndex(unsigned int i, bool follow=true); - Parameter::Pointer GetParameterByKey(std::string name); + Parameter::Pointer GetParameterByKey(std::string name, bool follow=true); /** rashad: Add xml parameters eg: -inxml -outxml */ void AddInXMLParameter(); @@ -93,6 +97,10 @@ public: return true; } + /** Resolve potential proxy parameters by following their targets until + * a non-proxy parameter. It will detect cycles and report an error */ + static Parameter* ResolveParameter(Parameter *param); + protected: ParameterGroup(); ~ParameterGroup() ITK_OVERRIDE; diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameterKey.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameterKey.h index 9237eac957c3c01d49c5e999fc1e81d1339532ce..3dac6f317a43e00b8c1bb7d74b01944e0f20c9c1 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameterKey.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameterKey.h @@ -103,7 +103,9 @@ last() : return "tata" } else { - itkGenericExceptionMacro( "Invalid key "<<val<<". Must be in lowercase, containing alphanumerical characters or \".\""); + itkGenericExceptionMacro( "Invalid key '" + << val << + "'. Must be in lowercase, containing alphanumerical characters or \".\""); } } diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperProxyParameter.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperProxyParameter.h new file mode 100644 index 0000000000000000000000000000000000000000..ea16db09d0e8ab7c7587cecdeca187a27870a697 --- /dev/null +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperProxyParameter.h @@ -0,0 +1,71 @@ +#ifndef otbWrapperProxyParameter_h +#define otbWrapperProxyParameter_h + +#include "itkObject.h" +#include "otbWrapperParameter.h" +#include <utility> + +namespace otb +{ +namespace Wrapper +{ +/** + * \class ProxyParameter + * + * \brief Parameter class acting as a proxy to a different parameter + * + * The target parameter of this proxy is defined as a pair of a group parameter + * containing the target and the targets key. It allows to define proxies on + * parameters that may be themselves replaced by a proxy + * + * \ingroup OTBApplicationEngine + */ +class ProxyParameter : public Parameter +{ +public: + typedef ProxyParameter Self; + typedef Parameter Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + itkNewMacro(Self); + + itkTypeMacro(ProxyParameter, Parameter); + + typedef std::pair<Parameter::Pointer, std::string> ProxyTargetType; + + /** Set the target parameter of the proxy + * \param target pair of a group parameter containing the target and its key + */ + void SetTarget(const ProxyTargetType& target) + { + m_Target = target; + } + + /** Get the target parameter of the proxy + * First part is the group parameter containing the target + * Second part is the key of the target */ + const ProxyTargetType & GetTarget(void) + { + return m_Target; + } + +protected: + ProxyParameter() {} + ~ProxyParameter() ITK_OVERRIDE {} + +private: + ProxyParameter(const Self &); //purposely not implemented + void operator =(const Self&); //purposely not implemented + + ProxyTargetType m_Target; +}; + +} +} + +//#ifndef OTB_MANUAL_INSTANTIATION +//#include "otbWrapperProxyParameter.txx" +//#endif + +#endif diff --git a/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt b/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt index 6d11c565ee8af5638682141dc0a8f911369203b5..c33fdbcdc04cf938d179a35c29271ffb39ce9e1b 100644 --- a/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt +++ b/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt @@ -27,6 +27,7 @@ set(OTBApplicationEngine_SRC otbWrapperChoiceParameter.cxx otbWrapperApplicationRegistry.cxx otbWrapperApplicationFactoryBase.cxx + otbWrapperCompositeApplication.cxx ) add_library(OTBApplicationEngine ${OTBApplicationEngine_SRC}) diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx index 0ab8e27f8ca12f727a1b18f11262e90c7d5afc9b..6a8a8795a44c47bedf99e1a60ac914fb9cc398a3 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx @@ -32,6 +32,7 @@ #include "otbWrapperInputImageListParameter.h" #include "otbWrapperInputProcessXMLParameter.h" #include "otbWrapperRAMParameter.h" +#include "otbWrapperProxyParameter.h" #include "otbWrapperAddProcessToWatchEvent.h" @@ -97,37 +98,192 @@ ParameterGroup* Application::GetParameterList() return m_ParameterList; } -Parameter* Application::GetParameterByKey(std::string name) +Parameter* Application::GetParameterByKey(std::string name, bool follow) { - return GetParameterList()->GetParameterByKey(name); + return GetParameterList()->GetParameterByKey(name, follow); } void Application::SetParameterInt(std::string parameter, int value, bool hasUserValueFlag) { - this->SetParameterInt(parameter, value); + Parameter* param = GetParameterByKey(parameter); + + if (dynamic_cast<IntParameter*>(param)) + { + IntParameter* paramInt = dynamic_cast<IntParameter*>(param); + paramInt->SetValue(value); + } + else if (dynamic_cast<FloatParameter*>(param)) + { + FloatParameter* paramFloat = dynamic_cast<FloatParameter*>(param); + paramFloat->SetValue(static_cast<float>(value)); + } + else if (dynamic_cast<RadiusParameter*>(param)) + { + RadiusParameter* paramRadius = dynamic_cast<RadiusParameter*>(param); + paramRadius->SetValue(static_cast<unsigned int>(value)); + } + else if (dynamic_cast<ChoiceParameter*>(param)) + { + ChoiceParameter* paramChoice = dynamic_cast<ChoiceParameter*>(param); + paramChoice->SetValue(value); + } + this->SetParameterUserValue(parameter, hasUserValueFlag); } void Application::SetParameterFloat(std::string parameter, float value, bool hasUserValueFlag) { - this->SetParameterFloat(parameter, value); + Parameter* param = GetParameterByKey(parameter); + + if (dynamic_cast<FloatParameter*>(param)) + { + FloatParameter* paramFloat = dynamic_cast<FloatParameter*>(param); + paramFloat->SetValue(value); + } + this->SetParameterUserValue(parameter, hasUserValueFlag); } void Application::SetParameterString(std::string parameter, std::string value, bool hasUserValueFlag) { - this->SetParameterString(parameter, value); + Parameter* param = GetParameterByKey(parameter); + + if (dynamic_cast<ChoiceParameter*>(param)) + { + ChoiceParameter* paramDown = dynamic_cast<ChoiceParameter*>(param); + paramDown->SetValue(value); + } + else if (dynamic_cast<ListViewParameter*>(param)) + { + ListViewParameter* paramDown = dynamic_cast<ListViewParameter*>(param); + paramDown->SetValue(value); + } + else if (dynamic_cast<StringParameter*>(param)) + { + StringParameter* paramDown = dynamic_cast<StringParameter*>(param); + paramDown->SetValue(value); + } + else if (dynamic_cast<InputFilenameParameter*>(param)) + { + InputFilenameParameter* paramDown = dynamic_cast<InputFilenameParameter*>(param); + paramDown->SetValue(value); + } + else if (dynamic_cast<OutputFilenameParameter*>(param)) + { + OutputFilenameParameter* paramDown = dynamic_cast<OutputFilenameParameter*>(param); + paramDown->SetValue(value); + } + else if (dynamic_cast<DirectoryParameter*>(param)) + { + DirectoryParameter* paramDown = dynamic_cast<DirectoryParameter*>(param); + paramDown->SetValue(value); + } + else if (dynamic_cast<FloatParameter*>(param)) + { + FloatParameter* paramDown = dynamic_cast<FloatParameter*>(param); + paramDown->SetValue(value); + } + else if (dynamic_cast<RadiusParameter*>(param)) + { + RadiusParameter* paramDown = dynamic_cast<RadiusParameter*>(param); + paramDown->SetValue(value); + } + else if (dynamic_cast<IntParameter*>(param)) + { + IntParameter* paramDown = dynamic_cast<IntParameter*>(param); + paramDown->SetValue(value); + } + else if (dynamic_cast<InputImageParameter*>(param)) + { + InputImageParameter* paramDown = dynamic_cast<InputImageParameter*>(param); + if ( !paramDown->SetFromFileName(value) ) + otbAppLogCRITICAL( <<"Invalid image filename " << value <<"."); + + } + else if (dynamic_cast<ComplexInputImageParameter*>(param)) + { + ComplexInputImageParameter* paramDown = dynamic_cast<ComplexInputImageParameter*>(param); + paramDown->SetFromFileName(value); + } + else if (dynamic_cast<InputVectorDataParameter*>(param)) + { + InputVectorDataParameter* paramDown = dynamic_cast<InputVectorDataParameter*>(param); + if ( !paramDown->SetFromFileName(value) ) + otbAppLogCRITICAL( <<"Invalid vector data filename " << value <<"."); + } + else if (dynamic_cast<OutputImageParameter*>(param)) + { + OutputImageParameter* paramDown = dynamic_cast<OutputImageParameter*>(param); + paramDown->SetFileName(value); + } + else if (dynamic_cast<ComplexOutputImageParameter*>(param)) + { + ComplexOutputImageParameter* paramDown = dynamic_cast<ComplexOutputImageParameter*>(param); + paramDown->SetFileName(value); + } + else if (dynamic_cast<OutputVectorDataParameter*>(param)) + { + OutputVectorDataParameter* paramDown = dynamic_cast<OutputVectorDataParameter*>(param); + paramDown->SetFileName(value); + } + else if (dynamic_cast<RAMParameter*>(param)) + { + RAMParameter* paramDown = dynamic_cast<RAMParameter*>(param); + paramDown->SetValue(value); + } + else if (dynamic_cast<OutputProcessXMLParameter*>(param)) + { + OutputProcessXMLParameter* paramDown = dynamic_cast<OutputProcessXMLParameter*>(param); + paramDown->SetValue(value); + } + else if (dynamic_cast<InputProcessXMLParameter*>(param)) + { + InputProcessXMLParameter* paramDown = dynamic_cast<InputProcessXMLParameter*>(param); + if ( !paramDown->SetFileName(value) ) + otbAppLogCRITICAL( <<"Invalid XML parameter filename " << value <<"."); + } + this->SetParameterUserValue(parameter, hasUserValueFlag); } void Application::SetParameterStringList(std::string parameter, std::vector<std::string> values, bool hasUserValueFlag) { - this->SetParameterStringList(parameter, values); + Parameter* param = GetParameterByKey(parameter); + + if (dynamic_cast<InputImageListParameter*>(param)) + { + InputImageListParameter* paramDown = dynamic_cast<InputImageListParameter*>(param); + if( !paramDown->SetListFromFileName(values) ) + otbAppLogCRITICAL( <<"At least one image filename is invalid."); + } + else if (dynamic_cast<InputVectorDataListParameter*>(param)) + { + InputVectorDataListParameter* paramDown = dynamic_cast<InputVectorDataListParameter*>(param); + if( !paramDown->SetListFromFileName(values) ) + otbAppLogCRITICAL( <<"At least one vector data filename is invalid.."); + } + else if (dynamic_cast<InputFilenameListParameter*>(param)) + { + InputFilenameListParameter* paramDown = dynamic_cast<InputFilenameListParameter*>(param); + if( !paramDown->SetListFromFileName(values) ) + otbAppLogCRITICAL( <<"At least one filename is invalid.."); + } + else if (dynamic_cast<StringListParameter*>(param)) + { + StringListParameter* paramDown = dynamic_cast<StringListParameter*>(param); + paramDown->SetValue(values); + } + else if(dynamic_cast<ListViewParameter *>(param)) + { + ListViewParameter * paramDown = dynamic_cast<ListViewParameter *>(param); + paramDown->SetSelectedNames(values); + } + this->SetParameterUserValue(parameter, hasUserValueFlag); } void Application::SetParameterEmpty(std::string parameter, bool value, bool hasUserValueFlag) { - this->SetParameterEmpty(parameter, value); + GetParameterByKey(parameter)->SetActive(value); this->SetParameterUserValue(parameter, hasUserValueFlag); } @@ -227,6 +383,9 @@ int Application::Execute() int Application::ExecuteAndWriteOutput() { + m_Chrono.Reset(); + m_Chrono.Start(); + int status = this->Execute(); if (status == 0) @@ -269,6 +428,11 @@ int Application::ExecuteAndWriteOutput() if(outputParam!=ITK_NULLPTR) { outputParam->InitializeWriters(); + std::string checkReturn = outputParam->CheckFileName(true); + if (!checkReturn.empty()) + { + otbAppLogWARNING("Check filename : "<<checkReturn); + } if (useRAM) { outputParam->SetRAMValue(ram); @@ -329,6 +493,7 @@ int Application::ExecuteAndWriteOutput() this->AfterExecuteAndWriteOutputs(); + m_Chrono.Stop(); return status; } @@ -419,11 +584,6 @@ Role Application::GetParameterRole(std::string paramKey) const return GetParameterByKey(paramKey)->GetRole(); } -void Application::SetParameterEmpty(std::string paramKey, bool active) -{ - GetParameterByKey(paramKey)->SetActive(active); -} - bool Application::GetParameterEmpty(std::string paramKey) { return GetParameterByKey(paramKey)->GetActive(); @@ -578,42 +738,6 @@ std::vector<std::string> Application::GetChoiceNames(std::string name) itkExceptionMacro(<< name << " is not a choice parameter"); } -void Application::SetParameterInt(std::string parameter, int value) -{ - Parameter* param = GetParameterByKey(parameter); - - if (dynamic_cast<IntParameter*>(param)) - { - IntParameter* paramInt = dynamic_cast<IntParameter*>(param); - paramInt->SetValue(value); - } - else if (dynamic_cast<FloatParameter*>(param)) - { - FloatParameter* paramFloat = dynamic_cast<FloatParameter*>(param); - paramFloat->SetValue(static_cast<float>(value)); - } - else if (dynamic_cast<RadiusParameter*>(param)) - { - RadiusParameter* paramRadius = dynamic_cast<RadiusParameter*>(param); - paramRadius->SetValue(static_cast<unsigned int>(value)); - } - else if (dynamic_cast<ChoiceParameter*>(param)) - { - ChoiceParameter* paramChoice = dynamic_cast<ChoiceParameter*>(param); - paramChoice->SetValue(value); - } -} - -void Application::SetParameterFloat(std::string parameter, float value) -{ - Parameter* param = GetParameterByKey(parameter); - - if (dynamic_cast<FloatParameter*>(param)) - { - FloatParameter* paramFloat = dynamic_cast<FloatParameter*>(param); - paramFloat->SetValue(value); - } -} void Application::SetDefaultParameterInt(std::string parameter, int value) { @@ -734,140 +858,20 @@ void Application::SetMaximumParameterFloatValue(std::string parameter, float val } - -void Application::SetParameterString(std::string parameter, std::string value) +void Application::SetListViewSingleSelectionMode(std::string parameter, bool status) { Parameter* param = GetParameterByKey(parameter); - if (dynamic_cast<ChoiceParameter*>(param)) - { - ChoiceParameter* paramDown = dynamic_cast<ChoiceParameter*>(param); - paramDown->SetValue(value); - } - else if (dynamic_cast<ListViewParameter*>(param)) - { - ListViewParameter* paramDown = dynamic_cast<ListViewParameter*>(param); - paramDown->SetValue(value); - } - else if (dynamic_cast<StringParameter*>(param)) - { - StringParameter* paramDown = dynamic_cast<StringParameter*>(param); - paramDown->SetValue(value); - } - else if (dynamic_cast<InputFilenameParameter*>(param)) - { - InputFilenameParameter* paramDown = dynamic_cast<InputFilenameParameter*>(param); - paramDown->SetValue(value); - } - else if (dynamic_cast<OutputFilenameParameter*>(param)) - { - OutputFilenameParameter* paramDown = dynamic_cast<OutputFilenameParameter*>(param); - paramDown->SetValue(value); - } - else if (dynamic_cast<DirectoryParameter*>(param)) - { - DirectoryParameter* paramDown = dynamic_cast<DirectoryParameter*>(param); - paramDown->SetValue(value); - } - else if (dynamic_cast<FloatParameter*>(param)) - { - FloatParameter* paramDown = dynamic_cast<FloatParameter*>(param); - paramDown->SetValue(value); - } - else if (dynamic_cast<RadiusParameter*>(param)) - { - RadiusParameter* paramDown = dynamic_cast<RadiusParameter*>(param); - paramDown->SetValue(value); - } - else if (dynamic_cast<IntParameter*>(param)) - { - IntParameter* paramDown = dynamic_cast<IntParameter*>(param); - paramDown->SetValue(value); - } - else if (dynamic_cast<InputImageParameter*>(param)) - { - InputImageParameter* paramDown = dynamic_cast<InputImageParameter*>(param); - if ( !paramDown->SetFromFileName(value) ) - otbAppLogCRITICAL( <<"Invalid image filename " << value <<"."); - - } - else if (dynamic_cast<ComplexInputImageParameter*>(param)) - { - ComplexInputImageParameter* paramDown = dynamic_cast<ComplexInputImageParameter*>(param); - paramDown->SetFromFileName(value); - } - else if (dynamic_cast<InputVectorDataParameter*>(param)) - { - InputVectorDataParameter* paramDown = dynamic_cast<InputVectorDataParameter*>(param); - if ( !paramDown->SetFromFileName(value) ) - otbAppLogCRITICAL( <<"Invalid vector data filename " << value <<"."); - } - else if (dynamic_cast<OutputImageParameter*>(param)) - { - OutputImageParameter* paramDown = dynamic_cast<OutputImageParameter*>(param); - paramDown->SetFileName(value); - } - else if (dynamic_cast<ComplexOutputImageParameter*>(param)) - { - ComplexOutputImageParameter* paramDown = dynamic_cast<ComplexOutputImageParameter*>(param); - paramDown->SetFileName(value); - } - else if (dynamic_cast<OutputVectorDataParameter*>(param)) - { - OutputVectorDataParameter* paramDown = dynamic_cast<OutputVectorDataParameter*>(param); - paramDown->SetFileName(value); - } - else if (dynamic_cast<RAMParameter*>(param)) - { - RAMParameter* paramDown = dynamic_cast<RAMParameter*>(param); - paramDown->SetValue(value); - } - else if (dynamic_cast<OutputProcessXMLParameter*>(param)) - { - OutputProcessXMLParameter* paramDown = dynamic_cast<OutputProcessXMLParameter*>(param); - paramDown->SetValue(value); - } - else if (dynamic_cast<InputProcessXMLParameter*>(param)) + if (dynamic_cast<ListViewParameter*>(param)) { - InputProcessXMLParameter* paramDown = dynamic_cast<InputProcessXMLParameter*>(param); - if ( !paramDown->SetFileName(value) ) - otbAppLogCRITICAL( <<"Invalid XML parameter filename " << value <<"."); + ListViewParameter* paramListView = dynamic_cast<ListViewParameter*>(param); + paramListView->SetSingleSelection(status); } + else + itkExceptionMacro(<<parameter << "parameter can't be casted to ListView"); + } -void Application::SetParameterStringList(std::string parameter, std::vector<std::string> value) -{ - Parameter* param = GetParameterByKey(parameter); - - if (dynamic_cast<InputImageListParameter*>(param)) - { - InputImageListParameter* paramDown = dynamic_cast<InputImageListParameter*>(param); - if( !paramDown->SetListFromFileName(value) ) - otbAppLogCRITICAL( <<"At least one image filename is invalid."); - } - else if (dynamic_cast<InputVectorDataListParameter*>(param)) - { - InputVectorDataListParameter* paramDown = dynamic_cast<InputVectorDataListParameter*>(param); - if( !paramDown->SetListFromFileName(value) ) - otbAppLogCRITICAL( <<"At least one vector data filename is invalid.."); - } - else if (dynamic_cast<InputFilenameListParameter*>(param)) - { - InputFilenameListParameter* paramDown = dynamic_cast<InputFilenameListParameter*>(param); - if( !paramDown->SetListFromFileName(value) ) - otbAppLogCRITICAL( <<"At least one filename is invalid.."); - } - else if (dynamic_cast<StringListParameter*>(param)) - { - StringListParameter* paramDown = dynamic_cast<StringListParameter*>(param); - paramDown->SetValue(value); - } - else if(dynamic_cast<ListViewParameter *>(param)) - { - ListViewParameter * paramDown = dynamic_cast<ListViewParameter *>(param); - paramDown->SetSelectedNames(value); - } -} void Application::SetParameterOutputImage(std::string parameter, FloatVectorImageType* value) { @@ -927,19 +931,22 @@ void Application::SetParameterOutputVectorData(std::string parameter, VectorData std::string Application::GetParameterName(std::string parameter) { - Parameter* param = GetParameterByKey(parameter); + // get the actual parameter, even if it is a proxy + Parameter* param = GetParameterByKey(parameter,false); return param->GetName(); } std::string Application::GetParameterDescription(std::string parameter) { - Parameter* param = GetParameterByKey(parameter); + // get the actual parameter, even if it is a proxy + Parameter* param = GetParameterByKey(parameter,false); return param->GetDescription(); } void Application::SetParameterDescription(std::string parameter, std::string desc) { - Parameter* param = GetParameterByKey(parameter); + // get the actual parameter, even if it is a proxy + Parameter* param = GetParameterByKey(parameter,false); param->SetDescription(desc); } @@ -1236,6 +1243,42 @@ void Application::SetNthParameterInputImageList(std::string parameter, const uns } +void Application::AddParameterStringList(std::string parameter, const std::string & str) +{ + Parameter* param = GetParameterByKey(parameter); + + InputImageListParameter * paramDown = dynamic_cast<InputImageListParameter *>(param); + + if(paramDown) + { + paramDown->AddFromFileName(str); + } + else + { + itkExceptionMacro(<<parameter << "parameter can't be casted to InputImageListParameter"); + } + +} + +void Application::SetNthParameterStringList(std::string parameter, const unsigned int &id, const std::string & str) +{ + Parameter* param = GetParameterByKey(parameter); + + InputImageListParameter * paramDown = dynamic_cast<InputImageListParameter *>(param); + + if(paramDown) + { + paramDown->SetNthFileName(id,str); + } + else + { + itkExceptionMacro(<<parameter << "parameter can't be casted to InputImageListParameter"); + } + +} + + + void Application::ClearParameterInputImageList(std::string parameter) { Parameter* param = GetParameterByKey(parameter); @@ -1623,6 +1666,10 @@ std::string Application::GetProgressDescription() const return m_ProgressSourceDescription; } +double Application::GetLastExecutionTiming() const +{ + return m_Chrono.GetTotal(); +} } } diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplicationHtmlDocGenerator.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplicationHtmlDocGenerator.cxx index 951e12cf11176aab488e51e5a9463c0f5407904a..bb6864898d0c35488195ba8cdff1d4c12403e5de 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplicationHtmlDocGenerator.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplicationHtmlDocGenerator.cxx @@ -25,7 +25,7 @@ namespace otb namespace Wrapper { -#define otbDocHtmlTitleMacro( value ) \ +#define otbDocHtmlTitleMacro( value ) \ oss << "</style></head><body style=\" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;\"><p align=\"center\" style=\" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:x-large; font-weight:600;\"><span style=\" font-size:x-large;\">"; \ oss << value; \ oss << "</span></p>"; @@ -40,29 +40,36 @@ namespace Wrapper oss << value; \ oss << "</span></p>"; -#define otbDocHtmlBodyMacro( value ) \ +#define otbDocHtmlBodyMacro( value ) \ oss << "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">"; \ oss << value; \ oss << "</p>"; -#define otbDocHtmlBodyCodeMacro( value ) \ +#define otbDocHtmlBodyCodeMacro( value ) \ oss << "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Courier New, courier';\">"; \ oss << value; \ oss << "</p>"; -#define otbDocHtmlParamMacro( type, param, showKey ) \ +#define otbDocHtmlParamMacro( type, param, fullKey, showKey ) \ oss << "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:'Courier New, courier'; font-weight:600;\"; >"; \ - oss << "["<<type<<"] "<< param->GetName(); \ - if( showKey == true && !std::string(param->GetKey()).empty() ) \ + oss << param->GetName(); \ + if( showKey == true && param->GetKey()[0] != '\0' ) \ { \ - oss << " (-"<< param->GetKey()<<")"; \ - } \ +if (!fullKey.empty()) \ + { \ + oss << " ("<< fullKey<< "." << param->GetKey() << ")"; \ + } \ +else \ + { \ + oss << " ("<< param->GetKey()<<")"; \ + } \ +} \ oss << ": </span>"; \ - if( std::string(param->GetDescription()).size()!=0 ) \ - { \ - oss << param->GetDescription(); \ - } \ - oss << "</p>"; +if( param->GetDescription()[0] != '\0' ) \ + { \ + oss << param->GetDescription(); \ + } \ +oss << "</p>"; ApplicationHtmlDocGenerator::ApplicationHtmlDocGenerator() @@ -141,7 +148,7 @@ ApplicationHtmlDocGenerator::GenerateDoc( const Application::Pointer app, std::s val = oss.str(); - // Replace "\n" string with <br/> +// Replace "\n" string with <br/> itksys::SystemTools::ReplaceString( val, "\n", "<br/>"); } @@ -165,6 +172,7 @@ ApplicationHtmlDocGenerator::GenerateDoc(const Application::Pointer app, const s void ApplicationHtmlDocGenerator::GetDocParameters( const Application::Pointer app, std::string & val, const bool showKey) { std::ostringstream oss; + const std::string emptyString; const std::vector<std::string> appKeyList = app->GetParametersKeys( false ); const unsigned int nbOfParam = appKeyList.size(); @@ -175,38 +183,38 @@ void ApplicationHtmlDocGenerator::GetDocParameters( const Application::Pointer a } else { - for( unsigned int i=0; i<nbOfParam; i++ ) - { - const std::string key(appKeyList[i]); - Parameter::Pointer param = app->GetParameterByKey( key ); - if( app->GetParameterType(key) == ParameterType_Group) - { - oss << "<li>"; - otbDocHtmlParamMacro( "group", param, showKey ); - std::string grDoc; - ApplicationHtmlDocGenerator::GetDocParameterGroup( app, grDoc, key, showKey ); - oss<<grDoc; - oss<<"</li><br />"; - } - else if( app->GetParameterType(key) == ParameterType_Choice ) - { - oss << "<li>"; - otbDocHtmlParamMacro( "choice", param, showKey ); - std::string grDoc; - ApplicationHtmlDocGenerator::GetDocParameterChoice(app, grDoc, key, showKey); - oss<<grDoc; - oss<<"</li><br />"; - } - else - { - oss << "<li>"; - otbDocHtmlParamMacro("param", param, showKey ); - oss << "</li>"; - } - } + for( unsigned int i=0; i<nbOfParam; i++ ) + { + const std::string key(appKeyList[i]); + Parameter::Pointer param = app->GetParameterByKey(key, false); + if( app->GetParameterType(key) == ParameterType_Group) + { + oss << "<li>"; + otbDocHtmlParamMacro( "group", param, emptyString, showKey ); + std::string grDoc; + ApplicationHtmlDocGenerator::GetDocParameterGroup( app, grDoc, key, showKey ); + oss<<grDoc; + oss<<"</li><br />"; + } + else if( app->GetParameterType(key) == ParameterType_Choice ) + { + oss << "<li>"; + otbDocHtmlParamMacro( "choice", param, emptyString, showKey ); + std::string grDoc; + ApplicationHtmlDocGenerator::GetDocParameterChoice(app, grDoc, key, showKey); + oss<<grDoc; + oss<<"</li><br />"; + } + else + { + oss << "<li>"; + otbDocHtmlParamMacro("param", param, emptyString, showKey ); + oss << "</li>"; + } + } } - val = oss.str(); + val = oss.str(); } void ApplicationHtmlDocGenerator::GetDocParameterGroup( const Application::Pointer app, std::string & val, const std::string & key, const bool showKey ) @@ -220,17 +228,18 @@ void ApplicationHtmlDocGenerator::GetDocParameterGroup( const Application::Point ParameterGroup * group = dynamic_cast<ParameterGroup *>(paramGr); const std::vector<std::string> appKeyList = group->GetParametersKeys( false ); unsigned int nbOfParam = appKeyList.size(); + const std::string emptyString; std::ostringstream oss; oss<<"<ul>"; for( unsigned int i=0; i<nbOfParam; i++ ) { const std::string fullKey(std::string(key).append(".").append(appKeyList[i])); - Parameter::Pointer param = app->GetParameterByKey( fullKey ); + Parameter::Pointer param = app->GetParameterByKey( fullKey, false); if( app->GetParameterType(fullKey) == ParameterType_Group) { oss<<"<li>"; - otbDocHtmlParamMacro( "group", param, showKey ); + otbDocHtmlParamMacro( "group", param, emptyString, showKey ); std::string grDoc; ApplicationHtmlDocGenerator::GetDocParameterGroup( app, grDoc, fullKey, showKey ); oss<<grDoc; @@ -239,7 +248,7 @@ void ApplicationHtmlDocGenerator::GetDocParameterGroup( const Application::Point else if( app->GetParameterType(fullKey) == ParameterType_Choice ) { oss<<"<li>"; - otbDocHtmlParamMacro( "choice", param, showKey ); + otbDocHtmlParamMacro( "choice", param, key, showKey ); std::string grDoc; ApplicationHtmlDocGenerator::GetDocParameterChoice(app, grDoc, fullKey, showKey ); oss<<grDoc; @@ -248,7 +257,7 @@ void ApplicationHtmlDocGenerator::GetDocParameterGroup( const Application::Point else { oss << "<li>"; - otbDocHtmlParamMacro( "param", param, showKey ); + otbDocHtmlParamMacro( "param", param, key, showKey ); oss <<"</li>"; } } @@ -267,6 +276,7 @@ void ApplicationHtmlDocGenerator::GetDocParameterChoice( const Application::Poin ChoiceParameter * choice = dynamic_cast<ChoiceParameter *>(paramCh); const std::vector<std::string> appKeyList = choice->GetChoiceKeys(); unsigned int nbOfParam = choice->GetNbChoices(); + const std::string emptyString; std::ostringstream oss; oss<<"<ul>"; @@ -277,7 +287,7 @@ void ApplicationHtmlDocGenerator::GetDocParameterChoice( const Application::Poin std::string grDoc; oss << "<li>"; - otbDocHtmlParamMacro( "group", group, showKey ); + otbDocHtmlParamMacro( "group", group, emptyString, showKey ); ApplicationHtmlDocGenerator::GetDocParameterGroup( app, grDoc, fullKey, showKey ); oss<<grDoc; oss<<"</li>"; @@ -287,5 +297,5 @@ void ApplicationHtmlDocGenerator::GetDocParameterChoice( const Application::Poin } } -} + } diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperChoiceParameter.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperChoiceParameter.cxx index b07f6685930dee7b2fa7b5b209767ceb4dc5255b..e823e002a302382cd16bc5ea84fadbd31345f2be 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperChoiceParameter.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperChoiceParameter.cxx @@ -31,7 +31,6 @@ ChoiceParameter::~ChoiceParameter() { } - void ChoiceParameter::AddChoice( std::string choicekey, std::string choiceName ) { @@ -41,7 +40,8 @@ ChoiceParameter::AddChoice( std::string choicekey, std::string choiceName ) choice.m_AssociatedParameter = ParameterGroup::New(); choice.m_AssociatedParameter->SetName(choiceName); choice.m_AssociatedParameter->SetRoot(this); - + choice.m_AssociatedParameter->SetKey(choicekey); + m_ChoiceList.push_back(choice); // check if the new choice matches the m_CurrentChoice : if so the group should be active. @@ -117,7 +117,7 @@ ChoiceParameter::GetChoiceParameterGroupByKey( std::string choiceKey ) } } - itkExceptionMacro(<< "Cannot find " << choiceKey); + itkExceptionMacro(<< "Cannot find choice key: '" << choiceKey << "'"); } unsigned int @@ -173,7 +173,10 @@ ChoiceParameter::SetValue(std::string choiceKey) ++i; } - itkExceptionMacro(<< "Cannot find " << choiceKey); + itkExceptionMacro(<< "Invalid parameter value '" + << choiceKey << "'" + << " given for parameter '-" + << this->GetKey() << "'"); } unsigned int diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperComplexOutputImageParameter.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperComplexOutputImageParameter.cxx index 382d87a66780a9d15dba00c73b360fb35e51287c..597f1b8726c9eaa54d1de4d8cb5fec9cd7db1f06 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperComplexOutputImageParameter.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperComplexOutputImageParameter.cxx @@ -210,8 +210,8 @@ ComplexOutputImageParameter::GetWriter() // 0 : image // 1 : VectorImage - if ( dynamic_cast<FloatVectorImageType*>( m_Image.GetPointer()) || - dynamic_cast<DoubleVectorImageType*>(m_Image.GetPointer())) + if ( dynamic_cast<ComplexFloatVectorImageType*>( m_Image.GetPointer()) || + dynamic_cast<ComplexDoubleVectorImageType*>(m_Image.GetPointer())) { type = 1; } diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperCompositeApplication.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperCompositeApplication.cxx new file mode 100644 index 0000000000000000000000000000000000000000..09f9e0fc3034ddcd1d26723f41e1c48dc281d844 --- /dev/null +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperCompositeApplication.cxx @@ -0,0 +1,216 @@ +/*========================================================================= + + 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. + + =========================================================================*/ + +#include "otbWrapperCompositeApplication.h" +#include "otbWrapperProxyParameter.h" +#include "otbWrapperApplicationRegistry.h" +#include "otbWrapperAddProcessToWatchEvent.h" +#include "otbWrapperParameterKey.h" + +namespace otb +{ +namespace Wrapper +{ + +CompositeApplication::CompositeApplication() +{ + m_LogOutput = itk::StdStreamLogOutput::New(); + m_LogOutput->SetStream(m_Oss); + m_AddProcessCommand = AddProcessCommandType::New(); + m_AddProcessCommand->SetCallbackFunction(this, &CompositeApplication::LinkWatchers); +} + +CompositeApplication::~CompositeApplication() +{ +} + +void +CompositeApplication +::LinkWatchers(itk::Object * itkNotUsed(caller), const itk::EventObject & event) +{ + if (typeid(AddProcessToWatchEvent) == typeid( event )) + { + this->InvokeEvent(event); + } +} + +bool +CompositeApplication +::AddApplication(std::string appType, std::string key, std::string desc) +{ + if (m_AppContainer.count(key)) + { + otbAppLogWARNING("The requested identifier for internal application is already used ("<<key<<")"); + return false; + } + InternalApplication container; + container.App = ApplicationRegistry::CreateApplication(appType); + container.Desc = desc; + // Setup logger + container.App->GetLogger()->AddLogOutput(m_LogOutput); + container.App->GetLogger()->SetTimeStampFormat(itk::LoggerBase::HUMANREADABLE); + container.App->AddObserver(AddProcessToWatchEvent(), m_AddProcessCommand.GetPointer()); + m_AppContainer[key] = container; + return true; +} + +void +CompositeApplication +::ClearApplications() +{ + m_AppContainer.clear(); +} + +bool +CompositeApplication +::Connect(std::string fromKey, std::string toKey) +{ + std::string key1(fromKey); + std::string key2(toKey); + Application *app1 = DecodeKey(key1); + Application *app2 = DecodeKey(key2); + + Parameter* rawParam1 = app1->GetParameterByKey(key1, false); + if (dynamic_cast<ProxyParameter*>(rawParam1)) + { + otbAppLogWARNING("Parameter is already connected ! Override current connection"); + } + ProxyParameter::Pointer proxyParam = ProxyParameter::New(); + ProxyParameter::ProxyTargetType target; + target.first = app2->GetParameterList(); + target.second = key2; + proxyParam->SetTarget(target); + proxyParam->SetName(rawParam1->GetName()); + proxyParam->SetDescription(rawParam1->GetDescription()); + return app1->GetParameterList()->ReplaceParameter(key1, proxyParam.GetPointer()); +} + +bool +CompositeApplication +::ShareParameter(std::string localKey, + std::string internalKey, + std::string name, + std::string desc) +{ + std::string internalKeyCheck(internalKey); + Application *app = DecodeKey(internalKeyCheck); + Parameter* rawTarget = app->GetParameterByKey(internalKeyCheck, false); + + // Check source + ParameterKey pKey(localKey); + std::string proxyKey(pKey.GetLastElement()); + + // Create and setup proxy parameter + ProxyParameter::Pointer proxyParam = ProxyParameter::New(); + ProxyParameter::ProxyTargetType target; + target.first = app->GetParameterList(); + target.second = internalKeyCheck; + proxyParam->SetTarget(target); + proxyParam->SetName( name.empty() ? rawTarget->GetName() : name); + proxyParam->SetDescription(desc.empty() ? rawTarget->GetDescription() : desc); + proxyParam->SetKey(proxyKey); + + // Get group parameter where the proxy should be added + Parameter::Pointer baseParam(proxyParam.GetPointer()); + ParameterGroup *parentGroup = this->GetParameterList(); + if (localKey.find('.') != std::string::npos) + { + Parameter::Pointer parentParam = this->GetParameterList()->GetParameterByKey(pKey.GetRoot()); + parentGroup = dynamic_cast<ParameterGroup*>(parentParam.GetPointer()); + baseParam->SetRoot(parentGroup); + parentGroup->AddChild(baseParam); + } + parentGroup->AddParameter(baseParam); + return true; +} + +Application* +CompositeApplication +::DecodeKey(std::string &key) +{ + Application *ret = this; + size_t pos = key.find('.'); + if (pos != std::string::npos && m_AppContainer.count(key.substr(0,pos))) + { + ret = m_AppContainer[key.substr(0,pos)].App; + key = key.substr(pos+1); + } + return ret; +} + +Application* +CompositeApplication +::GetInternalApplication(std::string id) +{ + if (!m_AppContainer.count(id)) + otbAppLogFATAL("Unknown internal application : "<<id); + return m_AppContainer[id].App; +} + +std::string +CompositeApplication +::GetInternalAppDescription(std::string id) +{ + if (!m_AppContainer.count(id)) + otbAppLogFATAL("Unknown internal application : "<<id); + return m_AppContainer[id].Desc; +} + +void +CompositeApplication +::ExecuteInternal(std::string key) +{ + otbAppLogINFO(<< GetInternalAppDescription(key) <<"..."); + try + { + GetInternalApplication(key)->Execute(); + } + catch(...) + { + this->GetLogger()->Write( itk::LoggerBase::FATAL, std::string("\n") + m_Oss.str() ); + throw; + } + if(!m_Oss.str().empty()) + { + otbAppLogINFO(<< "\n" << m_Oss.str()); + m_Oss.str(std::string("")); + } +} + +void +CompositeApplication +::UpdateInternalParameters(std::string key) +{ + try + { + GetInternalApplication(key)->UpdateParameters(); + } + catch(...) + { + this->GetLogger()->Write( itk::LoggerBase::FATAL, std::string("\n") + m_Oss.str() ); + throw; + } + if(!m_Oss.str().empty()) + { + otbAppLogINFO(<< "\n" << m_Oss.str()); + m_Oss.str(std::string("")); + } +} + +} // end namespace Wrapper +} // end namespace otb diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperElevationParametersHandler.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperElevationParametersHandler.cxx index e72145ce085f42418074a7643a740d7ffb6cc756..409f8ad46ed49cad63f9b735ddd32261018bb773 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperElevationParametersHandler.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperElevationParametersHandler.cxx @@ -107,10 +107,20 @@ void ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(const Ap // Set DEM directory if available if(IsDEMUsed(app,key)) { - oss.str(""); - oss<<"Elevation management: using DEM directory ("<<GetDEMDirectory(app,key)<<")"<<std::endl; - otb::DEMHandler::Instance()->OpenDEMDirectory(GetDEMDirectory(app,key)); - app->GetLogger()->Info(oss.str()); + std::string demDirectory = GetDEMDirectory(app,key); + if(otb::DEMHandler::Instance()->IsValidDEMDirectory(demDirectory.c_str())) + { + oss.str( "" ); + oss << "Elevation management: using DEM directory (" << demDirectory << ")" << std::endl; + otb::DEMHandler::Instance()->OpenDEMDirectory( demDirectory ); + app->GetLogger()->Info( oss.str() ); + } + else + { + oss.str( "" ); + oss << "DEM directory : " << demDirectory << " is not a valid DEM directory"; + app->GetLogger()->Warning( oss.str() ); + } } } @@ -161,10 +171,10 @@ ElevationParametersHandler::IsGeoidUsed(const Application::Pointer app, const st bool ElevationParametersHandler::IsDEMUsed(const Application::Pointer app, const std::string& key) { - std::ostringstream geoidKey; - geoidKey<< key<<".dem"; + std::ostringstream demKey; + demKey<< key<<".dem"; - return app->IsParameterEnabled(geoidKey.str()) && app->HasValue(geoidKey.str()); + return app->IsParameterEnabled(demKey.str()) && app->HasValue(demKey.str()); } diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperListViewParameter.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperListViewParameter.cxx index 2d3fa76b12f676b618ea47795c11d0ccd69fbe34..ecaf772f6e10990fd4679197fc844e6bf6bc9fa5 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperListViewParameter.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperListViewParameter.cxx @@ -23,7 +23,12 @@ namespace Wrapper { ListViewParameter::ListViewParameter() - : m_CurrentChoice(0) + : m_ChoiceList(), + m_CurrentChoice(0), + m_SelectedItems(), + m_SelectedKeys(), + m_SelectedNames(), + m_SingleSelection(false) { } @@ -106,7 +111,9 @@ ListViewParameter::GetNbChoices( void ) void ListViewParameter::SetValue(unsigned int v) { + std::vector<int> selectedItems(1,v); m_CurrentChoice = v; + this->SetSelectedItems(selectedItems); SetActive(true); // Call Modified(); this->Modified(); @@ -145,14 +152,21 @@ ListViewParameter::ClearChoices() m_ChoiceList.clear(); } + void -ListViewParameter::SetSelectedItemsByNames() +ListViewParameter::SetSelectedNames(std::vector<std::string> selectedNames) { std::vector<int> selectedItems; std::vector<std::string> names = this->GetChoiceNames(); - for(unsigned int i=0; i<m_SelectedNames.size(); i++) + + if(m_SingleSelection && selectedNames.size() > 1) + { + itkExceptionMacro(<<"Single selection mode is on, but there are "<<selectedNames.size()<<" selected items"); + } + + for(unsigned int i=0; i<selectedNames.size(); i++) { - const std::string selectedName = m_SelectedNames[i]; + const std::string selectedName = selectedNames[i]; unsigned int j(0); for(; j<names.size(); j++) { @@ -182,13 +196,19 @@ ListViewParameter::SetSelectedItemsByNames() void -ListViewParameter::SetSelectedItemsByKeys() +ListViewParameter::SetSelectedKeys(std::vector<std::string> selectedKeys) { std::vector<int> selectedItems; std::vector<std::string> keys = this->GetChoiceKeys(); + +if(m_SingleSelection && m_SelectedKeys.size() > 1) + { + itkExceptionMacro(<<"Single selection mode is on, but there are "<<m_SelectedKeys.size()<<" selected items"); + } + for(unsigned int i=0; i<m_SelectedKeys.size(); i++) { - const std::string selectedKey = m_SelectedKeys[i]; + const std::string selectedKey = selectedKeys[i]; unsigned int j(0); std::ostringstream oss; for(; j<keys.size(); j++) diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputImageParameter.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputImageParameter.cxx index 475e445d1012d63aaaba3122a94af70cf41f4171..b6bd4f94e5214019e0178012925559725c4424fd 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputImageParameter.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputImageParameter.cxx @@ -18,6 +18,8 @@ #include "otbWrapperOutputImageParameter.h" #include "otbClampImageFilter.h" #include "otbClampVectorImageFilter.h" +#include "otbImageIOFactory.h" +#include "itksys/SystemTools.hxx" #ifdef OTB_USE_MPI @@ -557,5 +559,46 @@ OutputImageParameter::HasValue() const return !filename.empty(); } +std::string +OutputImageParameter::CheckFileName(bool fixMissingExtension) +{ + std::string ret(""); + // Check that there is an ImageIO capable of writing the file + otb::ExtendedFilenameToWriterOptions::Pointer filenameHelper = + otb::ExtendedFilenameToWriterOptions::New(); + filenameHelper->SetExtendedFileName(this->GetFileName()); + std::string simpleFilename = filenameHelper->GetSimpleFileName(); + // TODO : check if simpleFilename is empty + + otb::ImageIOBase::Pointer imageIO = + otb::ImageIOFactory::CreateImageIO(simpleFilename.c_str(), + otb::ImageIOFactory::WriteMode); + if(imageIO.IsNull()) + { + // check for missing extension + std::string outExt = itksys::SystemTools::GetFilenameLastExtension(simpleFilename); + if (outExt.empty()) + { + if (fixMissingExtension) + { + // try with .tif + std::string fullFileName(this->GetFileName()); + std::string extendedPart = fullFileName.substr(simpleFilename.size()); + this->SetFileName(simpleFilename+std::string(".tif")+extendedPart); + ret += std::string("no extension detected, using TIF as default."); + } + else + { + // TODO : call exception here? + } + } + else + { + // TODO : call exception here? + } + } + return ret; +} + } } diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputProcessXMLParameter.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputProcessXMLParameter.cxx index 385baaa75777a6f9a578551f64c676fb68e561c0..42e70793d494d3bfe6822d087b82a4856ae2fd37 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputProcessXMLParameter.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputProcessXMLParameter.cxx @@ -130,8 +130,19 @@ OutputProcessXMLParameter::Write(Application::Pointer app) AddChildNodeTo(n_OTB, "version", version); - TiXmlElement *n_App; - n_App = AddChildNodeTo(n_OTB, "application"); + // Parse application + TiXmlElement *n_App = ParseApplication(app); + n_OTB->LinkEndChild(n_App); + + // Finally, write xml contents to file + doc.SaveFile( m_FileName.c_str() ); +} + +TiXmlElement* +OutputProcessXMLParameter::ParseApplication(Application::Pointer app) +{ + TiXmlElement * n_App = new TiXmlElement("application"); + AddChildNodeTo(n_App, "name", app->GetName()); AddChildNodeTo(n_App, "descr", app->GetDescription()); @@ -315,10 +326,7 @@ OutputProcessXMLParameter::Write(Application::Pointer app) } } } - - // Finally, write xml contents to file - doc.SaveFile( m_FileName.c_str() ); - + return n_App; } } //end namespace wrapper diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperParameterGroup.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperParameterGroup.cxx index 48f68da28c40a2d591068c3556a000b66b9b7c1f..93c76d99f6ce4dced9ede92f6803cf00032a5745 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperParameterGroup.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperParameterGroup.cxx @@ -36,6 +36,7 @@ #include "otbWrapperInputProcessXMLParameter.h" #include "otbWrapperParameterKey.h" #include "otbWrapperRAMParameter.h" +#include "otbWrapperProxyParameter.h" #include "otb_boost_string_header.h" @@ -61,7 +62,11 @@ ParameterGroup::GetParametersKeys(bool recursive) for (pit = m_ParameterList.begin(); pit != m_ParameterList.end(); ++pit) { Parameter* param = *pit; - parameters.push_back( param->GetKey() ); + std::string currentKey(param->GetKey()); + parameters.push_back( currentKey ); + + // follow proxy parameters + param = this->ResolveParameter(param); if (recursive && dynamic_cast<ParameterGroup*>(param)) { @@ -70,7 +75,7 @@ ParameterGroup::GetParametersKeys(bool recursive) for (std::vector<std::string>::const_iterator it = subparams.begin(); it != subparams.end(); ++it) { - parameters.push_back( std::string(paramAsGroup->GetKey()) + "." + *it ); + parameters.push_back( currentKey + "." + *it ); } } else if (recursive && dynamic_cast<ChoiceParameter*>(param)) @@ -81,7 +86,7 @@ ParameterGroup::GetParametersKeys(bool recursive) for (std::vector<std::string>::const_iterator it = subparams.begin(); it != subparams.end(); ++it) { - parameters.push_back( std::string(paramAsChoice->GetKey()) + "." + *it ); + parameters.push_back( currentKey + "." + *it ); } } } @@ -120,11 +125,15 @@ ParameterGroup::AddChoice(std::string paramKey, std::string paramName) else { itkExceptionMacro(<<parentkey << " is not a choice"); + } } else { - itkExceptionMacro(<<"No choice parameter key given"); + itkExceptionMacro( + << "No choice parameter key given: paramKey = '" + << paramKey + << "'"); } } @@ -132,37 +141,27 @@ ParameterGroup::AddChoice(std::string paramKey, std::string paramName) void ParameterGroup::ClearChoices(std::string paramKey) { - ParameterKey pKey( paramKey ); - // Split the parameter name - std::vector<std::string> splitKey = pKey.Split(); - std::string parentkey; - Parameter::Pointer parentParam; + Parameter * param = GetParameterByKey(paramKey); - if (splitKey.size() > 1) - { - parentkey = pKey.GetRoot(); - parentParam = GetParameterByKey(parentkey); - } - else + if(!param) { - parentParam = GetParameterByKey(splitKey[0]); + itkExceptionMacro("Parameter "<<paramKey<<" not found"); } + + // param must be a choice, a listBox or this is an error + ListViewParameter* paramAsChoice = dynamic_cast<ListViewParameter*>(param); - // parentParam must be a choice, a listBox or this is an error - ListViewParameter* listBoxParentAsChoice = dynamic_cast<ListViewParameter*>(parentParam.GetPointer()); - - if (listBoxParentAsChoice) + if (paramAsChoice) { - listBoxParentAsChoice->ClearChoices(); + paramAsChoice->ClearChoices(); } else { - itkExceptionMacro(<<parentkey << " is not a ListView"); + itkExceptionMacro(<<paramKey << " is not a ListView"); } } - void ParameterGroup::AddOutXMLParameter() { Parameter::Pointer tmpParam; @@ -207,34 +206,25 @@ void ParameterGroup::AddInXMLParameter() std::vector<int> ParameterGroup::GetSelectedItems(std::string paramKey) { - std::vector<int> selectedItems; - ParameterKey pKey( paramKey ); - // Split the parameter name - std::vector<std::string> splitKey = pKey.Split(); + Parameter * param = GetParameterByKey(paramKey); - std::string parentkey; - Parameter::Pointer parentParam; - - if (splitKey.size() > 1) - { - parentkey = pKey.GetRoot(); - parentParam = GetParameterByKey(parentkey); - } - else + if(!param) { - parentParam = GetParameterByKey(splitKey[0]); + itkExceptionMacro("Parameter "<<paramKey<<" not found"); } + + // param must be a choice, a listBox or this is an error + ListViewParameter* paramAsChoice = dynamic_cast<ListViewParameter*>(param); + + std::vector<int> selectedItems; - // parentParam must be a choice, a listBox or this is an error - ListViewParameter* listBoxParentAsChoice = dynamic_cast<ListViewParameter*>(parentParam.GetPointer()); - - if (listBoxParentAsChoice) + if (paramAsChoice) { - selectedItems = listBoxParentAsChoice->GetSelectedItems(); + selectedItems = paramAsChoice->GetSelectedItems(); } else { - itkExceptionMacro(<<parentkey << " is not a ListView"); + itkExceptionMacro(<<paramKey << " is not a ListView"); } return selectedItems; @@ -666,14 +656,79 @@ ParameterGroup::AddParameter(Parameter::Pointer p) m_ParameterList.push_back(p); } +bool +ParameterGroup::ReplaceParameter(std::string &key, Parameter::Pointer p) +{ + bool ret = true; + ParameterKey pName(key); + std::vector<std::string> splitName = pName.Split(); + std::string lastkey = pName.GetLastElement(); + std::string parentkey = pName.GetRoot(); + ParameterGroup* parentGroup = this; + if( splitName.size() > 1 ) + { + Parameter* parentParam = GetParameterByKey(parentkey); + parentGroup = dynamic_cast<ParameterGroup*>(parentParam); + if (parentGroup) + { + ret = parentGroup->ReplaceParameter(lastkey, p); + } + else + { + ret = false; + } + } + else + { + // find current parameter in the current group + Parameter::Pointer oldParam; + ParameterListType::iterator vit; + for (vit = m_ParameterList.begin(); vit != m_ParameterList.end(); ++vit) + { + if (lastkey.compare((*vit)->GetKey()) == 0) + { + oldParam = *vit; + break; + } + } + if (oldParam.IsNull()) + { + // parameter to replace not found : return false + ret = false; + } + else + { + // parameter already exists : replace it + *vit = p; + p->SetKey(lastkey); + } + } + if (ret) + { + if( splitName.size() > 1 ) + { + p->SetRoot(parentGroup); + parentGroup->AddChild(p); + } + } + // don't check type compatibility here, we may want to handle special cases + // at higher level + return ret; +} + Parameter::Pointer -ParameterGroup::GetParameterByIndex(unsigned int i) +ParameterGroup::GetParameterByIndex(unsigned int i, bool follow) { - return m_ParameterList[i]; + Parameter *param = m_ParameterList[i]; + if (follow) + { + param = this->ResolveParameter(param); + } + return Parameter::Pointer(param); } Parameter::Pointer -ParameterGroup::GetParameterByKey(std::string name) +ParameterGroup::GetParameterByKey(std::string name, bool follow) { ParameterKey pName(name); @@ -701,6 +756,14 @@ ParameterGroup::GetParameterByKey(std::string name) itkExceptionMacro(<< "Could not find parameter " << name) } + // follow proxy parameters (resolve intermediate group parameter because + // we need to get to the requested parameter) + if (follow || splitName.size() > 1) + { + Parameter *rawParam = this->ResolveParameter(parentParam.GetPointer()); + parentParam = rawParam; + } + // If the name contains a child, make a recursive call if (splitName.size() > 1) { @@ -774,5 +837,33 @@ ParameterGroup::GetNumberOfParameters() return m_ParameterList.size(); } +Parameter* ParameterGroup::ResolveParameter(Parameter *param) +{ + Parameter* ret = param; + if (ret == ITK_NULLPTR) + { + itkGenericExceptionMacro("Can't resolve NULL parameter!"); + } + while (dynamic_cast<ProxyParameter*>(ret)) + { + ProxyParameter* castParam = dynamic_cast<ProxyParameter*>(ret); + ProxyParameter::ProxyTargetType target = castParam->GetTarget(); + ParameterGroup* targetGroup = dynamic_cast<ParameterGroup*>(target.first.GetPointer()); + if (targetGroup) + { + ret = targetGroup->GetParameterByKey(target.second); + } + else + { + itkGenericExceptionMacro("Target group of a proxy parameter is not of type ParameterGroup"); + } + if (ret == param) + { + itkGenericExceptionMacro("Cycle detected with proxy parameters!"); + } + } + return ret; +} + } } diff --git a/Modules/Wrappers/ApplicationEngine/test/CMakeLists.txt b/Modules/Wrappers/ApplicationEngine/test/CMakeLists.txt index 753d0016ad7cb2d0075de2a9055961ad5f97378b..7b6dee37b275ed7ec8a2c99e6842e13ec5814002 100644 --- a/Modules/Wrappers/ApplicationEngine/test/CMakeLists.txt +++ b/Modules/Wrappers/ApplicationEngine/test/CMakeLists.txt @@ -177,3 +177,7 @@ otb_add_test(NAME owTvApplicationMemoryConnectTest COMMAND otbApplicationEngineT $<TARGET_FILE_DIR:otbapp_Smoothing> ${INPUTDATA}/poupees.tif ${TEMP}/owTvApplicationMemoryConnectTestOutput.tif) + +otb_add_test(NAME owTvParameterGroup COMMAND otbApplicationEngineTestDriver + otbWrapperParameterList + ) diff --git a/Modules/Wrappers/ApplicationEngine/test/otbApplicationEngineTestDriver.cxx b/Modules/Wrappers/ApplicationEngine/test/otbApplicationEngineTestDriver.cxx index 3cb4aaddcdfb84ccd62bf6e44b4fe5171bcf1619..2d6145cedbb23434b53fb12a212e3b1e85f28920 100644 --- a/Modules/Wrappers/ApplicationEngine/test/otbApplicationEngineTestDriver.cxx +++ b/Modules/Wrappers/ApplicationEngine/test/otbApplicationEngineTestDriver.cxx @@ -20,6 +20,7 @@ void RegisterTests() REGISTER_TEST(otbWrapperDocExampleStructureTest); REGISTER_TEST(otbWrapperParameterKey); REGISTER_TEST(otbWrapperParameterListNew); + REGISTER_TEST(otbWrapperParameterList); REGISTER_TEST(otbWrapperEmptyParameterNew); REGISTER_TEST(otbWrapperInputImageListParameterNew); REGISTER_TEST(otbWrapperInputImageListParameterTest1); diff --git a/Modules/Wrappers/ApplicationEngine/test/otbApplicationMemoryConnectTest.cxx b/Modules/Wrappers/ApplicationEngine/test/otbApplicationMemoryConnectTest.cxx index e0f646d59565adb1f98323c18fd4f59d58d3231f..b9d92f8d265f873ef87b6ef0e038ab6119b513df 100644 --- a/Modules/Wrappers/ApplicationEngine/test/otbApplicationMemoryConnectTest.cxx +++ b/Modules/Wrappers/ApplicationEngine/test/otbApplicationMemoryConnectTest.cxx @@ -64,6 +64,7 @@ int otbApplicationMemoryConnectTest(int argc, char * argv[]) app4->AddImageToParameterInputImageList("il",app2->GetParameterOutputImage("out")); app4->AddImageToParameterInputImageList("il",app3->GetParameterOutputImage("out")); + app4->AddParameterStringList("il",infname); app4->ExecuteAndWriteOutput(); diff --git a/Modules/Wrappers/ApplicationEngine/test/otbWrapperParameterListTest.cxx b/Modules/Wrappers/ApplicationEngine/test/otbWrapperParameterListTest.cxx index 5d14917b40d3389d20bf30ef226231f1b7664eb8..966db2ceac9724911b6249b2d66e702d6ea024d3 100644 --- a/Modules/Wrappers/ApplicationEngine/test/otbWrapperParameterListTest.cxx +++ b/Modules/Wrappers/ApplicationEngine/test/otbWrapperParameterListTest.cxx @@ -20,6 +20,9 @@ #endif #include "otbWrapperParameterGroup.h" +#include "otbWrapperStringParameter.h" +#include "otbWrapperNumericalParameter.h" +#include "otbWrapperProxyParameter.h" int otbWrapperParameterListNew(int itkNotUsed(argc), char * itkNotUsed(argv)[]) { @@ -30,3 +33,66 @@ int otbWrapperParameterListNew(int itkNotUsed(argc), char * itkNotUsed(argv)[]) return EXIT_SUCCESS; } + +int otbWrapperParameterList(int itkNotUsed(argc), char * itkNotUsed(argv)[]) +{ + typedef otb::Wrapper::ParameterGroup GroupPrm; + typedef otb::Wrapper::StringParameter StringPrm; + typedef otb::Wrapper::IntParameter IntPrm; + typedef otb::Wrapper::ProxyParameter ProxyPrm; + + // setup first group of parameters + GroupPrm::Pointer parameters = GroupPrm::New(); + + StringPrm::Pointer strParam = StringPrm::New(); + strParam->SetKey("str"); + + IntPrm::Pointer numParam = IntPrm::New(); + numParam->SetKey("num"); + numParam->SetValue(1); + + parameters->AddParameter(strParam.GetPointer()); + parameters->AddParameter(numParam.GetPointer()); + + // setup second group of parameters + GroupPrm::Pointer otherParameters = GroupPrm::New(); + + IntPrm::Pointer hiddenParam = IntPrm::New(); + hiddenParam->SetKey("hidden"); + hiddenParam->SetValue(2); + + otherParameters->AddParameter(hiddenParam.GetPointer()); + + ProxyPrm::Pointer proxyParam = ProxyPrm::New(); + ProxyPrm::ProxyTargetType target; + target.first = otherParameters; + target.second = "hidden"; + proxyParam->SetTarget(target); + + // try to set a proxy to "hidden" in the first group + std::string proxyKey("num"); + if (! parameters->ReplaceParameter(proxyKey, proxyParam.GetPointer())) + { + std::cout << "Failed to replace with proxy parameter" << std::endl; + return EXIT_FAILURE; + } + + // check that we get the right value in "num" + otb::Wrapper::Parameter* resultParam = GroupPrm::ResolveParameter(parameters->GetParameterByKey("num")); + IntPrm* castInt = dynamic_cast<IntPrm*>(resultParam); + if (castInt) + { + if (castInt->GetValue() != 2) + { + std::cout << "Failed to setup proxy on int parameter, got "<< castInt->GetValue()<< ", expected 2."<< std::endl; + return EXIT_FAILURE; + } + } + else + { + std::cout << "Can't cast parameter to Int, probably wrong type."<< std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx b/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx index b69ef724c34ba6ac3a7ead16e7520172cedffad4..c75e921044d320ac88361b26b22929d77d81ec74 100644 --- a/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx +++ b/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx @@ -494,7 +494,17 @@ CommandLineLauncher::ParamResultType CommandLineLauncher::LoadParameters() else if (type == ParameterType_ListView) { - dynamic_cast<ListViewParameter *> (param.GetPointer())->SetSelectedNames(values); + + ListViewParameter * tmpLV = dynamic_cast<ListViewParameter *>(param.GetPointer()); + + if(tmpLV->GetSingleSelection() && values.size() > 1) + { + std::cerr << "ERROR: Invalid number of value for: \"" << paramKey + << "\", invalid number of values " << values.size() << std::endl; + return INVALIDNUMBEROFVALUE; + } + + tmpLV->SetSelectedNames(values); } else if(values.size() != 1) @@ -750,6 +760,14 @@ std::string CommandLineLauncher::DisplayParameterHelp(const Parameter::Pointer & return ""; } + bool singleSelectionForListView = false; + + if(type == ParameterType_ListView) + { + ListViewParameter * tmp = static_cast<ListViewParameter *>(param.GetPointer()); + singleSelectionForListView = tmp->GetSingleSelection(); + } + std::ostringstream oss; // When a parameter is mandatory : @@ -822,7 +840,7 @@ std::string CommandLineLauncher::DisplayParameterHelp(const Parameter::Pointer & } else if (type == ParameterType_InputFilename || type == ParameterType_OutputFilename ||type == ParameterType_Directory || type == ParameterType_InputImage || type == ParameterType_OutputProcessXML || type == ParameterType_InputProcessXML || type == ParameterType_ComplexInputImage || type == ParameterType_InputVectorData || type == ParameterType_OutputVectorData || - type == ParameterType_String || type == ParameterType_Choice ) + type == ParameterType_String || type == ParameterType_Choice || (type == ParameterType_ListView && singleSelectionForListView)) { oss << "<string> "; } @@ -830,7 +848,7 @@ std::string CommandLineLauncher::DisplayParameterHelp(const Parameter::Pointer & { oss << "<string> [pixel]"; } - else if (type == ParameterType_Choice || type == ParameterType_ListView || type == ParameterType_InputImageList || + else if (type == ParameterType_Choice || (type == ParameterType_ListView && !singleSelectionForListView) || type == ParameterType_InputImageList || type == ParameterType_InputVectorDataList || type == ParameterType_InputFilenameList || type == ParameterType_StringList ) { @@ -840,7 +858,7 @@ std::string CommandLineLauncher::DisplayParameterHelp(const Parameter::Pointer & itkExceptionMacro("Not handled parameter type."); - oss<< " " << param->GetName() << " "; + oss<< " " << m_Application->GetParameterName(paramKey) << " "; if (type == ParameterType_OutputImage) { diff --git a/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetModel.h b/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetModel.h index e08678a2bd36e359ba2be86f270e0d8a3c7d6cb8..856c2528238fbd10fe25ffac2d3f2d4dedfed462 100644 --- a/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetModel.h +++ b/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetModel.h @@ -19,6 +19,7 @@ #define otbWrapperQtWidgetModel_h #include <QtGui> +#include <QTimer> #ifndef Q_MOC_RUN // See: https://bugreports.qt-project.org/browse/QTBUG-22829 //tag=QT4-boost-compatibility #include "otbWrapperApplication.h" #include "otbQtLogOutput.h" @@ -162,6 +163,8 @@ private slots: */ void OnApplicationExecutionDone( int status ); + void TimerDone(); + private: QtWidgetModel(const QtWidgetModel&); //purposely not implemented void operator=(const QtWidgetModel&); //purposely not implemented @@ -171,6 +174,8 @@ private: QtLogOutput::Pointer m_LogOutput; bool m_IsRunning; + + QTimer *m_Timer; }; diff --git a/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetView.h b/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetView.h index e39f5d17de5bc5e226291cc0dfc6c28847002fa2..b4d69cc539b8492e5af2799f9d55c7bbf3b97fb0 100644 --- a/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetView.h +++ b/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetView.h @@ -54,6 +54,7 @@ public slots: private slots: void UpdateMessageAfterExecuteClicked(); + void UpdateMessageAfterExecution(int status); void UpdateMessageAfterApplicationReady(bool val); signals: diff --git a/Modules/Wrappers/QtWidget/src/otbApplicationLauncherQt.cxx b/Modules/Wrappers/QtWidget/src/otbApplicationLauncherQt.cxx index 99e0779a571dd5ebcb88e8b87d1a9f51f7b44290..3fa73b3298cd958948aad992c45e20821d23b33b 100644 --- a/Modules/Wrappers/QtWidget/src/otbApplicationLauncherQt.cxx +++ b/Modules/Wrappers/QtWidget/src/otbApplicationLauncherQt.cxx @@ -103,5 +103,12 @@ int main(int argc, char* argv[]) mainWindow->show(); // Start event processing loop - return qtApp.exec(); + int ret = qtApp.exec(); + + // Clean resources + if (mainWindow) delete mainWindow; + app = ITK_NULLPTR; + ApplicationRegistry::CleanRegistry(); + + return ret; } diff --git a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetListViewParameter.cxx b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetListViewParameter.cxx index 9427927737d607479fdebfe7279d14831a925f5e..21c289468d34b2e0ffb65ca56369fb5427548840 100644 --- a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetListViewParameter.cxx +++ b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetListViewParameter.cxx @@ -70,7 +70,15 @@ void QtWidgetListViewParameter::DoCreateWidget() { m_ListView = new QListWidget(); m_ListView->setToolTip(m_ListViewParam->GetDescription()); - m_ListView->setSelectionMode(QAbstractItemView::ExtendedSelection); + + if(m_ListViewParam->GetSingleSelection()) + { + m_ListView->setSelectionMode(QAbstractItemView::SingleSelection); + } + else + { + m_ListView->setSelectionMode(QAbstractItemView::ExtendedSelection); + } connect( m_ListView, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItems()) ); @@ -97,6 +105,10 @@ void QtWidgetListViewParameter::SelectedItems() } } m_ListViewParam->SetSelectedItems(m_SelectedItems); + + // make sure parameter is enabled + m_ListViewParam->SetActive(true); + m_ListViewParam->SetUserValue(true); } } diff --git a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetModel.cxx b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetModel.cxx index 73157927ab95baa74e73b252ca3e7ca9973c5f48..e9587623dbc3eeeea23a7fb28c345fbcc95aa9df 100644 --- a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetModel.cxx +++ b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetModel.cxx @@ -17,6 +17,9 @@ =========================================================================*/ #include "otbWrapperQtWidgetModel.h" +//Use to create command line from the application parameters +#include "otbWrapperOutputProcessXMLParameter.h" + namespace otb { @@ -37,13 +40,25 @@ QtWidgetModel m_LogOutput = QtLogOutput::New(); - // Attach log output to the Application logger + // Attach log output to the Application logger m_Application->GetLogger()->SetTimeStampFormat(itk::LoggerBase::HUMANREADABLE); m_Application->GetLogger()->AddLogOutput(m_LogOutput); + + m_Timer = new QTimer(this); + m_Timer->setSingleShot(true); + m_Timer->setInterval(1000); + QObject::connect( + m_Timer, + SIGNAL( timeout() ), + this, + SLOT( TimerDone() ) + ); } QtWidgetModel::~QtWidgetModel() { + if (m_Timer) + delete m_Timer; } void @@ -70,6 +85,81 @@ QtWidgetModel emit SetApplicationReady(false); m_IsRunning = true; + //Buld corresponding command line and display to the Log tab + + //Build XML DOM from m_application + OutputProcessXMLParameter::Pointer outXMLParam = OutputProcessXMLParameter::New(); + + TiXmlElement* XMLAppElement = outXMLParam->ParseApplication(m_Application); + + //Create command line from the XML document + TiXmlElement * pName, *pParam; + std::ostringstream cmdLine; + + cmdLine << ""; + + if(XMLAppElement) + { + pName = XMLAppElement->FirstChildElement("name"); + + cmdLine << "otbcli_" << pName->GetText(); +#ifdef _WIN32 + cmdLine << ".bat"; +#endif + cmdLine << " "; + + //Parse application parameters + pParam = XMLAppElement->FirstChildElement("parameter"); + + while(pParam) + { + //Get pareter key + cmdLine << "-"; + cmdLine << pParam->FirstChildElement("key")->GetText(); + cmdLine << " "; + + //Some parameters can have multiple values. Test it and handle this + //specific case + TiXmlElement * values = pParam->FirstChildElement("values"); + + if (values) + { + //Loop over value + TiXmlElement * pValue = values->FirstChildElement("value"); + while(pValue) + { + cmdLine << pValue->GetText(); + cmdLine << " "; + + pValue = pValue->NextSiblingElement(); // iteration over multiple values + } + } + else + { + //Get parameter value + cmdLine << pParam->FirstChildElement("value")->GetText(); + cmdLine << " "; + + //In case of OutputImageparameter we need to report output pixel type + TiXmlElement * pPixType = pParam->FirstChildElement("pixtype"); + + if (pPixType) + { + cmdLine << pPixType->GetText(); + cmdLine << " "; + } + } + + pParam = pParam->NextSiblingElement(); // iteration over parameters + } + + //Insert a new line character at the end of the command line + cmdLine << std::endl; + + //Report the command line string to the application logger + m_Application->GetLogger()->Write(itk::LoggerBase::INFO, cmdLine.str()); + } + // launch the output image writing AppliThread * taskAppli = new AppliThread( m_Application ); @@ -89,26 +179,45 @@ QtWidgetModel SLOT( OnApplicationExecutionDone( int ) ) ); - taskAppli->Execute(); + QObject::connect( + taskAppli, + SIGNAL( finished() ), + taskAppli, + SLOT( deleteLater() ) + ); // Tell the Progress Reporter to begin emit SetProgressReportBegin(); + + taskAppli->Execute(); } void QtWidgetModel ::OnApplicationExecutionDone( int status ) { - m_IsRunning = false; + // For the progressReport to close the Progress widget + // and the GUI to update message + emit SetProgressReportDone( status ); - // Require GUI update. - NotifyUpdate(); + if (status >= 0) + { + std::ostringstream oss; + oss << "Execution took "<< m_Application->GetLastExecutionTiming() << " sec"; + SendLogINFO(oss.str()); + } - // For the view to activate the button "Execute" - emit SetApplicationReady( true ); + // start timer + m_Timer->start(); +} - // For the progressReport to close the Progress widget - emit SetProgressReportDone( status ); +void +QtWidgetModel +::TimerDone() +{ + m_IsRunning = false; + // Require GUI update. + NotifyUpdate(); } void diff --git a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetParameterGroup.cxx b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetParameterGroup.cxx index fbb113c46ad3b7b0c6cf77cb76e6cef45d54effa..872b4b4703e65e59603ed19359ebaaae77d4f86d 100644 --- a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetParameterGroup.cxx +++ b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetParameterGroup.cxx @@ -55,6 +55,7 @@ void QtWidgetParameterGroup::DoCreateWidget() for (unsigned int i = 0; i < nbParams; ++i) { Parameter* param = m_ParamList->GetParameterByIndex(i); + Parameter* rawParam = m_ParamList->GetParameterByIndex(i,false); if (param != ITK_NULLPTR) { @@ -70,7 +71,7 @@ void QtWidgetParameterGroup::DoCreateWidget() if (paramAsGroup == ITK_NULLPTR && paramAsChoice == ITK_NULLPTR && !paramIsXML) { // Label (col 1) - QWidget* label = new QtWidgetParameterLabel( param ); + QWidget* label = new QtWidgetParameterLabel( rawParam ); gridLayout->addWidget(label, i, 1); // Parameter Widget (col 2) @@ -149,7 +150,7 @@ void QtWidgetParameterGroup::DoCreateWidget() } connect(group, SIGNAL(clicked(bool)), specificWidget, SLOT(SetActivationState(bool))); - group->setTitle(param->GetName()); + group->setTitle(rawParam->GetName()); gridLayout->addWidget(group, i, 0, 1, -1); m_WidgetList.push_back(specificWidget); diff --git a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetParameterLabel.cxx b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetParameterLabel.cxx index 5ca4d2595d7b282f584df8790df03c498f5a3a91..13eb52a04e55b8d9a38b665be0c5828b876abc2c 100644 --- a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetParameterLabel.cxx +++ b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetParameterLabel.cxx @@ -28,7 +28,7 @@ QtWidgetParameterLabel::QtWidgetParameterLabel(Parameter* param) QLabel *label = new QLabel; label->setText(param->GetName()); - label->setToolTip(param->GetName()); + label->setToolTip(param->GetKey()); QVBoxLayout *labelLayout = new QVBoxLayout; labelLayout->setSpacing(0); diff --git a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetSimpleProgressReport.cxx b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetSimpleProgressReport.cxx index 75fa895a602ec0abb835af4f8feda79da947ef9c..5aa25cc481d362dbb88b102b2983b7c67f47b392 100644 --- a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetSimpleProgressReport.cxx +++ b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetSimpleProgressReport.cxx @@ -32,7 +32,6 @@ QtWidgetSimpleProgressReport::QtWidgetSimpleProgressReport(QtWidgetModel * model { m_Model = model; connect(model, SIGNAL(SetProgressReportBegin()), this, SLOT(show()) ); - connect(model, SIGNAL(SetProgressReportDone()), this, SLOT(close()) ); connect(model, SIGNAL(SetProgressReportDone()), this, SLOT(Init()) ); connect(this, SIGNAL(AddNewProcessToReport()), this, SLOT(ReportProcess()) ); @@ -90,7 +89,7 @@ void QtWidgetSimpleProgressReport::ReportProcess() void QtWidgetSimpleProgressReport::Init() { m_Bar->setValue(0); - m_Label->setText("No process yet..."); + m_Label->setText("No process"); } } diff --git a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetView.cxx b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetView.cxx index 70ccd2a331329e59acbdfc8a2a6639537eaf27c8..43f7472ca46f7466cbc081fdf698f9e581c5e05d 100644 --- a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetView.cxx +++ b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetView.cxx @@ -40,7 +40,7 @@ QtWidgetView::QtWidgetView(Application* app) QtWidgetView::~QtWidgetView() { - + delete m_Model; } void QtWidgetView::CreateGui() @@ -61,6 +61,7 @@ void QtWidgetView::CreateGui() m_Message = new QLabel("<center><font color=\"#FF0000\">Select parameters</font></center>"); connect( m_Model, SIGNAL(SetApplicationReady(bool)), this, SLOT(UpdateMessageAfterApplicationReady(bool)) ); + connect( m_Model, SIGNAL(SetProgressReportDone(int)), this, SLOT(UpdateMessageAfterExecution(int)) ); mainLayout->addWidget(m_Message); QtWidgetSimpleProgressReport * progressReport = new QtWidgetSimpleProgressReport(m_Model); @@ -86,10 +87,22 @@ void QtWidgetView::UpdateMessageAfterExecuteClicked() m_Message->setText("<center><font color=\"#FF0000\">Running</font></center>"); } +void QtWidgetView::UpdateMessageAfterExecution(int status) +{ + if (status >= 0) + { + m_Message->setText("<center><font color=\"#00A000\">DONE</font></center>"); + } + else + { + m_Message->setText("<center><font color=\"#FF0000\">FAILED !</font></center>"); + } +} + void QtWidgetView::UpdateMessageAfterApplicationReady( bool val ) { if(val == true) - m_Message->setText("<center><font color=\"#00FF00\">Ready to run</font></center>"); + m_Message->setText("<center><font color=\"#00A000\">Ready to run</font></center>"); else m_Message->setText("<center><font color=\"#FF0000\">Select parameters</font></center>"); } @@ -147,7 +160,7 @@ QWidget* QtWidgetView::CreateDoc() QTextDocument * doc = new QTextDocument(); std::string docContain; - ApplicationHtmlDocGenerator::GenerateDoc( m_Application, docContain); + ApplicationHtmlDocGenerator::GenerateDoc( m_Application, docContain, true); doc->setHtml(docContain.c_str()); diff --git a/Modules/Wrappers/QtWidget/test/otbWrapperQtWidgetShowWidget.cxx b/Modules/Wrappers/QtWidget/test/otbWrapperQtWidgetShowWidget.cxx index 21067b3270fd1a8c5311136271a49a97fb3e3837..c19a43065bf43682d6355212ea8247f89e055582 100644 --- a/Modules/Wrappers/QtWidget/test/otbWrapperQtWidgetShowWidget.cxx +++ b/Modules/Wrappers/QtWidget/test/otbWrapperQtWidgetShowWidget.cxx @@ -104,6 +104,8 @@ int otbWrapperQtWidgetShowWidget(int argc, char* argv[]) // clean main window if (mainWindow) delete mainWindow; } + + ApplicationRegistry::CleanRegistry(); if (result) { diff --git a/Modules/Wrappers/SWIG/src/CMakeLists.txt b/Modules/Wrappers/SWIG/src/CMakeLists.txt index af424622ef8ff03ed7f4b925190781038ca03552..9126f98b2d9d21477f3f6cb2efc973f2b74eb6ad 100644 --- a/Modules/Wrappers/SWIG/src/CMakeLists.txt +++ b/Modules/Wrappers/SWIG/src/CMakeLists.txt @@ -28,7 +28,7 @@ if ( OTB_WRAP_PYTHON ) include_directories(${NUMPY_INCLUDE_DIRS}) list(APPEND CMAKE_SWIG_FLAGS "-DOTB_SWIGNUMPY=1") endif() - set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}) + set(CMAKE_SWIG_OUTDIR ${CMAKE_BINARY_DIR}/${OTB_INSTALL_PYTHON_DIR}) set(SWIG_MODULE_otbApplication_EXTRA_DEPS ${CMAKE_CURRENT_SOURCE_DIR}/Python.i ${CMAKE_CURRENT_SOURCE_DIR}/PyCommand.i @@ -36,6 +36,7 @@ if ( OTB_WRAP_PYTHON ) OTBApplicationEngine) SWIG_add_module( otbApplication python otbApplication.i otbApplicationPYTHON_wrap.cxx itkPyCommand.cxx ) SWIG_link_libraries( otbApplication ${PYTHON_LIBRARIES} OTBApplicationEngine ) + set_target_properties(_otbApplication PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SWIG_OUTDIR}) if(MSVC) set_source_files_properties( ${CMAKE_CURRENT_BINARY_DIR}/otbApplicationPYTHON_wrap.cxx COMPILE_FLAGS "/wd4005" ) else() @@ -47,7 +48,9 @@ if ( OTB_WRAP_PYTHON ) TARGET _otbApplication POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Byte-compiling otbApplication.py" - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/CMake/PythonCompile.py otbApplication.py + COMMAND ${PYTHON_EXECUTABLE} + ${CMAKE_SOURCE_DIR}/CMake/PythonCompile.py + ${CMAKE_SWIG_OUTDIR}/otbApplication.py DEPENDS _otbApplication ) @@ -57,8 +60,8 @@ if ( OTB_WRAP_PYTHON ) DESTINATION ${OTB_INSTALL_PYTHON_DIR} COMPONENT RuntimeLibraries ) - install( FILES ${CMAKE_CURRENT_BINARY_DIR}/otbApplication.py - ${CMAKE_CURRENT_BINARY_DIR}/otbApplication.pyc + install( FILES ${CMAKE_SWIG_OUTDIR}/otbApplication.py + ${CMAKE_SWIG_OUTDIR}/otbApplication.pyc DESTINATION ${OTB_INSTALL_PYTHON_DIR} COMPONENT RuntimeLibraries ) diff --git a/Modules/Wrappers/SWIG/src/otbApplication.i b/Modules/Wrappers/SWIG/src/otbApplication.i index c617e05e7220d28d8db455a92f130c8e0ebed7f4..d02d01a36d11aa7119c3eba841824fd6883c51cf 100644 --- a/Modules/Wrappers/SWIG/src/otbApplication.i +++ b/Modules/Wrappers/SWIG/src/otbApplication.i @@ -181,16 +181,11 @@ public: bool IsApplicationReady(); - void SetParameterInt(std::string parameter, int value); - void SetParameterFloat(std::string parameter, float value); - void SetParameterString(std::string parameter, std::string value); - void SetParameterStringList(std::string parameter, std::vector<std::string> value); - - void SetParameterInt(std::string parameter, int value, bool hasUserValueFlag); - void SetParameterFloat(std::string parameter, float value, bool hasUserValueFlag); - void SetParameterString(std::string parameter, std::string value, bool hasUserValueFlag); - void SetParameterStringList(std::string parameter, std::vector<std::string> values, bool hasUserValueFlag); - void SetParameterEmpty(std::string parameter, bool value, bool hasUserValueFlag); + void SetParameterInt(std::string parameter, int value, bool hasUserValueFlag = true); + void SetParameterFloat(std::string parameter, float value, bool hasUserValueFlag = true); + void SetParameterString(std::string parameter, std::string value, bool hasUserValueFlag = true); + void SetParameterStringList(std::string parameter, std::vector<std::string> values, bool hasUserValueFlag = true); + void SetParameterEmpty(std::string parameter, bool value, bool hasUserValueFlag = true); void SetParameterOutputImagePixelType(std::string parameter, otb::Wrapper::ImagePixelType pixelType); void SetParameterComplexOutputImagePixelType(std::string parameter, otb::Wrapper::ComplexImagePixelType cpixelType); @@ -209,7 +204,9 @@ public: ComplexInputImageParameter::ImageBaseType * GetParameterComplexOutputImage(std::string parameter); void SetParameterComplexInputImage(std::string parameter, ComplexInputImageParameter::ImageBaseType * inputImage); void AddImageToParameterInputImageList(std::string parameter,InputImageParameter::ImageBaseType * img); - void SetNthParameterInputImageList(std::string parameter, const unsigned int &id, InputImageParameter::ImageBaseType * img); + void AddParameterStringList(std::string parameter,const std::string & str); + void SetNthParameterInputImageList(std::string parameter, const unsigned int &id, InputImageParameter::ImageBaseType * img); + void SetNthParameterStringList(std::string parameter, const unsigned int &id, const std::string& str); void ClearParameterInputImageList(std::string parameter); unsigned int GetNumberOfElementsInParameterInputImageList(std::string parameter); @@ -414,6 +411,7 @@ private: void operator =(const Application&); }; + DECLARE_REF_COUNT_CLASS( Application ) diff --git a/Modules/Wrappers/SWIG/test/python/PythonConnectApplications.py b/Modules/Wrappers/SWIG/test/python/PythonConnectApplications.py index 0b25eb0018f1044a737b69e776df8e6acd1d4393..30a0be351910636d28e5969d050e0df2c3548bd6 100644 --- a/Modules/Wrappers/SWIG/test/python/PythonConnectApplications.py +++ b/Modules/Wrappers/SWIG/test/python/PythonConnectApplications.py @@ -21,6 +21,7 @@ def test(otb, argv): app4.AddImageToParameterInputImageList("il",app2.GetParameterOutputImage("out")); app4.AddImageToParameterInputImageList("il",app3.GetParameterOutputImage("out")); + app4.AddParameterStringList("il",argv[1]) app4.OUT = argv[2] app4.ExecuteAndWriteOutput() diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 9f4946140f5f7ff173446c045420dd4d452eee29..bd8070c1c6eecdcf6b3a75588cd089ac91da989c 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,3 +1,61 @@ +OTB-v.5.10.0 - Changes since version 5.8.0 (February 14th, 2017) +--------------------------------------------------------------- + +* Request for Changes (http://wiki.orfeo-toolbox.org/index.php/Requests_for_Changes): + * Request for Changes-69: Force Monteverdi no-GLSL option (adopted, merged) + * Request for Changes-70: Composite application framework (adopted, merged) + * Request for Changes-71: Enhance class field selection in training applications (adopted, merged) + * Request for Changes-72: Remove JPEG2000ImageIO (adopted, merged) + * Request for Changes-73: Compatibility with muparserx 4.0.7 (last stable release) (adopted, merged) + * Request for Changes-74: Translate the application GUI to the corresponding command line (adopted, merged) + * Request for Changes-75: Monteverdi/App November code sprint (adopted, merged) + * Request for Changes-76: Single band color-mapping in Monteverdi (adopted, merged) + * Request for Changes-77: New application for wavelet and fft domain transform (adopted, merged) + * Request for Changes-78: Refactor TrainImagesClassifier (adopted, merged) + * Request for Changes-79: BundleToPerfectSensor implemented as composite application (adopted, merged) + * Request for Changes-80: Compute sub-sampled Haralick textures (adopted, merged) + +* Bugfixes : + + * Monteverdi + * 0001351: Broken 5.10 standalone package on Linux (missing libstdc++) + * 0001334: On Windows standalone package, selection and drag&drop is broken on Monteverdi layer stack + * 0001338: Monteverdi does not correctly free memory + * 0001345: Wrong behavior of minimum image size for overviews in preference dialog + * 0001320: Pixel picking in Monteverdi is half-pixel shifted + * 0001309: Monteverdi 5.8: cannot drag and drop filename to OTB app + + * OTB-Packaging + * 0001361: _dl_close error message in Linux standalone package when closing the application + * 0001357: segfault when loading OTB applications in linux standalone package + * 0001356: Linux package requires OTB_USE_SYSTEM_GTK=1 on CentOS 7 + * 0001355: Patch to set OTB_APPLICATION_PATH environment variable in monteverdi desktop file + * 0001335: On Windows standalone package, TOC calibration crashes monteverdi + * 0001326: OTB python bindings does not work + * 0001336: setup.sh is missing in Windows standalone packages + * 0001337: On windows standalone package otbcli.bat misses the GDAL_DATA environment variable + * 0001325: libsvm URL in superbuild does not exists anymore + + * OTB-applications + * 0001341: Rescale application does not exactly rescale image + * 0001339: ExtractROI application yields wrong size through python bindings + * 0001321: Unable to apply radiometric calibration to S1A SLC product + * 0001316: Application parameter of type ListView are not export in XML + + * Orfeo Toolbox (OTB) + * 0001317: cmake c and cxx flags are not written in OTBConfig.cmake or UseOTB.cmake + * 0001323: Install monteverdi icons along with the application. + * 0001342: Download of libsvm is failing when (super)building + * 0001331: TrainVectorClassifier: misleading error message + * 0001330: Superbuild crashes with invalid libSVM source link + * 0001327: Quicklook application introduces a shift + * 0001328: OTB 5.8 : superImpose introduce "NODATA" + * 0001319: OTB 5.8 vector Sampler + * 0001324: Add Keywords to desktop entry file. + + * Documentation + * 0001313: Some latex fragments are not rendered in RST cookbook + OTB-v.5.8.0 - Changes since version 5.6.1 (November 8th, 2016) -------------------------------------------------------------- @@ -1299,7 +1357,7 @@ OTB-v.3.14.0 - Changes since version 3.12.0 (2012/07/09) * 0000555: monteverdi -in does not work with JP2 images * 0000560: Monteverdi compilation error * 0000527: While saving dataset with rescaling option, - the channels n° > 3 are incorrect + the channels nb > 3 are incorrect * OTB-applications * 0000518: Missing GDAL dependencies diff --git a/SuperBuild/CMake/External_itk.cmake b/SuperBuild/CMake/External_itk.cmake index 0aa81ff9106c7198e3ad53d75d26c4e1a7ce2ceb..92e674a38f62c4a24731875bf3bc1ab9327777b5 100644 --- a/SuperBuild/CMake/External_itk.cmake +++ b/SuperBuild/CMake/External_itk.cmake @@ -156,11 +156,11 @@ ExternalProject_Add(ITK -DITK_USE_SYSTEM_ZLIB:BOOL=ON -DITK_USE_SYSTEM_TIFF:BOOL=ON -DITK_USE_SYSTEM_PNG:BOOL=ON + -DITK_FORBID_DOWNLOADS:BOOL=ON ${ITK_SB_CONFIG} DEPENDS ${ITK_DEPENDENCIES} CMAKE_COMMAND ${SB_CMAKE_COMMAND} ) -set(ITK_DIFF_FILES ${CMAKE_SOURCE_DIR}/patches/ITK/itk-1-fftw-all.diff) +SUPERBUILD_PATCH_SOURCE(ITK) -SUPERBUILD_PATCH_SOURCE(ITK "" ${ITK_DIFF_FILES}) diff --git a/SuperBuild/CMake/External_libsvm.cmake b/SuperBuild/CMake/External_libsvm.cmake index 3c81b65c05365a8c8520e22e17ec2bc31bcf3e34..34789c84b4481ed1282b270d7ba05f9b5a7c99c2 100644 --- a/SuperBuild/CMake/External_libsvm.cmake +++ b/SuperBuild/CMake/External_libsvm.cmake @@ -4,8 +4,8 @@ SETUP_SUPERBUILD(LIBSVM) ExternalProject_Add(LIBSVM PREFIX LIBSVM - URL "http://www.csie.ntu.edu.tw/~cjlin/libsvm/libsvm-3.20.tar.gz" - URL_MD5 5f088e5f89da1c65b642300c9c5ea772 + URL "https://github.com/cjlin1/libsvm/archive/v322.tar.gz" + URL_MD5 d9617d29efad013573f63ca9a517f490 BINARY_DIR ${LIBSVM_SB_BUILD_DIR} DOWNLOAD_DIR ${DOWNLOAD_LOCATION} INSTALL_DIR ${SB_INSTALL_PREFIX} diff --git a/SuperBuild/CMake/External_muparserx.cmake b/SuperBuild/CMake/External_muparserx.cmake index fe64272d9138f71270efd9940a784f046339c29e..19b9e164c1eef2e3f9192c283c122befaddb7c9f 100644 --- a/SuperBuild/CMake/External_muparserx.cmake +++ b/SuperBuild/CMake/External_muparserx.cmake @@ -2,33 +2,31 @@ INCLUDE_ONCE_MACRO(MUPARSERX) SETUP_SUPERBUILD(MUPARSERX) +package_require_cxx11(MUPARSERX) + +#Don't build muparserx examples set(MUPARSERX_FLAGS) -if(APPLE) - set(MUPARSERX_FLAGS "-DCMAKE_CXX_FLAGS:STRING=-std=c++0x") -endif() +list(APPEND MUPARSERX_FLAGS -DBUILD_EXAMPLES:BOOL=OFF) -# We provide a zip archive of last muparserx release (3.0.5) -# Archive was generated using commit sha on muparserx github page -# Commands to create source archive: -# wget https://github.com/beltoforion/muparserx/archive/2ace83b5411f1ab9940653c2bab0efa5140efb71.zip -# mv 2ace83b5411f1ab9940653c2bab0efa5140efb71.zip muparserx_v3_0_5.zip +if(MSVC AND BUILD_SHARED_LIBS) + list(APPEND MUPARSERX_FLAGS -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS:BOOL=ON) +endif() ExternalProject_Add(MUPARSERX PREFIX MUPARSERX - URL "https://www.orfeo-toolbox.org/packages/muparserx_v3_0_5.zip" - URL_MD5 ad86b88c159ab68f4bfc99d71166e3c5 + URL "https://github.com/beltoforion/muparserx/archive/v4.0.7.zip" + URL_MD5 67819fc478436ea8f647c804e6f2e1a2 BINARY_DIR ${MUPARSERX_SB_BUILD_DIR} INSTALL_DIR ${SB_INSTALL_PREFIX} DOWNLOAD_DIR ${DOWNLOAD_LOCATION} - CMAKE_CACHE_ARGS ${SB_CMAKE_CACHE_ARGS} ${MUPARSERX_FLAGS} + CMAKE_CACHE_ARGS + ${SB_CMAKE_CACHE_ARGS} + ${MUPARSERX_FLAGS} CMAKE_COMMAND ${SB_CMAKE_COMMAND} DEPENDS ${MUPARSERX_DEPENDENCIES} - PATCH_COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_SOURCE_DIR}/patches/MUPARSERX/CMakeLists.txt - ${MUPARSERX_SB_SRC} - UPDATE_COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_SOURCE_DIR}/patches/MUPARSERX/mpParserMessageProvider.cpp - ${MUPARSERX_SB_SRC}/parser/ ) -SUPERBUILD_UPDATE_CMAKE_VARIABLES(MUPARSERX FALSE) \ No newline at end of file +#Patch mpParserMessageProvider.cpp. This patch is integrated upstream but not yet released (last release is 4.0.7) +SUPERBUILD_PATCH_SOURCE(MUPARSERX) + +SUPERBUILD_UPDATE_CMAKE_VARIABLES(MUPARSERX FALSE muparserx muparserx) diff --git a/SuperBuild/CMake/External_otb.cmake b/SuperBuild/CMake/External_otb.cmake index 860e33a73ad65d42453b5704288980631a7d94ce..6720cf30b02a00b8f87fef34d7e66df36f901c97 100644 --- a/SuperBuild/CMake/External_otb.cmake +++ b/SuperBuild/CMake/External_otb.cmake @@ -187,7 +187,6 @@ ExternalProject_Add(OTB -DOTB_USE_MUPARSERX:BOOL=${OTB_USE_MUPARSERX} -DOTB_USE_OPENCV:BOOL=${OTB_USE_OPENCV} -DOTB_USE_SHARK:BOOL=${OTB_USE_SHARK} - -DOTB_USE_OPENJPEG:BOOL=OFF -DOTB_USE_QT4:BOOL=${OTB_USE_QT4} -DOTB_USE_SIFTFAST:BOOL=${OTB_USE_SIFTFAST} -DOTB_USE_OPENGL:BOOL=${OTB_USE_OPENGL} @@ -202,6 +201,7 @@ ExternalProject_Add(OTB ${OTB_ADDITIONAL_CACHE} CMAKE_ARGS ${OTB_SB_CONFIG} CMAKE_COMMAND ${SB_CMAKE_COMMAND} + LOG_CONFIGURE 1 ) diff --git a/SuperBuild/CMake/External_pkgtools.cmake b/SuperBuild/CMake/External_pkgtools.cmake index ebef802c129cd99d86114164f941ca77d22c0a8b..1f7ef735f91a6aefad3464449ce109ae10dd2b2d 100644 --- a/SuperBuild/CMake/External_pkgtools.cmake +++ b/SuperBuild/CMake/External_pkgtools.cmake @@ -1,3 +1,24 @@ + +set(PKGTOOLS_SB_PREFIX_DIR "${CMAKE_BINARY_DIR}/PACKAGE-TOOLS") + +set(PATCHELF_SOURCE_DIR "${PKGTOOLS_SB_PREFIX_DIR}/src/patchelf") +# PATCHELF_BINARY_DIR is same as PATCHELF_SOURCE_DIR +set(PATCHELF_INSTALL_DIR "${PKGTOOLS_SB_PREFIX_DIR}/install/patchelf") +set(PATCHELF_STAMP_DIR "${PKGTOOLS_SB_PREFIX_DIR}/stamp/patchelf") +set(PATCHELF_TMP_DIR "${PKGTOOLS_SB_PREFIX_DIR}/tmp/patchelf") + +#This variable is referenced in CreateCMakeProjects.cmake +set(PATCHELF_PROGRAM "${PATCHELF_SOURCE_DIR}/src/patchelf") + + +set(MAKESELF_SOURCE_DIR "${PKGTOOLS_SB_PREFIX_DIR}/src/makeself") +# MAKESELF_SOURCE_DIR is same as MAKESELF_BINARY_DIR and MAKESELF_INSTALL_DIR +set(MAKESELF_STAMP_DIR "${PKGTOOLS_SB_PREFIX_DIR}/stamp/makeself") +set(MAKESELF_TMP_DIR "${PKGTOOLS_SB_PREFIX_DIR}/tmp/makeself") + +#This variable is referenced in CreateCMakeProjects.cmake +set(MAKESELF_SCRIPT "${MAKESELF_SOURCE_DIR}/makeself.sh") + if( __EXTERNAL_PACKAGE_TOOLS__) return() else() @@ -9,57 +30,41 @@ if(WIN32) return() endif() -if(UNIX AND NOT WIN32) - - include(ExternalProject) - - set(PKGTOOLS_SB_PREFIX_DIR "${CMAKE_BINARY_DIR}/PACKAGE-TOOLS") +include(ExternalProject) - if(APPLE) - add_custom_target(PATCHELF) - else() - set(PATCHELF_INSTALL_DIR ${PKGTOOLS_SB_PREFIX_DIR}/install-patchelf) - set(PATCHELF_PROGRAM ${PATCHELF_INSTALL_DIR}/patchelf) - ExternalProject_Add(PATCHELF - PREFIX "${PKGTOOLS_SB_PREFIX_DIR}" - URL "http://nixos.org/releases/patchelf/patchelf-0.9/patchelf-0.9.tar.bz2" - URL_MD5 d02687629c7e1698a486a93a0d607947 - DOWNLOAD_DIR ${DOWNLOAD_LOCATION} - SOURCE_DIR "${PKGTOOLS_SB_PREFIX_DIR}/src-patchelf" - BINARY_DIR "${PKGTOOLS_SB_PREFIX_DIR}/build-patchelf" - TMP_DIR "${PKGTOOLS_SB_PREFIX_DIR}/tmp-patchelf" - STAMP_DIR "${PKGTOOLS_SB_PREFIX_DIR}/stamp-patchelf" - PATCH_COMMAND ${CMAKE_COMMAND} -E make_directory ${PKGTOOLS_SB_PREFIX_DIR}/install - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E chdir ${PKGTOOLS_SB_PREFIX_DIR}/src-patchelf - ./configure --prefix ${PATCHELF_INSTALL_DIR} - BUILD_COMMAND ${CMAKE_COMMAND} -E chdir ${PKGTOOLS_SB_PREFIX_DIR}/src-patchelf ${CMAKE_MAKE_PROGRAM} - INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ${PKGTOOLS_SB_PREFIX_DIR}/src-patchelf/src/patchelf ${PATCHELF_PROGRAM} - ) - endif(APPLE) - set(MAKESELF_INSTALL_DIR ${PKGTOOLS_SB_PREFIX_DIR}/install-makeself) - set(MAKESELF_SCRIPT ${MAKESELF_INSTALL_DIR}/makeself.sh) - set(MAKESELF_HEADER_SCRIPT ${MAKESELF_INSTALL_DIR}/makeself-header.sh) - - ExternalProject_Add(MAKESELF +if(APPLE) + add_custom_target(PATCHELF) +else() + ExternalProject_Add(PATCHELF PREFIX "${PKGTOOLS_SB_PREFIX_DIR}" - URL "https://www.orfeo-toolbox.org/packages/makeself-2.2.0.tar.gz" - URL_MD5 3c61df934b0c61ddcd7bd63b391e951d - DOWNLOAD_DIR ${DOWNLOAD_LOCATION} - SOURCE_DIR "${PKGTOOLS_SB_PREFIX_DIR}/src-makeself" - BINARY_DIR "${PKGTOOLS_SB_PREFIX_DIR}/build-makeself" - TMP_DIR "${PKGTOOLS_SB_PREFIX_DIR}/tmp-makeself" - STAMP_DIR "${PKGTOOLS_SB_PREFIX_DIR}/stamp-makeself" - CONFIGURE_COMMAND "" - BUILD_COMMAND ${CMAKE_COMMAND} -E copy - ${PKGTOOLS_SB_PREFIX_DIR}/src-makeself/makeself-header.sh - ${MAKESELF_HEADER_SCRIPT} - INSTALL_COMMAND ${CMAKE_COMMAND} -E copy - ${PKGTOOLS_SB_PREFIX_DIR}/src-makeself/makeself.sh - ${MAKESELF_SCRIPT} - DEPENDS PATCHELF + URL "http://nixos.org/releases/patchelf/patchelf-0.9/patchelf-0.9.tar.bz2" + URL_MD5 d02687629c7e1698a486a93a0d607947 + DOWNLOAD_DIR "${DOWNLOAD_LOCATION}" + SOURCE_DIR "${PATCHELF_SOURCE_DIR}" + BINARY_DIR "${PATCHELF_SOURCE_DIR}" + INSTALL_DIR "${PATCHELF_INSTALL_DIR}" + STAMP_DIR "${PATCHELF_STAMP_DIR}" + TMP_DIR "${PATCHELF_TMP_DIR}" + CONFIGURE_COMMAND "./configure" "--prefix" "${PATCHELF_INSTALL_DIR}" + INSTALL_COMMAND "" ) +endif() - add_custom_target(PACKAGE-TOOLS DEPENDS MAKESELF) +ExternalProject_Add(MAKESELF + PREFIX "${PKGTOOLS_SB_PREFIX_DIR}" + URL "https://www.orfeo-toolbox.org/packages/makeself-2.2.0.tar.gz" + URL_MD5 3c61df934b0c61ddcd7bd63b391e951d + DOWNLOAD_DIR "${DOWNLOAD_LOCATION}" + SOURCE_DIR "${MAKESELF_SOURCE_DIR}" + BINARY_DIR "${MAKESELF_SOURCE_DIR}" + INSTALL_DIR "${MAKESELF_SOURCE_DIR}" + STAMP_DIR "${MAKESELF_STAMP_DIR}" + TMP_DIR "${MAKESELF_TMP_DIR}" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + DEPENDS PATCHELF + ) -endif(UNIX AND NOT WIN32) +add_custom_target(PACKAGE-TOOLS DEPENDS MAKESELF) diff --git a/SuperBuild/CMake/External_proj.cmake b/SuperBuild/CMake/External_proj.cmake index ff30d40bb0db554c8f508c205690124d75f07640..032a58d986a3d948f5ed21451955915550133df8 100644 --- a/SuperBuild/CMake/External_proj.cmake +++ b/SuperBuild/CMake/External_proj.cmake @@ -18,6 +18,12 @@ if(MSVC) else() + if(APPLE) + set(PROJ_SB_ENV_CONFIGURE_CMD ${SB_ENV_CONFIGURE_CMD} LDFLAGS=-headerpad_max_install_names) + else() + set(PROJ_SB_ENV_CONFIGURE_CMD ${SB_ENV_CONFIGURE_CMD}) + endif() + ExternalProject_Add(PROJ PREFIX PROJ URL "http://download.osgeo.org/proj/proj-4.8.0.tar.gz" diff --git a/SuperBuild/CMake/External_qt4.cmake b/SuperBuild/CMake/External_qt4.cmake index 639734156bf662ef445d3e7c6580bf36d1ddfc9c..cffeefa9231eb2f02a4235a6e6d2c37d702e1ecc 100644 --- a/SuperBuild/CMake/External_qt4.cmake +++ b/SuperBuild/CMake/External_qt4.cmake @@ -11,7 +11,7 @@ SETUP_SUPERBUILD(QT4) # endif() -option(QT4_SB_ENABLE_GTK "Enable GTK+ style with qt using -gtkstlye. Default is OFF" OFF) +set(QT4_SB_ENABLE_GTK OFF CACHE INTERNAL "Enable GTK+ style with qt using -gtkstlye. Default is OFF") if(NOT DEFINED git_protocol) set(git_protocol "git") @@ -34,7 +34,8 @@ if(UNIX) set(QT4_SB_CONFIG "${QT4_SB_CONFIG} -no-framework") else() #Linux if(QT4_SB_ENABLE_GTK) - message(STATUS "QT4_SB_ENABLE_GTK is activated. QT4 build includes gtk+ and libfreetype, libpng (dependencies of gtk+ package)") + message(WARNING "QT4_SB_ENABLE_GTK support is experimental") + set(QT4_SB_CONFIG "${QT4_SB_CONFIG} -sm -xrender -xrandr -gtkstyle") else() set(QT4_SB_CONFIG "${QT4_SB_CONFIG} -no-gtkstyle") @@ -64,6 +65,10 @@ else() set(QT4_CONFIGURE_COMMAND_IN ${CMAKE_SOURCE_DIR}/patches/QT4/configure_qt4.sh.in) endif() +if(EXISTS "${QT4_CONFIGURE_COMMAND}") + execute_process(COMMAND ${CMAKE_COMMAND} -E remove -f "${QT4_CONFIGURE_COMMAND}") +endif() + configure_file(${QT4_CONFIGURE_COMMAND_IN} ${QT4_CONFIGURE_COMMAND} @ONLY ) #Remove left over or previous installation from install prefix. diff --git a/SuperBuild/CMake/SuperBuild_Macro.cmake b/SuperBuild/CMake/SuperBuild_Macro.cmake index cabeeec69e7811f2b207b062b89f3e33b236163a..66438bd05befef7dbf82bd13c202ee0d70ffd1d5 100644 --- a/SuperBuild/CMake/SuperBuild_Macro.cmake +++ b/SuperBuild/CMake/SuperBuild_Macro.cmake @@ -148,16 +148,16 @@ endmacro(SUPERBUILD_PATCH_SOURCE) macro(SUPERBUILD_UPDATE_CMAKE_VARIABLES PROJECT with_prefix) - if("${ARGV3}" STREQUAL "") + if("${ARGV2}" STREQUAL "") string(TOLOWER ${PROJECT} lib_file_we) else() - set(lib_file_we "${ARGV3}") + set(lib_file_we "${ARGV2}") endif() - if("${ARGV4}" STREQUAL "") + if("${ARGV3}" STREQUAL "") set(include_dir "include") else() - set(include_dir "include/${ARGV4}") + set(include_dir "include/${ARGV3}") endif() if(WIN32) diff --git a/SuperBuild/CMake/post_install.cmake b/SuperBuild/CMake/post_install.cmake new file mode 100644 index 0000000000000000000000000000000000000000..603c8c24e5b86fbd4f1266a9a06d9c7642a961ef --- /dev/null +++ b/SuperBuild/CMake/post_install.cmake @@ -0,0 +1,26 @@ +#check variables are set +foreach(var P_DIRS P_MATCH P_REPLACE) + if(NOT ${var}) + message(FATAL_ERROR "${var} not set") + endif() +endforeach() + +string(REPLACE "|" ";" P_DIRS ${P_DIRS}) + + +foreach( p_dir ${P_DIRS} ) +set(file_list) +file( GLOB file_list "${p_dir}/*.cmake" ) +list(SORT file_list) +foreach( cmake_file ${file_list} ) + + file(STRINGS "${cmake_file}" MATCH_FOUND REGEX "${P_MATCH}") + if(MATCH_FOUND) + message("Replacing '${P_MATCH}' with '${P_REPLACE}' in ${cmake_file}") + file(STRINGS "${cmake_file}" cmake_file_CONTENTS NEWLINE_CONSUME) + string(REPLACE "${P_MATCH}" "$${}{${P_REPLACE}}" cmake_file_CONTENTS ${cmake_file_CONTENTS}) + file(WRITE "${cmake_file}" "# This file is modified by OTB after installation. + \n${cmake_file_CONTENTS}") + endif() +endforeach() # foreach( cmake_file +endforeach() # foreach( p_dir diff --git a/SuperBuild/Packaging/CMakeLists.txt b/SuperBuild/Packaging/CMakeLists.txt index 391bc3e2c3136245086b7bcf710b1142bbb00a45..ce9f3eeb6d4f0cdc5f7e120557a30bf08fa99c6c 100644 --- a/SuperBuild/Packaging/CMakeLists.txt +++ b/SuperBuild/Packaging/CMakeLists.txt @@ -4,7 +4,6 @@ # stop generation of msvc packages for windows. 04-apr-2016. point OTB. ##### check if standalone project ###### -set(PACKAGE_OTB_SRC_DIR) set(OUT_OF_SOURCE_BUILD FALSE) if(NOT PROJECT_NAME) cmake_minimum_required(VERSION 2.6) @@ -32,7 +31,7 @@ if(NOT PROJECT_NAME) mark_as_advanced(PYTHON_LIBRARY) endif() - if(WIN32 AND NOT MSVC) + if(OTB_MINGW) set(OTB_BINARY_DIR "" CACHE PATH "OTB binary directory") set(OTB_INSTALL_DIR "" CACHE PATH "OTB install directory") else() @@ -61,21 +60,24 @@ if(NOT GENERATE_PACKAGE AND NOT GENERATE_XDK) return() endif() +set(LINUX FALSE) +set(OTB_MINGW FALSE) if(WIN32 AND NOT MSVC) - if(NOT MXE_TARGET_DIR) - message(FATAL_ERROR "you must set MXE_TARGET_DIR") + set(OTB_MINGW TRUE) +else() + if( "${CMAKE_SYSTEM_NAME}" MATCHES "Linux") + set(LINUX TRUE) endif() endif() -if(NOT PACKAGE_OTB_SRC_DIR) - message(FATAL_ERROR "you must set PACKAGE_OTB_SRC_DIR") -endif() +find_program(FILE_COMMAND "file") +mark_as_advanced(FILE_COMMAND) set(SUPERBUILD_SOURCE_DIR ${PACKAGE_OTB_SRC_DIR}/SuperBuild) include(${SUPERBUILD_SOURCE_DIR}/CMake/SuperBuild_Macro.cmake) include(${PACKAGE_OTB_SRC_DIR}/CMake/OTBCheckTargetSystemArch.cmake) -include(${CMAKE_CURRENT_SOURCE_DIR}/PMacros.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/CreateCMakeProjects.cmake) if(WIN32) set(ZIP_EXE_NAMES 7z 7za) @@ -85,19 +87,22 @@ if(WIN32) endif() endif() -if(WIN32 AND NOT MSVC) +if(OTB_MINGW) set(required_vars - PACKAGE_OTB_SRC_DIR OTB_BINARY_DIR OTB_INSTALL_DIR + MXE_TARGET_DIR + ) +else() + set(required_vars + SUPERBUILD_BINARY_DIR + SUPERBUILD_INSTALL_DIR + SUPERBUILD_SOURCE_DIR ) endif() foreach(req ${required_vars} - SUPERBUILD_BINARY_DIR - SUPERBUILD_INSTALL_DIR - SUPERBUILD_SOURCE_DIR PACKAGE_OTB_SRC_DIR OTB_TARGET_SYSTEM_ARCH OTB_TARGET_SYSTEM_ARCH_IS_X64 @@ -110,6 +115,8 @@ endforeach(req) message("\n${vars}\n") +set(PKG_DEBUG OFF) + set(EXTRA_CACHE_CONFIG) set(CMAKE_INSTALL_PREFIX "${SUPERBUILD_INSTALL_DIR}") @@ -117,12 +124,19 @@ set(CMAKE_INSTALL_PREFIX "${SUPERBUILD_INSTALL_DIR}") set(PACKAGE_LONG_NAME OrfeoToolBox) # Make up part of output package file +set(NAME_SUFFIX "" CACHE STRING "extra suffix for package name") + set(PACKAGE_NAME OTB) + +if(NAME_SUFFIX) + set(PACKAGE_NAME OTB${NAME_SUFFIX}) +endif() + if(APPLE) set(PACKAGE_PLATFORM_NAME "Darwin") elseif(WIN32) set(PACKAGE_PLATFORM_NAME "win") -elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") +elseif(LINUX) set(PACKAGE_PLATFORM_NAME "Linux") endif() @@ -131,13 +145,13 @@ if(OTB_TARGET_SYSTEM_ARCH_IS_X64) set(PACKAGE_ARCH "64") endif() -if(MINGW) +if(OTB_MINGW) get_filename_component(MXE_MXEROOT ${MXE_TARGET_DIR} PATH) get_filename_component(MXE_MXEROOT ${MXE_MXEROOT} PATH) set(EXTRA_CACHE_CONFIG "set(CMAKE_CROSSCOMPILING TRUE) set(WIN32 TRUE) - set(MXE_ARCH \"${MXE_ARCH}\") + set(MINGW TRUE) set(MXE_MXEROOT \"${MXE_MXEROOT}\")" ) set(CMAKE_INSTALL_PREFIX "${OTB_INSTALL_DIR}") @@ -145,7 +159,7 @@ endif() # get itk version from External_itk.cmake if not on mingw # because mxe has different version -if(NOT MINGW) +if(NOT OTB_MINGW) get_version( INPUT_FILE "${SUPERBUILD_SOURCE_DIR}/CMake/External_itk.cmake" MATCH_STRINGS "SB_ITK_VERSION_MAJOR" "SB_ITK_VERSION_MINOR" @@ -165,10 +179,10 @@ get_version( set(PKG_OTB_VERSION_STRING ${PKG_OTB_VERSION_MAJOR}.${PKG_OTB_VERSION_MINOR}.${PKG_OTB_VERSION_PATCH}) -if(MINGW) +if(OTB_MINGW) set(OTB_BINARY_DIR "${OTB_BINARY_DIR}") set(OTB_INSTALL_DIR "${OTB_INSTALL_DIR}") - set(DEPENDENCIES_INSTALL_DIR "${MXE_MXEROOT}/usr/${MXE_ARCH}-w64-mingw32.shared") + set(DEPENDENCIES_INSTALL_DIR "${MXE_MXEROOT}/usr/${OTB_TARGET_SYSTEM_ARCH}-w64-mingw32.shared") set(QT_PLUGINS_DIR "${DEPENDENCIES_INSTALL_DIR}/qt/plugins") set(QT_TRANSLATIONS_DIR "${DEPENDENCIES_INSTALL_DIR}/qt/translations") else() #unixes diff --git a/SuperBuild/Packaging/PMacros.cmake b/SuperBuild/Packaging/CreateCMakeProjects.cmake similarity index 68% rename from SuperBuild/Packaging/PMacros.cmake rename to SuperBuild/Packaging/CreateCMakeProjects.cmake index f2fae4528e7d55de7b1f45174248310e207cb31f..69649513442b7122cf8484203ab13abd24e64cb1 100644 --- a/SuperBuild/Packaging/PMacros.cmake +++ b/SuperBuild/Packaging/CreateCMakeProjects.cmake @@ -2,6 +2,8 @@ macro(macro_setup_cmake_project pkg) message( "-- Configuring ${pkg} package") + set(PATCHELF_PROGRAM) + set(MAKESELF_SCRIPT) include(${SUPERBUILD_SOURCE_DIR}/CMake/External_pkgtools.cmake) #reset it again in macro(macro_create_targets_for_package pkg) @@ -9,18 +11,17 @@ macro(macro_setup_cmake_project pkg) set(PACKAGE_PROJECT_DIR ${CMAKE_BINARY_DIR}/PACKAGE-${pkg}) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${PACKAGE_PROJECT_DIR}/build") - if("${pkg}" STREQUAL "XDK") - set(archive_name ${PACKAGE_NAME}-${PKG_OTB_VERSION_STRING}-xdk-${PACKAGE_PLATFORM_NAME}${PACKAGE_ARCH}) - else() - set(archive_name ${PACKAGE_NAME}-${PKG_OTB_VERSION_STRING}-${PACKAGE_PLATFORM_NAME}${PACKAGE_ARCH}) - endif() - - if("${pkg}" STREQUAL "XDK") + if("${pkg}" STREQUAL "XDK") set(PKG_GENERATE_XDK ON) else() set(PKG_GENERATE_XDK OFF) endif() - + + if(PKG_GENERATE_XDK) + set(archive_name ${PACKAGE_NAME}-${PKG_OTB_VERSION_STRING}-xdk-${PACKAGE_PLATFORM_NAME}${PACKAGE_ARCH}) + else() + set(archive_name ${PACKAGE_NAME}-${PKG_OTB_VERSION_STRING}-${PACKAGE_PLATFORM_NAME}${PACKAGE_ARCH}) + endif() #set archive name inside loop file(WRITE "${PACKAGE_PROJECT_DIR}/src/CMakeLists.txt" @@ -29,6 +30,7 @@ macro(macro_setup_cmake_project pkg) include(CMakeDetermineSystem) set(CMAKE_BUILD_TYPE Release) set(PACKAGE_OTB_SRC_DIR \"${PACKAGE_OTB_SRC_DIR}\") + set(SUPERBUILD_BINARY_DIR \"${SUPERBUILD_BINARY_DIR}\") set(OTB_BINARY_DIR \"${OTB_BINARY_DIR}\") set(OTB_INSTALL_DIR \"${OTB_INSTALL_DIR}\") set(QT_PLUGINS_DIR \"${QT_PLUGINS_DIR}\") @@ -42,42 +44,50 @@ macro(macro_setup_cmake_project pkg) set(PKG_OTB_VERSION_PATCH \"${PKG_OTB_VERSION_PATCH}\") set(PKG_OTB_VERSION_STRING \"${PKG_OTB_VERSION_STRING}\") set(PYTHON_EXECUTABLE \"${PYTHON_EXECUTABLE}\") + set(PATCHELF_PROGRAM \"${PATCHELF_PROGRAM}\") set(PKG_GENERATE_XDK ${PKG_GENERATE_XDK}) - set(PATCHELF_PROGRAM ${PATCHELF_PROGRAM}) set(OTB_TARGET_SYSTEM_ARCH ${OTB_TARGET_SYSTEM_ARCH}) set(OTB_TARGET_SYSTEM_ARCH_IS_X64 ${OTB_TARGET_SYSTEM_ARCH_IS_X64}) set(OTB_WRAP_PYTHON ${OTB_WRAP_PYTHON}) + set(PKG_DEBUG ${PKG_DEBUG}) + set(FILE_COMMAND \"${FILE_COMMAND}\") ${EXTRA_CACHE_CONFIG} + include(${SUPERBUILD_SOURCE_DIR}/Packaging/PackageMacros.cmake) include(${SUPERBUILD_SOURCE_DIR}/Packaging/PackageHelper.cmake) + include(${SUPERBUILD_SOURCE_DIR}/Packaging/InstallSupportFiles.cmake) + include(${SUPERBUILD_SOURCE_DIR}/Packaging/PackageGlobals.cmake) macro_super_package(STAGE_DIR \"${archive_name}\")" ) - if(UNIX) - if(APPLE) - set(README_FILE ${PACKAGE_OTB_SRC_DIR}/Documentation/Cookbook/rst/Installation_Macx.txt) - else() #not osx - set(README_FILE ${PACKAGE_OTB_SRC_DIR}/Documentation/Cookbook/rst/Installation_Linux.txt) - endif() #if(APPLE) - else() #windows - set(README_FILE ${PACKAGE_OTB_SRC_DIR}/Documentation/Cookbook/rst/Installation_Windows.txt) - endif() #if(UNIX) - - configure_file( - "${README_FILE}" - ${PACKAGE_PROJECT_DIR}/src/README - ) +set(README_FILE_SUFFIX) +if(PKG_GENERATE_XDK) + set(README_FILE_SUFFIX "_xdk") +endif() +if(APPLE) + set(README_FILE ${PACKAGE_OTB_SRC_DIR}/Documentation/Cookbook/rst/Installation_Macx${README_FILE_SUFFIX}.txt) +elseif(LINUX) #not osx + set(README_FILE ${PACKAGE_OTB_SRC_DIR}/Documentation/Cookbook/rst/Installation_Linux${README_FILE_SUFFIX}.txt) +elseif(WIN32) #windows + set(README_FILE ${PACKAGE_OTB_SRC_DIR}/Documentation/Cookbook/rst/Installation_Windows${README_FILE_SUFFIX}.txt) +endif() + +configure_file( + "${README_FILE}" + ${PACKAGE_PROJECT_DIR}/src/README + ) - macro_create_targets_for_package(${pkg}) +macro_create_targets_for_package(${pkg}) endmacro() macro(macro_create_targets_for_package pkg) if(WIN32 AND NOT MSVC) - add_custom_target(PACKAGE-${pkg}-check - COMMAND ${CMAKE_COMMAND} --build "." --target install - WORKING_DIRECTORY "${OTB_BINARY_DIR}" - ) + + add_custom_target(PACKAGE-${pkg}-check + COMMAND ${CMAKE_COMMAND} --build "." --target install + WORKING_DIRECTORY "${OTB_BINARY_DIR}" + ) else() #Using SuperBuild #For out of source build, #we assume the otb is built correctly with superbuild @@ -94,32 +104,32 @@ macro(macro_create_targets_for_package pkg) endif() add_dependencies(PACKAGE-${pkg}-check PACKAGE-TOOLS) +# add_dependencies(PACKAGE-${pkg}-check PACKAGE-${pkg}-clean) - if("${pkg}" STREQUAL "XDK") - set(PACKAGE_PLATFORM_NAME_ "xdk-${PACKAGE_PLATFORM_NAME}") - set(PKG_GENERATE_XDK ON) - else() - set(PACKAGE_PLATFORM_NAME_ "${PACKAGE_PLATFORM_NAME}") - set(PKG_GENERATE_XDK OFF) - endif() + if(NOT archive_name) + message(FATAL_ERROR "archive_name not set. Cannot continue") + endif() + set(PACKAGE_PROJECT_DIR ${CMAKE_BINARY_DIR}/PACKAGE-${pkg}) - if("${pkg}" STREQUAL "XDK") - set(archive_name ${PACKAGE_NAME}-${PKG_OTB_VERSION_STRING}-xdk-${PACKAGE_PLATFORM_NAME}${PACKAGE_ARCH}) + + if(WIN32) + set(PACKAGE_OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/${archive_name}.zip") else() - set(archive_name ${PACKAGE_NAME}-${PKG_OTB_VERSION_STRING}-${PACKAGE_PLATFORM_NAME}${PACKAGE_ARCH}) + set(PACKAGE_OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/${archive_name}.run") endif() - + #configure add_custom_target(PACKAGE-${pkg}-configure - COMMAND ${CMAKE_COMMAND} -E make_directory "${PACKAGE_PROJECT_DIR}/build" + COMMAND ${CMAKE_COMMAND} -E remove "${PACKAGE_OUTPUT_FILE}" + COMMAND ${CMAKE_COMMAND} -E make_directory "${PACKAGE_PROJECT_DIR}/build" WORKING_DIRECTORY "${PACKAGE_PROJECT_DIR}" COMMAND ${CMAKE_COMMAND} "-G${CMAKE_GENERATOR}" "${PACKAGE_PROJECT_DIR}/src" WORKING_DIRECTORY "${PACKAGE_PROJECT_DIR}/build" DEPENDS PACKAGE-${pkg}-check ) - +# COMMAND ${CMAKE_COMMAND} -E remove_directory "${PACKAGE_PROJECT_DIR}" #build add_custom_target(PACKAGE-${pkg}-build COMMAND ${CMAKE_COMMAND} @@ -130,13 +140,15 @@ macro(macro_create_targets_for_package pkg) #create package # creation of package is different from windows and unix like + # WORKING_DIRECTORY must be CMAKE_INSTALL_PREFIX and not + # CMAKE_CURRENT_BINARY_DIR like in unix if(WIN32) add_custom_target(PACKAGE-${pkg} COMMAND ${ZIP_EXECUTABLE} "a" "-r" "-y" - "${CMAKE_BINARY_DIR}/${archive_name}.zip" "${archive_name}/*" + "${PACKAGE_OUTPUT_FILE}" "${archive_name}/*" WORKING_DIRECTORY "${CMAKE_INSTALL_PREFIX}" DEPENDS PACKAGE-${pkg}-build - COMMENT "Creating ${CMAKE_BINARY_DIR}/${archive_name}.zip" + COMMENT "Creating ${PACKAGE_OUTPUT_FILE}" ) else() add_custom_target(PACKAGE-${pkg} @@ -150,20 +162,17 @@ macro(macro_create_targets_for_package pkg) "./pkgsetup" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" DEPENDS PACKAGE-${pkg}-build - COMMENT "Creating ${CMAKE_CURRENT_BINARY_DIR}/${archive_name}.run" + COMMENT "Creating ${PACKAGE_OUTPUT_FILE}" ) endif() - set(PACKAGE_EXTENSION .run) - if(WIN32) - set(PACKAGE_EXTENSION .zip) - endif() + #clean add_custom_target(PACKAGE-${pkg}-clean COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/PACKAGE-${pkg}" COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/PACKAGE-TOOLS" - COMMAND ${CMAKE_COMMAND} -E remove "${CMAKE_BINARY_DIR}/${archive_name}${PACKAGE_EXTENSION}" + COMMAND ${CMAKE_COMMAND} -E remove "${PACKAGE_OUTPUT_FILE}" COMMAND ${CMAKE_COMMAND} "${CMAKE_BINARY_DIR}" WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" ) diff --git a/SuperBuild/Packaging/Files/linux_pkgsetup.in b/SuperBuild/Packaging/Files/linux_pkgsetup.in index d99176aaf122bbf95e7addb5a842cd4bf4c9f7c9..98e060f50a62045b1d51137e6dfc681c5ed2ede8 100644 --- a/SuperBuild/Packaging/Files/linux_pkgsetup.in +++ b/SuperBuild/Packaging/Files/linux_pkgsetup.in @@ -8,36 +8,45 @@ cd "$DIRNAME_0" OUT_DIR=$(pwd) -PATCH_ELF_EXE="$OUT_DIR/tools/patchelf" +PATCH_ELF_EXE="$OUT_DIR/patchelf" # No no interference with LD_LIBRARY_PATH LD_LIBRARY_PATH= echo "Configuring..." -BINARY_FILES="@VAR_IN_PKGSETUP_CONFIGURE@" +#see next call below for otb applications +BINARY_FILES=$(find $OUT_DIR/lib $OUT_DIR/bin -maxdepth 1 -type f -exec file {} \; | grep -i elf|cut -f1 -d':') + # run patchelf for bin_file in $BINARY_FILES; do - #echo "adding rpath to $OUT_DIR/$bin_file" - if [ -f "$OUT_DIR/$bin_file" ]; then - "$PATCH_ELF_EXE" "--set-rpath" "$OUT_DIR/lib" "$OUT_DIR/$bin_file" + #echo "adding rpath to $bin_file" + if [ -f "$bin_file" ]; then + "$PATCH_ELF_EXE" "--set-rpath" "$OUT_DIR/lib" "$bin_file" fi done I_AM_XDK=@IS_XDK@ -if [ "$I_AM_XDK" = true ] ; then - sed -i "s,@DEPENDENCIES_INSTALL_DIR@,$OUT_DIR,g" lib/cmake/ITK-@PKG_ITK_SB_VERSION@/Modules/ITKZLIB.cmake - sed -i "s,@DEPENDENCIES_INSTALL_DIR@,$OUT_DIR,g" lib/cmake/ITK-@PKG_ITK_SB_VERSION@/ITKConfig.cmake - sed -i "s,@DEPENDENCIES_INSTALL_DIR@,$OUT_DIR,g" lib/cmake/ITK-@PKG_ITK_SB_VERSION@/ITKTargets-release.cmake -else +# if [ "$I_AM_XDK" = true ] ; then +# sed -i "s,@DEPENDENCIES_INSTALL_DIR@,$OUT_DIR,g" lib/cmake/ITK-@PKG_ITK_SB_VERSION@/Modules/ITKZLIB.cmake +# sed -i "s,@DEPENDENCIES_INSTALL_DIR@,$OUT_DIR,g" lib/cmake/ITK-@PKG_ITK_SB_VERSION@/ITKConfig.cmake +# sed -i "s,@DEPENDENCIES_INSTALL_DIR@,$OUT_DIR,g" lib/cmake/ITK-@PKG_ITK_SB_VERSION@/ITKTargets-release.cmake +# else + +if [ "$I_AM_XDK" = false ] ; then +OTB_APP_FILES=$(find $OUT_DIR/lib/otb/applications -maxdepth 1 -type f -exec file {} \; | grep -i elf|cut -f1 -d':') + # run patchelf +for app_file in $OTB_APP_FILES; do + #echo "adding rpath to $app_file" + if [ -f "$app_file" ]; then + "$PATCH_ELF_EXE" "--set-rpath" "$OUT_DIR/lib" "$app_file" + fi +done cat > "$OUT_DIR/monteverdi.sh" << EOF #!/bin/sh -unset LD_LIBRARY_PATH - -. $OUT_DIR/bin/env_exports -export OTB_APPLICATION_PATH=$OUT_DIR/lib/otb/applications +. $OUT_DIR/otbenv.profile $OUT_DIR/bin/monteverdi "\$@" EOF @@ -46,49 +55,108 @@ chmod +x "$OUT_DIR/monteverdi.sh" cat > "$OUT_DIR/mapla.sh" << EOF #!/bin/sh -unset LD_LIBRARY_PATH - -. $OUT_DIR/bin/env_exports -export OTB_APPLICATION_PATH=$OUT_DIR/lib/otb/applications +. $OUT_DIR/otbenv.profile $OUT_DIR/bin/mapla "\$@" EOF chmod +x "$OUT_DIR/mapla.sh" -cat > "$OUT_DIR/bin/env_exports" << EOF +cat > "$OUT_DIR/otbenv.profile" << EOF #!/bin/sh -export LC_NUMERIC=C +# The below environment variables only affect current shell +# So if you run again from a terminal. you need to run the script again +# see how this is sourced in monteverdi.sh and mapla.sh + +# unset any existing LD_LIBRARY_PATH +unset LD_LIBRARY_PATH + +# if OTB_USE_LOCAL_GTK is set to one, +# we must include <OUT_DIR>/lib/gtk because glib files are +# installed there. -if [ -z "\$OTB_USE_SYSTEM_GTK" ] || [ "\$OTB_USE_SYSTEM_GTK" == "0" ]; then +# OTB_USE_LOCAL_GTK is not set by default (use GTK system) +if [ "\$OTB_USE_LOCAL_GTK" = "1" ]; then LD_LIBRARY_PATH=$OUT_DIR/lib/gtk + export LD_LIBRARY_PATH fi +# check and set OTB_APPLICATION_PATH +if [ -z "\$OTB_APPLICATION_PATH" ] || [ "\$OTB_APPLICATION_PATH" = "" ]; then + OTB_APPLICATION_PATH=$OUT_DIR/lib/otb/applications +else + OTB_APPLICATION_PATH=\$(readlink -f "\$OTB_APPLICATION_PATH") + if ! [ "\$OTB_APPLICATION_PATH" = "$OUT_DIR/lib/otb/applications" ]; then + OTB_APPLICATION_PATH=$OUT_DIR/lib/otb/applications:\$OTB_APPLICATION_PATH + fi +fi + +# Add bin direcotory to system PATH +PATH=$OUT_DIR/bin:\$PATH + +# export PYTHONPATH to import otbApplication.py +PYTHONPATH=$OUT_DIR/lib/python:\$PYTHONPATH + +# set numeric locale to C +LC_NUMERIC=C + +# set GDAL_DATA variable used by otb application GDAL_DATA=$OUT_DIR/share/gdal + +# set GEOTIFF_CSV variable used by otb application GEOTIFF_CSV=$OUT_DIR/share/epsg_csv +# export variables +export LC_NUMERIC export GDAL_DATA export GEOTIFF_CSV -export LD_LIBRARY_PATH +export OTB_APPLICATION_PATH +export PATH +export PYTHONPATH + EOF -cat > "$OUT_DIR/otbenv.profile" << EOF + +chmod +x "$OUT_DIR/otbenv.profile" + +else + +cat > "$OUT_DIR/xdkenv.profile" << EOF #!/bin/sh -PATH=\$PATH:$OUT_DIR/bin -PYTHONPATH=$OUT_DIR/lib/python:\$PYTHONPATH + +# The below environment variables only affect current shell +# So if you run again from a terminal. you need to run the script again + +# unset any existing LD_LIBRARY_PATH +unset LD_LIBRARY_PATH + +# Add bin direcotory to system PATH +PATH=$OUT_DIR/bin:\$PATH + +# set numeric locale to C +LC_NUMERIC=C + +# set GDAL_DATA variable used by otb application GDAL_DATA=$OUT_DIR/share/gdal + +# set GEOTIFF_CSV variable used by otb application GEOTIFF_CSV=$OUT_DIR/share/epsg_csv -export LC_NUMERIC=C -export PATH +CMAKE_PREFIX_PATH=$OUT_DIR + +# export variables +export LC_NUMERIC export GDAL_DATA export GEOTIFF_CSV -export PYTHONPATH +export CMAKE_PREFIX_PATH +export PATH + EOF -chmod +x "$OUT_DIR/otbenv.profile" + +chmod +x "$OUT_DIR/xdkenv.profile" fi @@ -118,7 +186,7 @@ python_patch_version=$($OTB_PYTHON_EXE -c "import sys;print(sys.version_info[2]) python_version="$python_major_version.$python_minor_version.$python_patch_version" python_check_failed() { - printf %s\\n "*****Error occured during installation******" + printf %s\\n "*****Error occurred during installation******" printf %s\\n "OTB python bindings requires python2.6 or python2.7 but current detected python version is $python_version" printf %s\\n "If you have python2.6 or Python2.7 installed in your system " printf %s\\n "You should set OTB_PYTHON_EXE and re-run this installation script." @@ -157,7 +225,7 @@ if [ "$found_python_lib" -eq "1" ]; then printf %s\\n "To test OTB python bindings:" printf %s\\n "$OTB_PYTHON_EXE -c 'import otbApplication'" else - printf %s\\n "*****Error occured during installation******" + printf %s\\n "*****Error occurred during installation******" printf %s\\n "Python interpreter detected is : $OTB_PYTHON_EXE ( version: $python_version )" printf %s\\n "$python_INSTSONAME cannot be found in any of search directories." printf %s\\n "We had searched following directories $python_lib_dirs" diff --git a/SuperBuild/Packaging/Files/macx_pkgsetup.in b/SuperBuild/Packaging/Files/macx_pkgsetup.in index e84321c7174be103eede91cf5da7d3b35cc570be..c196337ae9982275d74a76a3d5589fb29e5b67a8 100755 --- a/SuperBuild/Packaging/Files/macx_pkgsetup.in +++ b/SuperBuild/Packaging/Files/macx_pkgsetup.in @@ -21,30 +21,44 @@ DYLD_LIBRARY_PATH= DYLD_FALLBACK_LIBRARY_PATH= echo "Configuring..." -BINARY_FILES="@VAR_IN_PKGSETUP_CONFIGURE@" -# #add rpath to LC_RPATH using install_name_tool -for bin_file in $BINARY_FILES; do - #echo "adding rpath to $OUT_DIR/$bin_file" - if [ -f "$OUT_DIR/$bin_file" ]; then - $INSTALL_NAME_TOOL "-add_rpath" "$OUT_DIR/lib" "$OUT_DIR/$bin_file" - fi + +LIBRARY_FILES=$(find "$OUT_DIR/lib" -maxdepth 1 -type f) +EXE_FILES=$(find "$OUT_DIR/bin" -type f -exec file {} \; | grep -i "Mach-O*.*executable"|cut -d ':' -f1) +# run install_name_tool +for lib_file in $LIBRARY_FILES $EXE_FILES; do + #echo "adding rpath to $OUT_DIR/$lib_file" + if [ -f "$lib_file" ]; then + #echo "$INSTALL_NAME_TOOL -add_rpath $OUT_DIR/lib $lib_file" + $INSTALL_NAME_TOOL "-add_rpath" "$OUT_DIR/lib" "$lib_file" + fi done + LONG_VERSION_STRING=@Monteverdi_VERSION_MAJOR@.@Monteverdi_VERSION_MINOR@.@Monteverdi_VERSION_PATCH@ SHORT_VERSION_STRING=@Monteverdi_VERSION_MAJOR@.@Monteverdi_VERSION_MINOR@ I_AM_XDK=@IS_XDK@ -if [ "$I_AM_XDK" = true ] ; then - - sed -i "" "s,@DEPENDENCIES_INSTALL_DIR@,$OUT_DIR,g" lib/cmake/ITK-@PKG_ITK_SB_VERSION@/Modules/ITKZLIB.cmake - sed -i "" "s,@DEPENDENCIES_INSTALL_DIR@,$OUT_DIR,g" lib/cmake/ITK-@PKG_ITK_SB_VERSION@/ITKConfig.cmake - sed -i "" "s,@DEPENDENCIES_INSTALL_DIR@,$OUT_DIR,g" lib/cmake/ITK-@PKG_ITK_SB_VERSION@/ITKTargets-release.cmake -else +# if [ "$I_AM_XDK" = true ] ; then + +# sed -i "" "s,@DEPENDENCIES_INSTALL_DIR@,$OUT_DIR,g" lib/cmake/ITK-@PKG_ITK_SB_VERSION@/Modules/ITKZLIB.cmake +# sed -i "" "s,@DEPENDENCIES_INSTALL_DIR@,$OUT_DIR,g" lib/cmake/ITK-@PKG_ITK_SB_VERSION@/ITKConfig.cmake +# sed -i "" "s,@DEPENDENCIES_INSTALL_DIR@,$OUT_DIR,g" lib/cmake/ITK-@PKG_ITK_SB_VERSION@/ITKTargets-release.cmake +# else +if [ "$I_AM_XDK" = false ] ; then + OTB_APP_FILES=$(find "$OUT_DIR/lib/otb/applications" -maxdepth 1 -type f) + # run install_name_tool + for app_file in $OTB_APP_FILES; do + #echo "adding rpath to $app_file" + if [ -f "$app_file" ]; then + $INSTALL_NAME_TOOL "-add_rpath" "$OUT_DIR/lib" "$app_file" + fi + done + rm -fr "Mapla.app" rm -fr "Monteveridi.app" - + mkdir -p "Mapla.app/Contents/MacOS" mkdir -p "Mapla.app/Contents/Resources" mkdir -p "Monteverdi.app/Contents/MacOS" @@ -126,7 +140,7 @@ EOF cat > "$OUT_DIR/otbenv.profile" << EOF #!/bin/sh -PATH=\$PATH:$OUT_DIR/bin +PATH=$OUT_DIR/bin:\$PATH PYTHONPATH=$OUT_DIR/lib/python:\$PYTHONPATH GDAL_DATA=$OUT_DIR/share/gdal GEOTIFF_CSV=$OUT_DIR/share/epsg_csv diff --git a/SuperBuild/Packaging/Files/otbenv.bash b/SuperBuild/Packaging/Files/otbenv.bash new file mode 100644 index 0000000000000000000000000000000000000000..4cc55aeb4034a77fd704fd76e25a5f944d3861f2 --- /dev/null +++ b/SuperBuild/Packaging/Files/otbenv.bash @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +CURRENT_DIR=$(cd -P -- "$(dirname -- "$BASH_SOURCE")" && printf '%s\n' "$(pwd -P)") + +unset LD_LIBRARY_PATH + +PATH=$CURRENT_DIR/bin:$PATH +GDAL_DATA=$CURRENT_DIR/share/gdal +GEOTIFF_CSV=$CURRENT_DIR/share/epsg_csv + +export PATH +export GDAL_DATA +export GEOTIFF_CSV diff --git a/SuperBuild/Packaging/Files/otbenv.cmd b/SuperBuild/Packaging/Files/otbenv.cmd index 493cfbde9719b9e0eb2f064022a58703961a4bc6..e7f605870e79019a5bafb0b018ed3164c355df86 100644 --- a/SuperBuild/Packaging/Files/otbenv.cmd +++ b/SuperBuild/Packaging/Files/otbenv.cmd @@ -1,6 +1,6 @@ set CURRENT_SCRIPT_DIR=%~dp0 -set PATH=%PATH%;%CURRENT_SCRIPT_DIR%\bin +set PATH=%CURRENT_SCRIPT_DIR%\bin;%PATH% set GDAL_DATA=%CURRENT_SCRIPT_DIR%\share\gdal diff --git a/SuperBuild/Packaging/Files/otbenv.profile b/SuperBuild/Packaging/Files/otbenv.profile deleted file mode 100644 index e36e0d62d07e9beb270cae3159ecf586b4431ce6..0000000000000000000000000000000000000000 --- a/SuperBuild/Packaging/Files/otbenv.profile +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -cd `dirname $0` - -CURRENT_DIR=`pwd` - -PATH=$PATH:$CURRENT_DIR/bin -GDAL_DATA=$CURRENT_DIR/share/gdal -GEOTIFF_CSV=$CURRENT_DIR/share/epsg_csv - -export PATH -export GDAL_DATA -export GEOTIFF_CSV diff --git a/SuperBuild/Packaging/InstallSupportFiles.cmake b/SuperBuild/Packaging/InstallSupportFiles.cmake new file mode 100644 index 0000000000000000000000000000000000000000..cd3b76d5b59c7af029b621e560cca8513d44b082 --- /dev/null +++ b/SuperBuild/Packaging/InstallSupportFiles.cmake @@ -0,0 +1,411 @@ +# Get the translation files coming with Qt, and install them in the bundle +# They are loaded by Monteverdi. +function(get_qt_translation_files RESULT) + # These files are the "qt_<localename>.qm" files + # They are located in QT_TRANSLATIONS_DIR, which comes from FindQt4 + file(GLOB translation_files ${QT_TRANSLATIONS_DIR}/qt_*) + + # We need to remove the "qt_help_<localename>.qm" files from this list + foreach(translation_item ${translation_files}) + if(${translation_item} MATCHES "qt_help") + list(REMOVE_ITEM translation_files ${translation_item}) + endif() + endforeach() + + set(${RESULT} ${translation_files} PARENT_SCOPE) + endfunction() + + +function(func_install_xdk_files) + + #The list of REQ_SHARE_DIR is made up from <mxe-target-dir>/share/ + #It may vary in future. I prefer not to glob on the share dir and + #end up distributing man, info etc.. which ar irrelvant for windows + + #TODO: cleaup this function. current + # code is bit of picking each .lib and .dll for now + # see opencv, itk, + foreach(REQ_SHARE_DIR + aclocal + Armadillo + applications + cmake + dbus-1 + fontconfig + libgta + locale + xml + applications + cmake + icons + OpenCV + pixmaps + pkgconfig + ) + if(EXISTS "${DEPENDENCIES_INSTALL_DIR}/share/${REQ_SHARE_DIR}") + func_install_without_message("${DEPENDENCIES_INSTALL_DIR}/share/${REQ_SHARE_DIR}" "share") + endif() + endforeach() + + set(ITK_CMAKE_DIR "${DEPENDENCIES_INSTALL_DIR}/lib/cmake/ITK-${PKG_ITK_SB_VERSION}") + message("COPY ${DEPENDENCIES_INSTALL_DIR}/lib/cmake/ITK-${PKG_ITK_SB_VERSION} to ${CMAKE_CURRENT_BINARY_DIR}/_tmp/ to patch") + execute_process( + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/_tmp/ + COMMAND ${CMAKE_COMMAND} + -E copy_directory + ${ITK_CMAKE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/_tmp/ITK-${PKG_ITK_SB_VERSION} + ) + + #reset ITK_CMAKE_DIR + set(ITK_CMAKE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_tmp/ITK-${PKG_ITK_SB_VERSION}") + + set(DIR_LIST "${CMAKE_CURRENT_BINARY_DIR}/_tmp/ITK-${PKG_ITK_SB_VERSION}|${CMAKE_CURRENT_BINARY_DIR}/_tmp/ITK-${PKG_ITK_SB_VERSION}/Modules") + + #SUPERBUILD_INSTALL_DIR + execute_process( + COMMAND ${CMAKE_COMMAND} + -DP_DIRS=${DIR_LIST} + -DP_MATCH=${CMAKE_INSTALL_PREFIX} + -DP_REPLACE=ITK_INSTALL_PREFIX + -P ${PACKAGE_OTB_SRC_DIR}/SuperBuild/CMake/post_install.cmake + RESULT_VARIABLE patch_itk_cmake_rv + ) + + file(STRINGS "${SUPERBUILD_BINARY_DIR}/ITK/build/CMakeCache.txt" + MATCH_FOUND REGEX "ITK_USE_SYSTEM_ZLIB:BOOL=ON") + if(MATCH_FOUND) + find_package(ZLIB QUIET) + get_filename_component(ZLIB_PREFIX ${ZLIB_LIBRARY} PATH) + execute_process( + COMMAND ${CMAKE_COMMAND} + -DP_DIRS=${DIR_LIST} + -DP_MATCH=${ZLIB_PREFIX} + -DP_REPLACE=ITK_INSTALL_PREFIX + -P ${PACKAGE_OTB_SRC_DIR}/SuperBuild/CMake/post_install.cmake + ) + + endif() + + func_install_without_message("${ITK_CMAKE_DIR}" "lib/cmake") + + set(QT_REQ_DIRS) + if(WIN32) + #only affects windows due to regex on dll + #.lib are not taken when processing dependencies. + # We just get .dlls which is enough for binary package + # For XDK, we need .lib files when building OTB using xdk + # For Linux. we get .so.X.Y.Z by finding the 'target' + # of any .so file. So there is no need for such a copy on + # Linux and OSX + if(MSVC) + file(GLOB LIB_FILES "${DEPENDENCIES_INSTALL_DIR}/lib/*.lib") + else() + file(GLOB LIB_FILES "${DEPENDENCIES_INSTALL_DIR}/lib/*dll.*") + endif() + + foreach(LIB_FILE ${LIB_FILES}) + pkg_install_rule(${LIB_FILE}) + endforeach() + + #qt/bin is also a special case for mxe. + file(GLOB QT_EXTRA_DLL_FILES "${DEPENDENCIES_INSTALL_DIR}/qt/bin/*.dll") + install(FILES ${QT_EXTRA_DLL_FILES} DESTINATION ${PKG_STAGE_DIR}/bin) + + #list(APPEND QT_REQ_DIRS lib) + list(APPEND QT_REQ_DIRS include) + list(APPEND QT_REQ_DIRS imports) + + #mxe installs qt in a separate directory under install prefix. So.. + set(QT_INSTALL_DIR "${DEPENDENCIES_INSTALL_DIR}/qt") + else() + set(QT_INSTALL_DIR "${DEPENDENCIES_INSTALL_DIR}") + + endif(WIN32) + + list(APPEND QT_REQ_DIRS mkspecs) + list(APPEND QT_REQ_DIRS plugins) + list(APPEND QT_REQ_DIRS translations) + foreach(QT_REQ_DIR ${QT_REQ_DIRS} ) + if(EXISTS "${QT_INSTALL_DIR}/${QT_REQ_DIR}") + func_install_without_message("${QT_INSTALL_DIR}/${QT_REQ_DIR}" "") + endif() + endforeach() + + # #install ${DEPENDENCIES_INSTALL_DIR}/include directory. Attention to OTB includes + file(GLOB ALL_IN_INCLUDE_DIR "${DEPENDENCIES_INSTALL_DIR}/include/*") + foreach(INCLUDE_DIR_ITEM ${ALL_IN_INCLUDE_DIR}) + get_filename_component(INCLUDE_DIR_ITEM_name ${INCLUDE_DIR_ITEM} NAME) + get_filename_component(INCLUDE_DIR_ITEM_name_we ${INCLUDE_DIR_ITEM} NAME_WE) + if(NOT "${INCLUDE_DIR_ITEM_name_we}" MATCHES "OTB|otb") + if( IS_DIRECTORY ${INCLUDE_DIR_ITEM}) + install(CODE + "message(STATUS \"Installing: ${CMAKE_INSTALL_PREFIX}/${PKG_STAGE_DIR}/include/${INCLUDE_DIR_ITEM_name}/\")" ) + install( + DIRECTORY "${INCLUDE_DIR_ITEM}" + DESTINATION "${PKG_STAGE_DIR}/include/" + MESSAGE_NEVER + ) + else() + install( + FILES "${INCLUDE_DIR_ITEM}" + DESTINATION "${PKG_STAGE_DIR}/include/" + ) + endif() #if( IS_DIRECTORY + endif() #if (NOT + endforeach() + +endfunction() #func_install_xdk_files + +function(func_install_support_files) + + #a convenient cmake var for storing <prefix>/bin + set(PKG_STAGE_BIN_DIR "${PKG_STAGE_DIR}/bin") + + #<prefix>/share for gdal data files + set(PKG_SHARE_DEST_DIR ${PKG_STAGE_DIR}/share) + + set(PKG_SHARE_SOURCE_DIR ${DEPENDENCIES_INSTALL_DIR}/share) + + set(GDAL_DATA ${PKG_SHARE_SOURCE_DIR}/gdal) + #MSVC install gdal-data in in a different directory. So we don't spoil it + if(MSVC) + set(GDAL_DATA ${DEPENDENCIES_INSTALL_DIR}/data) + endif() + + # Just check if required variables are defined. + foreach(req + DEPENDENCIES_INSTALL_DIR + PKG_STAGE_DIR + PACKAGE_SUPPORT_FILES_DIR + OTB_INSTALL_DIR + ) + if(NOT DEFINED ${req}) + message(FATAL_ERROR "you must set ${req} before calling this method") + endif() + set(vars "${vars} ${req}=[${${req}}]\n") + endforeach(req) + + # one for debugging.. + # install(CODE "message(\"CMake/PackageHelper.cmake:install_supoport_files(${outdir})\n${vars}\n\")") + if(NOT PKG_GENERATE_XDK) + func_install_otb_support_files() + + #check if monteverdi executable is built? + if(EXISTS "${OTB_INSTALL_DIR}/bin/monteverdi${EXE_EXT}") + func_install_monteverdi_support_files() + endif() + + endif() #NOT PKG_GENERATE_XDK + + ####################### install GDAL data ############################ + if(NOT EXISTS "${GDAL_DATA}/epsg.wkt") + message(FATAL_ERROR + "Cannot generate package without GDAL_DATA : ${GDAL_DATA} ${DEPENDENCIES_INSTALL_DIR}") + endif() + + + # install( + # DIRECTORY ${GDAL_DATA} + # DESTINATION ${PKG_SHARE_DEST_DIR} + # ) + + func_install_without_message("${GDAL_DATA}" "share" ) + ####################### install GeoTIFF data ######################## + #install( DIRECTORY ${PKG_SHARE_SOURCE_DIR}/epsg_csv DESTINATION ${PKG_SHARE_DEST_DIR} ) + + func_install_without_message("${PKG_SHARE_SOURCE_DIR}/epsg_csv" "share" ) + + ####################### install OSSIM data ########################## + #install( DIRECTORY ${PKG_SHARE_SOURCE_DIR}/ossim DESTINATION ${PKG_SHARE_DEST_DIR}) + + func_install_without_message("${PKG_SHARE_SOURCE_DIR}/ossim" "share" ) + + ####################### install proj share ########################## + if(EXISTS ${PKG_SHARE_SOURCE_DIR}/proj) + #install(DIRECTORY ${PKG_SHARE_SOURCE_DIR}/proj DESTINATION ${PKG_SHARE_DEST_DIR}) + func_install_without_message("${PKG_SHARE_SOURCE_DIR}/proj" "share" ) + endif() + + ####################### Install copyrights ########################## + #install license for windows package + #install(DIRECTORY ${PKG_SHARE_SOURCE_DIR}/copyright DESTINATION ${PKG_SHARE_DEST_DIR} ) + func_install_without_message("${PKG_SHARE_SOURCE_DIR}/copyright" "share" ) + install(FILES ${PKG_SHARE_SOURCE_DIR}/copyright/LICENSE DESTINATION ${PKG_STAGE_DIR}) + + ####################### Install VERSION ########################## + + set(PKG_VERSION_FILE + "${OTB_INSTALL_DIR}/share/doc/${PKG_OTB_VERSION_MAJOR}.${PKG_OTB_VERSION_MINOR}/VERSION") + if(EXISTS ${PKG_VERSION_FILE} ) + install(FILES ${PKG_VERSION_FILE} DESTINATION ${PKG_STAGE_DIR}) + endif() + +endfunction() + +function(func_install_otb_support_files) + foreach(req + PKG_STAGE_DIR + OTB_INSTALL_DIR + DEPENDENCIES_INSTALL_DIR + ) + if(NOT DEFINED ${req}) + message(FATAL_ERROR "you must set ${req} before calling this method") + endif() + set(vars "${vars} ${req}=[${${req}}]\n") + endforeach(req) + + #a convenient cmake var for storing <prefix>/bin + set(PKG_STAGE_BIN_DIR "${PKG_STAGE_DIR}/bin") + + #<prefix>/share for gdal data files + set(PKG_SHARE_DEST_DIR ${PKG_STAGE_DIR}/share) + + set(PKG_SHARE_SOURCE_DIR ${DEPENDENCIES_INSTALL_DIR}/share) + + #For Unixes we make them in the *pkgsetup.in + ##################### install environment setup file ########################## + if(WIN32) + install( + FILES ${PACKAGE_SUPPORT_FILES_DIR}/otbenv.cmd + DESTINATION ${PKG_STAGE_DIR} + ) + + install( + FILES ${PACKAGE_SUPPORT_FILES_DIR}/otbenv.bash + DESTINATION ${PKG_STAGE_DIR} + ) + + #we need startup files for mapla monteverdi in the root directory + #For Unixes, we make them inside pkgsetup script! + foreach(exe_file mapla monteverdi) + install( + PROGRAMS ${PACKAGE_SUPPORT_FILES_DIR}/${exe_file}.bat + DESTINATION "${PKG_STAGE_DIR}" + ) + endforeach() + endif() + + ####################### install cli and gui scripts ########################### + file(GLOB PKG_APP_SCRIPTS + ${OTB_INSTALL_DIR}/bin/otbcli* + ${OTB_INSTALL_DIR}/bin/otbgui*) # + + list(LENGTH PKG_APP_SCRIPTS PKG_APP_SCRIPTS_LENGTH) + if (PKG_APP_SCRIPTS_LENGTH LESS 1) + message(WARNING "PKG_APP_SCRIPTS is empty: ${PKG_APP_SCRIPTS}") + endif() + + ##################### install cli and gui scripts ####################### + install(PROGRAMS ${PKG_APP_SCRIPTS} DESTINATION ${PKG_STAGE_BIN_DIR}) + + +endfunction() + +function(func_install_monteverdi_support_files) + + #name/ext of qt's sqlite plugin. Varies with platform/OS + if(WIN32) + set(PKG_QTSQLITE_FILENAME "qsqlite4.dll") + elseif(APPLE) + set(PKG_QTSQLITE_FILENAME "libqsqlite.dylib") + elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") + set(PKG_QTSQLITE_FILENAME "libqsqlite.so") + else() + message(FATAL_ERROR "func_install_monteverdi_support_files: Unknown OS/Platform") + endif() + + #root folder where qt plugins are installed + set(PKG_QTPLUGINS_DIR "${PKG_STAGE_DIR}/lib/qt4/plugins") + + #qt4's distributes some translation of common message string used in Qt. + #This are provided with any qt installation. We reuse them in otb package + #so as not to reinvent the wheels. + set(PKG_QT_TRANSLATIONS_DIR "${PKG_STAGE_DIR}/lib/qt4/translations") + + #<prefix>/share for otb i18n directory. This is different from qt's i18N directory + #which is <prefix>/share/qt4/translations. + #set(PKG_xxOTB_Ixxx18N_DIR "${PKG_STAGE_DIR}/${PKG_OTB_INSTALL_DATA_DIR}/i18n") + # we find this value by parsing ConfigureMonteverdi.h + set(ConfigureMonteverdi_H "${OTB_BINARY_DIR}/Modules/Visualization/MonteverdiCore/ConfigureMonteverdi.h") + if(NOT EXISTS "${ConfigureMonteverdi_H}") + #maybe deactivate monteverdi? + message(FATAL_ERROR "${ConfigureMonteverdi_H} does not exists. Cannot continue") + endif() + + file( + STRINGS "${ConfigureMonteverdi_H}" + ConfigureMonteverdi_H_CONTENTS + REGEX "^#define.Monteverdi_INSTALL_DATA_DIR") + + string(REGEX REPLACE + "^#define.Monteverdi_INSTALL_DATA_DIR" "" + ConfigureMonteverdi_H_CONTENTS + ${ConfigureMonteverdi_H_CONTENTS} ) + + if(NOT ConfigureMonteverdi_H_CONTENTS) + message(FATAL_ERROR "Parse error in ${ConfigureMonteverdi_H}. Cannot continue") + endif() + + string( + REGEX REPLACE "\"" "" + PKG_OTB_INSTALL_DATA_DIR + "${ConfigureMonteverdi_H_CONTENTS}") + + if(NOT PKG_OTB_INSTALL_DATA_DIR) + message(FATAL_ERROR "parse error in ${ConfigureMonteverdi_H_CONTENTS}. Cannot continue") + endif() + + string(STRIP "${PKG_OTB_INSTALL_DATA_DIR}" PKG_OTB_INSTALL_DATA_DIR) + + set(PKG_OTB_TRANSLATIONS_DIRNAME "${PKG_OTB_INSTALL_DATA_DIR}/i18n") + + # Just check if required variables are defined. + foreach(req + PACKAGE_OTB_SRC_DIR + PACKAGE_SUPPORT_FILES_DIR + QT_PLUGINS_DIR + PKG_STAGE_BIN_DIR + PKG_QTSQLITE_FILENAME + PKG_QTPLUGINS_DIR + PKG_QT_TRANSLATIONS_DIR + PKG_OTB_TRANSLATIONS_DIRNAME + ) + if(NOT DEFINED ${req} OR "${${req}}" STREQUAL "") + message(FATAL_ERROR "you must set ${req} before calling this method") + endif() + set(vars "${vars} ${req}=[${${req}}]\n") + endforeach(req) + + #install icon file for .app file. Monteverdi and Mapla has same icon! + if(APPLE) + install(FILES ${PACKAGE_SUPPORT_FILES_DIR}/Monteverdi.icns + DESTINATION ${PKG_STAGE_DIR}) + endif() + + ####################### install sqldriver plugin ######################## + install(FILES ${QT_PLUGINS_DIR}/sqldrivers/${PKG_QTSQLITE_FILENAME} + DESTINATION ${PKG_QTPLUGINS_DIR}/sqldrivers) + + ####################### install qt4 translations ########################### + #get all translations already distributed with qt4 + get_qt_translation_files(QT_TRANSLATIONS_FILES) + + #install all files in ${QT_TRANSLATIONS_FILES} + install(FILES ${QT_TRANSLATIONS_FILES} DESTINATION ${PKG_QT_TRANSLATIONS_DIR}) + + ####################### install monteverdi translations ##################### + #translation of monteverdi specific strings + if(NOT EXISTS "${OTB_INSTALL_DIR}/${PKG_OTB_TRANSLATIONS_DIRNAME}") + message(FATAL_ERROR "Error ${OTB_INSTALL_DIR}/${PKG_OTB_TRANSLATIONS_DIRNAME} not exists") + endif() + + file(GLOB APP_TS_FILES ${PACKAGE_OTB_SRC_DIR}/i18n/*.ts) # qm files + foreach(APP_TS_FILE ${APP_TS_FILES}) + get_filename_component(APP_TS_FILENAME ${APP_TS_FILE} NAME_WE) + install(FILES ${OTB_INSTALL_DIR}/${PKG_OTB_TRANSLATIONS_DIRNAME}/${APP_TS_FILENAME}.qm + DESTINATION ${PKG_STAGE_DIR}/${PKG_OTB_TRANSLATIONS_DIRNAME} + ) + endforeach() + +endfunction() diff --git a/SuperBuild/Packaging/PackageGlobals.cmake b/SuperBuild/Packaging/PackageGlobals.cmake new file mode 100644 index 0000000000000000000000000000000000000000..863fb92c2f174c2b9ab8529c2c3c663beedc2096 --- /dev/null +++ b/SuperBuild/Packaging/PackageGlobals.cmake @@ -0,0 +1,138 @@ +set(WINDOWS_SYSTEM_DLLS + user32.dll + gdi32.dll + shell32.dll + kernel32.dll + ws2_32.dll + wldap32.dll + ole32.dll + comdlg32.dll + shfolder.dll + secur32.dll + wsock32.dll + advapi32.dll + crypt32.dll + imm32.dll + oleaut32.dll + winmm.dll + opengl32.dll + glu32.dll + rpcrt4.dll + winspool.drv + normaliz.dll + odbc32.dll + psapi.dll + python...dll + ) + +if(MINGW) + set(WINDOWS_SYSTEM_DLLS + ${WINDOWS_SYSTEM_DLLS} + msvcrt.dll + ) +endif() + +if(PKG_GENERATE_XDK) + set(WINDOWS_SYSTEM_DLLS + ${WINDOWS_SYSTEM_DLLS} + api-ms-win-* + concrt140.dll + ucrtbase.dll + msvcp140.dll + msvrt140.dll + vcomp140.dll + ) +endif() + +set(LINUX_SYSTEM_DLLS + libm.so + libc.so + libstdc* + libgcc_s.so + librt.so + libdl.so + libpthread.so + libidn.so + libgomp.so* + ld-linux-x86-64.so* + libX11.so* + libXext.so* + libXau.so* + libXdmcp.so* + libXxf86vm.so* + libdrm.so.2 + libGL.so* + libGLU.so* + libXrender.so* + libSM.so* + libICE.so* + libXrandr.so* + libpython* + libexpat.so.* + libfontconfig.so* + libfreetype.so* + ) + +# libgcc_s.*dylib and other *.framework are dragged by QT +set(APPLE_SYSTEM_DLLS + libSystem.*dylib + libiconv.*dylib + libc\\+\\+.*dylib + libstdc.*dylib + libobjc.*dylib + ApplicationServices.framework + CoreFoundation.framework + CoreServices.framework + Security.framework + Carbon.framework + AppKit.framework + Foundation.framework + Python.framework + AGL.framework + OpenGL.framework + libgcc_s.*dylib + ) + +if(WIN32) + set(SYSTEM_DLLS "${WINDOWS_SYSTEM_DLLS}") +else() #case for unixes + if(APPLE) + set(SYSTEM_DLLS "${APPLE_SYSTEM_DLLS}") + else() + set(SYSTEM_DLLS "${LINUX_SYSTEM_DLLS}") + endif() +endif(WIN32) + +# Take gtk libs from system. we should fix this to take from custom +# build location +set(PKG_GTK_SEARCHDIRS + /usr/lib64 + /lib64 + /lib/x86_64-linux-gnu/ + /usr/lib/x86_64-linux-gnu/ + ) + +#superbuild cannot manage build of gtk2+ just for qt gtkstyle. +# -gtkstyle option is deactivated by default in build of QT4 +# So the list of requirements on building OTB with superbuild stays same. +#For our user base, we need monteverdi with a nice look and feel +# rather than simply X11 based windows. Hence we need -gtkstyle +# This forces us to have system gtk+ installed on the system. +# OTB package manager 'this script' will pick them up and put +# into the binary package. Below cmake variable controls the list of +#libraries coming from /usr/lib a.k.a system. + +set(GTK_LIB_LIST_1 + libgthread-2.0.so.0 + libglib-2.0.so.0 + libgobject-2.0.so.0 + libXrender.so.1 + libpcre.so.3 + libffi.so.6 + ) +set(GTK_LIB_LIST_2 + libz.so.1 + libpng12.so.0 + ) + +set(ALLOWED_SYSTEM_DLLS ${GTK_LIB_LIST_1} ${GTK_LIB_LIST_2}) diff --git a/SuperBuild/Packaging/PackageHelper.cmake b/SuperBuild/Packaging/PackageHelper.cmake index 1d1aa8b6245972690585793272c1e9a71cb8107c..dd42ddf4b43759c50821f518bf740bbf6c1bd9b5 100644 --- a/SuperBuild/Packaging/PackageHelper.cmake +++ b/SuperBuild/Packaging/PackageHelper.cmake @@ -1,97 +1,124 @@ -#RK: TODO: do a sweep when mxe is out and msvc builds are stabilized - macro(macro_super_package) cmake_parse_arguments(PKG "" "STAGE_DIR" "" ${ARGN} ) - - if(${PKG_STAGE_DIR} STREQUAL "") + + set(LINUX FALSE) + if( "${CMAKE_SYSTEM_NAME}" MATCHES "Linux" AND NOT MINGW) + set(LINUX TRUE) + endif() + + if("${PKG_STAGE_DIR}" STREQUAL "") message(FATAL_ERROR "PKG_STAGE_DIR is empty. Just can't continue.") endif() - if(NOT WIN32 AND NOT APPLE) + if(NOT DEPENDENCIES_INSTALL_DIR) + message(FATAL_ERROR "DEPENDENCIES_INSTALL_DIR is not set of empty") + endif() + + if(LINUX) + if(NOT FILE_COMMAND) + message(FATAL_ERROR "warning: No 'file' command, cannot continue...") + endif() + if(NOT PATCHELF_PROGRAM) message(FATAL_ERROR "PATCHELF_PROGRAM not set") endif() - endif() + endif(LINUX) + + #setting this variable. prints a lot of debug information + #set( PKG_DEBUG 1) set(loader_program_PATHS) - if(WIN32) - if(MSVC) - set(loader_program_names "dumpbin") - set(loader_program_PATHS) - set(LOADER_PROGRAM_ARGS "/DEPENDENTS") - else() - set(loader_program_names "${MXE_ARCH}-w64-mingw32.shared-objdump") - set(loader_program_PATHS "${MXE_MXEROOT}/usr/bin") - set(LOADER_PROGRAM_ARGS "-p") - endif() + set(eol_char "E") + if(MSVC) + set(loader_program_PATHS) + set(loader_program_names "dumpbin") + set(loader_program_args "/DEPENDENTS") + set(loader_program_regex "^ ([^ ].*[Dd][Ll][Ll])${eol_char}$") + elseif(APPLE) + set(loader_program_PATHS) + set(loader_program_names otool) + set(loader_program_args "-l" ) + set(loader_program_regex ".*name.*([ ].*dylib ).*${eol_char}$") + elseif(LINUX) + set(loader_program_PATHS) + set(loader_program_names objdump) + set(loader_program_args "-p" ) + set(loader_program_regex "^..NEEDED.*([ ].*so.*)${eol_char}$") + elseif(MINGW) + set(loader_program_PATHS "${MXE_MXEROOT}/usr/bin") + set(loader_program_names "${OTB_TARGET_SYSTEM_ARCH}-w64-mingw32.shared-objdump") + set(loader_program_args "-p") + set(loader_program_regex "^\t*DLL Name: (.*\\.[Dd][Ll][Ll])${eol_char}$") else() - if(APPLE) - set(loader_program_names otool) - set(LOADER_PROGRAM_ARGS "-l") - set(loader_program_PATHS /opt/local/bin) # a path that is already listed i path on apple - else() - set(loader_program_names objdump) - set(LOADER_PROGRAM_ARGS "-p") - set(loader_program_PATHS /usr/bin) # a path that is already listed in default path on Linux - endif() - if(NOT DEPENDENCIES_INSTALL_DIR) - message(FATAL_ERROR "DEPENDENCIES_INSTALL_DIR is not set of empty") - endif() + message(FATAL_ERROR "Unknown platform: ") endif() - + find_program(LOADER_PROGRAM "${loader_program_names}" PATHS ${loader_program_PATHS}) - if(NOT EXISTS ${LOADER_PROGRAM}) - message(FATAL_ERROR "${loader_program_names} not found in ${loader_program_PATHS}. please check LOADER_PROGRAM variable is set correctly") + if(NOT LOADER_PROGRAM) + message(FATAL_ERROR "${loader_program_names} not found in ${loader_program_PATHS}.") endif() - execute_process( - COMMAND ${PYTHON_EXECUTABLE} - -c - "import sys; from distutils import sysconfig; print (sysconfig.get_config_var('INSTSONAME'));" - RESULT_VARIABLE python_INSTALLED_SONAME_rv - OUTPUT_VARIABLE python_INSTALLED_SONAME_ov - ) - - if(NOT python_INSTALLED_SONAME_rv EQUAL 0) - message( FATAL_ERROR - "python_INSTALLED_SONAME_rv=${python_INSTALLED_SONAME_rv}: Cannot find python library") - endif() - set(python_INSTALLED_SONAME "${python_INSTALLED_SONAME_ov}") - include(GetPrerequisites) + set(LOADER_PROGRAM_ARGS ${loader_program_args}) + + set(DEST_BIN_DIR bin) + set(DEST_APP_DIR lib/otb/applications) + + set(LIB_PREFIX lib) + set(DEST_LIB_DIR lib) + set(EXE_EXT "") + set(SCR_EXT ".sh") + set(LIB_EXT ".so") + set(PYMODULE_EXT ".so") + if(WIN32) + set(LIB_PREFIX) + set(DEST_LIB_DIR bin) + set(EXE_EXT ".exe") + set(LIB_EXT ".dll") + set(SCR_EXT ".bat") + set(PYMODULE_EXT ".pyd") + elseif(APPLE) + set(LIB_EXT ".dylib") + endif() + + # find_loader_and_args(LOADER_PROGRAM LOADER_PROGRAM_ARGS) + + find_python_soname(python_INSTALLED_SONAME) + set(PKG_SEARCHDIRS) if(WIN32) if(MSVC) list(APPEND PKG_SEARCHDIRS "${DEPENDENCIES_INSTALL_DIR}/bin") #all other dlls list(APPEND PKG_SEARCHDIRS "${DEPENDENCIES_INSTALL_DIR}/lib") #Qt & Qwt dlls - if(DEFINED ENV{UniversalCRTSdkDir}) - file(TO_CMAKE_PATH "$ENV{UniversalCRTSdkDir}" UCRT_SDK_DIR) - list( - APPEND - PKG_SEARCHDIRS - "${UCRT_SDK_DIR}/Redist/ucrt/DLLs/${OTB_TARGET_SYSTEM_ARCH}" - ) #ucrt dlls - else() - message(FATAL_ERROR - "UniversalCRTSdkDir variable not set. - call vcvarsall.bat <arch> first before starting build.") - endif() - - #addtional msvc redist dll from VCINSTALLDIR - if(DEFINED ENV{VCINSTALLDIR}) - file(TO_CMAKE_PATH "$ENV{VCINSTALLDIR}" PKG_VCINSTALLDIR) - list( - APPEND - PKG_SEARCHDIRS - "${PKG_VCINSTALLDIR}/redist/${OTB_TARGET_SYSTEM_ARCH}/Microsoft.VC140.CRT/" - "${PKG_VCINSTALLDIR}/redist/${OTB_TARGET_SYSTEM_ARCH}/Microsoft.VC140.OPENMP/" - ) - else() - message(FATAL_ERROR - "VCINSTALLDIR variable not set. call vcvarsall.bat <arch> first before starting build.") - endif() + if(NOT PKG_GENERATE_XDK) + if(DEFINED ENV{UniversalCRTSdkDir}) + file(TO_CMAKE_PATH "$ENV{UniversalCRTSdkDir}" UCRT_SDK_DIR) + list( + APPEND + PKG_SEARCHDIRS + "${UCRT_SDK_DIR}/Redist/ucrt/DLLs/${OTB_TARGET_SYSTEM_ARCH}" + ) #ucrt dlls + else() + message(FATAL_ERROR + "UniversalCRTSdkDir variable not set. call vcvarsall.bat <arch> first before starting build.") + endif() + + #additional msvc redist dll from VCINSTALLDIR + if(DEFINED ENV{VCINSTALLDIR}) + file(TO_CMAKE_PATH "$ENV{VCINSTALLDIR}" PKG_VCINSTALLDIR) + list( + APPEND + PKG_SEARCHDIRS + "${PKG_VCINSTALLDIR}/redist/${OTB_TARGET_SYSTEM_ARCH}/Microsoft.VC140.CRT" + "${PKG_VCINSTALLDIR}/redist/${OTB_TARGET_SYSTEM_ARCH}/Microsoft.VC140.OPENMP" + ) + else() + message(FATAL_ERROR + "VCINSTALLDIR variable not set. call vcvarsall.bat <arch> first before starting build.") + endif() + endif() #NOT PKG_GENERATE_XDK else() file(GLOB MXE_GCC_LIB_DIR "${DEPENDENCIES_INSTALL_DIR}/bin/gcc*") list(APPEND PKG_SEARCHDIRS ${MXE_GCC_LIB_DIR}) @@ -111,101 +138,74 @@ macro(macro_super_package) list(APPEND PKG_SEARCHDIRS "${OTB_APPLICATIONS_DIR}") #otb apps list(APPEND PKG_SEARCHDIRS "${OTB_INSTALL_DIR}/lib/otb/python") #otbApplication.py - set(EXE_SEARCHDIRS ${OTB_INSTALL_DIR}/bin) - list(APPEND EXE_SEARCHDIRS ${DEPENDENCIES_INSTALL_DIR}/bin) + if(PKG_GENERATE_XDK) + list(APPEND PKG_SEARCHDIRS ${OTB_BINARY_DIR}/bin) + endif() macro_empty_package_staging_directory() set(PKG_PEFILES) - if(NOT WIN32) - #NOTE: VAR_IN_PKGSETUP_CONFIGURE is copied to linux_pkgsetup.in - #during configure_file. This will be processed by func_lisp - set(VAR_IN_PKGSETUP_CONFIGURE) - endif() - - set(QT_EXECUTABLES) - list(APPEND QT_EXECUTABLES "lrelease") - list(APPEND QT_EXECUTABLES "moc") - list(APPEND QT_EXECUTABLES "qmake") - list(APPEND QT_EXECUTABLES "rcc") - list(APPEND QT_EXECUTABLES "uic") func_prepare_package() - file(STRINGS "${CMAKE_BINARY_DIR}/install_to_bin" install_to_bin_list) - func_lisp(install_to_bin_list ) - foreach(install_to_bin_item ${install_to_bin_list}) - is_file_executable("${install_to_bin_item}" is_exe) - if(is_exe) - install(PROGRAMS "${install_to_bin_item}" DESTINATION ${PKG_STAGE_DIR}/bin) - else() - install(FILES "${install_to_bin_item}" DESTINATION ${PKG_STAGE_DIR}/bin) - endif() - endforeach() + set(program_list) + set(WITH_PYTHON "false") + if(OTB_WRAP_PYTHON) + set(WITH_PYTHON "true") + endif() + + set(IS_XDK "false") - file(STRINGS "${CMAKE_BINARY_DIR}/install_to_lib" install_to_lib_list) - func_lisp( install_to_lib_list ) - #install lib files into lib as install(FILES .. - foreach(install_to_lib_item ${install_to_lib_list}) - install(FILES "${install_to_lib_item}" DESTINATION ${PKG_STAGE_DIR}/lib) - endforeach() + if(LINUX) + set(PKGSETUP_IN_FILENAME linux_pkgsetup.in) + elseif(APPLE) + set(PKGSETUP_IN_FILENAME macx_pkgsetup.in) + endif() + + if(PKG_GENERATE_XDK) + set(IS_XDK "true") + set(WITH_PYTHON "false") + message(STATUS "OTB_WRAP_PYTHON is set. But this will not be included in XDK") + if("${PKG_ITK_SB_VERSION}" STREQUAL "") + message(FATAL_ERROR "PKG_ITK_SB_VERSION not set. This is required for XDK") + endif() + func_install_xdk_files() + endif() #PKG_GENERATE_XDK + ############# install package configure script ################ - if(UNIX AND NOT WIN32) + #if(UNIX AND NOT WIN32) + if(UNIX AND NOT WIN32) #avoid OTB stuff inside make_symlinks script file(STRINGS "${CMAKE_BINARY_DIR}/make_symlinks_temp" make_symlinks_list) - func_lisp( make_symlinks_list ) - file(WRITE ${CMAKE_BINARY_DIR}/make_symlinks "#!/usr/bin/env bash\n") +# func_lisp( make_symlinks_list ) + file(WRITE ${CMAKE_BINARY_DIR}/make_symlinks "#!/bin/sh\n") foreach(make_symlink_cmd ${make_symlinks_list}) file(APPEND ${CMAKE_BINARY_DIR}/make_symlinks "${make_symlink_cmd}\n") endforeach() - set(WITH_PYTHON "false") - if(OTB_WRAP_PYTHON) - set(WITH_PYTHON "true") - endif() - - set(IS_XDK "false") - if(PKG_GENERATE_XDK) - set(IS_XDK "true") - set(WITH_PYTHON "false") - message(STATUS "OTB_WRAP_PYTHON is set. But this will not be included in XDK") - - if("${PKG_ITK_SB_VERSION}" STREQUAL "") - message(FATAL_ERROR "PKG_ITK_SB_VERSION not set. This is required for XDK") - endif() - - #avoid OTB stuff inside pkgsetup for XDK - separate_arguments( VAR_IN_PKGSETUP_CONFIGURE ) - func_lisp( VAR_IN_PKGSETUP_CONFIGURE ) - string(REPLACE ";" " " VAR_IN_PKGSETUP_CONFIGURE "${VAR_IN_PKGSETUP_CONFIGURE}") - endif() - set(PKGSETUP_IN_FILENAME linux_pkgsetup.in) - if(APPLE) - set(PKGSETUP_IN_FILENAME macx_pkgsetup.in) - endif() - configure_file(${PACKAGE_SUPPORT_FILES_DIR}/${PKGSETUP_IN_FILENAME} ${CMAKE_BINARY_DIR}/pkgsetup @ONLY) - - install(PROGRAMS - ${CMAKE_BINARY_DIR}/pkgsetup - ${CMAKE_BINARY_DIR}/make_symlinks - DESTINATION ${PKG_STAGE_DIR} - ) - - ########### install patchelf( linux only) ################## - if(NOT APPLE) - install(PROGRAMS ${PATCHELF_PROGRAM} - DESTINATION ${PKG_STAGE_DIR}/tools) + + list(APPEND program_list "${CMAKE_BINARY_DIR}/pkgsetup") + list(APPEND program_list "${CMAKE_BINARY_DIR}/make_symlinks") + + ########### install patchelf( linux only) ################## + if(LINUX) + list(APPEND program_list "${PATCHELF_PROGRAM}") endif() - endif() # if(UNIX) - - if(PKG_GENERATE_XDK) - func_install_xdk_files() + endif() + + foreach(prog ${program_list}) + install( + PROGRAMS ${prog} + DESTINATION ${PKG_STAGE_DIR}) + endforeach() + + # We need qt.conf on windows. for macx and linux we write it # after extracting package if(WIN32 AND NOT PKG_GENERATE_XDK) @@ -221,986 +221,328 @@ macro(macro_super_package) endmacro(macro_super_package) -function(func_install_xdk_files) - - #The list of REQ_SHARE_DIR is made up from <mxe-target-dir>/share/ - #It may vary in future. I prefer not to glob on the share dir and - #end up distributing man, info etc.. which ar irrelvant for windows - foreach(REQ_SHARE_DIR - aclocal - Armadillo - applications - cmake - dbus-1 - fontconfig - libgta - locale - xml - applications - cmake - icons - OpenCV - pixmaps - pkgconfig - ) - if(EXISTS "${DEPENDENCIES_INSTALL_DIR}/share/${REQ_SHARE_DIR}") - func_install_without_message("${DEPENDENCIES_INSTALL_DIR}/share/${REQ_SHARE_DIR}" "share") - endif() - endforeach() - - file(GLOB LIB_CMAKE_DIRS "${DEPENDENCIES_INSTALL_DIR}/lib/cmake/*") - foreach(LIB_CMAKE_DIR ${LIB_CMAKE_DIRS}) - get_filename_component(LIB_CMAKE_DIR_name_we ${LIB_CMAKE_DIR} NAME_WE) - if(NOT "${LIB_CMAKE_DIR_name_we}" MATCHES "OTB") - func_install_without_message("${LIB_CMAKE_DIR}" "lib/cmake") - endif() - endforeach() - set(QT_REQ_DIRS) - if(WIN32) - #only affects windows due to regex on dll - if(MSVC) - file(GLOB LIB_FILES "${DEPENDENCIES_INSTALL_DIR}/lib/*.lib") - else() - file(GLOB LIB_FILES "${DEPENDENCIES_INSTALL_DIR}/lib/*dll.*") - endif() - func_lisp(LIB_FILES ) - - install(FILES ${LIB_FILES} DESTINATION ${PKG_STAGE_DIR}/lib ) - - file(GLOB ITK_EXTRA_DLL_FILES_1 "${DEPENDENCIES_INSTALL_DIR}/bin/libITK*.dll") - install(FILES ${ITK_EXTRA_DLL_FILES_1} DESTINATION ${PKG_STAGE_DIR}/bin) - - file(GLOB ITK_EXTRA_DLL_FILES_2 "${DEPENDENCIES_INSTALL_DIR}/bin/libitk*.dll") - install(FILES ${ITK_EXTRA_DLL_FILES_2} DESTINATION ${PKG_STAGE_DIR}/bin) - - file(GLOB OPENCV_EXTRA_DLL_FILES "${DEPENDENCIES_INSTALL_DIR}/bin/libopencv*.dll") - install(FILES ${OPENCV_EXTRA_DLL_FILES} DESTINATION ${PKG_STAGE_DIR}/bin) - - file(GLOB OPENCV_EXTRA_A_FILES "${DEPENDENCIES_INSTALL_DIR}/lib/libopencv*.a") - install(FILES ${OPENCV_EXTRA_A_FILES} DESTINATION ${PKG_STAGE_DIR}/lib) - - #opencv cmake config files in two directories. - # ${PKG_STAGE_DIR}/lib and ${PKG_STAGE_DIR} - file(GLOB OPENCV_CONFIG_FILES_1 "${DEPENDENCIES_INSTALL_DIR}/lib/OpenCV*.cmake") - install(FILES ${OPENCV_CONFIG_FILES_1} DESTINATION ${PKG_STAGE_DIR}/lib) - - file(GLOB OPENCV_CONFIG_FILES_2 "${DEPENDENCIES_INSTALL_DIR}/OpenCV*.cmake") - install(FILES ${OPENCV_CONFIG_FILES_2} DESTINATION ${PKG_STAGE_DIR}) - - #mxe installs qt in a separate directory under install prefix. So.. - set(QT_INSTALL_DIR "${DEPENDENCIES_INSTALL_DIR}/qt") - - #qt/bin is also a special case for mxe. - file(GLOB QT_EXTRA_DLL_FILES "${DEPENDENCIES_INSTALL_DIR}/qt/bin/*.dll") - install(FILES ${QT_EXTRA_DLL_FILES} DESTINATION ${PKG_STAGE_DIR}/bin) - - #list(APPEND QT_REQ_DIRS lib) - list(APPEND QT_REQ_DIRS include) - list(APPEND QT_REQ_DIRS imports) - - else() - set( - QT_INSTALL_DIR "${DEPENDENCIES_INSTALL_DIR}") +function(func_prepare_package) - endif(WIN32) + file(WRITE ${CMAKE_BINARY_DIR}/make_symlinks_temp "") - if(NOT QT_EXECUTABLES) - message(FATAL_ERROR "QT_EXECUTABLES not set") + #This must exist in any OTB Installation. minimal or full + #set(PKG_PEFILES "${OTB_INSTALL_DIR}/bin/otbApplicationLauncherCommandLine${EXE_EXT}") + if(NOT EXISTS "${OTB_INSTALL_DIR}/bin/otbApplicationLauncherCommandLine${EXE_EXT}") + message( + FATAL_ERROR + "${OTB_INSTALL_DIR}/bin/otbApplicationLauncherCommandLine${EXE_EXT} not found.") endif() + + set(PKG_PEFILES "otbApplicationLauncherCommandLine${EXE_EXT}") - list(APPEND QT_REQ_DIRS mkspecs) - list(APPEND QT_REQ_DIRS plugins) - list(APPEND QT_REQ_DIRS translations) - foreach(QT_REQ_DIR ${QT_REQ_DIRS} ) - if(EXISTS "${QT_INSTALL_DIR}/${QT_REQ_DIR}") - func_install_without_message("${QT_INSTALL_DIR}/${QT_REQ_DIR}" "") + foreach(exe_file + "otbApplicationLauncherQt" "iceViewer" "otbTestDriver" "monteverdi" "mapla") + if(EXISTS "${OTB_INSTALL_DIR}/bin/${exe_file}${EXE_EXT}") + list(APPEND PKG_PEFILES "${exe_file}${EXE_EXT}") + else() + message(STATUS "${exe_file}${EXE_EXT} not found in ${OTB_INSTALL_DIR}/bin. (skipping)") endif() endforeach() - - # #install ${DEPENDENCIES_INSTALL_DIR}/include directory. Attention to OTB includes - file(GLOB ALL_IN_INCLUDE_DIR "${DEPENDENCIES_INSTALL_DIR}/include/*") - foreach(INCLUDE_DIR_ITEM ${ALL_IN_INCLUDE_DIR}) - get_filename_component(INCLUDE_DIR_ITEM_name ${INCLUDE_DIR_ITEM} NAME) - get_filename_component(INCLUDE_DIR_ITEM_name_we ${INCLUDE_DIR_ITEM} NAME_WE) - if(NOT "${INCLUDE_DIR_ITEM_name_we}" MATCHES "OTB|otb") - if( IS_DIRECTORY ${INCLUDE_DIR_ITEM}) - install(CODE - "message(STATUS \"Installing: ${CMAKE_INSTALL_PREFIX}/${PKG_STAGE_DIR}/include/${INCLUDE_DIR_ITEM_name}/\")" ) - install( - DIRECTORY "${INCLUDE_DIR_ITEM}" - DESTINATION "${PKG_STAGE_DIR}/include/" - MESSAGE_NEVER - ) - else() - install( - FILES "${INCLUDE_DIR_ITEM}" - DESTINATION "${PKG_STAGE_DIR}/include/" - ) - endif() #if( IS_DIRECTORY - endif() #if (NOT - endforeach() - -endfunction() #func_install_xdk_files - -function(func_install_without_message src_dir dst_dir_suffix) - set (extra_func_args ${ARGN}) - list(LENGTH extra_func_args num_extra_args) - if (${num_extra_args} GREATER 0) - list(GET extra_func_args 0 optional_msg) - endif() - - if( "${dst_dir_suffix}" STREQUAL "") - set(dst_dir "${PKG_STAGE_DIR}") - else() - set(dst_dir "${PKG_STAGE_DIR}/${dst_dir_suffix}") - endif() - - get_filename_component(src_dir_name ${src_dir} NAME) - set(install_msg "message(STATUS \"Installing: ${CMAKE_INSTALL_PREFIX}/${dst_dir}/${src_dir_name} ${optional_msg}\")") - install(CODE "${install_msg}" ) - install( - DIRECTORY ${src_dir} - DESTINATION ${dst_dir} - MESSAGE_NEVER ) -endfunction() - -function(func_install_support_files) - - #a convenient cmake var for storing <prefix>/bin - set(PKG_STAGE_BIN_DIR "${PKG_STAGE_DIR}/bin") - - #<prefix>/share for gdal data files - set(PKG_SHARE_DEST_DIR ${PKG_STAGE_DIR}/share) - - set(PKG_SHARE_SOURCE_DIR ${DEPENDENCIES_INSTALL_DIR}/share) - - set(GDAL_DATA ${PKG_SHARE_SOURCE_DIR}/gdal) - #MSVC install gdal-data in in a different directory. So we don't spoil it - if(MSVC) - set(GDAL_DATA ${DEPENDENCIES_INSTALL_DIR}/data) - endif() - - # Just check if required variables are defined. - foreach(req - DEPENDENCIES_INSTALL_DIR - OTB_APPLICATIONS_DIR - PKG_STAGE_DIR - PACKAGE_SUPPORT_FILES_DIR - OTB_INSTALL_DIR - ) - if(NOT DEFINED ${req}) - message(FATAL_ERROR "you must set ${req} before calling this method") - endif() - set(vars "${vars} ${req}=[${${req}}]\n") - endforeach(req) - - # one for debugging.. - # install(CODE "message(\"CMake/PackageHelper.cmake:install_supoport_files(${outdir})\n${vars}\n\")") - if(NOT PKG_GENERATE_XDK) - func_install_otb_support_files() - - #check if monteverdi executable is built? - if(EXISTS "${OTB_INSTALL_DIR}/bin/monteverdi${EXE_EXT}") - func_install_monteverdi_support_files() + + if(PKG_GENERATE_XDK) + #Qt stuff + list(APPEND PKG_PEFILES "lrelease${EXE_EXT}") + list(APPEND PKG_PEFILES "moc${EXE_EXT}") + list(APPEND PKG_PEFILES "qmake${EXE_EXT}") + list(APPEND PKG_PEFILES "rcc${EXE_EXT}") + list(APPEND PKG_PEFILES "uic${EXE_EXT}") + list(APPEND PKG_PEFILES "proj${EXE_EXT}") + list(APPEND PKG_PEFILES "cs2cs${EXE_EXT}") + + #shark is optional + if(EXISTS "${DEPENDENCIES_INSTALL_DIR}/bin/sharkVersion${EXE_EXT}") + list(APPEND PKG_PEFILES "sharkVersion${EXE_EXT}") endif() + + #RK: there is a bug in itk cmake files in install tree + #we workaround with below code + #start hack + file(GLOB itk_all_lib_files + "${DEPENDENCIES_INSTALL_DIR}/${DEST_LIB_DIR}/${LIB_PREFIX}itk*${LIB_EXT}*" + "${DEPENDENCIES_INSTALL_DIR}/${DEST_LIB_DIR}/${LIB_PREFIX}ITK*${LIB_EXT}*" + ) + + foreach(itk_lib_file ${itk_all_lib_files}) + func_is_file_a_symbolic_link("${itk_lib_file}" a_symlink itk_lib_file_target) + if(NOT a_symlink) + list(APPEND PKG_PEFILES "${itk_lib_file}") + endif() + endforeach() + #end hack - endif() #NOT PKG_GENERATE_XDK - - ####################### install GDAL data ############################ - if(NOT EXISTS "${GDAL_DATA}/epsg.wkt") - message(FATAL_ERROR - "Cannot generate package without GDAL_DATA : ${GDAL_DATA} ${DEPENDENCIES_INSTALL_DIR}") + file(GLOB otb_test_exe_list + "${DEPENDENCIES_INSTALL_DIR}/bin/gdal*${EXE_EXT}" + "${OTB_BINARY_DIR}/bin/*Test*${EXE_EXT}" + ) + foreach(otb_test_exe ${otb_test_exe_list}) + get_filename_component(otb_test_exe_name ${otb_test_exe} NAME) + list(APPEND PKG_PEFILES ${otb_test_exe_name}) + endforeach() endif() - install(DIRECTORY ${GDAL_DATA} DESTINATION ${PKG_SHARE_DEST_DIR}) - - ####################### install GeoTIFF data ######################## - install(DIRECTORY ${PKG_SHARE_SOURCE_DIR}/epsg_csv DESTINATION ${PKG_SHARE_DEST_DIR}) - - ####################### install OSSIM data ########################## - install(DIRECTORY ${PKG_SHARE_SOURCE_DIR}/ossim DESTINATION ${PKG_SHARE_DEST_DIR}) - - ####################### install proj share ########################## - if(EXISTS ${PKG_SHARE_SOURCE_DIR}/proj) - install(DIRECTORY ${PKG_SHARE_SOURCE_DIR}/proj DESTINATION ${PKG_SHARE_DEST_DIR}) + # special case for msvc: ucrtbase.dll must be explicitly vetted. + if(MSVC AND NOT PKG_GENERATE_XDK) + list(APPEND PKG_PEFILES "ucrtbase.dll") endif() - - set(PKG_VERSION_FILE - "${OTB_INSTALL_DIR}/share/doc/${PKG_OTB_VERSION_MAJOR}.${PKG_OTB_VERSION_MINOR}/VERSION") - ####################### Install copyrights ########################## - if(NOT MINGW) - #install license for windows package - install(DIRECTORY ${PKG_SHARE_SOURCE_DIR}/copyright DESTINATION ${PKG_SHARE_DEST_DIR}) - install(FILES ${PKG_SHARE_SOURCE_DIR}/copyright/LICENSE DESTINATION ${PKG_STAGE_DIR}) - endif() + file(GLOB OTB_APPS_LIST "${OTB_APPLICATIONS_DIR}/otbapp_*${LIB_EXT}") # /lib/otb + list(APPEND PKG_PEFILES ${OTB_APPS_LIST}) - ####################### Install VERSION ########################## - if(EXISTS ${PKG_VERSION_FILE} ) - install(FILES ${PKG_VERSION_FILE} DESTINATION ${PKG_STAGE_DIR}) - endif() + if(NOT PKG_GENERATE_XDK) + if(EXISTS "${OTB_INSTALL_DIR}/lib/otb/python/_otbApplication${PYMODULE_EXT}") + install( + DIRECTORY + ${OTB_INSTALL_DIR}/lib/otb/python + DESTINATION ${PKG_STAGE_DIR}/lib + ) + else() + if(OTB_WRAP_PYTHON) + message(FATAL_ERROR "OTB_WRAP_PYTHON is set , but cannot find _otbApplication${PYMODULE_EXT}") + endif() + endif() + endif()# if(NOT PKG_GENERATE_XDK) -endfunction() -function(func_install_otb_support_files) - foreach(req - PKG_STAGE_DIR - OTB_INSTALL_DIR - DEPENDENCIES_INSTALL_DIR - OTB_APPLICATIONS_DIR - ) - if(NOT DEFINED ${req}) - message(FATAL_ERROR "you must set ${req} before calling this method") - endif() - set(vars "${vars} ${req}=[${${req}}]\n") - endforeach(req) + func_install_support_files() - #a convenient cmake var for storing <prefix>/bin - set(PKG_STAGE_BIN_DIR "${PKG_STAGE_DIR}/bin") + unset(matched_vars CACHE) + get_vars_ending_with("_USED|_RESOLVED" matched_vars) + foreach (var_to_unset IN LISTS matched_vars) + if(PKG_DEBUG) + message("unset ${var_to_unset} from cache") + endif() + unset(${var_to_unset} CACHE) + endforeach() - #root folder where otb applications are installed - set(PKG_OTBLIBS_DIR "${PKG_STAGE_DIR}/lib/otb") + foreach(infile ${PKG_PEFILES}) + get_filename_component(bn ${infile} NAME) + func_process_deps(${bn}) + endforeach() + +endfunction() #func_prepare_package - #<prefix>/share for gdal data files - set(PKG_SHARE_DEST_DIR ${PKG_STAGE_DIR}/share) +function(func_process_deps input_file) - set(PKG_SHARE_SOURCE_DIR ${DEPENDENCIES_INSTALL_DIR}/share) + set(input_file_full_path) + search_library(${input_file} PKG_SEARCHDIRS input_file_full_path) - #For Unixes we make them in the *pkgsetup.in - ##################### install environment source ########################## - if(WIN32) - foreach(ENV_SOURCE_FILE - "${PACKAGE_SUPPORT_FILES_DIR}/otbenv.cmd" - "${PACKAGE_SUPPORT_FILES_DIR}/otbenv.profile") - if(EXISTS ${ENV_SOURCE_FILE}) - install(FILES ${ENV_SOURCE_FILE} DESTINATION ${PKG_STAGE_DIR}) + if(NOT input_file_full_path) + if(LINUX) + setif_value_in_list(is_gtk_lib "${input_file}" ALLOWED_SYSTEM_DLLS) + if(is_gtk_lib) + search_library(${input_file} PKG_GTK_SEARCHDIRS input_file_full_path) + if( NOT input_file_full_path) + message(FATAL_ERROR "${input_file} not found. searched in ${PKG_GTK_SEARCHDIRS}") + endif() endif() - endforeach() + if( NOT input_file_full_path) + message(FATAL_ERROR "${input_file} not found. searched in ${PKG_SEARCHDIRS}") + endif() + endif(LINUX) - #we need startup files for mapla monteverdi in the root directory - #For Unixes, we make them inside pkgsetup script! - foreach(exe_file mapla monteverdi) - install( - PROGRAMS ${PACKAGE_SUPPORT_FILES_DIR}/${exe_file}.bat - DESTINATION "${PKG_STAGE_DIR}" - ) - endforeach() - endif() - - ####################### install cli and gui scripts ########################### - file(GLOB PKG_APP_SCRIPTS - ${OTB_INSTALL_DIR}/bin/otbcli* - ${OTB_INSTALL_DIR}/bin/otbgui*) # + endif() #if(NOT input_file_full_path) - list(LENGTH PKG_APP_SCRIPTS PKG_APP_SCRIPTS_LENGTH) - if (PKG_APP_SCRIPTS_LENGTH LESS 1) - message(WARNING "PKG_APP_SCRIPTS is empty: ${PKG_APP_SCRIPTS}") + if(NOT PKG_DEBUG) + message("Processing ${input_file_full_path}") endif() - ##################### install cli and gui scripts ####################### - install(PROGRAMS ${PKG_APP_SCRIPTS} DESTINATION ${PKG_STAGE_BIN_DIR}) - - ####################### Install otb applications #################### - install(DIRECTORY "${OTB_APPLICATIONS_DIR}" DESTINATION ${PKG_OTBLIBS_DIR}) + set(is_executable FALSE) + is_file_executable2(input_file_full_path is_executable) -endfunction() + if(NOT is_executable) + #copy back to input_file_full_path + pkg_install_rule(${input_file_full_path}) + message("not is_executable ${input_file_full_path}") + return() + endif() #NOT is_executable -function(func_install_monteverdi_support_files) + if(UNIX) + # Deal with symlinks. + # For any valid symlinks, (see 'not_valid' below) + # we append ln -s source target commands to a file + # That file is executed during installation. + get_filename_component(bn_we ${input_file_full_path} NAME_WE) + get_filename_component(bn_path ${input_file_full_path} PATH) + + file(GLOB sofiles "${bn_path}/${bn_we}*") + foreach(sofile ${sofiles}) + get_filename_component(basename_of_sofile ${sofile} NAME) + get_filename_component(sofile_ext ${sofile} EXT) + set(not_valid FALSE) + if( "${sofile_ext}" MATCHES ".la" + OR "${sofile_ext}" MATCHES ".prl" + OR "${sofile_ext}" MATCHES ".a" + OR IS_DIRECTORY "${sofile}" ) + set(not_valid TRUE) + endif() - #name/ext of qt's sqlite plugin. Varies with platform/OS - if(WIN32) - set(PKG_QTSQLITE_FILENAME "qsqlite4.dll") - elseif(APPLE) - set(PKG_QTSQLITE_FILENAME "libqsqlite.dylib") - elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") - set(PKG_QTSQLITE_FILENAME "libqsqlite.so") - else() - message(FATAL_ERROR "func_install_monteverdi_support_files: Unknown OS/Platform") - endif() + if(not_valid) + continue() + endif() - #root folder where qt plugins are installed - set(PKG_QTPLUGINS_DIR "${PKG_STAGE_DIR}/lib/qt4/plugins") - - #qt4's distributes some translation of common message string used in Qt. - #This are provided with any qt installation. We reuse them in otb package - #so as not to reinvent the wheels. - set(PKG_QT_TRANSLATIONS_DIR "${PKG_STAGE_DIR}/lib/qt4/translations") - - #<prefix>/share for otb i18n directory. This is different from qt's i18N directory - #which is <prefix>/share/qt4/translations. - #set(PKG_xxOTB_Ixxx18N_DIR "${PKG_STAGE_DIR}/${PKG_OTB_INSTALL_DATA_DIR}/i18n") - # we find this value by parsing ConfigureMonteverdi.h - set(ConfigureMonteverdi_H "${OTB_BINARY_DIR}/Modules/Visualization/MonteverdiCore/ConfigureMonteverdi.h") - if(NOT EXISTS "${ConfigureMonteverdi_H}") - message(FATAL_ERROR "${ConfigureMonteverdi_H} does not exists. Cannot continue") - endif() + func_is_file_a_symbolic_link("${sofile}" is_symlink linked_to_file) - file( - STRINGS "${ConfigureMonteverdi_H}" - ConfigureMonteverdi_H_CONTENTS - REGEX "^#define.Monteverdi_INSTALL_DATA_DIR") + if(is_symlink) + add_to_symlink_list("${linked_to_file}" "${basename_of_sofile}") + endif() # is_symlink - string(REGEX REPLACE - "^#define.Monteverdi_INSTALL_DATA_DIR" "" - ConfigureMonteverdi_H_CONTENTS - ${ConfigureMonteverdi_H_CONTENTS} ) + endforeach() - if(NOT ConfigureMonteverdi_H_CONTENTS) - message(FATAL_ERROR "Parse error in ${ConfigureMonteverdi_H}. Cannot continue") - endif() + endif(UNIX) - string( - REGEX REPLACE "\"" "" - PKG_OTB_INSTALL_DATA_DIR - "${ConfigureMonteverdi_H_CONTENTS}") + set(raw_items) - if(NOT PKG_OTB_INSTALL_DATA_DIR) - message(FATAL_ERROR "parse error in ${ConfigureMonteverdi_H_CONTENTS}. Cannot continue") - endif() + execute_process( + COMMAND ${LOADER_PROGRAM} ${LOADER_PROGRAM_ARGS} "${input_file_full_path}" + RESULT_VARIABLE loader_rv + OUTPUT_VARIABLE loader_ov + ERROR_VARIABLE loader_ev + ) - string(STRIP "${PKG_OTB_INSTALL_DATA_DIR}" PKG_OTB_INSTALL_DATA_DIR) - - set(PKG_OTB_TRANSLATIONS_DIRNAME "${PKG_OTB_INSTALL_DATA_DIR}/i18n") - - # Just check if required variables are defined. - foreach(req - PACKAGE_OTB_SRC_DIR - PACKAGE_SUPPORT_FILES_DIR - QT_PLUGINS_DIR - PKG_STAGE_BIN_DIR - PKG_QTSQLITE_FILENAME - PKG_QTPLUGINS_DIR - PKG_QT_TRANSLATIONS_DIR - PKG_OTB_TRANSLATIONS_DIRNAME - ) - if(NOT DEFINED ${req} OR "${${req}}" STREQUAL "") - message(FATAL_ERROR "you must set ${req} before calling this method") - endif() - set(vars "${vars} ${req}=[${${req}}]\n") - endforeach(req) - - #install icon file for .app file. Monteverdi and Mapla has same icon! - if(APPLE) - install(FILES ${PACKAGE_SUPPORT_FILES_DIR}/Monteverdi.icns - DESTINATION ${PKG_STAGE_DIR}) + if(loader_rv) + message(FATAL_ERROR "loader_ev=${loader_ev}\n PACKAGE-OTB: result_variable is '${loader_rv}'") endif() - ####################### install sqldriver plugin ######################## - install(FILES ${QT_PLUGINS_DIR}/sqldrivers/${PKG_QTSQLITE_FILENAME} - DESTINATION ${PKG_QTPLUGINS_DIR}/sqldrivers) - - ####################### install qt4 translations ########################### - #get all translations already distributed with qt4 - get_qt_translation_files(QT_TRANSLATIONS_FILES) - - #install all files in ${QT_TRANSLATIONS_FILES} - install(FILES ${QT_TRANSLATIONS_FILES} DESTINATION ${PKG_QT_TRANSLATIONS_DIR}) - - ####################### install monteverdi translations ##################### - #translation of monteverdi specific strings - if(NOT EXISTS "${OTB_INSTALL_DIR}/${PKG_OTB_TRANSLATIONS_DIRNAME}") - message(FATAL_ERROR "Error ${OTB_INSTALL_DIR}/${PKG_OTB_TRANSLATIONS_DIRNAME} not exists") - endif() + string(REPLACE ";" "\\;" candidates "${loader_ov}") + string(REPLACE "\n" "${eol_char};" candidates "${candidates}") - file(GLOB APP_TS_FILES ${PACKAGE_OTB_SRC_DIR}/i18n/*.ts) # qm files - foreach(APP_TS_FILE ${APP_TS_FILES}) - get_filename_component(APP_TS_FILENAME ${APP_TS_FILE} NAME_WE) - install(FILES ${OTB_INSTALL_DIR}/${PKG_OTB_TRANSLATIONS_DIRNAME}/${APP_TS_FILENAME}.qm - DESTINATION ${PKG_STAGE_DIR}/${PKG_OTB_TRANSLATIONS_DIRNAME} - ) - endforeach() - -endfunction() - -macro(macro_empty_package_staging_directory) - message(STATUS "Empty package staging directory: ${CMAKE_INSTALL_PREFIX}/${PKG_STAGE_DIR}") - execute_process( - COMMAND ${CMAKE_COMMAND} - -E remove_directory - "${CMAKE_INSTALL_PREFIX}/${PKG_STAGE_DIR}" - ) -endmacro() #macro_empty_package_staging_directory + get_filename_component(bn_name ${input_file_full_path} NAME) + set(${bn_name}_USED TRUE CACHE INTERNAL "") -#NOTE: -# VAR_IN_PKGSETUP_CONFIGURE cmake variable is set below. -# This is important and useful running configure_file() -# over *pkgsetup.in - -function(func_prepare_package) - - set(DEST_LIB_DIR lib) - set(DEST_BIN_DIR bin) - set(DEST_APP_DIR lib/otb/applications) - set(EXE_EXT "") - set(SCR_EXT ".sh") - set(LIB_EXT ".so") - set(PYMODULE_EXT ".so") - if(WIN32) - set(EXE_EXT ".exe") - set(LIB_EXT ".dll") - set(SCR_EXT ".bat") - set(PYMODULE_EXT ".pyd") - set(DEST_LIB_DIR bin) - elseif(APPLE) - set(LIB_EXT ".dylib") + if(PKG_DEBUG) + message("Processing ${input_file} started. Set ${bn_name}_USED=${${bn_name}_USED}") endif() - file(WRITE ${CMAKE_BINARY_DIR}/make_symlinks_temp "") - file(WRITE ${CMAKE_BINARY_DIR}/install_to_bin "") - file(WRITE ${CMAKE_BINARY_DIR}/install_to_lib "") + foreach(candidate ${candidates}) + if(NOT candidate) + continue() + endif() - #This must exist in any OTB Installation minimal or full - set(VAR_IN_PKGSETUP_CONFIGURE "bin/otbApplicationLauncherCommandLine") - set(PKG_PEFILES "${OTB_INSTALL_DIR}/bin/otbApplicationLauncherCommandLine${EXE_EXT}") - if(NOT EXISTS "${OTB_INSTALL_DIR}/bin/otbApplicationLauncherCommandLine${EXE_EXT}") - message( - FATAL_ERROR - "${OTB_INSTALL_DIR}/bin/otbApplicationLauncherCommandLine${EXE_EXT} not found.") - endif() + if(NOT "${candidate}" MATCHES "${loader_program_regex}") + continue() + endif() + + string(REGEX REPLACE "${loader_program_regex}" "\\1" raw_item "${candidate}") - set(EXE_FILES) - list(APPEND EXE_FILES "otbApplicationLauncherQt") - list(APPEND EXE_FILES "iceViewer") - list(APPEND EXE_FILES "otbTestDriver") + if(NOT raw_item) + continue() + endif() - if(PKG_GENERATE_XDK) - #itk - list(APPEND EXE_FILES "itkTestDriver") - #Qt stuff - list(APPEND EXE_FILES ${QT_EXECUTABLES}) - endif() + string(STRIP ${raw_item} raw_item) + set(is_system FALSE) + setif_value_in_list(is_system "${raw_item}" SYSTEM_DLLS) - list(APPEND EXE_FILES "monteverdi") - list(APPEND EXE_FILES "mapla") - - foreach(EXE_FILE ${EXE_FILES}) - set(FOUND_${EXE_FILE} FALSE) - foreach(EXE_SEARCHDIR ${EXE_SEARCHDIRS}) - if(NOT FOUND_${EXE_FILE}) - if(EXISTS "${EXE_SEARCHDIR}/${EXE_FILE}${EXE_EXT}") - set(FOUND_${EXE_FILE} TRUE) - #see the first comment about VAR_IN_PKGSETUP_CONFIGURE - set(VAR_IN_PKGSETUP_CONFIGURE "${VAR_IN_PKGSETUP_CONFIGURE} bin/${EXE_FILE}${EXE_EXT}") - list(APPEND PKG_PEFILES "${EXE_SEARCHDIR}/${EXE_FILE}${EXE_EXT}") - endif() - endif() #(NOT FOUND_${EXE_FILE}) - endforeach() #EXE_SEARCH_DIR - endforeach() - - # special case for msvc: ucrtbase.dll must be explicitly vetted. - if(MSVC) - list(APPEND PKG_PEFILES "ucrtbase.dll") - endif() - - #loop again to report if anything is not found - foreach( EXE_FILE ${EXE_FILES} ) - if(NOT FOUND_${EXE_FILE}) - message(STATUS "'${OTB_INSTALL_DIR}/bin/${EXE_FILE}${EXE_EXT}'(not found. skipping)") + if(APPLE AND NOT is_system) + if("${raw_item}" MATCHES "@rpath") + string(REGEX REPLACE "@rpath." "" raw_item "${raw_item}") + else() + message(FATAL_ERROR "'${raw_item}' does not have @rpath") + endif() endif() - endforeach() - file(GLOB OTB_APPS_LIST "${OTB_APPLICATIONS_DIR}/otbapp_*${LIB_EXT}") # /lib/otb + if(PKG_DEBUG AND ${raw_item}_RESOLVED) + message("${raw_item} is already resolved [${raw_item}_RESOLVED=${${raw_item}_RESOLVED}]") + endif() - #see the first comment about VAR_IN_PKGSETUP_CONFIGURE - #NOTE: this is not used in windows yet.. - foreach(OTB_APP_SO ${OTB_APPS_LIST}) - get_filename_component(OTB_APP_SO_NAME ${OTB_APP_SO} NAME) - set(VAR_IN_PKGSETUP_CONFIGURE - "${VAR_IN_PKGSETUP_CONFIGURE} lib/otb/applications/${OTB_APP_SO_NAME}") + if(is_system OR ${raw_item}_RESOLVED OR ${raw_item}_USED) + continue() + endif() + + list(APPEND raw_items ${raw_item}) + endforeach() - list(APPEND PKG_PEFILES ${OTB_APPS_LIST}) - if(EXISTS "${OTB_INSTALL_DIR}/lib/otb/python/_otbApplication${PYMODULE_EXT}") - #DO NOT ADD _otbApplication.* to PKG_PEFILES. we install it in next step with - # install( DIRECTORY .. - # list( - # APPEND - # PKG_PEFILES - # "${OTB_INSTALL_DIR}/lib/otb/python/_otbApplication${PYMODULE_EXT}" - # ) - - install( - DIRECTORY - ${OTB_INSTALL_DIR}/lib/otb/python - DESTINATION ${PKG_STAGE_DIR}/lib/ - ) - else() - if(OTB_WRAP_PYTHON) - message(FATAL_ERROR "OTB_WRAP_PYTHON is set , but cannot find _otbApplication${PYMODULE_EXT}") + if(PKG_DEBUG) + string(REPLACE ";" "\n" raw_items_pretty_print "${raw_items}") + # message(FATAL_ERROR "raw_items=${raw_items_pretty_print}") + endif(PKG_DEBUG) + + if(raw_items) + list(REVERSE raw_items) + foreach(item ${raw_items}) + search_library(${item} PKG_SEARCHDIRS item_full_path) + set(is_a_symlink FALSE) + set(item_target_file) + func_is_file_a_symbolic_link("${item_full_path}" is_a_symlink item_target_file) + if(is_a_symlink) + set(${item}_RESOLVED TRUE CACHE INTERNAL "") + set(item ${item_target_file}) endif() - endif() - - # Take gtk libs from system. we should fix this to take from custom - # build location - set(GTK_SYSTEM_LIBS_SEARCH_PATHS - /usr/lib - /lib64 ) - - func_install_support_files() - - execute_process( - COMMAND ${CMAKE_COMMAND} - -E remove_directory - "${CMAKE_BINARY_DIR}/temp_so_names_dir" - ) - - execute_process( - COMMAND ${CMAKE_COMMAND} - -E make_directory - "${CMAKE_BINARY_DIR}/temp_so_names_dir" - ) - - set(alldlls) - set(notfound_dlls) - #message(STATUS "Processing start") - foreach(infile ${PKG_PEFILES}) - get_filename_component(bn ${infile} NAME) - func_process_deps(${bn}) - endforeach() - #message(STATUS "Processing done") - list(REMOVE_DUPLICATES notfound_dlls) - if(UNIX AND NOT APPLE) - foreach(allowed_system_dll ${ALLOWED_SYSTEM_DLLS}) - list (FIND notfound_dlls "${allowed_system_dll}" found_index) - if(${found_index} GREATER -1) - #find_file (<VAR> NAMES name PATHS paths... NO_DEFAULT_PATH) - find_file ( ${allowed_system_dll}_abs_path NAMES ${allowed_system_dll} - PATHS ${GTK_SYSTEM_LIBS_SEARCH_PATHS} NO_DEFAULT_PATH) - if(${allowed_system_dll}_abs_path) - file(GLOB fff "${${allowed_system_dll}_abs_path}*") - foreach(f ${fff}) - func_is_file_a_symbolic_link("${f}" is_symlink linked_to_file) - if(is_symlink) - get_filename_component(name_of_f ${f} NAME) - file(APPEND - ${CMAKE_BINARY_DIR}/make_symlinks_temp - "ln -sf $OUT_DIR/lib/gtk/${linked_to_file} $OUT_DIR/lib/gtk/${name_of_f}\n" - ) - else() # is_symlink - install(FILES ${f} DESTINATION ${PKG_STAGE_DIR}/lib/gtk) - endif() - endforeach() - list(REMOVE_ITEM notfound_dlls "${allowed_system_dll}") - endif() + if(PKG_DEBUG) + message("${bn_name} depends on '${item}'. So we now process '${item}'") # [ ${item}_USED=${${item}_USED} ${item}_RESOLVED=${${item}_RESOLVED}]") endif() + func_process_deps(${item}) endforeach() - endif() #UNIX AND NOT APPLE - - list(LENGTH notfound_dlls nos) - if(${nos} GREATER 0) - message(FATAL_ERROR "Following dlls were not found: ${notfound_dlls}. Please consider adding their paths to PKG_SEARCHDIRS when calling macro_super_package macro.") - endif() #( ${nos} GREATER 0) - - file(GLOB temp_files "${CMAKE_BINARY_DIR}/temp_so_names_dir/*") # /lib/otb - foreach(temp_file ${temp_files}) - get_filename_component(basename_of_temp_file ${temp_file} NAME) - set(VAR_IN_PKGSETUP_CONFIGURE "${VAR_IN_PKGSETUP_CONFIGURE} lib/${basename_of_temp_file}") - endforeach() - - #remove this temporary directory - execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/temp_so_names_dir") - - set(VAR_IN_PKGSETUP_CONFIGURE "${VAR_IN_PKGSETUP_CONFIGURE}" PARENT_SCOPE) - -endfunction() #func_prepare_package - -function(func_process_deps infile) - - if(APPLE) - if( "${infile}" MATCHES "@rpath") - string(REGEX REPLACE "@rpath." "" infile "${infile}") - endif() - endif() - if(WIN32) - string(TOLOWER "${infile}" infile_lower ) - endif() - - # is_system_dll is first pass check the file is not a system dll - # there is a second pass after looking all searchdirs which is where - # we make the call to list it as not-found-dlls - is_system_dll(is_system "${infile}") - if(EXISTS ${infile} AND NOT is_system) - if(APPLE) - # We want all non-system deps to start with rpath - message(FATAL_ERROR "Found dependency without @rpath : ${infile}") - endif() - get_filename_component(infile ${infile} NAME) endif() - get_filename_component(bn ${infile} NAME) - - list_contains(contains "${bn}" "${alldlls}") - if(NOT contains) - set(DLL_FOUND FALSE) - - foreach(SEARCHDIR ${PKG_SEARCHDIRS}) - if(NOT DLL_FOUND) - if(WIN32) - if(NOT EXISTS ${SEARCHDIR}/${infile} ) - if(EXISTS ${SEARCHDIR}/${infile_lower} ) - set(infile ${infile_lower}) - endif() - endif() - endif() - if(EXISTS ${SEARCHDIR}/${infile}) - set(DLL_FOUND TRUE) - message(STATUS "Processing ${SEARCHDIR}/${infile}") - - is_file_executable("${SEARCHDIR}/${infile}" is_executable) - if(is_executable) - file(APPEND ${CMAKE_BINARY_DIR}/install_to_${DEST_BIN_DIR} "${SEARCHDIR}/${infile}\n") - else(is_executable) - get_filename_component(bn_we ${infile} NAME_WE) - file(GLOB sofiles "${SEARCHDIR}/${bn_we}*") - foreach(sofile ${sofiles}) - get_filename_component(sofile_ext ${sofile} EXT) - set(is_valid TRUE) - if ("${sofile_ext}" MATCHES ".la" - OR "${sofile_ext}" MATCHES ".prl" - OR "${sofile_ext}" MATCHES ".a") - set(is_valid FALSE) - endif() - if(is_valid) - get_filename_component(basename_of_sofile ${sofile} NAME) - func_is_file_a_symbolic_link("${sofile}" is_symlink linked_to_file) - if(is_symlink) - # NOTE: $OUT_DIR is set actually in pkgsetup.in. So don't try - # any pre-mature optimization on that variable names - file(APPEND - ${CMAKE_BINARY_DIR}/make_symlinks_temp - "ln -sf $OUT_DIR/lib/${linked_to_file} $OUT_DIR/lib/${basename_of_sofile}\n" - ) - # message("${sofile} is a symlink to ${linked_to_file}") - else() # is_symlink - if(NOT "${basename_of_sofile}" MATCHES "otbapp_") - if( NOT IS_DIRECTORY ${sofile} ) - file(APPEND ${CMAKE_BINARY_DIR}/install_to_${DEST_LIB_DIR} "${sofile}\n") - #just install the so file to <staging-dir>/lib - #install(FILES "${sofile}" DESTINATION ${PKG_STAGE_DIR}/lib MESSAGE_NEVER) - # Finally touch a file in temp directory for globbing later - # message("touching ${basename_of_sofile}") - execute_process(COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/temp_so_names_dir/${basename_of_sofile}") - endif() # ( EXISTS ${SEARCHDIR}/${sofile} ) - endif() # if(.. MATCHES "otbapp_") - endif() # is_symlink - endif() #is_valid - endforeach() - endif(is_executable) - execute_process( - COMMAND ${LOADER_PROGRAM} ${LOADER_PROGRAM_ARGS} "${SEARCHDIR}/${infile}" - RESULT_VARIABLE loader_rv - OUTPUT_VARIABLE loader_ov - ERROR_VARIABLE loader_ev - ) - if(loader_rv) - message(FATAL_ERROR "loader_ev=${loader_ev}\n PACKAGE-OTB: result_variable is '${loader_rv}'") - endif() - if(WIN32) - if(MSVC) - #skip entries from section 'delay load dependencies' - string(REGEX MATCHALL - "Image.has.the.following.dependencies.(.*[Dd][Ll][Ll])" loader_ov "${loader_ov}") - string(REGEX REPLACE - "Image.has.the.following.dependencies.." "" loader_ov "${loader_ov}") - #beware of .DLL and .dll - string(REGEX REPLACE ".DLL" ".dll" loader_ov "${loader_ov}") - #convert to cmake list - string(REGEX REPLACE ".dll" ".dll;" needed_dlls "${loader_ov}") - else() - string(REGEX MATCHALL "DLL.Name..[A-Za-z(0-9\\.0-9)+_\\-]*" loader_ov "${loader_ov}") - string(REGEX REPLACE "DLL.Name.." "" needed_dlls "${loader_ov}") - endif() - else() #case for unixes - if(APPLE) - string(REGEX REPLACE "[^\n]+cmd LC_LOAD_DYLIB\n[^\n]+\n[^\n]+name ([^\n]+).\\(offset[^\n]+\n" "rpath \\1\n" loader_ov "${loader_ov}") - string(REGEX MATCHALL "rpath [^\n]+" loader_ov "${loader_ov}") - string(REGEX REPLACE "rpath " "" needed_dlls "${loader_ov}") - else(APPLE) - string(REGEX MATCHALL "NEEDED\\ *[A-Za-z(0-9\\.0-9)+_\\-]*" loader_ov "${loader_ov}") - string(REGEX REPLACE "NEEDED" "" needed_dlls "${loader_ov}") - endif(APPLE) - endif() - - foreach(needed_dll ${needed_dlls}) - string(STRIP ${needed_dll} needed_dll) - func_process_deps(${needed_dll}) - endforeach() - endif() - endif(NOT DLL_FOUND) - endforeach() + set(${bn_name}_RESOLVED TRUE CACHE INTERNAL "") + if(PKG_DEBUG) + message("All dependencies of ${bn_name} are processed. Install file and set ${bn_name}_RESOLVED=${${bn_name}_RESOLVED}") + endif() - if(NOT DLL_FOUND) - is_system_dll(iss "${infile}") - if(NOT iss) - set(notfound_dlls "${notfound_dlls};${infile}") - endif() - else(NOT DLL_FOUND) - set( alldlls "${alldlls};${bn}" PARENT_SCOPE ) - endif(NOT DLL_FOUND) - set(notfound_dlls "${notfound_dlls}" PARENT_SCOPE ) - endif() + #Install the file with pkg_install_rule. This function has specific rules to decide wheather install file or not + pkg_install_rule(${input_file_full_path}) endfunction() #function(func_process_deps infile) -# The below function is modified from GetPrerequisities.cmake -# which is distributed with CMake. -function(func_is_file_a_symbolic_link file result_var1 result_var2) - # - # A file is not executable until proven otherwise: - # - set(${result_var1} 0 PARENT_SCOPE) - set(${result_var2} "" PARENT_SCOPE) - - get_filename_component(file_full "${file}" ABSOLUTE) - string(TOLOWER "${file_full}" file_full_lower) - - # If file name ends in .exe on Windows, *assume* executable: - # - if(WIN32 AND NOT UNIX) - if("${file_full_lower}" MATCHES "\\.lnk$") - set(${result_var1} 1 PARENT_SCOPE) - #Assuming the file is linked to a file with same name without .lnk extension - get_filename_component(name_we_lnk "${file_full_lower}" NAME_WE) - set(${result_var2} "${name_we_lnk}" PARENT_SCOPE) - return() - endif() - - # A clause could be added here that uses output or return value of dumpbin - # to determine ${result_var}. In 99%+? practical cases, the exe name - # match will be sufficient... - # - endif() - - # Use the information returned from the Unix shell command "file" to - # determine if ${file_full} should be considered an executable file... - # - # If the file command's output contains "executable" and does *not* contain - # "text" then it is likely an executable suitable for prerequisite analysis - # via the get_prerequisites macro. - # - if(UNIX) - if(NOT file_cmd) - find_program(file_cmd "file") - mark_as_advanced(file_cmd) - endif() +function(pkg_install_rule src_file) - if(file_cmd) - execute_process(COMMAND "${file_cmd}" "${file_full}" - RESULT_VARIABLE file_rv - OUTPUT_VARIABLE file_ov - ERROR_VARIABLE file_ev - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - if(NOT file_rv STREQUAL "0") - message(FATAL_ERROR "${file_cmd} failed: ${file_rv}\n${file_ev}") - endif() + get_filename_component(src_file_EXT ${src_file} EXT) + get_filename_component(src_file_NAME ${src_file} NAME) - # Replace the name of the file in the output with a placeholder token - # (the string " _file_full_ ") so that just in case the path name of - # the file contains the word "text" or "executable" we are not fooled - # into thinking "the wrong thing" because the file name matches the - # other 'file' command output we are looking for... - # - string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}") - string(TOLOWER "${file_ov}" file_ov_lower) - - #message(FATAL_ERROR "file_ov='${file_ov}'") - if("${file_ov_lower}" MATCHES "symbolic link") - #message(STATUS "symbolic link!") - set(${result_var1} 1 PARENT_SCOPE) - #Now find where the symlink is linked to. - #Do a regex replace - if(UNIX) - if(APPLE) - string(REGEX REPLACE "_file_full_*.*symbolic.link.to." - "" symlinked_to ${file_ov}) - else(APPLE) - string(REGEX REPLACE "_file_full_*.*symbolic.link.to.." - "" symlinked_to ${file_ov}) - endif(APPLE) - endif(UNIX) - #Take out last character which is a single quote - string(REPLACE "'" "" symlinked_to "${symlinked_to}") - #strip for our own sanity - string(STRIP ${symlinked_to} symlinked_to) - set(${result_var2} "${symlinked_to}" PARENT_SCOPE) - #message(FATAL_ERROR "${file_full} is symlinked_to ${symlinked_to}") - return() - endif() + set(file_type PROGRAMS) + if(NOT src_file_EXT) + set(output_dir "bin") + elseif("${src_file_EXT}" MATCHES "(.[Dd][Ll][Ll]|.exe)") + set(output_dir "bin") + elseif("${src_file_EXT}" MATCHES "(.lib|.so|.dylib)") + set(output_dir "lib") + set(file_type FILES) + else() + message(FATAL_ERROR "unreachable code") + endif() + + set(SKIP_INSTALL FALSE) + setif_value_in_list(is_gtk_lib "${src_file_NAME}" GTK_LIB_LIST_1) + if(is_gtk_lib) + if(PKG_GENERATE_XDK) + set(SKIP_INSTALL TRUE) else() - message(STATUS "warning: No 'file' command, skipping execute_process...") - endif() + set(output_dir "lib/gtk") + endif() #if(PKG_GENERATE_XDK) + endif() #if(is_gtk_lib) + + #special case + if("${src_file_NAME}" MATCHES "^otbapp_") + set(output_dir "lib/otb/applications") + set(file_type PROGRAMS) endif() -endfunction() - -macro(is_system_dll matched value) - set(${matched}) - string(TOLOWER ${value} value_) - foreach (pattern ${SYSTEM_DLLS}) - string(TOLOWER ${pattern} pattern_) - if("${value_}" MATCHES "${pattern_}") - set(${matched} TRUE) - endif() - endforeach() -endmacro() - -macro(list_contains var value) - set(${var}) - foreach(value2 ${ARGN}) - if(${value} STREQUAL ${value2}) - set(${var} TRUE) - endif() - endforeach(value2) -endmacro() - -# Get the translation files coming with Qt, and install them in the bundle -# They are loaded by Monteverdi. -function(get_qt_translation_files RESULT) - # These files are the "qt_<localename>.qm" files - # They are located in QT_TRANSLATIONS_DIR, which comes from FindQt4 - file(GLOB translation_files ${QT_TRANSLATIONS_DIR}/qt_*) - - # We need to remove the "qt_help_<localename>.qm" files from this list - foreach(translation_item ${translation_files}) - if(${translation_item} MATCHES "qt_help") - list(REMOVE_ITEM translation_files ${translation_item}) - endif() - endforeach() - set(${RESULT} ${translation_files} PARENT_SCOPE) -endfunction() - -#func_lisp: - A list_process function (func_lisp) -#This method process the input list inplace. -#It first remove all entries in the list starting with otbapp_* -#Then when generating XDK package it also remove -#the all OTB and Monteverdi binaries are lib. -#Value of PKG_GENERATE_XDK is set already -#The final list is use to create install() commands later -function(func_lisp install_list ) - foreach(install_list_item ${${install_list}}) - get_filename_component(install_list_item_NAME_WE ${install_list_item} NAME_WE) - #MUST remove otb applications. Installed later in otb_support_files function - #message("${install_list_item}") - if ("${install_list_item_NAME_WE}" MATCHES "otbapp_*") - list(REMOVE_ITEM ${install_list} "${install_list_item}") + if(PKG_GENERATE_XDK) + if ("${src_file_NAME}" + MATCHES + "([Oo][Tt][Bb])|([Mm]onteverdi)|mapla|iceViewer" + ) + set(SKIP_INSTALL TRUE) + + message("SKIP_INSTALL for ${src_file_NAME}") endif() - if(PKG_GENERATE_XDK) - if ("${install_list_item_NAME_WE}" - MATCHES - "libOTB|libotb|otbApp|otbTest|libMonteverdi|monteverdi|mapla|iceViewer" - ) - list(REMOVE_ITEM ${install_list} "${install_list_item}") - endif() - endif() - endforeach() + endif() -# message(FATAL_ERROR "install_list=${${install_list}}") - set(${install_list} "${${install_list}}" PARENT_SCOPE) - -endfunction() # func_lisp - -set(WINDOWS_SYSTEM_DLLS - user32.dll - gdi32.dll - shell32.dll - kernel32.dll - ws2_32.dll - wldap32.dll - ole32.dll - comdlg32.dll - shfolder.dll - secur32.dll - wsock32.dll - advapi32.dll - crypt32.dll - imm32.dll - oleaut32.dll - winmm.dll - opengl32.dll - glu32.dll - rpcrt4.dll - winspool.drv - normaliz.dll - odbc32.dll - psapi.dll - python...dll - Image.has.the.following.delay.load - ) - -set(LINUX_SYSTEM_DLLS - libm.so - libc.so - libstdc* - libgcc_s.so - librt.so - libdl.so - libpthread.so - libidn.so - libgomp.so* - ld-linux-x86-64.so* - libX11.so* - libXext.so* - libXau.so* - libXdmcp.so* - libXxf86vm.so* - libdrm.so.2 - libGL.so* - libGLU.so* - libXrender.so* - libSM.so* - libICE.so* - libXrandr.so* - libpython* - ) - -# libgcc_s.*dylib and other *.framework are dragged by QT -set(APPLE_SYSTEM_DLLS - libSystem.*dylib - libiconv.*dylib - libc\\+\\+.*dylib - libstdc.*dylib - libobjc.*dylib - ApplicationServices.framework - CoreFoundation.framework - CoreServices.framework - Security.framework - Carbon.framework - AppKit.framework - Foundation.framework - Python.framework - AGL.framework - OpenGL.framework - libgcc_s.*dylib - ) - -if(WIN32) - set(SYSTEM_DLLS "${WINDOWS_SYSTEM_DLLS}") -else() #case for unixes - if(APPLE) - set(SYSTEM_DLLS "${APPLE_SYSTEM_DLLS}") - else() - set(SYSTEM_DLLS "${LINUX_SYSTEM_DLLS}") + if(NOT SKIP_INSTALL) + install(${file_type} + "${src_file}" + DESTINATION + "${PKG_STAGE_DIR}/${output_dir}") endif() -endif(WIN32) - -#superbuild cannot manage build of gtk2+ just for qt gtkstyle. -# -gtkstyle option is deactivated by default in build of QT4 -# So the list of requirements on building OTB with superbuild stays same. -#For our user base, we need monteverdi with a nice look and feel -# rather than simply X11 based windows. Hence we need -gtkstyle -# This forces us to have system gtk+ installed on the system. -# OTB package manager 'this script' will pick them up and put -# into the binary package. Below cmake variable controls the list of -#libraries coming from /usr/lib a.k.a system. -set(ALLOWED_SYSTEM_DLLS - libfreetype.so.6 - libgthread-2.0.so.0 - libglib-2.0.so.0 - libgobject-2.0.so.0 - libXrender.so.1 - libfontconfig.so.1 - ) + +endfunction() + diff --git a/SuperBuild/Packaging/PackageMacros.cmake b/SuperBuild/Packaging/PackageMacros.cmake new file mode 100755 index 0000000000000000000000000000000000000000..6a5ac835872e7ec892d6a82ed2984deb0b0bf2e3 --- /dev/null +++ b/SuperBuild/Packaging/PackageMacros.cmake @@ -0,0 +1,352 @@ +function(find_python_soname result) + set(${result} PARENT_SCOPE) + execute_process( + COMMAND ${PYTHON_EXECUTABLE} + -c + "import sys; from distutils import sysconfig; print (sysconfig.get_config_var('INSTSONAME'));" + RESULT_VARIABLE python_INSTALLED_SONAME_rv + OUTPUT_VARIABLE python_INSTALLED_SONAME_ov + ) + + if(NOT python_INSTALLED_SONAME_rv EQUAL 0) + message( FATAL_ERROR + "python_INSTALLED_SONAME_rv=${python_INSTALLED_SONAME_rv}: Cannot find python library") + endif() + set(${result} "${python_INSTALLED_SONAME_ov}" PARENT_SCOPE) +endfunction() + + +function(func_install_without_message src_dir dst_dir_suffix) + set (extra_func_args ${ARGN}) + list(LENGTH extra_func_args num_extra_args) + if (${num_extra_args} GREATER 0) + list(GET extra_func_args 0 optional_msg) + endif() + + if( "${dst_dir_suffix}" STREQUAL "") + set(dst_dir "${PKG_STAGE_DIR}") + else() + set(dst_dir "${PKG_STAGE_DIR}/${dst_dir_suffix}") + endif() + + get_filename_component(src_dir_name ${src_dir} NAME) + set(install_msg "message(STATUS \"Installing: ${CMAKE_INSTALL_PREFIX}/${dst_dir}/${src_dir_name} ${optional_msg}\")") + install(CODE "${install_msg}" ) + install( + DIRECTORY ${src_dir} + DESTINATION ${dst_dir} + MESSAGE_NEVER ) +endfunction() #func_install_without_message + + +macro(macro_empty_package_staging_directory) + message(STATUS "Empty package staging directory: ${CMAKE_INSTALL_PREFIX}/${PKG_STAGE_DIR}") + execute_process( + COMMAND ${CMAKE_COMMAND} + -E remove_directory + "${CMAKE_INSTALL_PREFIX}/${PKG_STAGE_DIR}" + ) +endmacro() #macro_empty_package_staging_directory + + +function(search_library input_file pkg_searchdirs result) + set(${result} "" PARENT_SCOPE) + foreach(pkg_searchdir ${${pkg_searchdirs}}) + + if(EXISTS ${pkg_searchdir}/${input_file} ) + if(PKG_DEBUG) + message("Found '${pkg_searchdir}/${input_file}' (return)") + endif() + set(${result} "${pkg_searchdir}/${input_file}" PARENT_SCOPE) + return() + endif() + + #check for file with lowercase + string(TOLOWER "${input_file}" input_file_lower ) + if(EXISTS ${pkg_searchdir}/${input_file_lower}) + set(${result} "${pkg_searchdir}/${input_file_lower}" PARENT_SCOPE) + return() + endif() + endforeach() + +endfunction() + +macro(add_to_symlink_list src_file_name link_file_name) + #TODO: avoid code duplication here and later in install_rule + + set(SKIP_INSTALL FALSE) + + get_filename_component(src_file_name_NAME ${src_file_name} NAME) + + if(PKG_GENERATE_XDK) + if ("${src_file_name_NAME}" + MATCHES + "libOTB|libotb|otbApp|otbapp_|otbTest|libMonteverdi|monteverdi|mapla|iceViewer" + ) + set(SKIP_INSTALL TRUE) + endif() + endif(PKG_GENERATE_XDK) + + setif_value_in_list(is_gtk_lib "${src_file_name_NAME}" GTK_LIB_LIST_1) + if(is_gtk_lib AND PKG_GENERATE_XDK) + set(SKIP_INSTALL TRUE) + endif() + + + # NOTE: $OUT_DIR is set actually in pkgsetup.in. So don't try + # any pre-mature optimization on that variable names + if(NOT SKIP_INSTALL) + + set(lib_dir "lib") + if(is_gtk_lib) + set(lib_dir "lib/gtk") + endif() + file(APPEND + ${CMAKE_BINARY_DIR}/make_symlinks_temp + "ln -sf \"$OUT_DIR/${lib_dir}/${src_file_name}\" \"$OUT_DIR/${lib_dir}/${link_file_name}\" \n" + ) + endif() +endmacro() + +function(is_file_executable2 file_var result_var) + # + # A file is not executable until proven otherwise: + # + set(${result_var} 0 PARENT_SCOPE) + + get_filename_component(file_full "${${file_var}}" ABSOLUTE) + string(TOLOWER "${file_full}" file_full_lower) + # If file name ends in .exe on Windows, *assume* executable: + # + if(WIN32 AND NOT UNIX) + if("${file_full_lower}" MATCHES "(\\.exe|\\.dll)$") + set(${result_var} 1 PARENT_SCOPE) + return() + endif() + + # A clause could be added here that uses output or return value of dumpbin + # to determine ${result_var}. In 99%+? practical cases, the exe name + # match will be sufficient... + # + endif() #WIN32 AND NOT UNIX + + func_is_file_a_symbolic_link("${file_full}" is_a_symlink file_full_target) + if(is_a_symlink) + message("Resolving '${file_full}' to '${file_full_target}") + get_filename_component(file_full_path "${file_full}" PATH) + set(file_full "${file_full_path}/${file_full_target}") + if( EXISTS "${file_full}") + set(${file_var} "${file_full}" PARENT_SCOPE) + else() + message(FATAL_ERROR "${file_full} does not exists. Cannot continue") + endif() + + string(TOLOWER "${file_full}" file_full_lower) + endif() + + # Use the information returned from the Unix shell command "file" to + # determine if ${file_full} should be considered an executable file... + # + # If the file command's output contains "executable" and does *not* contain + # "text" then it is likely an executable suitable for prerequisite analysis + # via the get_prerequisites macro. + # + #if we are not on a unix or unix-like platform, then we don't have any business here + if(NOT UNIX) + return() + endif() + + if(NOT FILE_COMMAND) + message(FATAL_ERROR "warning: No 'file' command, cannot continue...") + endif() + + if(NOT EXISTS "${file_full}") + message(FATAL_ERROR "err. '${file_full}' does not exists or is not absolute path") + set(${file_var} "" PARENT_SCOPE) + endif() + + execute_process(COMMAND "${FILE_COMMAND}" "${file_full}" + RESULT_VARIABLE file_rv + OUTPUT_VARIABLE file_ov + ERROR_VARIABLE file_ev + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(NOT file_rv STREQUAL "0") + message(FATAL_ERROR "${FILE_COMMAND} failed: ${file_rv}\n${file_ev}") + endif() + + # Replace the name of the file in the output with a placeholder token + # (the string " _file_full_ ") so that just in case the path name of + # the file contains the word "text" or "executable" we are not fooled + # into thinking "the wrong thing" because the file name matches the + # other 'file' command output we are looking for... + # + string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}") + string(TOLOWER "${file_ov}" file_ov) + + # message(STATUS "file_ov='${file_ov}'") + # below executable check works for both mac osx and linux + # message("file_full=${file_ov}") + if("${file_ov}" MATCHES "executable") + #message(STATUS "executable!") + if("${file_ov}" MATCHES "text") + set(${result_var} 0 PARENT_SCOPE) + #message(FATAL_ERROR "but text, so *not* a binary executable!") + else() + set(${result_var} 1 PARENT_SCOPE) + return() + endif() + endif() + + # detect position independent executables on Linux, + # where "file" gives "dynamically linked (uses shared libraries)" + if("${file_ov}" MATCHES "dynamically linked.*\(uses shared libs\)") + set(${result_var} 1 PARENT_SCOPE) + return() + endif() + + # detect position independent executables on Linux, + # where "file" gives "shared object ... (uses shared libraries)" + if("${file_ov}" MATCHES "shared object.*\(uses shared libs\)") + set(${result_var} 1 PARENT_SCOPE) + return() + endif() + + # detect shared libraries on Linux, + # where "file" gives "ELF 64-bit LSB shared object, AMD x86-64, version 1 (SYSV), not stripped" + if("${file_ov}" MATCHES "elf.*shared object.*version") + set(${result_var} 1 PARENT_SCOPE) + return() + endif() + + # "file" version 5.22 does not print "(used shared libraries)" + # but uses "interpreter" + if("${file_ov}" MATCHES "shared object.*interpreter") + set(${result_var} 1 PARENT_SCOPE) + return() + endif() + + if(APPLE) + # detect shared libraries on Mac OSX + # where "file" gives "Mach-O 64-bit x86_64 dynamically linked shared library" + if("${file_ov}" MATCHES "mach-o.*dynamically linked shared library") + set(${result_var} 1 PARENT_SCOPE) + return() + endif() + + #below check is redundant. detect executables on Mac OSX + # where "file" gives "Mach-O 64-bit x86_64 executable" + if("${file_ov}" MATCHES "mach-o.*executable") + set(${result_var} 1 PARENT_SCOPE) + return() + endif() + + endif(APPLE) + +endfunction() + + +# The below function is modified from GetPrerequisities.cmake +# which is distributed with CMake. +function(func_is_file_a_symbolic_link file result_var1 result_var2) + # + # A file is not executable until proven otherwise: + # + set(${result_var1} 0 PARENT_SCOPE) + set(${result_var2} "" PARENT_SCOPE) + + get_filename_component(file_full "${file}" ABSOLUTE) + string(TOLOWER "${file_full}" file_full_lower) + + # If file name ends in .exe on Windows, *assume* executable: + # + if(WIN32 AND NOT UNIX) + if("${file_full_lower}" MATCHES "\\.lnk$") + set(${result_var1} 1 PARENT_SCOPE) + #Assuming the file is linked to a file with same name without .lnk extension + get_filename_component(name_we_lnk "${file_full_lower}" NAME_WE) + set(${result_var2} "${name_we_lnk}" PARENT_SCOPE) + return() + endif() + + # A clause could be added here that uses output or return value of dumpbin + # to determine ${result_var}. In 99%+? practical cases, the exe name + # match will be sufficient... + # + endif() + + #if we are not on a unix or unix-like platform, then we don't have any business here + if(NOT UNIX) + return() + endif() + + # Use the information returned from the Unix shell command "file" to + # determine if ${file_full} should be considered an executable file... + # + # If the file command's output contains "executable" and does *not* contain + # "text" then it is likely an executable suitable for prerequisite analysis + # via the get_prerequisites macro. + # + if(NOT FILE_COMMAND) + message(FATAL_ERROR "warning: No 'file' command, cannot continue...") + endif() + + execute_process(COMMAND "${FILE_COMMAND}" "${file_full}" + RESULT_VARIABLE file_rv + OUTPUT_VARIABLE file_ov + ERROR_VARIABLE file_ev + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(NOT file_rv STREQUAL "0") + message(FATAL_ERROR "${FILE_COMMAND} failed: ${file_rv}\n${file_ev}") + endif() + + # Replace the name of the file in the output with a placeholder token + # (the string " _file_full_ ") so that just in case the path name of + # the file contains the word "text" or "executable" we are not fooled + # into thinking "the wrong thing" because the file name matches the + # other 'file' command output we are looking for... + # + string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}") + string(TOLOWER "${file_ov}" file_ov_lower) + + # message(FATAL_ERROR "file_ov='${file_ov}'") + if("${file_ov_lower}" MATCHES "symbolic link") + set(${result_var1} 1 PARENT_SCOPE) + #Now find where the symlink is linked to. + #Do a regex replace + string(REGEX REPLACE "_file_full_*.*symbolic.link.to." "" symlinked_to ${file_ov}) + + #older version of file command output has [`} character(remove it). + string(REPLACE "`" "" symlinked_to ${symlinked_to} ) + + #older version of file command output has {'} character(remove it). + string(REPLACE "'" "" symlinked_to "${symlinked_to}") + + #strip final output + string(STRIP ${symlinked_to} symlinked_to) + set(${result_var2} "${symlinked_to}" PARENT_SCOPE) + + #message(FATAL_ERROR "${file_full} is symlinked_to ${symlinked_to}") + return() + endif() + +endfunction() + +macro(setif_value_in_list matched value list) + set(${matched}) + string(TOLOWER ${value} value_) + foreach (pattern ${${list}}) + string(TOLOWER ${pattern} pattern_) + if("${value_}" MATCHES "${pattern_}") + set(${matched} TRUE) + endif() + endforeach() + #message("'${value}' not found in ${list}") +endmacro() + +function (get_vars_ending_with suffix result) + get_cmake_property(all_cmake_vars VARIABLES) + string (REGEX MATCHALL "(^|;)[A-Za-z0-9_\\.\\-]*(${suffix})" _matchedVars "${all_cmake_vars}") + set(${result} ${_matchedVars} PARENT_SCOPE) +endfunction() diff --git a/SuperBuild/patches/MUPARSERX/CMakeLists.txt b/SuperBuild/patches/MUPARSERX/CMakeLists.txt deleted file mode 100644 index 70ee71d29c7fddf6c64c1ba1c906fe8a39c98b75..0000000000000000000000000000000000000000 --- a/SuperBuild/patches/MUPARSERX/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -cmake_minimum_required(VERSION 2.8.3) - -project(muparserx) - -# Set a default build type if none was specified -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - message(STATUS "Setting build type to 'Release' as none was specified.") - set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE) - # Set the possible values of build type for cmake-gui - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") -endif() - -option(BUILD_SHARED_LIBS "Building shared libs. Default is ON" ON) - -if(MSVC AND BUILD_SHARED_LIBS) - set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) -endif() - -file(GLOB MUPARSERX_SRCS "parser/*.cpp" ) -file(GLOB MUPARSERX_HEADERS "parser/*.h") -# avoid noxious mpCompat.h -list(REMOVE_ITEM MUPARSERX_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/parser/mpCompat.h") - - -add_library(muparserx ${MUPARSERX_SRCS}) - -option(BUILD_SAMPLES "Build sample executable" ON) -include_directories(parser) -add_executable(muparserx-sample sample/timer.cpp sample/example.cpp) -target_link_libraries(muparserx-sample muparserx) - -install(TARGETS muparserx - RUNTIME DESTINATION bin COMPONENT RuntimeLibraries - LIBRARY DESTINATION lib COMPONENT RuntimeLibraries - ARCHIVE DESTINATION lib COMPONENT Development) - -install(FILES ${MUPARSERX_HEADERS} - DESTINATION include - COMPONENT Development) diff --git a/SuperBuild/patches/MUPARSERX/mpParserMessageProvider.cpp b/SuperBuild/patches/MUPARSERX/mpParserMessageProvider.cpp deleted file mode 100644 index dbd442743a97a76782f8441f653d27141f2e63e5..0000000000000000000000000000000000000000 --- a/SuperBuild/patches/MUPARSERX/mpParserMessageProvider.cpp +++ /dev/null @@ -1,181 +0,0 @@ -#include "mpParserMessageProvider.h" -#include <cassert> -#include "mpError.h" - - -MUP_NAMESPACE_START - - //------------------------------------------------------------------------------------------------- - // - // class ParserMessageProviderBase - Base class for message providers - // - //------------------------------------------------------------------------------------------------- - - ParserMessageProviderBase::ParserMessageProviderBase() - :m_vErrMsg(0) - {} - - //----------------------------------------------------------------------------------------------- - ParserMessageProviderBase::~ParserMessageProviderBase() - {} - - //----------------------------------------------------------------------------------------------- - void ParserMessageProviderBase::Init() - { - InitErrorMessages(); - for (int i=0; i<ecCOUNT; ++i) - { - if (!m_vErrMsg[i].length()) - throw std::runtime_error("Incomplete translation (at least one error code missing)"); - } - } - - //--------------------------------------------------------------------------------------------- - string_type ParserMessageProviderBase::GetErrorMsg(EErrorCodes eError) const - { - int nError = (int)eError; - return (nError<(int)m_vErrMsg.size()) ? m_vErrMsg[nError] : string_type(); - } - - //----------------------------------------------------------------------------------------------- - // - // class ParserMessageProviderEnglish - English Parser Messages (default) - // - //----------------------------------------------------------------------------------------------- - - ParserMessageProviderEnglish::ParserMessageProviderEnglish() - :ParserMessageProviderBase() - {} - - //----------------------------------------------------------------------------------------------- - void ParserMessageProviderEnglish::InitErrorMessages() - { - m_vErrMsg.resize(ecCOUNT); - - m_vErrMsg[ecUNASSIGNABLE_TOKEN] = _T("Undefined token \"$IDENT$\" found at position $POS$."); - m_vErrMsg[ecINTERNAL_ERROR] = _T("Internal error."); - m_vErrMsg[ecUNKNOWN_ESCAPE_SEQUENCE] = _T("Unknown escape sequence."); - m_vErrMsg[ecINVALID_NAME] = _T("Invalid function, variable or constant name."); - m_vErrMsg[ecINVALID_FUN_PTR] = _T("Invalid pointer to callback function."); - m_vErrMsg[ecINVALID_VAR_PTR] = _T("Invalid pointer to variable."); - m_vErrMsg[ecUNEXPECTED_OPERATOR] = _T("Unexpected operator \"$IDENT$\" found at position $POS$."); - m_vErrMsg[ecUNEXPECTED_EOF] = _T("Unexpected end of expression found at position $POS$."); - m_vErrMsg[ecUNEXPECTED_COMMA] = _T("Unexpected comma found at position $POS$."); - m_vErrMsg[ecUNEXPECTED_PARENS] = _T("Unexpected parenthesis \"$IDENT$\" found at position $POS$."); - m_vErrMsg[ecUNEXPECTED_FUN] = _T("Unexpected function \"$IDENT$\" found at position $POS$."); - m_vErrMsg[ecUNEXPECTED_VAL] = _T("Unexpected value \"$IDENT$\" found at position $POS$."); - m_vErrMsg[ecUNEXPECTED_VAR] = _T("Unexpected variable \"$IDENT$\" found at position $POS$."); - m_vErrMsg[ecUNEXPECTED_STR] = _T("Unexpected string token found at position $POS$."); - m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = _T("The \"$IDENT$\" operator must be preceded by a closing bracket."); - m_vErrMsg[ecUNEXPECTED_NEWLINE] = _T("Unexprected newline."); - m_vErrMsg[ecMISSING_PARENS] = _T("Missing parenthesis."); - m_vErrMsg[ecMISSING_ELSE_CLAUSE] = _T("If-then-else operator is missing an else clause."); - m_vErrMsg[ecMISPLACED_COLON] = _T("Misplaced colon at position $POS$."); - m_vErrMsg[ecTOO_MANY_PARAMS] = _T("Too many parameters passed to function \"$IDENT$\"."); - m_vErrMsg[ecTOO_FEW_PARAMS] = _T("Too few parameters passed to function \"$IDENT$\"."); - m_vErrMsg[ecDIV_BY_ZERO] = _T("Division by zero occurred."); - m_vErrMsg[ecDOMAIN_ERROR] = _T("The value passed as argument to function/operator \"$IDENT$\" is not part of its domain."); - m_vErrMsg[ecNAME_CONFLICT] = _T("Name conflict."); - m_vErrMsg[ecOPT_PRI] = _T("Invalid value for operator priority (must be greater or equal to zero)."); - m_vErrMsg[ecBUILTIN_OVERLOAD] = _T("Binary operator identifier conflicts with a built in operator."); - m_vErrMsg[ecUNTERMINATED_STRING] = _T("Unterminated string starting at position $POS$."); - m_vErrMsg[ecSTRING_EXPECTED] = _T("String function called with a non string type of argument."); - m_vErrMsg[ecVAL_EXPECTED] = _T("Numerical function called with a non value type of argument."); - m_vErrMsg[ecTYPE_CONFLICT] = _T("Value \"$IDENT$\" is of type '$TYPE1$'. There is no implicit conversion to type '$TYPE2$'."); - m_vErrMsg[ecTYPE_CONFLICT_FUN] = _T("Argument $ARG$ of function/operator \"$IDENT$\" is of type '$TYPE1$' whereas type '$TYPE2$' was expected."); - m_vErrMsg[ecTYPE_CONFLICT_IDX] = _T("Index to \"$IDENT$\" must be a positive integer value. '$TYPE1$' is not an acceptable type."); - m_vErrMsg[ecGENERIC] = _T("Parser error."); - m_vErrMsg[ecINVALID_TYPE] = _T("Invalid argument type."); - m_vErrMsg[ecINVALID_TYPECAST] = _T("Value type conversion from type '$TYPE1$' to '$TYPE2$' is not supported!"); - m_vErrMsg[ecARRAY_SIZE_MISMATCH] = _T("Array size mismatch."); - m_vErrMsg[ecNOT_AN_ARRAY] = _T("Using the index operator on the scalar variable \"$IDENT$\" is not allowed."); - m_vErrMsg[ecUNEXPECTED_SQR_BRACKET] = _T("Unexpected \"[]\"."); - m_vErrMsg[ecUNEXPECTED_CURLY_BRACKET] = _T("Unexpected \"{}\"."); - m_vErrMsg[ecINDEX_OUT_OF_BOUNDS] = _T("Index to variable \"$IDENT$\" is out of bounds."); - m_vErrMsg[ecINDEX_DIMENSION] = _T("Index operator dimension error."); - m_vErrMsg[ecMISSING_SQR_BRACKET] = _T("Missing \"]\"."); - m_vErrMsg[ecMISSING_CURLY_BRACKET] = _T("Missing \"}\"."); - m_vErrMsg[ecASSIGNEMENT_TO_VALUE] = _T("Assignment operator \"$IDENT$\" can't be used in this context."); - m_vErrMsg[ecEVAL] = _T("Can't evaluate function/operator \"$IDENT$\": $HINT$"); - m_vErrMsg[ecINVALID_PARAMETER] = _T("Parameter $ARG$ of function \"$IDENT$\" is invalid."); - m_vErrMsg[ecINVALID_NUMBER_OF_PARAMETERS] = _T("Invalid number of function arguments."); - m_vErrMsg[ecOVERFLOW] = _T("Possible arithmetic overflow occurred in function/operator \"$IDENT$\"."); - m_vErrMsg[ecMATRIX_DIMENSION_MISMATCH] = _T("Matrix dimension error."); - m_vErrMsg[ecVARIABLE_DEFINED] = _T("Variable \"$IDENT$\" is already defined."); - m_vErrMsg[ecCONSTANT_DEFINED] = _T("Constant \"$IDENT$\" is already defined."); - m_vErrMsg[ecFUNOPRT_DEFINED] = _T("Function/operator \"$IDENT$\" is already defined."); - } - -#if defined(_UNICODE) - - //------------------------------------------------------------------------------------------------- - // - // class ParserMessageProviderGerman - German translations of Parser Messages - // - //------------------------------------------------------------------------------------------------- - - ParserMessageProviderGerman::ParserMessageProviderGerman() - :ParserMessageProviderBase() - {} - - //----------------------------------------------------------------------------------------------- - void ParserMessageProviderGerman::InitErrorMessages() - { - m_vErrMsg.resize(ecCOUNT); - - m_vErrMsg[ecUNASSIGNABLE_TOKEN] = _T("Unbekanntes Token \"$IDENT$\" an Position $POS$ gefunden."); - m_vErrMsg[ecINTERNAL_ERROR] = _T("Interner Fehler."); - m_vErrMsg[ecUNKNOWN_ESCAPE_SEQUENCE] = _T("Unbekannte Escape-Sequenz."); - m_vErrMsg[ecINVALID_NAME] = _T("Ungültiger Funktions-, Variablen- oder Konstantenbezeichner."); - m_vErrMsg[ecINVALID_FUN_PTR] = _T("Ungültiger Zeiger auf eine Callback-Funktion."); - m_vErrMsg[ecINVALID_VAR_PTR] = _T("Ungültiger Variablenzeiger."); - m_vErrMsg[ecUNEXPECTED_OPERATOR] = _T("Unerwarteter Operator \"$IDENT$\" an Position $POS$."); - m_vErrMsg[ecUNEXPECTED_EOF] = _T("Unerwartetes Formelende an Position $POS$."); - m_vErrMsg[ecUNEXPECTED_COMMA] = _T("Unerwartetes Komma an Position $POS$."); - m_vErrMsg[ecUNEXPECTED_PARENS ] = _T("Unerwartete Klammer \"$IDENT$\" an Position $POS$ gefunden."); - m_vErrMsg[ecUNEXPECTED_FUN] = _T("Unerwartete Funktion \"$IDENT$\" an Position $POS$ gefunden."); - m_vErrMsg[ecUNEXPECTED_VAL] = _T("Unerwarteter Wert \"$IDENT$\" an Position $POS$ gefunden."); - m_vErrMsg[ecUNEXPECTED_VAR] = _T("Unerwartete Variable \"$IDENT$\" an Position $POS$ gefunden."); - m_vErrMsg[ecUNEXPECTED_STR] = _T("Unerwarteter Text an Position $POS$ gefunden."); - m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = _T("Der Operator \"$IDENT$\" muss stets auf eine schließenden Klammer folgen."); - m_vErrMsg[ecUNEXPECTED_NEWLINE] = _T("Unerwarteter Zeilenumbruch."); - m_vErrMsg[ecMISSING_PARENS] = _T("Fehlende Klammer."); - m_vErrMsg[ecMISSING_ELSE_CLAUSE] = _T("\"If-then-else\" Operator ohne \"else\" Zweig verwendet."); - m_vErrMsg[ecMISPLACED_COLON] = _T("Komma an unerwarteter Position $POS$ gefunden."); - m_vErrMsg[ecTOO_MANY_PARAMS] = _T("Der Funktion \"$IDENT$\" wurden zu viele Argumente übergeben."); - m_vErrMsg[ecTOO_FEW_PARAMS] = _T("Der Funktion \"$IDENT$\" wurden nicht genug Argumente übergeben."); - m_vErrMsg[ecDIV_BY_ZERO] = _T("Division durch Null."); - m_vErrMsg[ecDOMAIN_ERROR] = _T("Der Parameter der Funktion \"$IDENT$\" hat einen Wert, der nicht Teil des Definitionsbereiches der Funktion ist."); - m_vErrMsg[ecNAME_CONFLICT] = _T("Namenskonflikt"); - m_vErrMsg[ecOPT_PRI] = _T("Ungültige Operatorpriorität (muss größer oder gleich Null sein)."); - m_vErrMsg[ecBUILTIN_OVERLOAD] = _T("Die Ãœberladung für diesen Binäroperator steht im Widerspruch zu intern vorhanden operatoren."); - m_vErrMsg[ecUNTERMINATED_STRING] = _T("Die Zeichenkette an Position $POS$ wird nicht beendet."); - m_vErrMsg[ecSTRING_EXPECTED] = _T("Es wurde eine Zeichenkette als Funktionseingabewert erwartet."); - m_vErrMsg[ecVAL_EXPECTED] = _T("Numerische Funktionen können nicht mit nichtnumerischen Parametern aufgerufen werden."); - m_vErrMsg[ecTYPE_CONFLICT] = _T("Der Wert \"$IDENT$\" ist vom Typ '$TYPE1$' und es gibt keine passende Typkonversion in den erwarteten Typ '$TYPE2$'."); - m_vErrMsg[ecTYPE_CONFLICT_FUN] = _T("Das Argument $ARG$ der Funktion oder des Operators \"$IDENT$\" ist vom Typ '$TYPE1$', erwartet wurde Typ '$TYPE2$'."); - m_vErrMsg[ecTYPE_CONFLICT_IDX] = _T("Der Index der Variable \"$IDENT$\" muss ein positiver Ganzzahlwert sein. Der übergebene Indexwert ist vom Typ '$TYPE1$'."); - m_vErrMsg[ecGENERIC] = _T("Allgemeiner Parser Fehler."); - m_vErrMsg[ecINVALID_TYPE] = _T("Ungültiger Funktionsargumenttyp."); - m_vErrMsg[ecINVALID_TYPECAST] = _T("Umwandlungen vom Typ '$TYPE1$' in den Typ '$TYPE2$' werden nicht unterstützt!"); - m_vErrMsg[ecARRAY_SIZE_MISMATCH] = _T("Feldgrößen stimmen nicht überein."); - m_vErrMsg[ecNOT_AN_ARRAY] = _T("Der Indexoperator kann nicht auf die Skalarvariable \"$IDENT$\" angewandt werden."); - m_vErrMsg[ecUNEXPECTED_SQR_BRACKET] = _T("Eckige Klammern sind an dieser Position nicht erlaubt."); - m_vErrMsg[ecUNEXPECTED_CURLY_BRACKET] = _T("Geschweifte Klammern sind an dieser Position nicht erlaubt."); - m_vErrMsg[ecINDEX_OUT_OF_BOUNDS] = _T("Indexüberschreitung bei Variablenzugriff auf \"$IDENT$\"."); - m_vErrMsg[ecINDEX_DIMENSION] = _T("Die Operation kann nicht auf Felder angewandt werden, deren Größe unterschiedlich ist."); - m_vErrMsg[ecMISSING_SQR_BRACKET] = _T("Fehlendes \"]\"."); - m_vErrMsg[ecMISSING_CURLY_BRACKET] = _T("Fehlendes \"}\"."); - m_vErrMsg[ecASSIGNEMENT_TO_VALUE] = _T("Der Zuweisungsoperator \"$IDENT$\" kann in diesem Zusammenhang nicht verwendet werden."); - m_vErrMsg[ecEVAL] = _T("Die Funktion bzw. der Operator \"$IDENT$\" kann nicht berechnet werden: $HINT$"); - m_vErrMsg[ecINVALID_PARAMETER] = _T("Der Parameter $ARG$ der Funktion \"$IDENT$\" is ungültig."); - m_vErrMsg[ecINVALID_NUMBER_OF_PARAMETERS] = _T("Unzulässige Zahl an Funktionsparametern."); - m_vErrMsg[ecOVERFLOW] = _T("Ein arithmetische Ãœberlauf wurde in Funktion/Operator \"$IDENT$\" entdeckt."); - m_vErrMsg[ecMATRIX_DIMENSION_MISMATCH] = _T("Matrixdimensionen stimmen nicht überein, Operation \"$IDENT$\" kann nicht ausgeführt werden."); - m_vErrMsg[ecVARIABLE_DEFINED] = _T("Die Variable \"$IDENT$\" is bereits definiert."); - m_vErrMsg[ecCONSTANT_DEFINED] = _T("Die Konstante \"$IDENT$\" is bereits definiert."); - m_vErrMsg[ecFUNOPRT_DEFINED] = _T("Ein Element mit der Bezeichnung \"$IDENT$\" ist bereits definiert."); - } -#endif // _UNICODE - -MUP_NAMESPACE_END diff --git a/SuperBuild/patches/MUPARSERX/muparserx-1-fixes-all.diff b/SuperBuild/patches/MUPARSERX/muparserx-1-fixes-all.diff new file mode 100644 index 0000000000000000000000000000000000000000..7fa0eb4e9ee5a21f52b3d47759390e056cd565b6 --- /dev/null +++ b/SuperBuild/patches/MUPARSERX/muparserx-1-fixes-all.diff @@ -0,0 +1,20 @@ +diff --git a/parser/mpParserMessageProvider.cpp b/parser/mpParserMessageProvider.cpp +index 22534e6..dbd4427 100644 +--- a/parser/mpParserMessageProvider.cpp ++++ b/parser/mpParserMessageProvider.cpp +@@ -1,5 +1,4 @@ +-#include "mpParserMessageProvider.h" +- ++#include "mpParserMessageProvider.h" + #include <cassert> + #include "mpError.h" + +@@ -111,7 +110,7 @@ MUP_NAMESPACE_START + + //------------------------------------------------------------------------------------------------- + // +- // class ParserMessageProviderGerman - German translations of Parser Messages ++ // class ParserMessageProviderGerman - German translations of Parser Messages + // + //------------------------------------------------------------------------------------------------- + diff --git a/SuperBuild/patches/MUPARSERX/muparserx-2-fixes-all.diff b/SuperBuild/patches/MUPARSERX/muparserx-2-fixes-all.diff new file mode 100644 index 0000000000000000000000000000000000000000..8d621bf29d5544be035671d8a6f32241cdf305e9 --- /dev/null +++ b/SuperBuild/patches/MUPARSERX/muparserx-2-fixes-all.diff @@ -0,0 +1,22 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 9cd37d6..7964e22 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -18,7 +18,7 @@ set(MUPARSERX_VERSION ${CMAKE_MATCH_1}) + ######################################################################## + # Compiler specific flags + ######################################################################## +-if(CMAKE_COMPILER_IS_GNUCXX) ++if(CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") +@@ -33,7 +33,7 @@ if(CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + endif() + +-endif(CMAKE_COMPILER_IS_GNUCXX) ++endif(CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) + + #enable c++11 extensions for OSX + if (APPLE) diff --git a/SuperBuild/patches/OSSIM/ossim-4-trac_2354-linux.diff b/SuperBuild/patches/OSSIM/ossim-4-trac_2354-linux.diff new file mode 100755 index 0000000000000000000000000000000000000000..b24dd823a006acb884d677fe3956224538f38619 --- /dev/null +++ b/SuperBuild/patches/OSSIM/ossim-4-trac_2354-linux.diff @@ -0,0 +1,51 @@ +Description: Fix build failure with GCC 6: no match for 'operator<<'. +Author: Rashad M <rashadkm@gmail.com> +Origin: https://trac.osgeo.org/ossim/attachment/ticket/2354/fix-ossim-trac-2354.diff +Bug-Debian: https://bugs.debian.org/811851 +Bug: https://trac.osgeo.org/ossim/ticket/2354 + +--- a/ossim/src/ossim/elevation/ossimElevManager.cpp ++++ b/ossim/src/ossim/elevation/ossimElevManager.cpp +@@ -643,14 +643,26 @@ std::ostream& ossimElevManager::print(os + << "\nm_useGeoidIfNullFlag = "<<m_useGeoidIfNullFlag + << "\nm_currentDatabaseIdx = "<<m_currentDatabaseIdx + << "\nm_dbRoundRobin.size = "<<m_dbRoundRobin.size(); ++ + for (ossim_uint32 i=0; i<m_dbRoundRobin.size(); ++i) + { + out<<"\nm_dbRoundRobin["<<i<<"].size = "<<m_dbRoundRobin[i].size()<<endl; + for (ossim_uint32 j=0; j<m_dbRoundRobin[i].size(); ++j) +- out<<"m_dbRoundRobin["<<i<<"]["<<j<<"] = "<<m_dbRoundRobin[i][j]->print(out)<<endl; ++ { ++ out<<"m_dbRoundRobin["<<i<<"]["<<j<<"] = "; ++ // GP: We have to separate this line. On MS it will not compile ++ // otherwise ++ m_dbRoundRobin[i][j]->print(out); ++ ++ } ++ out<<endl; + } +- cout<<"\n"<<ossimElevSource::print(cout); ++ out<<"\n"; ++ ossimElevSource::print(out); + return out; ++ ++ ++ + } + + +--- a/ossim/src/ossim/elevation/ossimElevSource.cpp ++++ b/ossim/src/ossim/elevation/ossimElevSource.cpp +@@ -269,8 +269,9 @@ std::ostream& ossimElevSource::print(std + << "\ntheMaxHeightAboveMSL = "<<theMaxHeightAboveMSL + << "\ntheNullHeightValue = "<<theNullHeightValue + << "\ntheSeaLevelValue = "<<theSeaLevelValue +- << "\ntheGroundRect = "<<theGroundRect +- << ossimSource::print(out); ++ << "\ntheGroundRect = "<<theGroundRect; ++ // GP: need this by itself. MS errors out ++ ossimSource::print(out); + return out; + } + diff --git a/SuperBuild/patches/QT4/qt4-3-force-std98-linux.diff b/SuperBuild/patches/QT4/qt4-3-force-std98-linux.diff new file mode 100755 index 0000000000000000000000000000000000000000..9baf1895663471b0671a44ee622f274259cc7603 --- /dev/null +++ b/SuperBuild/patches/QT4/qt4-3-force-std98-linux.diff @@ -0,0 +1,12 @@ +diff -burN qt-everywhere-opensource-src-4.8.7.orig/mkspecs/common/linux.conf qt-everywhere-opensource-src-4.8.7/mkspecs/common/linux.conf +--- qt-everywhere-opensource-src-4.8.7.orig/mkspecs/common/linux.conf 2016-12-07 11:19:59.964124979 +0100 ++++ qt-everywhere-opensource-src-4.8.7/mkspecs/common/linux.conf 2016-12-07 11:22:29.116132748 +0100 +@@ -1,7 +1,7 @@ + # + # qmake configuration for common linux + # +- ++QMAKE_CXXFLAGS += -w -std=c++98 + QMAKE_CFLAGS_THREAD += -D_REENTRANT + QMAKE_CXXFLAGS_THREAD += $$QMAKE_CFLAGS_THREAD + diff --git a/SuperBuild/patches/QT4/qt4-4-mantis1334-qpoint-initialization-all.diff b/SuperBuild/patches/QT4/qt4-4-mantis1334-qpoint-initialization-all.diff new file mode 100644 index 0000000000000000000000000000000000000000..d37eb1f13220801e1d35446b5c12d638774326b5 --- /dev/null +++ b/SuperBuild/patches/QT4/qt4-4-mantis1334-qpoint-initialization-all.diff @@ -0,0 +1,30 @@ +--- qt-everywhere-opensource-src-4.8.7.orig/src/gui/itemviews/qtreeview.cpp 2015-05-07 16:14:43.000000000 +0200 ++++ qt-everywhere-opensource-src-4.8.7/src/gui/itemviews/qtreeview.cpp 2017-02-07 15:30:57.463689900 +0100 +@@ -2261,10 +2261,23 @@ + return; + + d->executePostedLayout(); +- QPoint tl(isRightToLeft() ? qMax(rect.left(), rect.right()) +- : qMin(rect.left(), rect.right()), qMin(rect.top(), rect.bottom())); +- QPoint br(isRightToLeft() ? qMin(rect.left(), rect.right()) : +- qMax(rect.left(), rect.right()), qMax(rect.top(), rect.bottom())); ++ QPoint tl(rect.left(),rect.top()); ++ QPoint br(rect.right(),rect.bottom()); ++ if (isRightToLeft()) { ++ if (rect.left() < rect.right()) { ++ tl.setX(rect.right()); ++ br.setX(rect.left()); ++ } ++ } else { ++ if (rect.left() > rect.right()) { ++ tl.setX(rect.right()); ++ br.setX(rect.left()); ++ } ++ } ++ if (rect.bottom() < rect.top()) { ++ tl.setY(rect.bottom()); ++ br.setY(rect.top()); ++ } + QModelIndex topLeft = indexAt(tl); + QModelIndex bottomRight = indexAt(br); + if (!topLeft.isValid() && !bottomRight.isValid()) { diff --git a/Utilities/Data/CMakeLists.txt b/Utilities/Data/CMakeLists.txt deleted file mode 100644 index d4060576ab3db7625996ddce4a2d2ee30e1735ed..0000000000000000000000000000000000000000 --- a/Utilities/Data/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -if (UNIX AND NOT APPLE) - -# ------------------------- -# Install icons -# following freedesktop recommandations -# http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html - -# The different icon sizes installed -# According to the specs, the 48x48 icon is mandatory, others are optional -set( icon_sizes 16 32 48 128 ) -foreach( icon_size ${icon_sizes} ) - install(FILES Icons/monteverdi-${icon_size}x${icon_size}.png - DESTINATION share/icons/hicolor/${icon_size}x${icon_size}/apps - RENAME monteverdi.png - COMPONENT Resources) -endforeach() - -# Fallback on "/usr/share/pixmaps" -# See http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#directory_layout -install(FILES Icons/monteverdi-32x32.png - DESTINATION share/pixmaps - RENAME monteverdi.png - COMPONENT Resources) - -install(FILES Icons/monteverdi-splash.png - DESTINATION share/pixmaps - RENAME monteverdi-splash.png - COMPONENT Resources) - - -install(FILES Icons/monteverdi-32x32.xpm - DESTINATION share/pixmaps - RENAME monteverdi.xpm - COMPONENT Resources) - -# ------------------------- -# Install freedesktop entry - -install(FILES monteverdi.desktop - DESTINATION share/applications - COMPONENT Resources) - -endif() diff --git a/Utilities/Data/Icons/edit-clear.png b/Utilities/Data/Icons/edit-clear.png new file mode 100644 index 0000000000000000000000000000000000000000..e6c8e8b9f341cbf3a1795631ccaafd14b0e0c911 Binary files /dev/null and b/Utilities/Data/Icons/edit-clear.png differ diff --git a/Utilities/Data/Icons/layer-delete.png b/Utilities/Data/Icons/layer-delete.png new file mode 100644 index 0000000000000000000000000000000000000000..7d6aaf6f257bee75a76325181f7a39b4b903034a Binary files /dev/null and b/Utilities/Data/Icons/layer-delete.png differ diff --git a/Utilities/Data/Icons/layer-delete_24x24.png b/Utilities/Data/Icons/layer-delete_24x24.png deleted file mode 100644 index bf57b112d72f6d8276168ff1ef39a2c0e7b63034..0000000000000000000000000000000000000000 Binary files a/Utilities/Data/Icons/layer-delete_24x24.png and /dev/null differ diff --git a/Utilities/Data/Icons/layers-remove_24x24.png b/Utilities/Data/Icons/layers-remove_24x24.png index 8e2713096c7071e7b38aa0bcfee465724e014780..2e2a29e433ed2b895c00fd32fb1dce53541efe1f 100644 Binary files a/Utilities/Data/Icons/layers-remove_24x24.png and b/Utilities/Data/Icons/layers-remove_24x24.png differ diff --git a/Utilities/Data/Icons/view-refresh.png b/Utilities/Data/Icons/view-refresh.png new file mode 100644 index 0000000000000000000000000000000000000000..3fd71d6e5929ba0c40db1960e36e9acba9d7e525 Binary files /dev/null and b/Utilities/Data/Icons/view-refresh.png differ diff --git a/Utilities/Data/monteverdi.desktop b/Utilities/Data/monteverdi.desktop.in similarity index 64% rename from Utilities/Data/monteverdi.desktop rename to Utilities/Data/monteverdi.desktop.in index 7664bb14d18e53ea542fea354b211cee19477e1a..ee8b5f1a2b74f5af426f794e7e6c9a2964795d3b 100644 --- a/Utilities/Data/monteverdi.desktop +++ b/Utilities/Data/monteverdi.desktop.in @@ -4,10 +4,11 @@ Name=Monteverdi Name[fr_FR]=Monteverdi GenericName=Image processing Comment=Remote sensing image processing application based on OrfeoToolbox -TryExec=/usr/bin/monteverdi -Exec=/usr/bin/monteverdi %F +TryExec=@CMAKE_INSTALL_PREFIX@/bin/monteverdi +Exec=env OTB_APPLICATION_PATH=@CMAKE_INSTALL_PREFIX@/@OTB_INSTALL_APP_DIR@ @CMAKE_INSTALL_PREFIX@/bin/monteverdi %F Terminal=false StartupNotify=false Icon=monteverdi Categories=Education;Science;ImageProcessing;Geography;Qt; MimeType=image/tiff;image/jpeg;image/jp2;application/x-esri-shape; +Keywords=otb;orfeo;toolbox;osgeo; diff --git a/Utilities/Maintenance/TravisBuild.cmake b/Utilities/Maintenance/TravisBuild.cmake index c0790ff2dde01f25af6d4c7f5cd7ff2b06892ed1..b5eab4f09366c725baf79bfd5a6f0aa6bae32fd5 100644 --- a/Utilities/Maintenance/TravisBuild.cmake +++ b/Utilities/Maintenance/TravisBuild.cmake @@ -57,17 +57,17 @@ OTB_USE_QT4:BOOL=ON OTB_USE_OPENGL:BOOL=ON OTB_USE_GLEW:BOOL=ON CMAKE_C_FLAGS:STRING=-Wextra -CMAKE_CXX_FLAGS:STRING=-Wextra -Wno-gnu-static-float-init -Wno-\\#warnings +CMAKE_CXX_FLAGS:STRING=-Wextra -Wno-gnu-static-float-init -Wno-\\#warnings -std=c++11 CMAKE_BUILD_TYPE=${CTEST_BUILD_CONFIGURATION} QT_INSTALL_TRANSLATIONS:PATH=${XDK_INSTALL_DIR}/translations QT_MOC_EXECUTABLE:FILEPATH=${XDK_INSTALL_DIR}/bin/moc QT_UIC_EXECUTABLE:FILEPATH=${XDK_INSTALL_DIR}/bin/uic QT_RCC_EXECUTABLE:FILEPATH=${XDK_INSTALL_DIR}/bin/rcc +QT_LRELEASE_EXECUTABLE:FILEPATH=${XDK_INSTALL_DIR}/bin/lrelease QT_INSTALL_PLUGINS:PATH=${XDK_INSTALL_DIR}/plugins QT_INSTALL_HEADERS:PATH=${XDK_INSTALL_DIR}/include QMAKE_MKSPECS:PATH=${XDK_INSTALL_DIR}/mkspecs " - ) file(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" ${INITIAL_CACHE}) diff --git a/i18n/fr_FR.ts b/i18n/fr_FR.ts index 3127cae92a120fc18d8369046efbb674cdb7cc47..1779a7ffbc860d921008dd0964a8fe7a195e7ae5 100644 --- a/i18n/fr_FR.ts +++ b/i18n/fr_FR.ts @@ -213,6 +213,46 @@ Veuillez, s'il vous plait, supprimer votre répertoire de cache Monteverdi. <source>512</source> <translation>512</translation> </message> + <message> + <source>Lookup table (jet)</source> + <translation>Table de couleur (jet)</translation> + </message> + <message> + <source>Local lookup table (jet)</source> + <translation>Table de couleur locale (jet)</translation> + </message> + <message> + <source>Lookup table (hot)</source> + <translation>Table de couleur (hot)</translation> + </message> + <message> + <source>Local lookup table (hot)</source> + <translation>Table de couleur locale (hot)</translation> + </message> + <message> + <source>Lookup table (winter)</source> + <translation>Table de couleur (winter)</translation> + </message> + <message> + <source>Local lookup table (winter)</source> + <translation>Table de couleur locale (winter)</translation> + </message> + <message> + <source>Lookup table (summer)</source> + <translation>Table de couleur (summer)</translation> + </message> + <message> + <source>Local lookup table (summer)</source> + <translation>Table de couleur locale (summer)</translation> + </message> + <message> + <source>Lookup table (cool)</source> + <translation>Table de couleur (cool)</translation> + </message> + <message> + <source>Local lookup table (cool)</source> + <translation>Table de couleur locale (cool)</translation> + </message> </context> <context> <name>mvd::AboutDialog</name> @@ -621,6 +661,10 @@ Veuillez, s'il vous plait, supprimer votre répertoire de cache Monteverdi. <source>Gamma: </source> <translation>Gamma : </translation> </message> + <message> + <source>Reset value to 1.</source> + <translation>Réinitialiser à 1.</translation> + </message> </context> <context> <name>mvd::ColorSetupController</name> @@ -1027,7 +1071,7 @@ Veuillez, s'il vous plait, supprimer votre répertoire de cache Monteverdi. </message> <message> <source>Zero relevant pixels found when computing histogram (probably because of no-data settings)</source> - <translation>Aucun pixel utilisable lors du calcul d'histogramme (probablement à cause des réglages no-data)</translation> + <translation>Aucun pixel utilisable lors du calcul d'histogramme (probablement à cause des réglages no-data)</translation> </message> </context> <context> @@ -1262,7 +1306,7 @@ Veuillez, s'il vous plait, supprimer votre répertoire de cache Monteverdi. </message> <message> <source>Cannot access settings file.</source> - <translation>Impossible d'accéder au fichiers des paramètres</translation> + <translation>Impossible d'accéder au fichiers des paramètres</translation> </message> <message> <source>Bad settings file format.</source> @@ -3614,11 +3658,11 @@ p, li { white-space: pre-wrap; } </message> <message> <source>I</source> - <translation>I</translation> + <translation type="obsolete">I</translation> </message> <message> <source>J</source> - <translation>J</translation> + <translation type="obsolete">J</translation> </message> <message> <source>Red</source> @@ -3640,6 +3684,14 @@ p, li { white-space: pre-wrap; } <source>Y</source> <translation>Y</translation> </message> + <message> + <source>Column</source> + <translation>Colonne</translation> + </message> + <message> + <source>Line</source> + <translation>Ligne</translation> + </message> </context> <context> <name>mvd::LayerStackWidget</name> @@ -3688,6 +3740,10 @@ p, li { white-space: pre-wrap; } <comment>Necessary for lupdate to be aware of C++ namespaces. Context comment for translator.</comment> <translation></translation> </message> + <message> + <source>Reset all layer effects to Normal</source> + <translation>Réinitialiser tous les effets à Normal</translation> + </message> </context> <context> <name>mvd::MainWindow</name> @@ -4080,6 +4136,14 @@ Charger '%1' provoquera l'affichage des couches dans une vue non <source>Ctrl+P</source> <translation>Ctrl+P</translation> </message> + <message> + <source>OpenGL texture</source> + <translation>Texture OpenGL</translation> + </message> + <message> + <source>Use OpenGL Shading Language (GLSL)</source> + <translation>Utiliser OpenGL Shading Language (GLSL)</translation> + </message> </context> <context> <name>mvd::MainWindowTitleLoader</name> @@ -4637,7 +4701,7 @@ Merci d'en sélectionner un autre.</translation> </message> <message> <source>mvd</source> - <translation>mvd</translation> + <translation type="obsolete">mvd</translation> </message> <message> <source>Rendering effects have been disabled because OpenGL Shading Language minimal requirements have not been met while running on this system.</source> @@ -4753,11 +4817,11 @@ Merci d'en sélectionner un autre.</translation> </message> <message> <source>Read tag '%1' does not match expected tag '%2'.</source> - <translation>L'étiquette lue '%1' ne correspond pas à l'étiquette attendue '%2'.</translation> + <translation>L'étiquette lue '%1' ne correspond pas à l'étiquette attendue '%2'.</translation> </message> <message> <source>Invalid tag name '%1'.</source> - <translation>Nom d'étiquette invalide '%1'.</translation> + <translation>Nom d'étiquette invalide '%1'.</translation> </message> <message> <source>Array dimension (%1) does not match expected dimension (%2).</source> @@ -4765,31 +4829,31 @@ Merci d'en sélectionner un autre.</translation> </message> <message> <source>Histogram sample count (%1) does not match written sample count (%2).</source> - <translation>Le nombre d'échantillons dans l'histrogramme (%1) ne correspond pas au nombre d'échantillons écrits (%2).</translation> + <translation>Le nombre d'échantillons dans l'histrogramme (%1) ne correspond pas au nombre d'échantillons écrits (%2).</translation> </message> <message> <source>Histogram mins dimension (%1) does not match expected dimension (%2).</source> - <translation>La taille des minima d'histogramme (%1) ne correspond pas à la taille attendue (%2).</translation> + <translation>La taille des minima d'histogramme (%1) ne correspond pas à la taille attendue (%2).</translation> </message> <message> <source>Histogram maxs dimension (%1) does not match expected dimension (%2).</source> - <translation>La taille des maxima d'histogramme (%1) ne correspond pas à la taille attendue (%2).</translation> + <translation>La taille des maxima d'histogramme (%1) ne correspond pas à la taille attendue (%2).</translation> </message> <message> <source>Histogram dimension (%1) does not match expected dimension (%2).</source> - <translation>La taille de l'histogramme (%1) ne correspond pas à la taille attendue (%2).</translation> + <translation>La taille de l'histogramme (%1) ne correspond pas à la taille attendue (%2).</translation> </message> <message> <source>Histogram bin count (%1) does not match expected bin count (%2).</source> - <translation>Le nombre de barres dans l'histogramme (%1) ne correspond pas à la valeur attendue (%2).</translation> + <translation>Le nombre de barres dans l'histogramme (%1) ne correspond pas à la valeur attendue (%2).</translation> </message> <message> <source>Histogram sample count (%1) does not match expected sample count (%2).</source> - <translation>Le nombre d'échantillons dans l'histogramme (%1) ne correspond pas à la valeur attendue (%2).</translation> + <translation>Le nombre d'échantillons dans l'histogramme (%1) ne correspond pas à la valeur attendue (%2).</translation> </message> <message> <source>Read sample count (histogram) (%1) does not match written sample count (%2).</source> - <translation>Le nombre d'échantillons lus (histrogramme) (%1) ne correspond pas au nombre d'échantillons écrits (%2).</translation> + <translation>Le nombre d'échantillons lus (histrogramme) (%1) ne correspond pas au nombre d'échantillons écrits (%2).</translation> </message> </context> <context>