diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4fc20dfd7866d1f4cc97d3b7ce116c4dda0ca598..9525bdc2898a29d2e111dba868cb80dc60bc912f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -30,6 +30,7 @@ after_script: stages: - precheck + - prepare - build .general: @@ -76,3 +77,41 @@ ubuntu-llvm: only: [merge_requests] extends: .common-build +superbuild-prepare: + only: [merge_requests] + extends: .general + stage: prepare + image: $BUILD_IMAGE_REGISTRY/otb-ubuntu-superbuild-base:18.04 + before_script: +# This override the previous before_script + - git checkout $CI_COMMIT_REF_NAME +# We are now doing the git-lfs install +# This is done after the checkout so we avoid downloading Data +# But we need it to upload the archive + - git-lfs install + - git config --global user.email "otbbot@orfeo-toolbox.org" + - git config --global user.name "otbbot" + - eval $(ssh-agent -s) + - ssh-add <(echo "$K8S_SECRET_SSH") +# This is for debug, we are checking the owner of the ssh key + - ssh -o StrictHostKeyChecking=no -T git@gitlab.orfeo-toolbox.org + script: + - ctest -VV -S CI/prepare_superbuild.cmake -DIMAGE_NAME:string=otb-ubuntu-superbuild-base + after_script: + - echo "Nothing to do for after_script" + artifacts: + expire_in: 24 hrs + paths: + # This recovers logs from superbuild build + - build/*/*/*/*.log + - sb_branch.txt + +superbuild-build: + only: [merge_requests] + extends: .general + stage: build + image: $BUILD_IMAGE_REGISTRY/otb-ubuntu-superbuild-base:18.04 + script: + - ctest -VV -S CI/main_superbuild.cmake -DIMAGE_NAME:string=otb-ubuntu-superbuild-base + dependencies: + - superbuild-prepare diff --git a/CI/main_superbuild.cmake b/CI/main_superbuild.cmake new file mode 100644 index 0000000000000000000000000000000000000000..93c896662166992ebdf1bd0e8cce860f26c2d959 --- /dev/null +++ b/CI/main_superbuild.cmake @@ -0,0 +1,161 @@ +# +# Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) +# +# This file is part of Orfeo Toolbox +# +# https://www.orfeo-toolbox.org/ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This script is a prototype for the future CI, it may evolve rapidly in a near future +set (ENV{LANG} "C") # Only ascii output +get_filename_component(OTB_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR} DIRECTORY) +get_filename_component(CI_PROJ_DIR ${OTB_SOURCE_DIR} DIRECTORY) +get_filename_component(CI_ROOT_DIR ${CI_PROJ_DIR} DIRECTORY) + +########################################################################### +########################################################################### +# Download xkd +########################################################################### +########################################################################### + +# How to get md5sum: +# * concatenate all source files in one +# * add configure result from previous job ${OTB_SOURCE_DIR}/build/CMakeCache.txt +########################### + +file(READ "${OTB_SOURCE_DIR}/sb_branch.txt" BRANCH_NAME) + +#################################### + + +# git clone $REPOSITORY_URL --branch $BRANCH_NAME --depth 1 superbuild-artifact +############################################################################### +set ( REMOTE "https://gitlab.orfeo-toolbox.org/gbonnefille/superbuild-artifact.git") +# set ( BRANCH_NAME "${IMAGE_NAME}/${SB_MD5}") +set( GIT "git" ) + +execute_process( + COMMAND ${GIT} "clone" "${REMOTE}" "--branch" "${BRANCH_NAME}" + "--depth" "1" "superbuild-artifact" + WORKING_DIRECTORY ${CI_PROJ_DIR} + RESULT_VARIABLE clone_res + OUTPUT_VARIABLE clone_out + ERROR_VARIABLE clone_err + ) + +if ( DEBUG ) + message( "Clone") + message( "clone_res = ${clone_res}" ) + message( "clone_out = ${clone_out}" ) + message( "clone_err = ${clone_err}" ) +endif() + +if (clone_res) + message( SEND_ERROR "Problem in retreiving the archive") + return() +endif() + +set (CMAKE_COMMAND "cmake") +execute_process( + COMMAND ${CMAKE_COMMAND} "-E" "tar" "xf" + "${CI_PROJ_DIR}/superbuild-artifact/SuperBuild_Install.tar" + WORKING_DIRECTORY ${CI_ROOT_DIR} + ) + +set( XDK_PATH "${CI_ROOT_DIR}/xdk") + +if ( DEBUG ) + if ( EXISTS "${XDK_PATH}") + message("Tar file exists at ${XDK_PATH}") + else() + message("Something went wrong no tar file in ${XDK_PATH}") + endif() +endif() + +########################################################################### +########################################################################### +# Building OTB +########################################################################### +########################################################################### + +set ( CTEST_BUILD_CONFIGURATION "Release" ) +set ( CTEST_CMAKE_GENERATOR "Unix Makefiles" ) +set ( CTEST_BUILD_FLAGS "-j16" ) +set ( CTEST_BUILD_NAME "Superbuild_Build_Otb" ) +set ( CTEST_SITE "${IMAGE_NAME}" ) + +# Directory variable +set ( CTEST_SOURCE_DIRECTORY "${OTB_SOURCE_DIR}" ) +set ( CTEST_BINARY_DIRECTORY "${OTB_SOURCE_DIR}/build/" ) +set ( CTEST_INSTALL_DIRECTORY "${OTB_SOURCE_DIR}/install/" ) +set ( PROJECT_SOURCE_DIR "${OTB_SOURCE_DIR}" ) + +set (CONFIGURE_OPTIONS "") +include ( "${CMAKE_CURRENT_LIST_DIR}/configure_option.cmake" ) +# SuperBuild case : one more configure option +set ( CONFIGURE_OPTIONS + "${CONFIGURE_OPTIONS}-DCMAKE_PREFIX_PATH=${XDK_PATH};") + +# Hack because there is no more superbuild available (LIBKML) +set ( CONFIGURE_OPTIONS + "${CONFIGURE_OPTIONS}-DOTB_USE_LIBKML:BOOL=OFF;" ) + +# FIX ME this part might platform dependent +set( GDAL_DATA "${XDK_PATH}/share/gdal" ) +set( GEOTIFF_CSV "${XDK_PATH}/share/epsg_csv" ) +set( PROJ_LIB "${XDK_PATH}/share" ) +set( CTEST_ENVIRONMENT +"PATH=${XDK_PATH}/lib:${XDK_PATH}/bin:$ENV{PATH} +GDAL_DATA= GDAL_DATA +GEOTIFF_CSV= GEOTIFF_CSV +PROJ_LIB= PROJ_LIB +") + +ctest_start (Experimental TRACK Experimental) + +ctest_configure(BUILD "${CTEST_BINARY_DIRECTORY}" + SOURCE "${OTB_SOURCE_DIR}" + OPTIONS "${CONFIGURE_OPTIONS}" + RETURN_VALUE _configure_rv + CAPTURE_CMAKE_ERROR _configure_error + ) + +if ( NOT _configure_rv EQUAL 0 ) + ctest_submit() + message( SEND_ERROR "An error occurs during ctest_configure.") +endif() + +ctest_build(BUILD "${CTEST_BINARY_DIRECTORY}" + RETURN_VALUE _build_rv + CAPTURE_CMAKE_ERROR _build_error + ) + +if ( NOT _build_rv EQUAL 0 ) + ctest_submit() + message( SEND_ERROR "An error occurs during ctest_build.") +endif() + +# Uncomment when ready for test +# ctest_test(PARALLEL_LEVEL 8 +# RETURN_VALUE _test_rv +# CAPTURE_CMAKE_ERROR _test_error +# ) + +# if ( NOT _test_rv EQUAL 0 ) +# ctest_submit() +# message( SEND_ERROR "An error occurs during ctest_test.") +# endif() + +ctest_submit() diff --git a/CI/prepare_superbuild.cmake b/CI/prepare_superbuild.cmake new file mode 100644 index 0000000000000000000000000000000000000000..c94329788b40a995e5c1a497823fbfc9c8b32743 --- /dev/null +++ b/CI/prepare_superbuild.cmake @@ -0,0 +1,345 @@ +# +# Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) +# +# This file is part of Orfeo Toolbox +# +# https://www.orfeo-toolbox.org/ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This script is for the superbuild build on the CI platform + +set (ENV{LANG} "C") # Only ascii output +get_filename_component(OTB_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR} DIRECTORY) +get_filename_component(CI_PROJ_DIR ${OTB_SOURCE_DIR} DIRECTORY) +get_filename_component(CI_ROOT_DIR ${CI_PROJ_DIR} DIRECTORY) + +# In GitLab we have : +# OTB_SOURCE_DIR=/builds/{project_dir}/otb +# CI_PROJ_DIR=/builds/{project_dir} +# CI_ROOT_DIR=/builds + +set ( DEBUG "1" ) + +set ( SUPERBUILD_SOURCE_DIR "${OTB_SOURCE_DIR}/SuperBuild" ) + +set ( CTEST_BUILD_CONFIGURATION "Release" ) +set ( CTEST_CMAKE_GENERATOR "Unix Makefiles" ) +set ( PROJECT_SOURCE_DIR "${SUPERBUILD_SOURCE_DIR}" ) +set ( CTEST_SOURCE_DIRECTORY "${SUPERBUILD_SOURCE_DIR}" ) +set ( CTEST_BINARY_DIRECTORY "${OTB_SOURCE_DIR}/build/" ) +set ( CTEST_SITE "${IMAGE_NAME}" ) +set ( CTEST_BUILD_NAME "Superbuild_Build_Depends" ) # FIXME + +# We need a directory independent from user +# in CI the architecture is /builds/user/otb +# So we will go in /builds/ +# This is platform dependent, and the next step (build) also +# depends on that, as some paths are hardcoded +# This can be fixed with a packaging of OTB_DEPENDS +set (CTEST_INSTALL_DIRECTORY "${CI_ROOT_DIR}/xdk/") + +# HACK +# This is needed because when using return() function ctest is trying +# to run the CTEST_COMMAND. And we need it to not produce an error +set (CTEST_COMMAND "echo \"Exit\"") # HACK FIX ME +set (CMAKE_COMMAND "cmake") + +######################################################################## +######################################################################## +# Build process +######################################################################## +######################################################################## + +ctest_start (Experimental TRACK Experimental) + +set(CTEST_BUILD_FLAGS "-j16") + +set ( SB_CONFIGURE_OPTIONS "") +include( "${CMAKE_CURRENT_LIST_DIR}/sb_configure_options.cmake" ) + +ctest_configure(BUILD "${CTEST_BINARY_DIRECTORY}" + SOURCE "${SUPERBUILD_SOURCE_DIR}" + OPTIONS "${SB_CONFIGURE_OPTIONS}" + RETURN_VALUE _configure_rv + CAPTURE_CMAKE_ERROR _configure_error + ) + +if ( NOT _configure_rv EQUAL 0 ) + ctest_submit() + message( SEND_ERROR "An error occurs during ctest_configure. Dependencies might be buggy.") + return() +endif() + +######################################################################## +######################################################################## +# Check process +######################################################################## +######################################################################## +# Once that we have configure our build we can check if it exists a +# corresponding SB on superbuild-artifact + +# How to get md5sum: +# * concatenate all source files in one +# * add configure result : CMakeCache.txt +#################################### +file( GLOB_RECURSE sb_file_list "${OTB_SOURCE_DIR}/SuperBuild/*") +set( SB_TXT "${OTB_SOURCE_DIR}/full_sb.txt") +foreach(sb_file ${sb_file_list}) + file(READ ${sb_file} CONTENTS) + file(APPEND ${SB_TXT} "${sb_file}${CONTENTS}") +endforeach(sb_file) +file(READ "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" CMAKE_ORIG) +string(REPLACE "${CI_PROJ_DIR}" "" CMAKE_UNIFIED ${CMAKE_ORIG}) +file(APPEND ${SB_TXT} "CMakeCache.txt${CMAKE_UNIFIED}") +file ( MD5 "${SB_TXT}" SB_MD5) +message ( "SB_MD5 = ${SB_MD5}" ) +file (REMOVE ${SB_TXT}) + +#################################### + +# checkout part +# we look for the right branch +# Branch name cannot have a ":" +# git ls-remote $REMOTE $BRANCH_NAME +#################################### +file ( WRITE "${OTB_SOURCE_DIR}/sb_branch.txt" "${IMAGE_NAME}/${SB_MD5}") +message( "Checking out git for existence of archive") +set ( REMOTE "https://gitlab.orfeo-toolbox.org/gbonnefille/superbuild-artifact/") +set ( BRANCH_NAME "${IMAGE_NAME}/${SB_MD5}") +set( GIT "git" ) +execute_process( + COMMAND ${GIT} "ls-remote" "${REMOTE}" "${BRANCH_NAME}" + OUTPUT_VARIABLE IS_SB_BUILD + ) +if ( IS_SB_BUILD ) + message( "Superbuild is already build for ${IMAGE_NAME} with sources as ${SB_MD5}") + return() +else() + message( "No build available, this job will build and push OTB_DEPENDS") +endif() +#################################### +# Back to build + +ctest_build(BUILD "${CTEST_BINARY_DIRECTORY}" + TARGET "OTB_DEPENDS" + RETURN_VALUE _build_rv + NUMBER_ERRORS _build_nb_err + CAPTURE_CMAKE_ERROR _build_error + ) + +if ( DEBUG ) + message( "Status for build:" ) + message("_build_rv=${_build_rv}") + message("_build_nb_err=${_build_nb_err}") + message("_build_error=${_build_error}") +endif() + +if ( ( NOT ${_build_nb_err} EQUAL 0 ) OR ( ${_build_error} EQUAL -1 )) + ctest_submit() + message( FATAL_ERROR "An error occurs during ctest_build.") +endif() + +ctest_submit() + +######################################################################## +######################################################################## +# Git process +######################################################################## +######################################################################## + +# WE PUSH ONLY IF BUILD SUCCEED +# The image used will be passed to this script. +# TODO verify that images does not have forbidden char in there name +# TODO right now we rely on ctest_build to know whether there has been an error +# in build, whereas SuperBuild does not necessarily return an error if something +#Â goes wrong +set ( SB_ARTIFACT_GIT "${CI_PROJ_DIR}/superbuild-artifact" ) + +# REPOSITORY_GIT_URL and REMOTE whould be the same. Right now there are +# different because one is https and one is ssh. Both should be ssh. +set( REPOSITORY_GIT_URL "git@gitlab.orfeo-toolbox.org:gbonnefille/superbuild-artifact.git") +# We clone master to have a basic configuration, mainly a correct .gitattribute +# git clone $REMOTE --branch master --depth 1 superbuild-artifact +execute_process( + COMMAND ${GIT} "clone" "${REPOSITORY_GIT_URL}" + "--branch" "master" "--depth" "1" "superbuild-artifact" + WORKING_DIRECTORY "${CI_PROJ_DIR}" + ) + +# setting up the repo +# StrictHostKeyChecking so we don't have to add the host as a known key +# -F /dev/null so the agent is not taking a default file ~/.ssh/.. +execute_process( + COMMAND ${GIT} "config" "core.sshCommand" + "ssh -o StrictHostKeyChecking=no -F /dev/null" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE ssh_res + OUTPUT_VARIABLE ssh_out + ERROR_VARIABLE ssh_err + ) + +if ( DEBUG ) + message( "Step 1: ssh") + message( "ssh_res = ${ssh_res}" ) + message( "ssh_out = ${ssh_out}" ) + message( "ssh_err = ${ssh_err}" ) +endif() + +execute_process( + COMMAND ${GIT} "config" "user.mail" "otbbot@orfeo-toolbox.org" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE mail_res + OUTPUT_VARIABLE mail_out + ERROR_VARIABLE mail_err + ) + +if ( DEBUG ) + message( "Step 2: mail") + message( "mail_res = ${mail_res}" ) + message( "mail_out = ${mail_out}" ) + message( "mail_err = ${mail_err}" ) +endif() + +execute_process( + COMMAND ${GIT} "config" "user.name" "otbbot" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE name_res + OUTPUT_VARIABLE name_out + ERROR_VARIABLE name_err + ) + +if ( DEBUG ) + message( "Step 3: name") + message( "name_res = ${name_res}" ) + message( "name_out = ${name_out}" ) + message( "name_err = ${name_err}" ) +endif() + +# create a branche +execute_process( + COMMAND ${GIT} "checkout" "-b" "${BRANCH_NAME}" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE co_res + OUTPUT_VARIABLE co_out + ERROR_VARIABLE co_err + ) + +if ( DEBUG ) + message( "Step 4: check-o") + message( "co_res = ${co_res}" ) + message( "co_out = ${co_out}" ) + message( "co_err = ${co_err}" ) +endif() + +set ( SB_TAR_NAME "SuperBuild_Install.tar" ) + +# create the tar +# We need to create tar in its directory to avoid weird name in file +# "tar: Removing leading `../../' from member names" +# WARNING +# We are creating a tar containing xdk/.., so when extracting the archive in +# an other environment the output file will be xdk... Obvious isn't it? +# Well... Not for everyone... +# May be for easier maintainability the tar name should be the same as the +# file inside. +execute_process( + COMMAND ${CMAKE_COMMAND} "-E" "tar" "cf" "${SB_TAR_NAME}" + -- "${CTEST_INSTALL_DIRECTORY}" + WORKING_DIRECTORY ${CI_ROOT_DIR} + ) + +# We need to copy the tar file, as it is on a different partition in the gitlab +# context +file ( COPY "${CI_ROOT_DIR}/${SB_TAR_NAME}" DESTINATION "${SB_ARTIFACT_GIT}") + +# In a near futur it might be nice to clean up the mess we made... + +if ( DEBUG ) + if (EXISTS "${SB_ARTIFACT_GIT}/${SB_TAR_NAME}") + message("Tar file exists in superbuild_artefact at: ${SB_ARTIFACT_GIT}/${SB_TAR_NAME}") + else() + message("Tar file does not exist") + endif() +endif() + +# add the file +execute_process( + COMMAND ${GIT} "add" "${SB_TAR_NAME}" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE add_res + OUTPUT_VARIABLE add_out + ERROR_VARIABLE add_err + ) + +if ( DEBUG ) + message( "Step 5: add") + message( "add_res = ${add_res}" ) + message( "add_out = ${add_out}" ) + message( "add_err = ${add_err}" ) +endif() + + +# commit +# We need the author because otherwise the mail is wrong +# In our case if toto is deploying a key in superbuild-artifact repo +# the the mail will be toto's +execute_process( + COMMAND ${GIT} "commit" "--author=\"otbbot <otbbot@orfeo-toolbox.org>\"" + "-m" "\"New Superbuild for ${SB_MD5} on ${IMAGE_NAME}\"" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE com_res + OUTPUT_VARIABLE com_out + ERROR_VARIABLE com_err + ) + +if ( DEBUG ) + message( "Step 6: com") + message( "com_res = ${com_res}" ) + message( "com_out = ${com_out}" ) + message( "com_err = ${com_err}" ) +endif() + + +# This part is just for debug +if ( DEBUG ) + execute_process( + COMMAND ${GIT} "log" "-1" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE log_res + OUTPUT_VARIABLE log_out + ERROR_VARIABLE log_err + ) + + message( "Step 6bis: log") + message( "log_res = ${log_res}" ) + message( "log_out = ${log_out}" ) + message( "log_err = ${log_err}" ) +endif() + +# push +# we should be able to do a simple : git push origin $BRANCH_NAME +execute_process( + COMMAND ${GIT} "push" "${REPOSITORY_GIT_URL}" "${BRANCH_NAME}" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE push_res + OUTPUT_VARIABLE push_out + ERROR_VARIABLE push_err + ) + +if ( DEBUG ) + message( "Step 7: push") + message( "push_res = ${push_res}" ) + message( "push_out = ${push_out}" ) + message( "push_err = ${push_err}" ) +endif() \ No newline at end of file diff --git a/CI/sb_configure_options.cmake b/CI/sb_configure_options.cmake new file mode 100644 index 0000000000000000000000000000000000000000..1487eedcaf79fce02a113d75d030a6635595c2dc --- /dev/null +++ b/CI/sb_configure_options.cmake @@ -0,0 +1,39 @@ +# +# Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) +# +# This file is part of Orfeo Toolbox +# +# https://www.orfeo-toolbox.org/ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For know OTB_DEPENDS is build with default value + +set ( cmake_configure_option +"CMAKE_BUILD_TYPE=${CTEST_BUILD_CONFIGURATION} +CMAKE_INSTALL_PREFIX:PATH=${CTEST_INSTALL_DIRECTORY}") + +set ( temporary_option +"OTB_USE_LIBKML=OFF") + +set(concat_options +"${cmake_configure_option} +${temporary_option} +") + +#Transform the previous string in list +string (REPLACE "\n" ";" sb_options ${concat_options}) + +foreach(item ${sb_options}) + set( SB_CONFIGURE_OPTIONS "${SB_CONFIGURE_OPTIONS}-D${item};") +endforeach(item) \ No newline at end of file diff --git a/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx b/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx index 95e3314e115ac5254d08d6320207b4e1a80f43fe..bbfb99010e2df503fc561fad3ba528b8b3904151 100644 --- a/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx +++ b/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx @@ -54,7 +54,7 @@ public: /** Filters typedef */ typedef otb::OGRDataToClassStatisticsFilter<FloatVectorImageType,UInt8ImageType> FilterType; - + typedef otb::StatisticsXMLFileWriter<FloatVectorImageType::PixelType> StatWriterType; typedef otb::GeometriesSet GeometriesType; @@ -64,7 +64,6 @@ public: private: PolygonClassStatistics() { - } void DoInit() override @@ -98,17 +97,17 @@ private: AddParameter(ParameterType_InputImage, "mask", "Input validity mask"); SetParameterDescription("mask", "Validity mask (only pixels corresponding to a mask value greater than 0 will be used for statistics)"); MandatoryOff("mask"); - + AddParameter(ParameterType_InputFilename, "vec", "Input vectors"); SetParameterDescription("vec","Input geometries to analyze"); - + AddParameter(ParameterType_OutputFilename, "out", "Output XML statistics file"); SetParameterDescription("out","Output file to store statistics (XML format)"); 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"); @@ -138,16 +137,16 @@ private: 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 || fieldType == OFTInteger64) { std::string tmpKey="field."+key.substr(0, end - key.begin()); @@ -159,7 +158,7 @@ private: // Check that the extension of the output parameter is XML (mandatory for // StatisticsXMLFileWriter) // Check it here to trigger the error before polygons analysis - + if ( HasValue("out") ) { // Store filename extension @@ -175,46 +174,39 @@ private: void DoExecute() override { - otb::ogr::DataSource::Pointer vectors = - otb::ogr::DataSource::New(this->GetParameterString("vec")); + otb::ogr::DataSource::Pointer vectors = otb::ogr::DataSource::New(this->GetParameterString("vec")); - // Retrieve the field name - std::vector<int> selectedCFieldIdx = GetSelectedItems("field"); + // Retrieve the field name + std::vector<int> selectedCFieldIdx = GetSelectedItems("field"); - if(selectedCFieldIdx.empty()) + 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"); - std::string imageProjectionRef = inputImg->GetProjectionRef(); - FloatVectorImageType::ImageKeywordlistType imageKwl = - inputImg->GetImageKeywordlist(); - std::string vectorProjectionRef = - vectors->GetLayer(GetParameterInt("layer")).GetProjectionRef(); - - otb::ogr::DataSource::Pointer reprojVector = vectors; - GeometriesType::Pointer inputGeomSet; - ProjectionFilterType::Pointer geometriesProjFilter; - GeometriesType::Pointer outputGeomSet; - const OGRSpatialReference imgOGRSref = - OGRSpatialReference( imageProjectionRef.c_str() ); - const OGRSpatialReference vectorOGRSref = - OGRSpatialReference( vectorProjectionRef.c_str() ); - bool doReproj = true; - // don't reproject for these cases - if ( vectorProjectionRef.empty() - || ( imgOGRSref.IsSame( &vectorOGRSref ) ) - || ( imageProjectionRef.empty() && imageKwl.GetSize() == 0) ) - doReproj = false; - - if (doReproj) + 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"); + std::string imageProjectionRef = inputImg->GetProjectionRef(); + FloatVectorImageType::ImageKeywordlistType imageKwl = inputImg->GetImageKeywordlist(); + std::string vectorProjectionRef = vectors->GetLayer(GetParameterInt("layer")).GetProjectionRef(); + + otb::ogr::DataSource::Pointer reprojVector = vectors; + GeometriesType::Pointer inputGeomSet; + ProjectionFilterType::Pointer geometriesProjFilter; + GeometriesType::Pointer outputGeomSet; + const OGRSpatialReference imgOGRSref = OGRSpatialReference(imageProjectionRef.c_str()); + const OGRSpatialReference vectorOGRSref = OGRSpatialReference(vectorProjectionRef.c_str()); + bool doReproj = true; + // don't reproject for these cases + if (vectorProjectionRef.empty() || (imgOGRSref.IsSame(&vectorOGRSref)) || (imageProjectionRef.empty() && imageKwl.GetSize() == 0)) + doReproj = false; + + if (doReproj) { inputGeomSet = GeometriesType::New(vectors); reprojVector = otb::ogr::DataSource::New(); @@ -236,7 +228,7 @@ private: filter->SetInput(this->GetParameterImage("in")); if (IsParameterEnabled("mask") && HasValue("mask")) { - filter->SetMask(this->GetParameterImage<UInt8ImageType>("mask")); + filter->SetMask(this->GetParameterUInt8Image("mask")); } filter->SetOGRData(reprojVector); filter->SetFieldName(fieldName); @@ -245,10 +237,10 @@ private: AddProcess(filter->GetStreamer(),"Analyze polygons..."); filter->Update(); - + FilterType::ClassCountMapType &classCount = filter->GetClassCountOutput()->Get(); FilterType::PolygonSizeMapType &polySize = filter->GetPolygonSizeOutput()->Get(); - + StatWriterType::Pointer statWriter = StatWriterType::New(); statWriter->SetFileName(this->GetParameterString("out")); statWriter->AddInputMap<FilterType::ClassCountMapType>("samplesPerClass",classCount); diff --git a/Modules/Applications/AppClassification/app/otbSampleSelection.cxx b/Modules/Applications/AppClassification/app/otbSampleSelection.cxx index a4f8b1fc33a73f4e1a2f123dafd8498238f3f984..959f3c129d0c32c3f77343f249c0b18e022232de 100644 --- a/Modules/Applications/AppClassification/app/otbSampleSelection.cxx +++ b/Modules/Applications/AppClassification/app/otbSampleSelection.cxx @@ -63,7 +63,7 @@ public: UInt8ImageType, otb::RandomSampler> RandomSamplerType; typedef otb::SamplingRateCalculator RateCalculatorType; - + typedef std::map<std::string, unsigned long> ClassCountMapType; typedef RateCalculatorType::MapRateType MapRateType; typedef itk::VariableLengthVector<float> MeasurementType; @@ -87,40 +87,41 @@ private: // Documentation SetDocName("Sample Selection"); - SetDocLongDescription("The application selects a set of samples from geometries " - "intended for training (they should have a field giving the associated " - "class). \n\nFirst of all, the geometries must be analyzed by the PolygonClassStatistics application " - "to compute statistics about the geometries, which are summarized in an xml file. " - "\nThen, this xml file must be given as input to this application (parameter instats).\n\n" - "The input support image and the input training vectors shall be given in " - "parameters 'in' and 'vec' respectively. Only the sampling grid (origin, size, spacing)" - "will be read in the input image.\n" - "There are several strategies to select samples (parameter strategy) : \n\n" - " - smallest (default) : select the same number of sample in each class" - " so that the smallest one is fully sampled.\n" - " - constant : select the same number of samples N in each class" - " (with N below or equal to the size of the smallest class).\n" - " - byclass : set the required number for each class manually, with an input CSV file" - " (first column is class name, second one is the required samples number).\n\n" - " - percent: set a target global percentage of samples to use. Class proportions will be respected. \n\n" - " - total: set a target total number of samples to use. Class proportions will be respected. \n\n" - "There is also a choice on the sampling type to performs : \n\n" - " - periodic : select samples uniformly distributed\n" - " - random : select samples randomly distributed\n\n" - "Once the strategy and type are selected, the application outputs samples positions" - "(parameter out).\n\n" - - "The other parameters to look at are : \n\n" - " - layer : index specifying from which layer to pick geometries.\n" - " - field : set the field name containing the class.\n" - " - mask : an optional raster mask can be used to discard samples.\n" - " - outrates : allows outputting a CSV file that summarizes the sampling rates for each class.\n" - - "\nAs with the PolygonClassStatistics application, different types of geometry are supported : " - "polygons, lines, points. \nThe behavior of this application is different for each type of geometry : \n\n" - " - polygon: select points whose center is inside the polygon\n" - " - lines : select points intersecting the line\n" - " - points : select closest point to the provided point"); + SetDocLongDescription( + "The application selects a set of samples from geometries " + "intended for training (they should have a field giving the associated " + "class). \n\nFirst of all, the geometries must be analyzed by the PolygonClassStatistics application " + "to compute statistics about the geometries, which are summarized in an xml file. " + "\nThen, this xml file must be given as input to this application (parameter instats).\n\n" + "The input support image and the input training vectors shall be given in " + "parameters 'in' and 'vec' respectively. Only the sampling grid (origin, size, spacing)" + "will be read in the input image.\n" + "There are several strategies to select samples (parameter strategy) : \n\n" + " - smallest (default) : select the same number of sample in each class" + " so that the smallest one is fully sampled.\n" + " - constant : select the same number of samples N in each class" + " (with N below or equal to the size of the smallest class).\n" + " - byclass : set the required number for each class manually, with an input CSV file" + " (first column is class name, second one is the required samples number).\n\n" + " - percent: set a target global percentage of samples to use. Class proportions will be respected. \n\n" + " - total: set a target total number of samples to use. Class proportions will be respected. \n\n" + "There is also a choice on the sampling type to performs : \n\n" + " - periodic : select samples uniformly distributed\n" + " - random : select samples randomly distributed\n\n" + "Once the strategy and type are selected, the application outputs samples positions" + "(parameter out).\n\n" + + "The other parameters to look at are : \n\n" + " - layer : index specifying from which layer to pick geometries.\n" + " - field : set the field name containing the class.\n" + " - mask : an optional raster mask can be used to discard samples.\n" + " - outrates : allows outputting a CSV file that summarizes the sampling rates for each class.\n" + + "\nAs with the PolygonClassStatistics application, different types of geometry are supported : " + "polygons, lines, points. \nThe behavior of this application is different for each type of geometry : \n\n" + " - polygon: select points whose center is inside the polygon\n" + " - lines : select points intersecting the line\n" + " - points : select closest point to the provided point"); SetDocLimitations("None"); SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); @@ -192,7 +193,7 @@ private: SetParameterDescription("strategy.total.v","The number of samples to generate"); SetMinimumParameterIntValue("strategy.total.v",1); SetDefaultParameterInt("strategy.total.v",1000); - + AddChoice("strategy.smallest","Set same number of samples for all classes, with the smallest class fully sampled"); SetParameterDescription("strategy.smallest","Set same number of samples for all classes, with the smallest class fully sampled"); @@ -238,16 +239,16 @@ private: 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 || fieldType == OFTInteger64) { std::string tmpKey="field."+key.substr(0, end - key.begin()); @@ -266,27 +267,26 @@ private: // 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"); - m_RateCalculator->SetClassCount(classCount); - - switch (this->GetParameterInt("strategy")) + + 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"); + m_RateCalculator->SetClassCount(classCount); + + switch (this->GetParameterInt("strategy")) { // byclass case 0: { otbAppLogINFO("Sampling strategy : set number of samples for each class"); - ClassCountMapType requiredCount = - otb::SamplingRateCalculator::ReadRequiredSamples(this->GetParameterString("strategy.byclass.in")); + ClassCountMapType requiredCount = otb::SamplingRateCalculator::ReadRequiredSamples(this->GetParameterString("strategy.byclass.in")); m_RateCalculator->SetNbOfSamplesByClass(requiredCount); } break; @@ -330,12 +330,12 @@ private: otbAppLogFATAL("Strategy mode unknown :"<<this->GetParameterString("strategy")); break; } - + if (IsParameterEnabled("outrates") && HasValue("outrates")) { m_RateCalculator->Write(this->GetParameterString("outrates")); } - + MapRateType rates = m_RateCalculator->GetRatesByClass(); std::ostringstream oss; oss << " className requiredSamples totalSamples rate" << std::endl; @@ -376,16 +376,14 @@ private: ProjectionFilterType::Pointer geometriesProjFilter; GeometriesType::Pointer outputGeomSet; bool doReproj = true; - const OGRSpatialReference imgOGRSref = - OGRSpatialReference( imageProjectionRef.c_str() ); - const OGRSpatialReference vectorOGRSref = - OGRSpatialReference( vectorProjectionRef.c_str() ); + const OGRSpatialReference imgOGRSref = OGRSpatialReference(imageProjectionRef.c_str()); + const OGRSpatialReference vectorOGRSref = OGRSpatialReference(vectorProjectionRef.c_str()); // don't reproject for these cases if ( vectorProjectionRef.empty() || ( imgOGRSref.IsSame( &vectorOGRSref ) ) || ( imageProjectionRef.empty() && imageKwl.GetSize() == 0) ) doReproj = false; - + if (doReproj) { inputGeomSet = GeometriesType::New(vectors); @@ -407,7 +405,7 @@ private: // Create output dataset for sample positions otb::ogr::DataSource::Pointer outputSamples = otb::ogr::DataSource::New(this->GetParameterString("out"),otb::ogr::DataSource::Modes::Overwrite); - + switch (this->GetParameterInt("sampler")) { // periodic @@ -426,7 +424,7 @@ private: periodicFilt->SetSamplerParameters(param); if (IsParameterEnabled("mask") && HasValue("mask")) { - periodicFilt->SetMask(this->GetParameterImage<UInt8ImageType>("mask")); + periodicFilt->SetMask(this->GetParameterUInt8Image("mask")); } periodicFilt->GetStreamer()->SetAutomaticTiledStreaming(this->GetParameterInt("ram")); AddProcess(periodicFilt->GetStreamer(),"Selecting positions with periodic sampler..."); @@ -444,7 +442,7 @@ private: randomFilt->SetLayerIndex(this->GetParameterInt("layer")); if (IsParameterEnabled("mask") && HasValue("mask")) { - randomFilt->SetMask(this->GetParameterImage<UInt8ImageType>("mask")); + randomFilt->SetMask(this->GetParameterUInt8Image("mask")); } randomFilt->GetStreamer()->SetAutomaticTiledStreaming(this->GetParameterInt("ram")); AddProcess(randomFilt->GetStreamer(),"Selecting positions with random sampler..."); diff --git a/Modules/Applications/AppClassification/test/CMakeLists.txt b/Modules/Applications/AppClassification/test/CMakeLists.txt index 9d40b00dd166e3d5230b30cb62792ebceb8ad6a9..6a05178e64311574862ceaf555fcff1310111815 100644 --- a/Modules/Applications/AppClassification/test/CMakeLists.txt +++ b/Modules/Applications/AppClassification/test/CMakeLists.txt @@ -179,6 +179,9 @@ foreach(classifier ${classifierList}) VALID ${valid} ) + set_tests_properties(apTvClTrainMethod${classifier}ImagesClassifierQB1 PROPERTIES + RESOURCE_LOCK ${INPUTDATA}/Classification/VectorData_${${lclassifier}_input}QB1_utm31n${vector_input_format}) + if(${_classifier_has_baseline} EQUAL -1) set(valid ${ascii_confmat_comparison} ${ascii_ref_path}/${OUTCONFMATFILE} ${TEMP}/${OUTCONFMATFILE}) else() diff --git a/Modules/Applications/AppImageUtils/app/otbManageNoData.cxx b/Modules/Applications/AppImageUtils/app/otbManageNoData.cxx index 561131caab6a86f6d21c50695838fb4ba0821fe2..4cd2b5f917dfdf22963006931c5bcd91b583bee8 100644 --- a/Modules/Applications/AppImageUtils/app/otbManageNoData.cxx +++ b/Modules/Applications/AppImageUtils/app/otbManageNoData.cxx @@ -50,7 +50,7 @@ public: /** Filters typedef */ typedef otb::ImageToNoDataMaskFilter<FloatVectorImageType,UInt8ImageType> FilterType; typedef otb::ChangeNoDataValueFilter<FloatVectorImageType,FloatVectorImageType> ChangeNoDataFilterType; - + typedef otb::ImageList<FloatImageType> ImageListType; typedef otb::VectorImageToImageListFilter<FloatVectorImageType,ImageListType> VectorToListFilterType; typedef otb::ImageListToVectorImageFilter<ImageListType,FloatVectorImageType> ListToVectorFilterType; @@ -81,12 +81,12 @@ private: AddParameter(ParameterType_Bool,"usenan", "Consider NaN as no-data"); SetParameterDescription("usenan","If active, the application will consider NaN as no-data values as well"); - + AddParameter(ParameterType_Choice,"mode","No-data handling mode"); SetParameterDescription("mode","Allows choosing between different no-data handling options"); AddChoice("mode.buildmask","Build a no-data Mask"); - + AddParameter(ParameterType_Float,"mode.buildmask.inv","Inside Value"); SetParameterDescription("mode.buildmask.inv","Value given in the output mask to pixels that are not no data pixels"); SetDefaultParameterInt("mode.buildmask.inv",1); @@ -132,7 +132,7 @@ private: void DoExecute() override { FloatVectorImageType::Pointer inputPtr = this->GetParameterImage("in"); - + m_Filter = FilterType::New(); m_Filter->SetInsideValue(this->GetParameterFloat("mode.buildmask.inv")); m_Filter->SetOutsideValue(this->GetParameterFloat("mode.buildmask.outv")); @@ -146,7 +146,7 @@ private: std::vector<double> newNoData(inputPtr->GetNumberOfComponentsPerPixel(),GetParameterFloat("mode.changevalue.newv")); m_ChangeNoDataFilter->SetNewNoDataValues(newNoData); - + if(GetParameterString("mode") == "buildmask") { SetParameterOutputImage("out",m_Filter->GetOutput()); @@ -158,7 +158,7 @@ private: else if (GetParameterString("mode") == "apply") { m_MaskFilters.clear(); - UInt8ImageType::Pointer maskPtr = this->GetParameterImage<UInt8ImageType>("mode.apply.mask"); + UInt8ImageType::Pointer maskPtr = this->GetParameterUInt8Image("mode.apply.mask"); unsigned int nbBands = inputPtr->GetNumberOfComponentsPerPixel(); itk::MetaDataDictionary &dict = inputPtr->GetMetaDataDictionary(); std::vector<bool> flags; @@ -221,4 +221,3 @@ private: } OTB_APPLICATION_EXPORT(otb::Wrapper::ManageNoData) - diff --git a/Modules/Applications/AppProjection/test/CMakeLists.txt b/Modules/Applications/AppProjection/test/CMakeLists.txt index e9d4c8a0de20aea3cfcbbd79a9106573c68fd173..28b843b2157b84c32720f2a218302b9e36942f2b 100644 --- a/Modules/Applications/AppProjection/test/CMakeLists.txt +++ b/Modules/Applications/AppProjection/test/CMakeLists.txt @@ -343,7 +343,8 @@ otb_test_application(NAME apTvPrConvertSensorToGeoPoint TESTENVOPTIONS ${TEMP}/apTvPrConvertSensorToGeoPoint.txt VALID --compare-ascii ${EPSILON_7} ${BASELINE_FILES}/apTvPrConvertSensorToGeoPoint.txt - ${TEMP}/apTvPrConvertSensorToGeoPoint.txt) + ${TEMP}/apTvPrConvertSensorToGeoPoint.txt + --ignore-lines-with 2 town country) #----------- Superimpose TESTS ---------------- diff --git a/Modules/Applications/AppSegmentation/app/otbLargeScaleMeanShift.cxx b/Modules/Applications/AppSegmentation/app/otbLargeScaleMeanShift.cxx index 8f09d36adf5f74b938dfe1e838e49aa8fbf233a5..bc414d0f2081c4d6d9a7951ea079b24318838cea 100644 --- a/Modules/Applications/AppSegmentation/app/otbLargeScaleMeanShift.cxx +++ b/Modules/Applications/AppSegmentation/app/otbLargeScaleMeanShift.cxx @@ -33,7 +33,7 @@ namespace Wrapper * * This application gathers the 4 steps of the large-scale MeanShift * segmentation framework. - * + * */ class LargeScaleMeanShift : public CompositeApplication { @@ -191,13 +191,11 @@ private: if (IsParameterEnabled("mode.vector.imfield") && HasValue("mode.vector.imfield")) { - GetInternalApplication("vectorization")->SetParameterInputImage("in", - GetParameterImage<ImageBaseType>("mode.vector.imfield")); + GetInternalApplication("vectorization")->SetParameterInputImage("in", GetParameterImageBase("mode.vector.imfield")); } else { - GetInternalApplication("vectorization")->SetParameterInputImage("in", - GetParameterImage<ImageBaseType>("in")); + GetInternalApplication("vectorization")->SetParameterInputImage("in", GetParameterImageBase("in")); } GetInternalApplication("vectorization")->SetParameterString("inseg", tmpFilenames[2]); diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h index d53f70c266f4b9e8f59aa68ee033ba2fd384dfb8..3baadd6f0f747b5f640b284fd3bd6a7aeab79254 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h @@ -765,13 +765,13 @@ public: void SetParameterImageBase(const std::string & key, ImageBaseType* img, unsigned int idx = 0); /** - Register all ProcessObject that are linked to parameters : + Register all ProcessObject that are linked to parameters : \li ParameterType_OutputImage \li ParameterType_OutputVectorData - Those ProcessObjects are stored in the m_Filters set and are deleted at the + Those ProcessObjects are stored in the m_Filters set and are deleted at the end of ExecuteAndWriteOutput (if there are only held by the set) - This method can be called just before the end of a DoExecute in a derived + This method can be called just before the end of a DoExecute in a derived class of Application. */ void RegisterPipeline(); @@ -850,21 +850,7 @@ protected: * \li ParameterType_InputImage */ template <class TImageType> - TImageType* GetParameterImage(std::string parameter) - { - typename TImageType::Pointer ret; - Parameter* param = GetParameterByKey(parameter); - InputImageParameter* paramDown = dynamic_cast<InputImageParameter*>(param); - if (paramDown) - { - return paramDown->GetImage<TImageType>(); - } - else - { - itkExceptionMacro(<<parameter << " parameter can't be casted to ImageType"); - return nullptr; - } - } + TImageType* GetParameterImage(std::string parameter); /** Declare a parameter as having an automatic value */ void AutomaticValueOn(std::string paramKey); @@ -878,16 +864,7 @@ protected: * \li ParameterType_OutputImage */ template <class TImageType> - void SetParameterOutputImage(std::string parameter, TImageType* value) - { - Parameter* param = GetParameterByKey(parameter); - - if (dynamic_cast<OutputImageParameter*>(param)) - { - OutputImageParameter* paramDown = dynamic_cast<OutputImageParameter*>(param); - paramDown->SetValue(value); - } - } + void SetParameterOutputImage(std::string parameter, TImageType* value); private: /* Implement this method to add parameters */ @@ -963,9 +940,90 @@ private: } //end namespace otb -//#ifndef OTB_MANUAL_INSTANTIATION -//#include "otbWrapperApplication.hxx" -//#endif +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbWrapperApplication.hxx" +#endif + + +namespace otb +{ +namespace Wrapper +{ + +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt8VectorImageType* Application::GetParameterImage<UInt8VectorImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE Int16VectorImageType* Application::GetParameterImage<Int16VectorImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt16VectorImageType* Application::GetParameterImage<UInt16VectorImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE Int32VectorImageType* Application::GetParameterImage<Int32VectorImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt32VectorImageType* Application::GetParameterImage<UInt32VectorImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE FloatVectorImageType* Application::GetParameterImage<FloatVectorImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE DoubleVectorImageType* Application::GetParameterImage<DoubleVectorImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexInt16VectorImageType* Application::GetParameterImage<ComplexInt16VectorImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexInt32VectorImageType* Application::GetParameterImage<ComplexInt32VectorImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexFloatVectorImageType* Application::GetParameterImage<ComplexFloatVectorImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexDoubleVectorImageType* Application::GetParameterImage<ComplexDoubleVectorImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt8RGBImageType* Application::GetParameterImage<UInt8RGBImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt8RGBAImageType* Application::GetParameterImage<UInt8RGBAImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt8ImageType* Application::GetParameterImage<UInt8ImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE Int16ImageType* Application::GetParameterImage<Int16ImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt16ImageType* Application::GetParameterImage<UInt16ImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE Int32ImageType* Application::GetParameterImage<Int32ImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt32ImageType* Application::GetParameterImage<UInt32ImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE FloatImageType* Application::GetParameterImage<FloatImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE DoubleImageType* Application::GetParameterImage<DoubleImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexInt16ImageType* Application::GetParameterImage<ComplexInt16ImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexInt32ImageType* Application::GetParameterImage<ComplexInt32ImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexFloatImageType* Application::GetParameterImage<ComplexFloatImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexDoubleImageType* Application::GetParameterImage<ComplexDoubleImageType>(std::string); + +// + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt8VectorImageType>(std::string, UInt8VectorImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<Int16VectorImageType>(std::string, Int16VectorImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt16VectorImageType>(std::string, UInt16VectorImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<Int32VectorImageType>(std::string, Int32VectorImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt32VectorImageType>(std::string, UInt32VectorImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<FloatVectorImageType>(std::string, FloatVectorImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<DoubleVectorImageType>(std::string, DoubleVectorImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt16VectorImageType>(std::string, + ComplexInt16VectorImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt32VectorImageType>(std::string, + ComplexInt32VectorImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexFloatVectorImageType>(std::string, + ComplexFloatVectorImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexDoubleVectorImageType>(std::string, + ComplexDoubleVectorImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt8RGBImageType>(std::string, UInt8RGBImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt8RGBAImageType>(std::string, UInt8RGBAImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt8ImageType>(std::string, UInt8ImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<Int16ImageType>(std::string, Int16ImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt16ImageType>(std::string, UInt16ImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<Int32ImageType>(std::string, Int32ImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt32ImageType>(std::string, UInt32ImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<FloatImageType>(std::string, FloatImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<DoubleImageType>(std::string, DoubleImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt16ImageType>(std::string, ComplexInt16ImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt32ImageType>(std::string, ComplexInt32ImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexFloatImageType>(std::string, ComplexFloatImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexDoubleImageType>(std::string, ComplexDoubleImageType*); + +} // namespace Wrapper +} // namespace otb #endif // otbWrapperApplication_h_ diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.hxx b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.hxx new file mode 100644 index 0000000000000000000000000000000000000000..33330cd2418fa7c81e506806d6a43b3d9d583f23 --- /dev/null +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.hxx @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef otbWrapperApplication_hxx +#define otbWrapperApplication_hxx + + +#include "otbWrapperApplication.h" + + +namespace otb +{ + + +namespace Wrapper +{ + + +template <class TImageType> +TImageType* +Application +::GetParameterImage(std::string parameter) + +{ + typename TImageType::Pointer ret; + Parameter* param = GetParameterByKey(parameter); + InputImageParameter* paramDown = dynamic_cast<InputImageParameter*>(param); + if (paramDown) + { + return paramDown->GetImage<TImageType>(); + } + else + { + itkExceptionMacro(<<parameter << " parameter can't be casted to ImageType"); + return nullptr; + } +} + + +template <class TImageType> +void +Application +::SetParameterOutputImage(std::string parameter, TImageType* value) +{ + Parameter* param = GetParameterByKey(parameter); + + if (dynamic_cast<OutputImageParameter*>(param)) + { + OutputImageParameter* paramDown = dynamic_cast<OutputImageParameter*>(param); + paramDown->SetValue(value); + } +} + + +} // End namespace Wrapper + +} // End namespace otb + +#endif diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperCastImage.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperCastImage.h new file mode 100644 index 0000000000000000000000000000000000000000..0e975d7adc2fea303e776ad7202cda5e7852f689 --- /dev/null +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperCastImage.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef otbWrapperCastimage_h +#define otbWrapperCastimage_h + + +#include "otbClampImageFilter.h" + +#include "OTBApplicationEngineExport.h" + +#include "otbWrapperTypes.h" + + +namespace otb +{ +namespace Wrapper +{ +namespace details +{ + +/** \class CastImage + * \brief Helper class (private) which casts and clamps input-image type into + * output-image type. + * + * \ingroup OTBApplicationEngine + */ +template <typename TOutputImage, typename TInputImage> +struct OTBApplicationEngine_EXPORT_TEMPLATE CastImage +{ + /** Input clamping */ + using InputClampImageFilter = ClampImageFilter<TInputImage, DoubleVectorImageType>; + + /** Output clamping */ + using OutputClampImageFilter = ClampImageFilter<DoubleVectorImageType, TOutputImage>; + + + /** Constructor. */ + CastImage(TInputImage* in) : icif(InputClampImageFilter::New()), ocif(OutputClampImageFilter::New()), out(ocif->GetOutput()) + { + assert(in); + + icif->SetInput(in); + + ocif->SetInput(icif->GetOutput()); + } + + /** Input-image clamp filter. */ + typename InputClampImageFilter::Pointer icif; + + /** Output-image clamp filter. */ + typename OutputClampImageFilter::Pointer ocif; + + /** Output image. */ + TOutputImage* out; +}; + + +/** \class CastImage + * \brief Partial template specialization which optimizes processing + * pipeline when input-image is DoubleVectorImageType. + * + * \ingroup OTBApplicationEngine + */ +template <typename TOutputImage> +struct OTBApplicationEngine_EXPORT_TEMPLATE CastImage<TOutputImage, DoubleVectorImageType> +{ + /** Output clamping */ + using OutputClampImageFilter = ClampImageFilter<DoubleVectorImageType, TOutputImage>; + + + /** Constructor. */ + CastImage(DoubleVectorImageType* in) : ocif(OutputClampImageFilter::New()), out(ocif->GetOutput()) + { + assert(in); + + ocif->SetInput(in); + } + + /** Input-image clamp filter. */ + itk::ProcessObject::Pointer icif; + + /** Output-image clamp filter. */ + typename OutputClampImageFilter::Pointer ocif; + + /** Output image. */ + TOutputImage* out; +}; + + +/** \class CastImage + * \brief Template specialization which optimizes the processing + * pipeline when input-image and output-image types are identical. + * + * \ingroup OTBApplicationEngine + */ +template <typename T> +struct OTBApplicationEngine_EXPORT_TEMPLATE CastImage<T, T> +{ + CastImage(T* in) : out(in) + { + assert(in); + } + + itk::ProcessObject::Pointer icif; + itk::ProcessObject::Pointer ocif; + T* out; +}; + + +/** \class CastImage + * \brief Template specialization which optimizes the processing + * pipeline when input-image and output-image types are identical. + * + * \ingroup OTBApplicationEngine + */ +template <> +struct OTBApplicationEngine_EXPORT_TEMPLATE CastImage<DoubleVectorImageType, DoubleVectorImageType> +{ + CastImage(DoubleVectorImageType* in) : out(in) + { + assert(in); + } + + itk::ProcessObject::Pointer icif; + itk::ProcessObject::Pointer ocif; + DoubleVectorImageType* out; +}; + +} // namespace details. + +} // namespace Wrapper + +} // namespace otb + +#endif diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.h index 80aefb371880dc53c0272de0496152b26f0c7a79..a49e4c2bfb477da878372e778b3174755361d5d3 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.h @@ -21,9 +21,13 @@ #ifndef otbWrapperInputImageParameter_h #define otbWrapperInputImageParameter_h + #include "otbImageFileReader.h" -#include "itkImageBase.h" +#include "otbClampImageFilter.h" #include "otbWrapperParameter.h" + +#include "itkImageBase.h" + #include <string> namespace otb @@ -56,27 +60,28 @@ public: itkGetConstReferenceMacro( FileName, std::string ); - /** Get the input image as FloatVectorImageType. */ - FloatVectorImageType* GetImage(); + /** Get input-image as ImageBaseType. */ + ImageBaseType const* GetImage() const; + ImageBaseType* GetImage(); /** Get the input image as XXXImageType */ - UInt8ImageType* GetUInt8Image(); + UInt8ImageType* GetUInt8Image(); UInt16ImageType* GetUInt16Image(); - Int16ImageType* GetInt16Image(); + Int16ImageType* GetInt16Image(); UInt32ImageType* GetUInt32Image(); - Int32ImageType* GetInt32Image(); - FloatImageType* GetFloatImage(); + Int32ImageType* GetInt32Image(); + FloatImageType* GetFloatImage(); DoubleImageType* GetDoubleImage(); - UInt8VectorImageType* GetUInt8VectorImage(); + UInt8VectorImageType* GetUInt8VectorImage(); UInt16VectorImageType* GetUInt16VectorImage(); - Int16VectorImageType* GetInt16VectorImage(); + Int16VectorImageType* GetInt16VectorImage(); UInt32VectorImageType* GetUInt32VectorImage(); - Int32VectorImageType* GetInt32VectorImage(); - FloatVectorImageType* GetFloatVectorImage(); + Int32VectorImageType* GetInt32VectorImage(); + FloatVectorImageType* GetFloatVectorImage(); DoubleVectorImageType* GetDoubleVectorImage(); - UInt8RGBImageType* GetUInt8RGBImage(); + UInt8RGBImageType* GetUInt8RGBImage(); UInt8RGBAImageType* GetUInt8RGBAImage(); // Complex image @@ -94,12 +99,8 @@ public: template <class TImageType> TImageType* GetImage(); - /** Set a FloatVectorImageType image.*/ - void SetImage(FloatVectorImageType* image); - /** Set a templated image.*/ - template <class TImageType> - void SetImage(TImageType* image); + void SetImage(ImageBaseType* image); /** Generic cast method that will be specified for each image type. */ @@ -120,48 +121,30 @@ protected: /** Destructor */ ~InputImageParameter() override; - ImageBaseType::Pointer m_Image; - std::string m_FileName; - - /** Readers typedefs */ - - typedef otb::ImageFileReader<UInt8ImageType> UInt8ReaderType; - typedef otb::ImageFileReader<Int16ImageType> Int16ReaderType; - typedef otb::ImageFileReader<UInt16ImageType> UInt16ReaderType; - typedef otb::ImageFileReader<Int32ImageType> Int32ReaderType; - typedef otb::ImageFileReader<UInt32ImageType> UInt32ReaderType; - typedef otb::ImageFileReader<FloatImageType> FloatReaderType; - typedef otb::ImageFileReader<DoubleImageType> DoubleReaderType; - - typedef otb::ImageFileReader<UInt8VectorImageType> UInt8VectorReaderType; - typedef otb::ImageFileReader<Int16VectorImageType> Int16VectorReaderType; - typedef otb::ImageFileReader<UInt16VectorImageType> UInt16VectorReaderType; - typedef otb::ImageFileReader<Int32VectorImageType> Int32VectorReaderType; - typedef otb::ImageFileReader<UInt32VectorImageType> UInt32VectorReaderType; - typedef otb::ImageFileReader<FloatVectorImageType> FloatVectorReaderType; - typedef otb::ImageFileReader<DoubleVectorImageType> DoubleVectorReaderType; +private: + InputImageParameter(const Parameter&) = delete; + void operator=(const Parameter&) = delete; + std::string m_FileName; + itk::ProcessObject::Pointer m_Reader; - typedef otb::ImageFileReader<UInt8RGBImageType> UInt8RGBReaderType; - typedef otb::ImageFileReader<UInt8RGBAImageType> UInt8RGBAReaderType; + ImageBaseType::Pointer m_Image; - // Complex - typedef otb::ImageFileReader<ComplexInt16ImageType> ComplexInt16ReaderType; - typedef otb::ImageFileReader<ComplexInt32ImageType> ComplexInt32ReaderType; - typedef otb::ImageFileReader<ComplexFloatImageType> ComplexFloatReaderType; - typedef otb::ImageFileReader<ComplexDoubleImageType> ComplexDoubleReaderType; + itk::ProcessObject::Pointer m_InputCaster; + itk::ProcessObject::Pointer m_OutputCaster; - typedef otb::ImageFileReader<ComplexInt16VectorImageType> ComplexInt16VectorReaderType; - typedef otb::ImageFileReader<ComplexInt32VectorImageType> ComplexInt32VectorReaderType; - typedef otb::ImageFileReader<ComplexFloatVectorImageType> ComplexFloatVectorReaderType; - typedef otb::ImageFileReader<ComplexDoubleVectorImageType> ComplexDoubleVectorReaderType; +private: + /** */ + template <typename T> + using InputClampImageFilter = ClampImageFilter<T, otb::Wrapper::DoubleVectorImageType>; - itk::ProcessObject::Pointer m_Reader; - itk::ProcessObject::Pointer m_Caster; + /** */ + template <typename T> + using OutputClampImageFilter = ClampImageFilter<otb::Wrapper::DoubleVectorImageType, T>; -private: - InputImageParameter(const Parameter &) = delete; - void operator =(const Parameter&) = delete; + /** */ + template <typename TOutputImage, typename TInputImage> + TOutputImage* Cast(TInputImage*); /** Store the loaded image filename */ std::string m_PreviousFileName; diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.hxx b/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.hxx index eb0f507910c6baf093bcb2297784fa6bad00f35c..37ffbd7efae807466a60d05f708ea29ac271c49f 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.hxx +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.hxx @@ -23,7 +23,7 @@ #include "otbWrapperInputImageParameter.h" -#include "otbClampImageFilter.h" +#include "otbWrapperCastImage.h" namespace otb { @@ -31,7 +31,70 @@ namespace Wrapper { -#define INPUT_IMAGE_PARAMETER_GET_IMAGE_EXCEPTION 0 +#define CLAMP_IMAGE_IF( Out, In, image_base ) \ + { \ + In * in_image = dynamic_cast< In * >( image_base ); \ + \ + if( in_image ) \ + return Cast< Out, In >( in_image ); \ + } + +#define CLAMP_IMAGE_BASE( T, image_base ) \ + { \ + CLAMP_IMAGE_IF( T, UInt8VectorImageType, image_base ); \ + CLAMP_IMAGE_IF( T, Int16VectorImageType, image_base ); \ + CLAMP_IMAGE_IF( T, UInt16VectorImageType, image_base ); \ + CLAMP_IMAGE_IF( T, Int32VectorImageType, image_base ); \ + CLAMP_IMAGE_IF( T, UInt32VectorImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, FloatVectorImageType, image_base ); \ + CLAMP_IMAGE_IF( T, DoubleVectorImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, ComplexInt16VectorImageType, image_base ); \ + CLAMP_IMAGE_IF( T, ComplexInt32VectorImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, ComplexFloatVectorImageType, image_base ); \ + CLAMP_IMAGE_IF( T, ComplexDoubleVectorImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, UInt8RGBImageType, image_base ); \ + CLAMP_IMAGE_IF( T, UInt8RGBAImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, UInt8ImageType, image_base ); \ + CLAMP_IMAGE_IF( T, Int16ImageType, image_base ); \ + CLAMP_IMAGE_IF( T, UInt16ImageType, image_base ); \ + CLAMP_IMAGE_IF( T, Int32ImageType, image_base ); \ + CLAMP_IMAGE_IF( T, UInt32ImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, FloatImageType, image_base ); \ + CLAMP_IMAGE_IF( T, DoubleImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, ComplexInt16ImageType, image_base ); \ + CLAMP_IMAGE_IF( T, ComplexInt32ImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, ComplexFloatImageType, image_base ); \ + CLAMP_IMAGE_IF( T, ComplexDoubleImageType, image_base ); \ + \ + return nullptr; \ + } + + +template< typename TOutputImage, + typename TInputImage > +TOutputImage * +InputImageParameter +::Cast( TInputImage * image ) +{ + details::CastImage< TOutputImage, TInputImage > clamp( image ); + + if( clamp.ocif ) + clamp.ocif->UpdateOutputInformation(); + + m_InputCaster = clamp.icif; + m_OutputCaster = clamp.ocif; + + return clamp.out; +} + template <class TImageType> TImageType* @@ -68,10 +131,6 @@ InputImageParameter::GetImage() } else { -#if INPUT_IMAGE_PARAMETER_GET_IMAGE_EXCEPTION - return dynamic_cast< TImageType* >( m_Image.GetPointer() ); - -#else // INPUT_IMAGE_PARAMETER_GET_IMAGE_EXCEPTION // In this case, the reader and the image should already be there if (m_Image.IsNull()) { @@ -89,7 +148,6 @@ InputImageParameter::GetImage() itkExceptionMacro("Cannot ask a different image type"); } } -#endif // INPUT_IMAGE_PARAMETER_GET_IMAGE_EXCEPTION } } @@ -98,119 +156,10 @@ InputImageParameter::GetImage() //////////////////////// Image case: if (m_Image.IsNull()) { -#if INPUT_IMAGE_PARAMETER_GET_IMAGE_EXCEPTION - itkExceptionMacro("No input image or filename detected..."); -#else return nullptr; -#endif } else - { - if (dynamic_cast<UInt8ImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt8ImageType, TImageType> (); - } - else if (dynamic_cast<Int16ImageType*> (m_Image.GetPointer())) - { - return CastImage<Int16ImageType, TImageType> (); - } - else if (dynamic_cast<UInt16ImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt16ImageType, TImageType> (); - } - else if (dynamic_cast<Int32ImageType*> (m_Image.GetPointer())) - { - return CastImage<Int32ImageType, TImageType> (); - } - else if (dynamic_cast<UInt32ImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt32ImageType, TImageType> (); - } - else if (dynamic_cast<FloatImageType*> (m_Image.GetPointer())) - { - return CastImage<FloatImageType, TImageType> (); - } - else if (dynamic_cast<DoubleImageType*> (m_Image.GetPointer())) - { - return CastImage<DoubleImageType, TImageType> (); - } - else if (dynamic_cast<ComplexInt16ImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexInt16ImageType, TImageType>(); - } - else if (dynamic_cast<ComplexInt32ImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexInt32ImageType, TImageType>(); - } - else if (dynamic_cast<ComplexFloatImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexFloatImageType, TImageType>(); - } - else if (dynamic_cast<ComplexDoubleImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexDoubleImageType, TImageType>(); - } - else if (dynamic_cast<UInt8VectorImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt8VectorImageType, TImageType> (); - } - else if (dynamic_cast<Int16VectorImageType*> (m_Image.GetPointer())) - { - return CastImage<Int16VectorImageType, TImageType> (); - } - else if (dynamic_cast<UInt16VectorImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt16VectorImageType, TImageType> (); - } - else if (dynamic_cast<Int32VectorImageType*> (m_Image.GetPointer())) - { - return CastImage<Int32VectorImageType, TImageType> (); - } - else if (dynamic_cast<UInt32VectorImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt32VectorImageType, TImageType> (); - } - else if (dynamic_cast<FloatVectorImageType*> (m_Image.GetPointer())) - { - return CastImage<FloatVectorImageType, TImageType> (); - } - else if (dynamic_cast<DoubleVectorImageType*> (m_Image.GetPointer())) - { - return CastImage<DoubleVectorImageType, TImageType> (); - } - else if (dynamic_cast<UInt8RGBAImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt8RGBAImageType, TImageType> (); - } - else if (dynamic_cast<UInt8RGBImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt8RGBImageType, TImageType> (); - } - else if (dynamic_cast<ComplexInt16VectorImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexInt16VectorImageType, TImageType>(); - } - else if (dynamic_cast<ComplexInt32VectorImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexInt32VectorImageType, TImageType>(); - } - else if (dynamic_cast<ComplexFloatVectorImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexFloatVectorImageType, TImageType>(); - } - else if (dynamic_cast<ComplexDoubleVectorImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexDoubleVectorImageType, TImageType>(); - } - else - { -#if INPUT_IMAGE_PARAMETER_GET_IMAGE_EXCEPTION - itkExceptionMacro("Unknown image type"); -#else - return nullptr; -#endif - } - } + CLAMP_IMAGE_BASE( TImageType, m_Image.GetPointer() ); } } @@ -221,41 +170,6 @@ ImageBaseType* InputImageParameter::GetImage<ImageBaseType>(); -template <class TInputImage, class TOutputImage> -TOutputImage* -InputImageParameter::CastImage() -{ - if ( dynamic_cast<TOutputImage*> (m_Image.GetPointer()) ) - { - return dynamic_cast<TOutputImage*> (m_Image.GetPointer()); - } - else - { - TInputImage* realInputImage = dynamic_cast<TInputImage*>(m_Image.GetPointer()); - - typedef ClampImageFilter<TInputImage, TOutputImage> CasterType; - typename CasterType::Pointer caster = CasterType::New(); - - caster->SetInput(realInputImage); - caster->UpdateOutputInformation(); - - m_Image = caster->GetOutput(); - m_Caster = caster; - - return caster->GetOutput(); - } - // itkExceptionMacro("Cast from "<<typeid(TInputImage).name()<<" to "<<typeid(TOutputImage).name()<<" not authorized."); -} - -template <class TInputImage> -void -InputImageParameter::SetImage(TInputImage* image) -{ - m_UseFilename = false; - m_Image = image; -} - - } // End namespace Wrapper } // End namespace otb diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputImageParameter.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputImageParameter.h index 5a454d57bae108501f0822770616775ed914034e..ec7a1a8f859118d6d63c12872476647fe54b062d 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputImageParameter.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputImageParameter.h @@ -27,6 +27,7 @@ #include "otbImageFileWriter.h" #include <string> + namespace otb { namespace Wrapper @@ -126,36 +127,34 @@ protected: /** Destructor */ ~OutputImageParameter() override; - template <class TInput> - int SwitchInput(TInput *img); - - //FloatVectorImageType::Pointer m_Image; - ImageBaseType::Pointer m_Image; - std::string m_FileName; - ImagePixelType m_PixelType; - ImagePixelType m_DefaultPixelType; - private: OutputImageParameter(const Parameter &) = delete; void operator =(const Parameter&) = delete; - unsigned int m_RAMValue; + /** Switch TInputImage according to expected output type. */ + template <typename TInputImage> + void SwitchInput(TInputImage*); + + /** */ + template <typename TOutputImage, typename TInputImage> + void ClampAndWriteVectorImage(TInputImage*); - itk::ProcessObject::Pointer m_Caster; + // FloatVectorImageType::Pointer m_Image; + ImageBaseType::Pointer m_Image; + + itk::ProcessObject::Pointer m_InputCaster; + itk::ProcessObject::Pointer m_OutputCaster; itk::ProcessObject::Pointer m_Writer; -}; // End class OutputImage Parameter + std::string m_FileName; -// Declare specialisation for UInt8RGBAImageType -template <> -int -OutputImageParameter::SwitchInput(UInt8RGBAImageType *img); + ImagePixelType m_PixelType; + ImagePixelType m_DefaultPixelType; -// Declare specialisation for UInt8RGBImageType -template <> -int -OutputImageParameter::SwitchInput(UInt8RGBImageType *img); + unsigned int m_RAMValue; + +}; // End class OutputImage Parameter } // End namespace Wrapper } // End namespace otb diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameter.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameter.h index 0a93e62995f0dba21b7f35d89457d963d29b9c7e..6ab769e5eca20ac6d8c7b575680e32ca0b0de784 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameter.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameter.h @@ -21,13 +21,18 @@ #ifndef otbWrapperParameter_h #define otbWrapperParameter_h -#include "otbMacro.h" -#include "itkObjectFactory.h" -#include "otbWrapperTypes.h" #include "OTBApplicationEngineExport.h" +#include "otbMacro.h" +#include "otbWrapperTypes.h" + + +#include <itkObjectFactory.h> + + #include <string> + namespace otb { namespace Wrapper @@ -65,11 +70,11 @@ public: /** Set/get the parameter key */ virtual void SetKey(const std::string&); virtual const char* GetKey() const; - + /** Set the parameter Active flag */ virtual void SetActive(bool flag); bool GetActive(bool recurseParents = false) const; - + /** Set the parameter Mandatory flag */ virtual void SetMandatory(bool flag); virtual bool GetMandatory() const; @@ -78,19 +83,19 @@ public: /** Set the parameter AutomaticValue flag (which is the opposite of UserValue)*/ virtual void SetAutomaticValue(bool flag); - + /** Get the parameter AutomaticValue flag */ virtual bool GetAutomaticValue() const; - + /** Toogle ON the parameter AutomaticValue flag */ void AutomaticValueOn(); - + /** Toogle OFF the parameter AutomaticValue flag */ void AutomaticValueOff(); /** Set the user access level */ virtual void SetUserLevel(const UserLevel level); - + /** Get the user access level */ virtual UserLevel GetUserLevel() const; @@ -104,7 +109,7 @@ public: * nothing */ virtual void Reset(); - + virtual bool HasValue() const = 0; virtual bool HasUserValue() const; diff --git a/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt b/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt index 6f0b8809cb026b1b4143277ac45e41c4d9d62529..fb220c564fbe628d9e9469f6f3f438352caa6454 100644 --- a/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt +++ b/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt @@ -1,3 +1,4 @@ + # # Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) # @@ -57,6 +58,7 @@ set( OTBApplicationEngine_SRC otbWrapperBoolParameter.cxx otbWrapperMetaDataHelper.cxx otbWrapperParameter.cxx + otbWrapperCastImage.cxx otbWrapperTypes.cxx ) diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx index 8c0d624ae5e2f79bf323b3c41d3821d0ad38a5b3..4297ae946d62476a88847a9974cd5aff72526fb3 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx @@ -71,6 +71,80 @@ ExceptionObject(file, line, message, loc) namespace Wrapper { + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt8VectorImageType* Application::GetParameterImage<UInt8VectorImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE Int16VectorImageType* Application::GetParameterImage<Int16VectorImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt16VectorImageType* Application::GetParameterImage<UInt16VectorImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE Int32VectorImageType* Application::GetParameterImage<Int32VectorImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt32VectorImageType* Application::GetParameterImage<UInt32VectorImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE FloatVectorImageType* Application::GetParameterImage<FloatVectorImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE DoubleVectorImageType* Application::GetParameterImage<DoubleVectorImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexInt16VectorImageType* Application::GetParameterImage<ComplexInt16VectorImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexInt32VectorImageType* Application::GetParameterImage<ComplexInt32VectorImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexFloatVectorImageType* Application::GetParameterImage<ComplexFloatVectorImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexDoubleVectorImageType* Application::GetParameterImage<ComplexDoubleVectorImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt8RGBImageType* Application::GetParameterImage<UInt8RGBImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt8RGBAImageType* Application::GetParameterImage<UInt8RGBAImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt8ImageType* Application::GetParameterImage<UInt8ImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE Int16ImageType* Application::GetParameterImage<Int16ImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt16ImageType* Application::GetParameterImage<UInt16ImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE Int32ImageType* Application::GetParameterImage<Int32ImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt32ImageType* Application::GetParameterImage<UInt32ImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE FloatImageType* Application::GetParameterImage<FloatImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE DoubleImageType* Application::GetParameterImage<DoubleImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexInt16ImageType* Application::GetParameterImage<ComplexInt16ImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexInt32ImageType* Application::GetParameterImage<ComplexInt32ImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexFloatImageType* Application::GetParameterImage<ComplexFloatImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexDoubleImageType* Application::GetParameterImage<ComplexDoubleImageType>(std::string); + +// + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt8VectorImageType>(std::string, UInt8VectorImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<Int16VectorImageType>(std::string, Int16VectorImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt16VectorImageType>(std::string, UInt16VectorImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<Int32VectorImageType>(std::string, Int32VectorImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt32VectorImageType>(std::string, UInt32VectorImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<FloatVectorImageType>(std::string, FloatVectorImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<DoubleVectorImageType>(std::string, DoubleVectorImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt16VectorImageType>(std::string, + ComplexInt16VectorImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt32VectorImageType>(std::string, + ComplexInt32VectorImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexFloatVectorImageType>(std::string, + ComplexFloatVectorImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexDoubleVectorImageType>(std::string, + ComplexDoubleVectorImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt8RGBImageType>(std::string, UInt8RGBImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt8RGBAImageType>(std::string, UInt8RGBAImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt8ImageType>(std::string, UInt8ImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<Int16ImageType>(std::string, Int16ImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt16ImageType>(std::string, UInt16ImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<Int32ImageType>(std::string, Int32ImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt32ImageType>(std::string, UInt32ImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<FloatImageType>(std::string, FloatImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<DoubleImageType>(std::string, DoubleImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt16ImageType>(std::string, ComplexInt16ImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt32ImageType>(std::string, ComplexInt32ImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexFloatImageType>(std::string, ComplexFloatImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexDoubleImageType>(std::string, ComplexDoubleImageType*); + + void Application::SetName( const std::string & name ) { m_Name = name; @@ -466,8 +540,7 @@ Application::RegisterPipeline() if ( GetParameterType(key) == ParameterType_OutputImage ) { Parameter* param = GetParameterByKey(key); - OutputImageParameter * outP = - dynamic_cast< OutputImageParameter * >( param ); + OutputImageParameter* outP = dynamic_cast<OutputImageParameter*>(param); itk::ImageBase< 2 > * outData = outP->GetValue(); if ( outData ) dataStack.push(outData); @@ -475,8 +548,7 @@ Application::RegisterPipeline() else if ( GetParameterType(key) == ParameterType_OutputVectorData ) { Parameter* param = GetParameterByKey(key); - OutputVectorDataParameter * outP = - dynamic_cast< OutputVectorDataParameter * >( param ); + OutputVectorDataParameter* outP = dynamic_cast<OutputVectorDataParameter*>(param); VectorDataType * outData = outP->GetValue(); if ( outData ) dataStack.push(outData); @@ -484,8 +556,7 @@ Application::RegisterPipeline() else if ( GetParameterType(key) == ParameterType_InputImage ) { Parameter* param = GetParameterByKey(key); - InputImageParameter * inP = - dynamic_cast< InputImageParameter * >( param ); + InputImageParameter* inP = dynamic_cast<InputImageParameter*>(param); if ( !inP->HasValue() ) continue; ImageBaseType * inData = inP->GetImage< ImageBaseType >(); @@ -495,13 +566,12 @@ Application::RegisterPipeline() else if ( GetParameterType(key) == ParameterType_InputImageList ) { Parameter * param = GetParameterByKey(key); - InputImageListParameter * inP = - dynamic_cast< InputImageListParameter * > ( param ); + InputImageListParameter* inP = dynamic_cast<InputImageListParameter*>(param); if ( !inP->HasValue() ) continue; const FloatVectorImageListType * list = inP->GetImageList(); - for ( auto it = list->Begin() ; it != list->End() ; ++it ) - { + for (auto it = list->Begin(); it != list->End(); ++it) + { FloatVectorImageType * inData = it.Get().GetPointer(); if ( inData && !inputData.count(inData) ) inputData.insert(inData); @@ -546,10 +616,9 @@ Application::RegisterPipeline() // if current is a list push every of its members in datastack if ( dynamic_cast< DataObjectListInterface *> (current) ) { - DataObjectListInterface * list = - dynamic_cast< DataObjectListInterface *> (current); - int length = list->Size(); - for ( int i = 0 ; i < length ; i++ ) + DataObjectListInterface* list = dynamic_cast<DataObjectListInterface*>(current); + int length = list->Size(); + for (int i = 0; i < length; i++) { itk::DataObject * newData = list->GetNthDataObject(i); if ( !current || inputData.count( current ) ) @@ -627,10 +696,9 @@ void Application::FreeRessources() // If input is a list if ( dynamic_cast< DataObjectListInterface *> (data.GetPointer()) ) { - DataObjectListInterface * list = - dynamic_cast< DataObjectListInterface *> (data.GetPointer()); - int length = list->Size(); - for ( int i = 0 ; i < length ; i++ ) + DataObjectListInterface* list = dynamic_cast<DataObjectListInterface*>(data.GetPointer()); + int length = list->Size(); + for (int i = 0; i < length; i++) { itk::DataObject * newData = list->GetNthDataObject(i); if ( !newData || dataSet.count( newData ) ) @@ -693,7 +761,7 @@ int Application::Execute() m_IsInPrivateDo = true; this->DoExecute(); m_IsInPrivateDo = false; - + // Ensure that all output image parameter have called UpdateOutputInformation() for (auto it = paramList.begin(); it != paramList.end(); ++it) { @@ -806,7 +874,7 @@ int Application::ExecuteAndWriteOutput() this->AfterExecuteAndWriteOutputs(); m_Chrono.Stop(); - + FreeRessources(); m_Filters.clear(); return status; @@ -1513,7 +1581,7 @@ Application::SetParameterImageBase(const std::string & key, ImageBaseType* img, if (dynamic_cast<InputImageParameter*>(param)) { InputImageParameter* paramDown = dynamic_cast<InputImageParameter*>(param); - paramDown->SetImage<ImageBaseType>(img); + paramDown->SetImage(img); } else if (dynamic_cast<InputImageListParameter*>(param)) { diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperCastImage.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperCastImage.cxx new file mode 100644 index 0000000000000000000000000000000000000000..347954c65e2bc783195d69db17d8a7619f42a0c1 --- /dev/null +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperCastImage.cxx @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "otbWrapperCastImage.h" diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperInputImageParameter.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperInputImageParameter.cxx index 65d6d6780585ceaa9bb696d18dbbc1da3b39f6dd..6959aba4ff523f3d14717e52babe45c43efae7b7 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperInputImageParameter.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperInputImageParameter.cxx @@ -24,6 +24,7 @@ #include "otbWrapperInputImageParameterMacros.h" #include "otb_boost_string_header.h" + namespace otb { @@ -62,12 +63,18 @@ InputImageParameter::SetFromFileName(const std::string& filename) } -FloatVectorImageType* -InputImageParameter::GetImage() +ImageBaseType* InputImageParameter ::GetImage() +{ + return m_Image.GetPointer(); +} + + +ImageBaseType const* InputImageParameter ::GetImage() const { - return this->GetImage<FloatVectorImageType>(); + return m_Image.GetPointer(); } + template <> ImageBaseType* InputImageParameter::GetImage<ImageBaseType>() @@ -81,21 +88,18 @@ InputImageParameter::GetImage<ImageBaseType>() otbGetImageMacro(UInt8RGBImage); otbGetImageMacro(UInt8RGBAImage); -void -InputImageParameter::SetImage(FloatVectorImageType* image) + +void InputImageParameter ::SetImage(ImageBaseType* image) { m_UseFilename = false; - this->SetImage<FloatVectorImageType>( image ); + m_Image = image; } bool InputImageParameter::HasValue() const { - if( m_FileName.empty() && m_Image.IsNull() ) - return false; - else - return true; + return !m_FileName.empty() || !m_Image.IsNull(); } void @@ -104,7 +108,8 @@ InputImageParameter { m_Image = nullptr; m_Reader = nullptr; - m_Caster = nullptr; + m_InputCaster = nullptr; + m_OutputCaster = nullptr; m_FileName = ""; m_PreviousFileName=""; m_UseFilename = true; diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputImageParameter.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputImageParameter.cxx index 7dcd30d0bfebe934c618c9a9ea43fc6d6e65b191..39b36a355b29517de756b0193206a053434fff36 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputImageParameter.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputImageParameter.cxx @@ -19,35 +19,54 @@ */ #include "otbWrapperOutputImageParameter.h" + #include "otbClampImageFilter.h" #include "otbImageIOFactory.h" -#include "itksys/SystemTools.hxx" +#include "otbWrapperCastImage.h" #ifdef OTB_USE_MPI - #include "otbMPIConfig.h" #include "otbMPIVrtWriter.h" - #ifdef OTB_USE_SPTW #include "otbSimpleParallelTiffWriter.h" #endif - #endif +#include "itksys/SystemTools.hxx" + + +#define CAST_IMAGE_BASE(T, image_base) \ + { \ + T* img = dynamic_cast<T*>(image_base); \ + \ + if (img) \ + { \ + SwitchInput<T>(img); \ + \ + return; \ + } \ + } + + namespace otb { namespace Wrapper { -OutputImageParameter::OutputImageParameter() - : m_PixelType(ImagePixelType_float), - m_DefaultPixelType(ImagePixelType_float), - m_RAMValue(0), - m_Caster(nullptr), - m_Writer(nullptr) + +// Declare specialisation for UInt8RGBAImageType +template <> +void OutputImageParameter::SwitchInput(UInt8RGBAImageType*); + +// Declare specialisation for UInt8RGBImageType +template <> +void OutputImageParameter::SwitchInput(UInt8RGBImageType*); + + +OutputImageParameter::OutputImageParameter() : m_PixelType(ImagePixelType_float), m_DefaultPixelType(ImagePixelType_float), m_RAMValue(0) { - this->SetName("Output Image"); - this->SetKey("out"); + SetName("Output Image"); + SetKey("out"); } @@ -57,6 +76,9 @@ OutputImageParameter::~OutputImageParameter() std::string OutputImageParameter::ConvertPixelTypeToString(ImagePixelType type) { + // TODO: Could be replaced by constant static string array e.g.: + // return PIXEL_TYPE_NAME[ type ]; + std::string ret; switch(type) { @@ -122,6 +144,9 @@ std::string OutputImageParameter::ConvertPixelTypeToString(ImagePixelType type) bool OutputImageParameter::ConvertStringToPixelType(const std::string &value, ImagePixelType &type) { + // TODO: Could be replaced std::find_if() in constant static string + // array (see ::ConvertPixelTypeToString(). + if (value == "uint8") type = ImagePixelType_uint8; else if (value == "int16") @@ -149,278 +174,207 @@ OutputImageParameter::ConvertStringToPixelType(const std::string &value, ImagePi return true; } -void OutputImageParameter::InitializeWriters() + +void OutputImageParameter ::InitializeWriters() { - ImageBaseType* imgBase = m_Image.GetPointer(); - // Guess the image type - std::string className(m_Image->GetNameOfClass()); - if (className == "VectorImage") - { - UInt8VectorImageType* imgUInt8 = dynamic_cast<UInt8VectorImageType*>(imgBase); - if (imgUInt8 && SwitchInput(imgUInt8)) return; + ImageBaseType* image = m_Image.GetPointer(); - Int16VectorImageType* imgInt16 = dynamic_cast<Int16VectorImageType*>(imgBase); - if (imgInt16 && SwitchInput(imgInt16)) return; + CAST_IMAGE_BASE(UInt8VectorImageType, image); + CAST_IMAGE_BASE(Int16VectorImageType, image); + CAST_IMAGE_BASE(UInt16VectorImageType, image); + CAST_IMAGE_BASE(Int32VectorImageType, image); + CAST_IMAGE_BASE(UInt32VectorImageType, image); - UInt16VectorImageType* imgUInt16 = dynamic_cast<UInt16VectorImageType*>(imgBase); - if (imgUInt16 && SwitchInput(imgUInt16)) return; + CAST_IMAGE_BASE(FloatVectorImageType, image); + CAST_IMAGE_BASE(DoubleVectorImageType, image); - Int32VectorImageType* imgInt32 = dynamic_cast<Int32VectorImageType*>(imgBase); - if (imgInt32 && SwitchInput(imgInt32)) return; + CAST_IMAGE_BASE(ComplexInt16VectorImageType, image); + CAST_IMAGE_BASE(ComplexInt32VectorImageType, image); + CAST_IMAGE_BASE(ComplexFloatVectorImageType, image); + CAST_IMAGE_BASE(ComplexDoubleVectorImageType, image); - UInt32VectorImageType* imgUInt32 = dynamic_cast<UInt32VectorImageType*>(imgBase); - if (imgUInt32 && SwitchInput(imgUInt32)) return; + CAST_IMAGE_BASE(UInt8ImageType, image); + CAST_IMAGE_BASE(Int16ImageType, image); + CAST_IMAGE_BASE(UInt16ImageType, image); + CAST_IMAGE_BASE(Int32ImageType, image); + CAST_IMAGE_BASE(UInt32ImageType, image); - FloatVectorImageType* imgFloat = dynamic_cast<FloatVectorImageType*>(imgBase); - if (imgFloat && SwitchInput(imgFloat)) return; + CAST_IMAGE_BASE(FloatImageType, image); + CAST_IMAGE_BASE(DoubleImageType, image); - DoubleVectorImageType* imgDouble = dynamic_cast<DoubleVectorImageType*>(imgBase); - if (imgDouble && SwitchInput(imgDouble)) return; + CAST_IMAGE_BASE(ComplexInt16ImageType, image); + CAST_IMAGE_BASE(ComplexInt32ImageType, image); + CAST_IMAGE_BASE(ComplexFloatImageType, image); + CAST_IMAGE_BASE(ComplexDoubleImageType, image); - ComplexInt16VectorImageType* imgCInt16 = dynamic_cast<ComplexInt16VectorImageType*>(imgBase); - if (imgCInt16 && SwitchInput(imgCInt16)) return; + CAST_IMAGE_BASE(UInt8RGBImageType, image); + CAST_IMAGE_BASE(UInt8RGBAImageType, image); - ComplexInt32VectorImageType* imgCInt32 = dynamic_cast<ComplexInt32VectorImageType*>(imgBase); - if (imgCInt32 && SwitchInput(imgCInt32)) return; + itkExceptionMacro("Unknown image-base type."); +} - ComplexFloatVectorImageType* imgCFloat = dynamic_cast<ComplexFloatVectorImageType*>(imgBase); - if (imgCFloat && SwitchInput(imgCFloat)) return; - ComplexDoubleVectorImageType* imgCDouble = dynamic_cast<ComplexDoubleVectorImageType*>(imgBase); - if (imgCDouble && SwitchInput(imgCDouble)) return; - } - else - { - UInt8ImageType* imgUInt8 = dynamic_cast<UInt8ImageType*>(imgBase); - if (imgUInt8 && SwitchInput(imgUInt8)) return; +template <typename TOutputImage, typename TInputImage> +void OutputImageParameter ::ClampAndWriteVectorImage(TInputImage* in) +{ + assert(in); + assert(!m_FileName.empty()); - Int16ImageType* imgInt16 = dynamic_cast<Int16ImageType*>(imgBase); - if (imgInt16 && SwitchInput(imgInt16)) return; + // Use metaprogramming to choose optimized pipeline. + details::CastImage<TOutputImage, TInputImage> clamp(in); - UInt16ImageType* imgUInt16 = dynamic_cast<UInt16ImageType*>(imgBase); - if (imgUInt16 && SwitchInput(imgUInt16)) return; - Int32ImageType* imgInt32 = dynamic_cast<Int32ImageType*>(imgBase); - if (imgInt32 && SwitchInput(imgInt32)) return; +#ifdef OTB_USE_MPI - UInt32ImageType* imgUInt32 = dynamic_cast<UInt32ImageType*>(imgBase); - if (imgUInt32 && SwitchInput(imgUInt32)) return; + otb::MPIConfig::Pointer mpiConfig = otb::MPIConfig::Instance(); - FloatImageType* imgFloat = dynamic_cast<FloatImageType*>(imgBase); - if (imgFloat && SwitchInput(imgFloat)) return; + if (mpiConfig->GetNbProcs() > 1) + { + std::string extension = itksys::SystemTools::GetFilenameExtension(m_FileName); - DoubleImageType* imgDouble = dynamic_cast<DoubleImageType*>(imgBase); - if (imgDouble && SwitchInput(imgDouble)) return; + if (extension == ".vrt") + { + // Use the MPIVrtWriter - ComplexInt16ImageType* imgCInt16 = dynamic_cast<ComplexInt16ImageType*>(imgBase); - if (imgCInt16 && SwitchInput(imgCInt16)) return; + auto vrtWriter = otb::MPIVrtWriter<TOutputImage>::New(); - ComplexInt32ImageType* imgCInt32 = dynamic_cast<ComplexInt32ImageType*>(imgBase); - if (imgCInt32 && SwitchInput(imgCInt32)) return; + vrtWriter->SetInput(clamp.out); + vrtWriter->SetFileName(m_FileName); + vrtWriter->SetAvailableRAM(m_RAMValue); - ComplexFloatImageType* imgCFloat = dynamic_cast<ComplexFloatImageType*>(imgBase); - if (imgCFloat && SwitchInput(imgCFloat)) return; + // Change internal state only when everything has been setup + // without raising exception. - ComplexDoubleImageType* imgCDouble = dynamic_cast<ComplexDoubleImageType*>(imgBase); - if (imgCDouble && SwitchInput(imgCDouble)) return; + m_InputCaster = clamp.icif; + m_OutputCaster = clamp.ocif; - UInt8RGBImageType* imgRGB = dynamic_cast<UInt8RGBImageType*>(imgBase); - if (imgRGB && SwitchInput(imgRGB)) return; + m_Writer = vrtWriter; - UInt8RGBAImageType* imgRGBA = dynamic_cast<UInt8RGBAImageType*>(imgBase); - if (imgRGBA && SwitchInput(imgRGBA)) return; + return; } - itkExceptionMacro("Unknown image type"); -} - +#ifdef OTB_USE_SPTW -template <typename TInput, typename TOutput> -std::pair<itk::ProcessObject::Pointer,itk::ProcessObject::Pointer> -ClampAndWriteVectorImage( TInput * in , - const std::string & filename , - const unsigned int & ramValue ) -{ - std::pair<itk::ProcessObject::Pointer,itk::ProcessObject::Pointer> ret; - typedef ClampImageFilter < TInput , TOutput > ClampFilterType; - typename ClampFilterType::Pointer clampFilter ( ClampFilterType::New() ); + else if (extension == ".tif") + { + // Use simple parallel tiff writer - clampFilter->SetInput( in); - ret.first = clampFilter.GetPointer(); - - bool useStandardWriter = true; + auto sptWriter = otb::SimpleParallelTiffWriter<TOutputImage>::New(); - #ifdef OTB_USE_MPI + sptWriter->SetFileName(m_FileName); + sptWriter->SetInput(clamp.out); + sptWriter->GetStreamingManager()->SetDefaultRAM(m_RAMValue); - otb::MPIConfig::Pointer mpiConfig = otb::MPIConfig::Instance(); + // Change internal state only when everything has been setup + // without raising exception. - if (mpiConfig->GetNbProcs() > 1) - { - useStandardWriter = false; + m_InputCaster = clamp.icif; + m_OutputCaster = clamp.ocif; - // Get file extension - std::string extension = itksys::SystemTools::GetFilenameExtension(filename); + m_Writer = sptWriter; - if(extension == ".vrt") - { - // Use the MPIVrtWriter - typedef otb::MPIVrtWriter<TOutput> VRTWriterType; + return; + } - typename VRTWriterType::Pointer vrtWriter = VRTWriterType::New(); - vrtWriter->SetInput(clampFilter->GetOutput()); - vrtWriter->SetFileName(filename); - vrtWriter->SetAvailableRAM(ramValue); - ret.second = vrtWriter.GetPointer(); - } - #ifdef OTB_USE_SPTW - else if (extension == ".tif") - { - // Use simple parallel tiff writer - typedef otb::SimpleParallelTiffWriter<TOutput> SPTWriterType; +#endif // OTB_USE_SPTW - typename SPTWriterType::Pointer sptWriter = SPTWriterType::New(); - sptWriter->SetFileName(filename); - sptWriter->SetInput(clampFilter->GetOutput()); - sptWriter->GetStreamingManager()->SetDefaultRAM(ramValue); - ret.second = sptWriter.GetPointer(); - } - - #endif else { - itkGenericExceptionMacro("File format "<<extension<<" not supported for parallel writing with MPI. Supported formats are .vrt and .tif. Extended filenames are not supported."); + itkGenericExceptionMacro("File format " << extension + << " not supported for parallel writing with MPI. Supported formats are " + ".vrt and .tif. Extended filenames are not supported."); } - - } - - #endif - - if(useStandardWriter) - { - typename otb::ImageFileWriter<TOutput>::Pointer writer = - otb::ImageFileWriter<TOutput>::New(); - writer->SetFileName( filename ); - writer->SetInput(clampFilter->GetOutput()); - writer->GetStreamingManager()->SetDefaultRAM(ramValue); - ret.second = writer.GetPointer(); } - return ret; +#endif // OTB_USE_MPI + + // + // Use default OTB writer. + + auto writer = otb::ImageFileWriter<TOutputImage>::New(); + + writer->SetFileName(m_FileName); + writer->SetInput(clamp.out); + writer->GetStreamingManager()->SetDefaultRAM(m_RAMValue); + + // Change internal state only when everything has been setup + // without raising exception. + + m_InputCaster = clamp.icif; + m_OutputCaster = clamp.ocif; + + m_Writer = writer; } -template <class TInput> -int -OutputImageParameter::SwitchInput(TInput *img) + +template <typename TInputImage> +void OutputImageParameter ::SwitchInput(TInputImage* image) { - if (! img) return 0; + assert(image); - std::pair<itk::ProcessObject::Pointer,itk::ProcessObject::Pointer> ret; - switch(m_PixelType ) - { - case ImagePixelType_uint8: - { - ret = ClampAndWriteVectorImage< TInput , UInt8VectorImageType > ( - img , - m_FileName , - m_RAMValue ); + switch (m_PixelType) + { + case ImagePixelType_uint8: + ClampAndWriteVectorImage<UInt8VectorImageType>(image); break; - } - case ImagePixelType_int16: - { - ret = ClampAndWriteVectorImage< TInput , Int16VectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_int16: + ClampAndWriteVectorImage<Int16VectorImageType>(image); break; - } - case ImagePixelType_uint16: - { - ret = ClampAndWriteVectorImage< TInput , UInt16VectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_uint16: + ClampAndWriteVectorImage<UInt16VectorImageType>(image); break; - } - case ImagePixelType_int32: - { - ret = ClampAndWriteVectorImage< TInput , Int32VectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_int32: + + ClampAndWriteVectorImage<Int32VectorImageType>(image); break; - } - case ImagePixelType_uint32: - { - ret = ClampAndWriteVectorImage< TInput , UInt32VectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_uint32: + ClampAndWriteVectorImage<UInt32VectorImageType>(image); break; - } - case ImagePixelType_float: - { - ret = ClampAndWriteVectorImage< TInput , FloatVectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_float: + ClampAndWriteVectorImage<FloatVectorImageType>(image); break; - } - case ImagePixelType_double: - { - ret = ClampAndWriteVectorImage< TInput , DoubleVectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_double: + ClampAndWriteVectorImage<DoubleVectorImageType>(image); break; - } - case ImagePixelType_cint16: - { - ret = ClampAndWriteVectorImage < TInput , ComplexInt16VectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_cint16: + ClampAndWriteVectorImage<ComplexInt16VectorImageType>(image); break; - } - case ImagePixelType_cint32: - { - ret = ClampAndWriteVectorImage < TInput , ComplexInt32VectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_cint32: + ClampAndWriteVectorImage<ComplexInt32VectorImageType>(image); break; - } - case ImagePixelType_cfloat: - { - ret = ClampAndWriteVectorImage < TInput , ComplexFloatVectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_cfloat: + ClampAndWriteVectorImage<ComplexFloatVectorImageType>(image); break; - } + case ImagePixelType_cdouble: - { - ret = ClampAndWriteVectorImage < TInput , ComplexDoubleVectorImageType > ( - img , - m_FileName , - m_RAMValue ); - break; - } + ClampAndWriteVectorImage<ComplexDoubleVectorImageType>(image); + break; + default: + assert(false && "Unexpected image-type."); break; } - // Save the caster and writer - m_Caster = ret.first; - m_Writer = ret.second; - return 1; } + void OutputImageParameter::Write() { m_Writer->Update(); // Clean internal filters - m_Caster = nullptr; + m_InputCaster = nullptr; + m_OutputCaster = nullptr; + m_Writer = nullptr; } @@ -444,11 +398,9 @@ OutputImageParameter::SetValue(ImageBaseType* image) SetActive(true); } -bool -OutputImageParameter::HasValue() const +bool OutputImageParameter ::HasValue() const { - std::string filename(this->GetFileName()); - return !filename.empty(); + return !m_FileName.empty(); } std::string @@ -493,43 +445,38 @@ OutputImageParameter::CheckFileName(bool fixMissingExtension) } // Specialization for UInt8RGBAImageType + template <> -int -OutputImageParameter::SwitchInput(UInt8RGBAImageType *img) +void OutputImageParameter ::SwitchInput(UInt8RGBAImageType* img) { - if (! img) return 0; - if( m_PixelType == ImagePixelType_uint8 ) - { - typename otb::ImageFileWriter<UInt8RGBAImageType>::Pointer writer = - otb::ImageFileWriter<UInt8RGBAImageType>::New(); - writer->SetFileName( this->GetFileName() ); - writer->SetInput(img); - writer->GetStreamingManager()->SetDefaultRAM(m_RAMValue); - m_Writer = writer.GetPointer(); - } - else - itkExceptionMacro("Unknown PixelType for RGBA Image. Only uint8 is supported."); - return 1; + assert(img); + + if (m_PixelType != ImagePixelType_uint8) + itkExceptionMacro("Unknown PixelType for RGBA Image. Only uint8 is supported."); + + auto writer = otb::ImageFileWriter<UInt8RGBAImageType>::New(); + + writer->SetFileName(GetFileName()); + writer->SetInput(img); + writer->GetStreamingManager()->SetDefaultRAM(m_RAMValue); + + m_Writer = writer; } // Specialization for UInt8RGBImageType template <> -int -OutputImageParameter::SwitchInput(UInt8RGBImageType *img) +void OutputImageParameter ::SwitchInput(UInt8RGBImageType* img) { - if (! img) return 0; - if( m_PixelType == ImagePixelType_uint8 ) - { - typename otb::ImageFileWriter<UInt8RGBImageType>::Pointer writer = - otb::ImageFileWriter<UInt8RGBImageType>::New(); - writer->SetFileName( this->GetFileName() ); - writer->SetInput(img); - writer->GetStreamingManager()->SetDefaultRAM(m_RAMValue); - m_Writer = writer.GetPointer(); - } - else - itkExceptionMacro("Unknown PixelType for RGB Image. Only uint8 is supported."); - return 1; + if (m_PixelType != ImagePixelType_uint8) + itkExceptionMacro("Unknown PixelType for RGB Image. Only uint8 is supported."); + + auto writer = otb::ImageFileWriter<UInt8RGBImageType>::New(); + + writer->SetFileName(GetFileName()); + writer->SetInput(img); + writer->GetStreamingManager()->SetDefaultRAM(m_RAMValue); + + m_Writer = writer; } void OutputImageParameter::SetFileName (const char* filename)