[Git][debian-gis-team/jeolib-jiplib][upstream] New upstream version 1.2+ds

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Fri Jul 24 20:14:40 BST 2026



Bas Couwenberg pushed to branch upstream at Debian GIS Project / jeolib-jiplib


Commits:
72afd06f by Bas Couwenberg at 2026-07-24T19:29:17+02:00
New upstream version 1.2+ds
- - - - -


23 changed files:

- CMakeLists.txt
- − cmake/modules/FindGSL.cmake
- doc/conf.py
- src/apps/AppFactory.h
- src/imageclasses/Jim.cc
- src/imageclasses/Jim.h
- src/imageclasses/JimList.cc
- + src/imageclasses/Json_compat.cc
- + src/imageclasses/Json_compat.h
- src/imageclasses/VectorOgr.cc
- src/imageclasses/fun2method_errortype.py
- src/imageclasses/fun2method_errortype_d.py
- src/imageclasses/fun2method_errortype_d_nm.py
- src/imageclasses/fun2method_errortype_nd.py
- src/imageclasses/fun2method_errortype_nm.py
- src/imageclasses/fun2method_imagelisttype.py
- src/imageclasses/fun2method_imagetype.py
- src/imageclasses/fun2method_imagetype_jimlist.py
- src/imageclasses/fun2method_imagetype_multi.py
- src/imageclasses/jlextractimg_lib.h
- src/imageclasses/jlstat_lib.cc
- src/python/__init__.py
- src/python/setup.py


Changes:

=====================================
CMakeLists.txt
=====================================
@@ -18,7 +18,357 @@
 # You should have received a copy of the GNU General Public License
 # along with jiplib.  If not, see <https://www.gnu.org/licenses/>.
 ###############################################################################
+
 cmake_minimum_required(VERSION 3.15)
+project(jiplib LANGUAGES CXX)
+
+# --- 1. Project Metadata ---
+set(JIPLIB_VERSION_MAJOR 1)
+set(JIPLIB_VERSION_MINOR 2)
+set(JIPLIB_VERSION_PATCH 0)
+set(JIPLIB_VERSION "${JIPLIB_VERSION_MAJOR}.${JIPLIB_VERSION_MINOR}.${JIPLIB_VERSION_PATCH}")
+set(JIPLIB_SOVERSION "${JIPLIB_VERSION_MAJOR}")
+
+# --- 2. Build Settings ---
+option(BUILD_SHARED_LIBS "Build with shared library" ON)
+
+find_package(Python REQUIRED COMPONENTS Interpreter Development.Module NumPy)
+
+if(TARGET miallib)
+    # 1. If we are building inside pyjeo, the 'miallib' target already exists!
+    message(STATUS "****** MIALLIB detected as an internal target. Skipping find_package.")
+    set(MIALLIB_FOUND TRUE)
+    set(MIALLIB_TARGET miallib)
+else()
+    # 2. If building jiplib STANDALONE, try to find it on the system
+    find_package(MIALLIB 1.2.0 QUIET NO_DEFAULT_PATH)
+
+    message(STATUS "Found MIALLIB_LIBRARY: ${MIALLIB_LIBRARIES}")
+    get_cmake_property(_vars VARIABLES)
+    foreach(_var ${_vars})
+        if(_var MATCHES "^MIALLIB")
+            message(STATUS "${_var} = ${${_var}}")
+        endif()
+    endforeach()
+    
+    if(TARGET miallib::miallib)
+	message(STATUS "Found target: miallib::miallib")
+	#If location not found, set path
+        set_target_properties(miallib::miallib PROPERTIES
+            IMPORTED_LOCATION "${MIALLIB_LIBRARIES}"
+	)
+	get_target_property(LOC miallib::miallib IMPORTED_LOCATION)
+        message(STATUS "DEBUG: miallib location is: ${LOC}")
+    elseif(TARGET miallib)
+	message(STATUS "Found target: miallib")
+    else()
+	message(STATUS "No target found, set miallib path variables")
+    endif()
+
+    if(NOT MIALLIB_FOUND)
+        # 3. Last resort: check if it's a sibling directory (common in dev)
+        if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../miallib")
+             add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../miallib" "${CMAKE_CURRENT_BINARY_DIR}/miallib_build")
+             set(MIALLIB_TARGET miallib)
+             set(MIALLIB_FOUND TRUE)
+        else()
+             message(FATAL_ERROR "MIALLIB not found. Please install it or provide it in external/miallib")
+        endif()
+    else()
+        set(MIALLIB_TARGET MIALLIB::MIALLIB)
+    endif()
+endif()
+# 1. Locate MIALLIB headers (as siblings in the pyjeo build)
+if(TARGET miallib)
+    get_target_property(MIALLIB_BASE_DIR miallib SOURCE_DIR)
+    set(MIALLIB_INCLUDE_DIR "${MIALLIB_BASE_DIR}/core/c")
+    MESSAGE(STATUS "MIALLIB_INCLUDE_DIR with target miallib: ${MIALLIB_INCLUDE_DIR}")
+else()
+    # Fallback for standalone jiplib build
+    set(MIALLIB_INCLUDE_DIR "${MIALLIB_INCLUDE_DIRS}")
+    MESSAGE(STATUS "MIALLIB_INCLUDE_DIR in standalone: ${MIALLIB_INCLUDE_DIR}")
+endif()
+
+file(GLOB MIALLIB_HEADER_FILES ${MIALLIB_INCLUDE_DIR}/miallib_*.h)
+MESSAGE(STATUS "MIALLIB_HEADER_FILES: ${MIALLIB_HEADER_FILES}")
+IF("${MIALLIB_HEADER_FILES}" STREQUAL "")
+  MESSAGE(FATAL_ERROR "Error: no header files found for miallib")
+ENDIF("${MIALLIB_HEADER_FILES}" STREQUAL "")
+file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_imagetype)
+file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_imagelisttype)
+file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype_nd)
+file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype_nm)
+file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype)
+#Miallib functions have been designed as destructive. We will therefore create a copy to avoid the destructive behaviour. The destructive method will still be available with the prefix d_
+#The following functions F_ND from miallib do not modify the input image and should therefore not create a copy. They will be treated in the same way as the destructive functions (without the prefix d_)
+SET(F_ND "dumpxyz|szcompat|szgeocompat|iminfo|tiffinfo|writeGnuPlot3D|vectorizeImage|IsPartitionEqual|IsPartitionFiner|dendro|getfirstmaxpos|volume|imequalp|getmax|getminmax")
+#The following functions F_NM from miallib are not compatible for multi-band processing
+SET(F_NM "addframebox|subframebox")
+#These functions must only be included if MCISRG is set
+SET(F_MCISRG "labelImage|segmentImage")
+#Create a text file with the list of headers to MIALLIB functions, e.g., miallib_imagetype for functions returning IMAGE *
+FOREACH(infileName ${MIALLIB_HEADER_FILES})
+  MESSAGE(STATUS "Process file: ${infileName}")
+  file(STRINGS ${infileName} FUN_IMAGETYPE REGEX "^extern IMAGE \\*[^*]")
+  FOREACH(fun ${FUN_IMAGETYPE})
+    IF("${fun}" MATCHES "${F_MCISRG}")
+      IF(MCISRG)
+        file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_imagetype "${fun}\n")
+      ENDIF(MCISRG)
+    ELSE("${fun}" MATCHES "${F_MCISRG}")
+      file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_imagetype "${fun}\n")
+    ENDIF("${fun}" MATCHES "${F_MCISRG}")
+  ENDFOREACH(fun)
+  file(STRINGS ${infileName} FUN_IMAGELISTTYPE REGEX "^extern IMAGE \\*\\*[^*]")
+  FOREACH(fun ${FUN_IMAGELISTTYPE})
+    file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_imagelisttype "${fun}\n")
+  ENDFOREACH(fun)
+  file(STRINGS ${infileName} FUN_ERRORTYPE REGEX "^extern ERROR")
+  FOREACH(fun ${FUN_ERRORTYPE})
+    IF("${fun}" MATCHES "${F_ND}")
+      file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype_nd "${fun}\n")
+    ELSE("${fun}" MATCHES "${F_ND}")
+      IF("${fun}" MATCHES "${F_NM}")
+        file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype_nm "${fun}\n")
+      ELSE("${fun}" MATCHES "${F_NM}")
+        file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype "${fun}\n")
+      ENDIF("${fun}" MATCHES "${F_NM}")
+    ENDIF("${fun}" MATCHES "${F_ND}")
+  ENDFOREACH(fun)
+ENDFOREACH(infileName)
+
+set(GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses")
+file(MAKE_DIRECTORY "${GEN_DIR}")
+
+# --- A. Copy rename.txt and scripts ---
+# rename.txt is the critical input for rename.sh
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/imageclasses/rename.txt" "${GEN_DIR}/rename.txt" COPYONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/imageclasses/rename.sh" "${GEN_DIR}/rename.sh" COPYONLY)
+
+# --- B. Copy the Python generators ---
+set(PY_GENERATORS
+    imagetype imagetype_multi imagetype_jimlist imagelisttype
+    errortype errortype_d errortype_nd errortype_nm errortype_d_nm
+)
+
+message(STATUS "****** Running Transformation Pipeline in ${GEN_DIR}")
+
+#test
+# 1. Standardize the paths
+get_filename_component(GEN_DIR_ABS "${GEN_DIR}" ABSOLUTE)
+set(MY_JSON_FILE "${GEN_DIR_ABS}/old2NewNames.json")
+
+message(STATUS "****** Preparing JSON mapping (replacing rename.sh)")
+message(STATUS "****** GEN_DIR_ABS: ${GEN_DIR_ABS}")
+
+
+#Read the source file directly
+file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/src/imageclasses/rename.txt" rename_lines)
+
+set(json_entries "")
+list(LENGTH rename_lines total_lines)
+message(STATUS "DEBUG: Found ${total_lines} lines in rename.txt. Generated ${len_c} entries for JSON.")
+math(EXPR last_idx "${total_lines} - 1")
+
+#Process each line
+foreach(i RANGE ${last_idx})
+    list(GET rename_lines ${i} line)
+
+    # Extract C Name: Look for word before the '('
+    # This replaces the logic that used to be in c_names.txt
+    string(REGEX MATCH "[a-zA-Z0-9_]+\\(" c_name_raw "${line}")
+    string(REPLACE "(" "" c_name "${c_name_raw}")
+
+    # Extract Method Name: Everything after the last space
+    # This replaces the 'sed' logic
+    string(REGEX REPLACE "^.* " "" m_name "${line}")
+
+    # Build the JSON entry in memory (This replaces 'paste')
+    if(NOT c_name STREQUAL "" AND NOT m_name STREQUAL "")
+        if(i LESS last_idx)
+            list(APPEND json_entries "  \"${c_name}\": \"${m_name}\",")
+        else()
+            list(APPEND json_entries "  \"${c_name}\": \"${m_name}\"")
+        endif()
+    endif()
+endforeach()
+
+#Write the final result
+string(REPLACE ";" "\n" json_body "${json_entries}")
+file(WRITE "${MY_JSON_FILE}" "{\n${json_body}\n}")
+if(NOT EXISTS "${MY_JSON_FILE}")
+    message(FATAL_ERROR
+        "CRITICAL ERROR: old2NewNames.json was not generated!\n"
+        "Expected at: ${MY_JSON_FILE}\n"
+        "Please check the previous regex extraction logic."
+    )
+else()
+    # Optional: Verify it isn't an empty file
+    file(SIZE "${MY_JSON_FILE}" _json_size)
+    if(_json_size LESS 5)
+        message(FATAL_ERROR "JSON file exists but appears to be empty or invalid.")
+    endif()
+    message(STATUS "SUCCESS: Confirmed old2NewNames.json exists and has data.")
+endif()
+# Run the Python loop
+foreach(gen ${PY_GENERATORS})
+    message(STATUS "****** Running Transformation Pipeline: fun2method_${gen}")
+    message(STATUS "   JSON:   '${MY_JSON_FILE}'")
+    execute_process(
+        COMMAND "${Python_EXECUTABLE}"
+                "${CMAKE_CURRENT_SOURCE_DIR}/src/imageclasses/fun2method_${gen}.py"
+                "-o"
+                "fun2method_${gen}"
+                "-j"
+                "${MY_JSON_FILE}"
+        WORKING_DIRECTORY "${GEN_DIR_ABS}"
+        RESULT_VARIABLE gen_res
+	OUTPUT_QUIET
+    )
+    if(NOT gen_res EQUAL 0)
+        message(FATAL_ERROR "Generation failed for ${gen}. Exit code: ${gen_res}")
+    endif()
+    if(NOT EXISTS "${GEN_DIR_ABS}/fun2method_${gen}.cc")
+        message(FATAL_ERROR
+            "CRITICAL ERROR: output file was not generated!"
+        )
+    endif()
+    if(NOT EXISTS "${GEN_DIR_ABS}/fun2method_${gen}.h")
+        message(FATAL_ERROR
+            "CRITICAL ERROR: output file was not generated!"
+        )
+    endif()
+
+    if(NOT gen_res EQUAL 0)
+        message(FATAL_ERROR "Generator fun2method_${gen}.py failed")
+    endif()
+endforeach()
+
+# Helper Macro for Code Injection ---
+macro(inject_code_block FILE_PATH MARKER_ID INJECT_FILE_NAME)
+    if(EXISTS "${FILE_PATH}")
+        file(READ "${FILE_PATH}" CURRENT_CONTENTS)
+
+        # Try finding the file in Source first, then Binary
+        set(PATH_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/imageclasses/${INJECT_FILE_NAME}")
+        set(PATH_BIN "${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/${INJECT_FILE_NAME}")
+
+        if(EXISTS "${PATH_SRC}")
+            set(INJECT_FILE_PATH "${PATH_SRC}")
+        elseif(EXISTS "${PATH_BIN}")
+            set(INJECT_FILE_PATH "${PATH_BIN}")
+        else()
+            set(INJECT_FILE_PATH "NOTFOUND")
+        endif()
+
+        if(NOT "${INJECT_FILE_PATH}" STREQUAL "NOTFOUND")
+            file(READ "${INJECT_FILE_PATH}" INJECT_DATA)
+
+            string(REGEX REPLACE
+                "(//start insert from ${MARKER_ID}\n)(.*)(\n//end insert from ${MARKER_ID})"
+                "\\1${INJECT_DATA}\\3"
+                UPDATED_CONTENTS
+                "${CURRENT_CONTENTS}")
+
+            message(STATUS "CHECK: Creating JSON for ${gen} with ${len_c} entries.")
+            file(WRITE "${FILE_PATH}" "${UPDATED_CONTENTS}")
+        else()
+            message(WARNING "Skipping injection: ${INJECT_FILE_NAME} not found in Source or Binary dirs.")
+        endif()
+    endif()
+endmacro()
+
+# Initialize the Adapted Files ---
+set(JIM_DEST "${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.h")
+set(JIMLIST_DEST "${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/JimList.h")
+
+# Copy the originals to the build dir first so we have a clean slate to modify
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses")
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/src/imageclasses/Jim.h" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses")
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/src/imageclasses/JimList.h" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses")
+
+# Run all Injections for Jim.h ---
+set(JIM_BLOCKS
+    "imagetype" "imagetype_multi" "imagelisttype" "errortype"
+    "errortype_d" "errortype_nd" "errortype_nm" "errortype_d_nm"
+)
+
+message(STATUS "DEBUG: Looking for injections in ${CMAKE_CURRENT_SOURCE_DIR}/src/imageclasses")
+
+foreach(block ${JIM_BLOCKS})
+    inject_code_block("${JIM_DEST}" "fun2method_${block}" "fun2method_${block}.h")
+endforeach()
+
+# Run all Injections for JimList.h ---
+inject_code_block("${JIMLIST_DEST}" "fun2method_imagetype_jimlist" "fun2method_imagetype_jimlist.h")
+inject_code_block("${JIMLIST_DEST}" "fun2method_imagelisttype" "fun2method_imagelisttype.h")
+
+message(STATUS "****** Jim.h and JimList.h have been successfully adapted via CMake.")
+
+# Prepare Jim.cc and JimList.cc in the build folder ---
+# Copy the original files if they haven't been copied yet
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/src/imageclasses/Jim.cc" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses")
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/src/imageclasses/JimList.cc" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses")
+
+set(JIM_CC_DEST "${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc")
+set(JIMLIST_CC_DEST "${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/JimList.cc")
+
+# --- 2. Define the includes we want to add ---
+set(JIM_INCLUDES
+    "fun2method_imagetype.cc"
+    "fun2method_imagetype_multi.cc"
+    "fun2method_imagelisttype.cc"
+    "fun2method_errortype.cc"
+    "fun2method_errortype_d.cc"
+    "fun2method_errortype_nd.cc"
+    "fun2method_errortype_nm.cc"
+    "fun2method_errortype_d_nm.cc"
+)
+
+# Robust Append for Jim.cc ---
+# We read the file first to check if we've already added the includes
+file(READ "${JIM_CC_DEST}" JIM_CC_CONTENT)
+
+set(NEW_INCLUDES "")
+foreach(inc_file ${JIM_INCLUDES})
+    set(LINE_TO_ADD "#include \"${inc_file}\"")
+    # Only add if the line isn't already there
+    if(NOT JIM_CC_CONTENT MATCHES "${LINE_TO_ADD}")
+        string(APPEND NEW_INCLUDES "${LINE_TO_ADD}\n")
+    endif()
+endforeach()
+
+if(NEW_INCLUDES)
+    file(APPEND "${JIM_CC_DEST}" "${NEW_INCLUDES}")
+endif()
+
+# Robust Append for JimList.cc ---
+file(READ "${JIMLIST_CC_DEST}" JIMLIST_CC_CONTENT)
+set(JIMLIST_LINE "#include \"fun2method_imagetype_jimlist.cc\"")
+
+if(NOT JIMLIST_CC_CONTENT MATCHES "${JIMLIST_LINE}")
+    file(APPEND "${JIMLIST_CC_DEST}" "${JIMLIST_LINE}\n")
+endif()
+
+message(STATUS "****** Jim.cc and JimList.cc include lines verified.")
+find_package(Boost REQUIRED CONFIG COMPONENTS filesystem system serialization)
+find_package(GDAL 3.00 REQUIRED)
+find_package(PkgConfig REQUIRED)
+find_package(OpenMP REQUIRED)
+
+message(STATUS "Searching (1) for FANN in: ${CMAKE_MODULE_PATH}")
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
+message(STATUS "Searching (2) for FANN in: ${CMAKE_MODULE_PATH}")
+FIND_PACKAGE(FANN 2.2 REQUIRED)
+message(STATUS "FANN_INCLUDE_DIRS: ${FANN_INCLUDE_DIRS}")
+message(STATUS "FANN_LIBRARIES: ${FANN_LIBRARIES}")
+
+find_package(SWIG REQUIRED)
+include(${SWIG_USE_FILE})
+
+# Source Preparation ---
+file(COPY ${PROJECT_SOURCE_DIR}/src DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+set(SRC_ROOT ${CMAKE_CURRENT_BINARY_DIR}/src)
 
 # The project's name and version
 project(jiplib)
@@ -27,12 +377,14 @@ project(jiplib)
 SET(JIPLIB_LIB_NAME jiplib)
 SET(JIPLIB_PYTHON_LIB_NAME jiplib)
 
+# Create the target here so all subsequent target_... commands work
+add_library(${JIPLIB_LIB_NAME} SHARED)
 enable_testing()
 INCLUDE(CTest)
 
 SET(JIPLIB_VERSION_MAJOR 1)
-SET(JIPLIB_VERSION_MINOR 1)
-SET(JIPLIB_VERSION_PATCH 7)
+SET(JIPLIB_VERSION_MINOR 2)
+SET(JIPLIB_VERSION_PATCH 0)
 SET(JIPLIB_VERSION "${JIPLIB_VERSION_MAJOR}.${JIPLIB_VERSION_MINOR}.${JIPLIB_VERSION_PATCH}")
 SET(PACKAGE_VERSION "${JIPLIB_VERSION}")
 SET(JIPLIB_SOVERSION "${JIPLIB_VERSION_MAJOR}")
@@ -46,40 +398,28 @@ SET(BUILD_WITH_LIBLAS FALSE CACHE BOOL "Choose if jiplib is to be built with lib
 SET(BUILD_WITH_FANN TRUE CACHE BOOL "Choose if jiplib is to be built with fann")
 SET(BUILD_WITH_PYTHON TRUE CACHE BOOL "Choose if jiplib is to be built with PYTHON support")
 SET(PROCESS_IN_PARALLEL TRUE CACHE BOOL "Choose if jiplib should be run in parallel")
-SET(BUILD_WITH_MIALLIB TRUE CACHE BOOL "Choose if jiplib should be compiled with miallib")
 #from https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling
 #By default if you don't change any RPATH related settings, CMake will
 # link the executables and shared libraries with full RPATH to all used
 # libraries in the build tree. When installing, it will clear the RPATH of
 # these targets so they are installed with an empty RPATH
-SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
-SET(CMAKE_INSTALL_RPATH "$\{ORIGIN\}:${CMAKE_CURRENT_BINARY_DIR}")
-SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
+set_target_properties(jiplib PROPERTIES INSTALL_RPATH "$ORIGIN")
 
 SET(PROJECT_INCLUDE_DIR include/jiplib)
 SET(PROJECT_TEST_DIR test)
 
 SET(CMAKE_COLOR_MAKEFILE ON)
 
-if(BUILD_WITH_MIALLIB)
-  SET(MIAL_BOOL 1)
-else(BUILD_WITH_MIALLIB)
-  SET(MIAL_BOOL 0)
-endif(BUILD_WITH_MIALLIB)
+SET(MIAL_BOOL 1)
 
 option (BUILD_SHARED_LIBS "Build with shared library" ON)
 
 # Platform and compiler specific settings
 
-INCLUDE(CheckCXXCompilerFlag)
-CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
-CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
-if(COMPILER_SUPPORTS_CXX11)
-  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-long-long")
-  message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has C++11 support.")
-else(COMPILER_SUPPORTS_CXX11)
-  message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
-endif()
+# Elevate to C++17 to match Conda dependencies
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
 
 ########## BUILDING INSTALLLER ##########
 # build a CPack driven installer package
@@ -120,14 +460,12 @@ SET(CPACK_COMPONENTS_ALL libraries headers wheels)
 
 add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)
 
-list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules")
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
 
 # Make sure Boost libraries are found
 SET(Boost_DEBUG 0)
-find_package(Boost COMPONENTS filesystem serialization REQUIRED)
 
 if(BUILD_WITH_PYTHON)
-  # SET(CREATE_WHEEL TRUE CACHE BOOL "Choose if jiplib PYTHON wheel is to be created")
   SET(CREATE_WHEEL TRUE CACHE BOOL "Choose if jiplib PYTHON wheel is to be created")
 endif(BUILD_WITH_PYTHON)
 
@@ -135,15 +473,9 @@ MESSAGE(STATUS "CREATE_WHEEL: ${CREATE_WHEEL}")
 
 SET(PYTHON3 ON CACHE BOOL "set ON for PYTHON3")
 
-find_package(Python COMPONENTS NumPy Interpreter Development)
+find_package(Python COMPONENTS Interpreter Development.Module NumPy REQUIRED)
 MESSAGE(STATUS "Python_NumPy_FOUND: ${Python_NumPy_FOUND}")
 
-# detect virtualenv and set Pip args accordingly
-# if(DEFINED ENV{VIRTUAL_ENV} OR DEFINED ENV{CONDA_PREFIX})
-#   set(_pip_args)
-# else()
-#   set(_pip_args "--user")
-# endif()
 message(STATUS "Python version found: ${Python_VERSION}")
 MESSAGE(STATUS "Python_LIBRARIES: ${Python_LIBRARIES}")
 MESSAGE(STATUS "Python_INCLUDE_DIRS: ${Python_INCLUDE_DIRS}")
@@ -213,20 +545,16 @@ if(GDAL_FOUND)
 endif()
 
 find_package(GSL REQUIRED)
+target_link_libraries(jiplib PRIVATE GSL::gsl)
 if(GSL_FOUND)
   message(STATUS "Found GSL: ${GSL_LIBRARIES}")
 endif()
 
-find_package(PkgConfig REQUIRED)
-pkg_check_modules(JSONCPP jsoncpp)
-if(JSONCPP_FOUND)
-  message(STATUS "JSONCPP package found: OK")
-else(JSONCPP_FOUND)
-  message(STATUS "Warning: JSONCPP package not found!")
-endif(JSONCPP_FOUND)
+#Find the module and create a modern target
+pkg_check_modules(JSONCPP REQUIRED IMPORTED_TARGET jsoncpp)
 
 if(PROCESS_IN_PARALLEL)
-  find_package(OpenMP)
+	find_package(OpenMP REQUIRED)
   if (OPENMP_FOUND)
     SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
     SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
@@ -273,15 +601,9 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jiplib-config.cmake
 configure_file ( "cmake.pc.in" "jiplib.pc"  @ONLY)
 
 
-SET(BUILD_WITH_MIALLIB TRUE CACHE BOOL "JIPlib needs to be built with mialiab")
-
 # Instruct CMake to inspect the following subfolders (with CMakeLists.txt in each subfolder)
 add_subdirectory ("${PROJECT_TEST_DIR}")
 
-if (BUILD_WITH_FANN)
-  FIND_PACKAGE(FANN 2.2 REQUIRED)
-endif(BUILD_WITH_FANN)
-
 ###############################################################################
 
 #we will use a copy of the imageclasses in the binary build directory, where we can change the content (for MIALLIB)
@@ -375,6 +697,7 @@ SET(IMGCLASS_H
   ${IMGCLASS_SRC_DIR}/jloperators_lib.h
   ${IMGCLASS_SRC_DIR}/jlextractimg_lib.h
   ${IMGCLASS_SRC_DIR}/jldem_lib.h
+  ${IMGCLASS_SRC_DIR}/Json_compat.h
   )
 
 SET(IMGCLASS_CC
@@ -405,6 +728,7 @@ SET(IMGCLASS_CC
   ${IMGCLASS_SRC_DIR}/jlwarp_lib.cc
   ${IMGCLASS_SRC_DIR}/jloperators_lib.cc
   ${IMGCLASS_SRC_DIR}/jldem_lib.cc
+  ${IMGCLASS_SRC_DIR}/Json_compat.cc
   )
 
 if(BUILD_WITH_FANN)
@@ -414,125 +738,104 @@ if(BUILD_WITH_FANN)
   )
 endif(BUILD_WITH_FANN)
 
-if(BUILD_WITH_MIALLIB)
-  find_package(MIALLIB REQUIRED)
-  if(MIALLIB_FOUND)
-    SET(MIALLIB_LIB_NAME miallib)
-    ADD_LIBRARY(${MIALLIB_LIB_NAME}::${MIALLIB_LIB_NAME} SHARED IMPORTED)
-    SET_TARGET_PROPERTIES(
-      ${MIALLIB_LIB_NAME}::${MIALLIB_LIB_NAME}
-      PROPERTIES
-      INTERFACE_INCLUDE_DIRECTORIES "${MIALLIB_INCLUDE_DIRS}"
-      IMPORTED_LOCATION ${MIALLIB_LIBRARY}
-      )
-    message(STATUS "MIALLIB was found with version ${MIALLIB_VERSION}")
-    message(STATUS "MIALLIB was found with major version ${MIALLIB_VERSION_MAJOR}")
-    message(STATUS "MIALLIB was found with minor version ${MIALLIB_VERSION_MINOR}")
-    message(STATUS "Found MIALLIB libraries: ${MIALLIB_LIBRARIES}")
-    message(STATUS "MIALLIB library name: ${MIALLIB_LIB_NAME}")
-    message(STATUS "Found MIALLIB INCLUDE dir: ${MIALLIB_INCLUDE_DIRS}")
-  endif()
-
-  SET(MIAL_BOOL 1)
-  message(STATUS "build with miallib: ${MIAL_BOOL}")
-
-else(BUILD_WITH_MIALLIB)
-  SET(MIAL_BOOL 0)
-  message(STATUS "build with miallib: ${MIAL_BOOL}")
-endif(BUILD_WITH_MIALLIB)
+if(TARGET miallib)
+  set(MIALLIB_TARGET miallib)
+else()
+  set(MIALLIB_TARGET MIALLIB::MIALLIB)
+endif()
 
-###############################################################################
-if(BUILD_WITH_MIALLIB)
-  file(GLOB MIALLIB_HEADER_FILES ${MIALLIB_INCLUDE_DIR}/miallib_*.h)
-  MESSAGE(STATUS "MIALLIB_HEADER_FILES: ${MIALLIB_HEADER_FILES}")
-  IF("${MIALLIB_HEADER_FILES}" STREQUAL "")
-    MESSAGE(FATAL_ERROR "Error: no header files found for miallib")
-  ENDIF("${MIALLIB_HEADER_FILES}" STREQUAL "")
-  file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_imagetype)
-  file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_imagelisttype)
-  file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype_nd)
-  file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype_nm)
-  file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype)
-  #Miallib functions have been designed as destructive. We will therefore create a copy to avoid the destructive behaviour. The destructive method will still be available with the prefix d_
-  #The following functions F_ND from miallib do not modify the input image and should therefore not create a copy. They will be treated in the same way as the destructive functions (without the prefix d_)
-  SET(F_ND "dumpxyz|szcompat|szgeocompat|iminfo|tiffinfo|writeGnuPlot3D|vectorizeImage|IsPartitionEqual|IsPartitionFiner|dendro|getfirstmaxpos|volume|imequalp|getmax|getminmax")
-  #The following functions F_NM from miallib are not compatible for multi-band processing
-  SET(F_NM "addframebox|subframebox")
-  #These functions must only be included if MCISRG is set
-  SET(F_MCISRG "labelImage|segmentImage")
-  #Create a text file with the list of headers to MIALLIB functions, e.g., miallib_imagetype for functions returning IMAGE *
-  FOREACH(infileName ${MIALLIB_HEADER_FILES})
-    MESSAGE(STATUS "Process file: ${infileName}")
-    file(STRINGS ${infileName} FUN_IMAGETYPE REGEX "^extern IMAGE \\*[^*]")
-    FOREACH(fun ${FUN_IMAGETYPE})
-      IF("${fun}" MATCHES "${F_MCISRG}")
-        IF(MCISRG)
-          file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_imagetype "${fun}\n")
-        ENDIF(MCISRG)
-      ELSE("${fun}" MATCHES "${F_MCISRG}")
+SET(MIAL_BOOL 1)
+message(STATUS "build with miallib: ${MIAL_BOOL}")
+
+file(GLOB MIALLIB_HEADER_FILES ${MIALLIB_INCLUDE_DIR}/miallib_*.h)
+MESSAGE(STATUS "MIALLIB_HEADER_FILES: ${MIALLIB_HEADER_FILES}")
+IF("${MIALLIB_HEADER_FILES}" STREQUAL "")
+  MESSAGE(FATAL_ERROR "Error: no header files found for miallib")
+ENDIF("${MIALLIB_HEADER_FILES}" STREQUAL "")
+file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_imagetype)
+file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_imagelisttype)
+file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype_nd)
+file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype_nm)
+file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype)
+#Miallib functions have been designed as destructive. We will therefore create a copy to avoid the destructive behaviour. The destructive method will still be available with the prefix d_
+#The following functions F_ND from miallib do not modify the input image and should therefore not create a copy. They will be treated in the same way as the destructive functions (without the prefix d_)
+SET(F_ND "dumpxyz|szcompat|szgeocompat|iminfo|tiffinfo|writeGnuPlot3D|vectorizeImage|IsPartitionEqual|IsPartitionFiner|dendro|getfirstmaxpos|volume|imequalp|getmax|getminmax")
+#The following functions F_NM from miallib are not compatible for multi-band processing
+SET(F_NM "addframebox|subframebox")
+#These functions must only be included if MCISRG is set
+SET(F_MCISRG "labelImage|segmentImage")
+#Create a text file with the list of headers to MIALLIB functions, e.g., miallib_imagetype for functions returning IMAGE *
+FOREACH(infileName ${MIALLIB_HEADER_FILES})
+  MESSAGE(STATUS "Process file: ${infileName}")
+  file(STRINGS ${infileName} FUN_IMAGETYPE REGEX "^extern IMAGE \\*[^*]")
+  FOREACH(fun ${FUN_IMAGETYPE})
+    IF("${fun}" MATCHES "${F_MCISRG}")
+      IF(MCISRG)
         file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_imagetype "${fun}\n")
-      ENDIF("${fun}" MATCHES "${F_MCISRG}")
-    ENDFOREACH(fun)
-    file(STRINGS ${infileName} FUN_IMAGELISTTYPE REGEX "^extern IMAGE \\*\\*[^*]")
-    FOREACH(fun ${FUN_IMAGELISTTYPE})
-      file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_imagelisttype "${fun}\n")
-    ENDFOREACH(fun)
-    file(STRINGS ${infileName} FUN_ERRORTYPE REGEX "^extern ERROR")
-    FOREACH(fun ${FUN_ERRORTYPE})
-      IF("${fun}" MATCHES "${F_ND}")
-        file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype_nd "${fun}\n")
-      ELSE("${fun}" MATCHES "${F_ND}")
-        IF("${fun}" MATCHES "${F_NM}")
-          file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype_nm "${fun}\n")
-        ELSE("${fun}" MATCHES "${F_NM}")
-          file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype "${fun}\n")
-        ENDIF("${fun}" MATCHES "${F_NM}")
-      ENDIF("${fun}" MATCHES "${F_ND}")
-    ENDFOREACH(fun)
-  ENDFOREACH(infileName)
-
-  #Create headers with new names in build directory
-  EXECUTE_PROCESS(COMMAND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/rename.sh ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses OUTPUT_QUIET)
-  EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagetype.py OUTPUT_QUIET)
-  EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagetype_multi.py OUTPUT_QUIET)
-  EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagetype_jimlist.py OUTPUT_QUIET)
-  EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagelisttype.py OUTPUT_QUIET)
-  EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype.py OUTPUT_QUIET)
-  EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_d.py OUTPUT_QUIET)
-  EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_nd.py OUTPUT_QUIET)
-  EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_nm.py OUTPUT_QUIET)
-  EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_d_nm.py OUTPUT_QUIET)
-
-  # remove all lines in between start and end in Jim.cc
-  execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_imagetype/,/\\/\\/end insert from fun2method_imagetype/{/\\/\\/start insert from fun2method_imagetype/!{/\\/\\/end insert from fun2method_imagetype/!d}}' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_imagetype/ {p; r fun2method_imagetype.h' -e ':a; n; /\\/\\/end insert from fun2method_imagetype/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_imagetype_multi/,/\\/\\/end insert from fun2method_imagetype_multi/{/\\/\\/start insert from fun2method_imagetype_multi/!{/\\/\\/end insert from fun2method_imagetype_multi/!d}}' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_imagetype_multi/ {p; r fun2method_imagetype_multi.h' -e ':a; n; /\\/\\/end insert from fun2method_imagetype_multi/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_imagetype_jimlist/,/\\/\\/end insert from fun2method_imagetype_jimlist/{/\\/\\/start insert from fun2method_imagetype_jimlist/!{/\\/\\/end insert from fun2method_imagetype_jimlist/!d}}' JimList.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_imagetype_jimlist/ {p; r fun2method_imagetype_jimlist.h' -e ':a; n; /\\/\\/end insert from fun2method_imagetype_jimlist/ {p; b}; ba}; p' JimList.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_imagelisttype/,/\\/\\/end insert from fun2method_imagelisttype/{/\\/\\/start insert from fun2method_imagelisttype/!{/\\/\\/end insert from fun2method_imagelisttype/!d}}' JimList.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_imagelisttype/ {p; r fun2method_imagelisttype.h' -e ':a; n; /\\/\\/end insert from fun2method_imagelisttype/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_errortype/,/\\/\\/end insert from fun2method_errortype/{/\\/\\/start insert from fun2method_errortype/!{/\\/\\/end insert from fun2method_errortype/!d}}' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_errortype/ {p; r fun2method_errortype.h' -e ':a; n; /\\/\\/end insert from fun2method_errortype/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_errortype_d/,/\\/\\/end insert from fun2method_errortype_d/{/\\/\\/start insert from fun2method_errortype_d/!{/\\/\\/end insert from fun2method_errortype_d/!d}}' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_errortype_d/ {p; r fun2method_errortype_d.h' -e ':a; n; /\\/\\/end insert from fun2method_errortype_d/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_errortype_nd/,/\\/\\/end insert from fun2method_errortype_nd/{/\\/\\/start insert from fun2method_errortype_nd/!{/\\/\\/end insert from fun2method_errortype_nd/!d}}' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_errortype_nd/ {p; r fun2method_errortype_nd.h' -e ':a; n; /\\/\\/end insert from fun2method_errortype_nd/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_errortype_nm/,/\\/\\/end insert from fun2method_errortype_nm/{/\\/\\/start insert from fun2method_errortype_nm/!{/\\/\\/end insert from fun2method_errortype_nm/!d}}' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_errortype_nm/ {p; r fun2method_errortype_nm.h' -e ':a; n; /\\/\\/end insert from fun2method_errortype_nm/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_errortype_d_nm/,/\\/\\/end insert from fun2method_errortype_d_nm/{/\\/\\/start insert from fun2method_errortype_d_nm/!{/\\/\\/end insert from fun2method_errortype_d_nm/!d}}' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_errortype_d_nm/ {p; r fun2method_errortype_d_nm.h' -e ':a; n; /\\/\\/end insert from fun2method_errortype_d_nm/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
-  #Append the source files to Jim.cc
-  file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagetype.cc\"\n")
-  file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagetype_multi.cc\"\n")
-  file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagelisttype.cc\"\n")
-  file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype.cc\"\n")
-  file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_d.cc\"\n")
-  file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_nd.cc\"\n")
-  file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_nm.cc\"\n")
-  file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_d_nm.cc\"\n")
-  file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/JimList.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagetype_jimlist.cc\"\n")
-endif(BUILD_WITH_MIALLIB)
+      ENDIF(MCISRG)
+    ELSE("${fun}" MATCHES "${F_MCISRG}")
+      file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_imagetype "${fun}\n")
+    ENDIF("${fun}" MATCHES "${F_MCISRG}")
+  ENDFOREACH(fun)
+  file(STRINGS ${infileName} FUN_IMAGELISTTYPE REGEX "^extern IMAGE \\*\\*[^*]")
+  FOREACH(fun ${FUN_IMAGELISTTYPE})
+    file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_imagelisttype "${fun}\n")
+  ENDFOREACH(fun)
+  file(STRINGS ${infileName} FUN_ERRORTYPE REGEX "^extern ERROR")
+  FOREACH(fun ${FUN_ERRORTYPE})
+    IF("${fun}" MATCHES "${F_ND}")
+      file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype_nd "${fun}\n")
+    ELSE("${fun}" MATCHES "${F_ND}")
+      IF("${fun}" MATCHES "${F_NM}")
+        file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype_nm "${fun}\n")
+      ELSE("${fun}" MATCHES "${F_NM}")
+        file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/miallib_errortype "${fun}\n")
+      ENDIF("${fun}" MATCHES "${F_NM}")
+    ENDIF("${fun}" MATCHES "${F_ND}")
+  ENDFOREACH(fun)
+ENDFOREACH(infileName)
+
+#Create headers with new names in build directory
+EXECUTE_PROCESS(COMMAND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/rename.sh ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses OUTPUT_QUIET)
+EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagetype.py OUTPUT_QUIET)
+EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagetype_multi.py OUTPUT_QUIET)
+EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagetype_jimlist.py OUTPUT_QUIET)
+EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagelisttype.py OUTPUT_QUIET)
+EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype.py OUTPUT_QUIET)
+EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_d.py OUTPUT_QUIET)
+EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_nd.py OUTPUT_QUIET)
+EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_nm.py OUTPUT_QUIET)
+EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses INPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_d_nm.py OUTPUT_QUIET)
+
+# remove all lines in between start and end in Jim.cc
+execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_imagetype/,/\\/\\/end insert from fun2method_imagetype/{/\\/\\/start insert from fun2method_imagetype/!{/\\/\\/end insert from fun2method_imagetype/!d}}' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_imagetype/ {p; r fun2method_imagetype.h' -e ':a; n; /\\/\\/end insert from fun2method_imagetype/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_imagetype_multi/,/\\/\\/end insert from fun2method_imagetype_multi/{/\\/\\/start insert from fun2method_imagetype_multi/!{/\\/\\/end insert from fun2method_imagetype_multi/!d}}' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_imagetype_multi/ {p; r fun2method_imagetype_multi.h' -e ':a; n; /\\/\\/end insert from fun2method_imagetype_multi/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_imagetype_jimlist/,/\\/\\/end insert from fun2method_imagetype_jimlist/{/\\/\\/start insert from fun2method_imagetype_jimlist/!{/\\/\\/end insert from fun2method_imagetype_jimlist/!d}}' JimList.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_imagetype_jimlist/ {p; r fun2method_imagetype_jimlist.h' -e ':a; n; /\\/\\/end insert from fun2method_imagetype_jimlist/ {p; b}; ba}; p' JimList.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_imagelisttype/,/\\/\\/end insert from fun2method_imagelisttype/{/\\/\\/start insert from fun2method_imagelisttype/!{/\\/\\/end insert from fun2method_imagelisttype/!d}}' JimList.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_imagelisttype/ {p; r fun2method_imagelisttype.h' -e ':a; n; /\\/\\/end insert from fun2method_imagelisttype/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_errortype/,/\\/\\/end insert from fun2method_errortype/{/\\/\\/start insert from fun2method_errortype/!{/\\/\\/end insert from fun2method_errortype/!d}}' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_errortype/ {p; r fun2method_errortype.h' -e ':a; n; /\\/\\/end insert from fun2method_errortype/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_errortype_d/,/\\/\\/end insert from fun2method_errortype_d/{/\\/\\/start insert from fun2method_errortype_d/!{/\\/\\/end insert from fun2method_errortype_d/!d}}' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_errortype_d/ {p; r fun2method_errortype_d.h' -e ':a; n; /\\/\\/end insert from fun2method_errortype_d/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_errortype_nd/,/\\/\\/end insert from fun2method_errortype_nd/{/\\/\\/start insert from fun2method_errortype_nd/!{/\\/\\/end insert from fun2method_errortype_nd/!d}}' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_errortype_nd/ {p; r fun2method_errortype_nd.h' -e ':a; n; /\\/\\/end insert from fun2method_errortype_nd/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_errortype_nm/,/\\/\\/end insert from fun2method_errortype_nm/{/\\/\\/start insert from fun2method_errortype_nm/!{/\\/\\/end insert from fun2method_errortype_nm/!d}}' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_errortype_nm/ {p; r fun2method_errortype_nm.h' -e ':a; n; /\\/\\/end insert from fun2method_errortype_nm/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i '/\\/\\/start insert from fun2method_errortype_d_nm/,/\\/\\/end insert from fun2method_errortype_d_nm/{/\\/\\/start insert from fun2method_errortype_d_nm/!{/\\/\\/end insert from fun2method_errortype_d_nm/!d}}' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+execute_process(COMMAND bash "-c" "sed -i -ne '/\\/\\/start insert from fun2method_errortype_d_nm/ {p; r fun2method_errortype_d_nm.h' -e ':a; n; /\\/\\/end insert from fun2method_errortype_d_nm/ {p; b}; ba}; p' Jim.h" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses)
+#Append the source files to Jim.cc
+file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagetype.cc\"\n")
+file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagetype_multi.cc\"\n")
+file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagelisttype.cc\"\n")
+file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype.cc\"\n")
+file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_d.cc\"\n")
+file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_nd.cc\"\n")
+file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_nm.cc\"\n")
+file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/Jim.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_errortype_d_nm.cc\"\n")
+file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/JimList.cc "#include \"${CMAKE_CURRENT_BINARY_DIR}/src/imageclasses/fun2method_imagetype_jimlist.cc\"\n")
 
 ###############################################################################
 # Define the jiplib library.
@@ -543,15 +846,22 @@ else(BUILD_WITH_LIBLAS)
   SET(JIPLIB_HEADER_FILES ${IMGCLASS_H} ${ALGOR_H} ${FILECLASS_H} ${BASE_H})
   SET(JIPLIB_SRC_FILES ${IMGCLASS_CC} ${ALGOR_CC} ${FILECLASS_CC} ${BASE_CC})
 endif(BUILD_WITH_LIBLAS)
-ADD_LIBRARY(${JIPLIB_LIB_NAME} ${JIPLIB_HEADER_FILES} ${JIPLIB_SRC_FILES})
+message(STATUS "JIPLIB_SRC_FILES: ${JIPLIB_SRC_FILES}")
+
+message(STATUS "${CMAKE_CURRENT_BINARY_DIR}: ${CMAKE_CURRENT_BINARY_DIR}")
+message(STATUS "${SRC_ROOT}: ${SRC_ROOT}")
+
+target_include_directories(jiplib PUBLIC
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
+    $<BUILD_INTERFACE:${SRC_ROOT}>
+    $<INSTALL_INTERFACE:include>
+)
+target_sources(jiplib PRIVATE ${JIPLIB_SRC_FILES})
 SET_TARGET_PROPERTIES(${JIPLIB_LIB_NAME} PROPERTIES PUBLIC_HEADER "${JIPLIB_HEADER_FILES}")
 
 ###############################################################################
 
 TARGET_COMPILE_DEFINITIONS(${JIPLIB_LIB_NAME} PUBLIC MIALLIB_DLL)
-if (BUILD_WITH_FANN)
-  TARGET_COMPILE_DEFINITIONS(${JIPLIB_LIB_NAME} PUBLIC FANN_DLL)
-endif(BUILD_WITH_FANN)
 TARGET_COMPILE_DEFINITIONS(${JIPLIB_LIB_NAME} PUBLIC GSL_DLL)
 TARGET_COMPILE_DEFINITIONS(${JIPLIB_LIB_NAME} PUBLIC HAVE_CONFIG_H)
 TARGET_INCLUDE_DIRECTORIES(${JIPLIB_LIB_NAME} PUBLIC ${Boost_INCLUDE_DIRS})
@@ -571,38 +881,33 @@ SET_TARGET_PROPERTIES(${JIPLIB_LIB_NAME}
   VERSION ${JIPLIB_VERSION}
 )
 
-target_link_libraries(
-  ${JIPLIB_LIB_NAME}
-  ${Boost_LIBRARIES}
-  ${Boost_FILESYSTEM_LIBRARY}
-  ${Boost_SYSTEM_LIBRARY}
-  ${Boost_SERIALIZATION_LIBRARY}
-  # ${BOOST_ARCHIVE_LIBRARY}
-  )
+get_target_property(JSON_LOC PkgConfig::JSONCPP INTERFACE_LINK_LIBRARIES)
+message(STATUS "JSONCPP Target Location: ${JSON_LOC}")
+target_link_libraries(${JIPLIB_LIB_NAME}
+    PUBLIC
+        miallib::miallib
+    PRIVATE
+        Python::Module
+        GDAL::GDAL
+        GSL::gsl
+	PkgConfig::JSONCPP
+        OpenMP::OpenMP_CXX
+        Boost::filesystem
+        Boost::system
+        Boost::serialization
+)
 
-if(BUILD_WITH_MIALLIB)
-  message(STATUS "Found MIALLIB_LIBRARY: ${MIALLIB_LIBRARIES}")
-  TARGET_INCLUDE_DIRECTORIES(${JIPLIB_LIB_NAME} PUBLIC
-    $<BUILD_INTERFACE:${MIALLIB_INCLUDE_DIR}
-    )
-  target_link_libraries(
-    ${JIPLIB_LIB_NAME}
-    miallib::miallib
-    )
-endif(BUILD_WITH_MIALLIB)
-
-target_link_libraries(
-  ${JIPLIB_LIB_NAME}
-  ${Python_LIBRARIES}
-  gomp
-  ${JSONCPP_LIBRARIES}
-  ${GDAL_LIBRARIES}
-  ${GSL_LIBRARIES}
-  )
+target_include_directories(jiplib PUBLIC
+ ${MIALLIB_INCLUDE_DIR}
+ )
+
+message(STATUS "JSONCPP LIBRARIES: ${JSONCPP_LIBRARIES}")
+message(STATUS "JSONCPP INCLUDE DIRS: ${JSONCPP_INCLUDE_DIRS}")
 
 if(BUILD_WITH_FANN)
   target_link_libraries(
     ${JIPLIB_LIB_NAME}
+    PRIVATE
     ${FANN_LIBRARIES}
     )
 endif(BUILD_WITH_FANN)
@@ -611,10 +916,6 @@ endif(BUILD_WITH_FANN)
 if(BUILD_WITH_PYTHON)
   ########## SWIG #############
   SET(PYTHON_SRC_DIR src/swig)
-  # SET(PYTHON_CC
-  #   ${PYTHON_SRC_DIR}/jiplib_wrap.cc
-  #   )
-  SET(JIPLIB_I ${PYTHON_SRC_DIR}/jiplib.i)
   FIND_PACKAGE(SWIG REQUIRED)
   MESSAGE(STATUS "CMAKE_CURRENT_BINARY_DIR: ${CMAKE_CURRENT_BINARY_DIR}")
   # todo adapt to new policies:
@@ -639,67 +940,79 @@ SET(CMAKE_SWIG_FLAGS "-keyword")
 SET(CMAKE_SWIG_FLAGS "-DMIALLIB=${MIAL_BOOL}")
 SET_PROPERTY(SOURCE ${JIPLIB_I} PROPERTY CPLUSPLUS ON)
 
-if(${CMAKE_VERSION} VERSION_LESS "3.8.0")
-  SWIG_ADD_MODULE(jiplib python ${JIPLIB_I})
-else(${CMAKE_VERSION} VERSION_LESS "3.8.0")
-  SWIG_ADD_LIBRARY(
-    jiplib_python
-    TYPE USE_BUILD_SHARED_LIBS
+SET_SOURCE_FILES_PROPERTIES(${JIPLIB_I} PROPERTIES SWIG_FLAGS "-W2")
+TARGET_INCLUDE_DIRECTORIES(jiplib PUBLIC 
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+    $<INSTALL_INTERFACE:include>
+)
+
+# SWIG Python Wrapper ---
+set_property(SOURCE src/swig/jiplib.i PROPERTY CPLUSPLUS ON)
+set_property(TARGET jiplib PROPERTY SWIG_USE_TARGET_INTERFACE_INCLUDE_DIRECTORIES ON)
+
+# Define Unique Names ---
+set(JIPLIB_LIB_NAME "jiplib")           # The C++ shared library (The Engine)
+set(JIPLIB_PYTHON_TARGET "jiplib_py")   # The SWIG target name (The Wrapper)
+
+# Create the SWIG Library ---
+# Use the unique 'jiplib_py' name to avoid CMP0002 errors
+# Clear out the old version-check block and use this:
+
+# Use the current source directory as a base to avoid the "//" issue
+set(JIPLIB_I "${CMAKE_CURRENT_SOURCE_DIR}/src/swig/jiplib.i")
+swig_add_library(jiplib_python
+    TYPE MODULE
     LANGUAGE python
-    SOURCES ${JIPLIB_I}
-    )
-  SET_PROPERTY(TARGET jiplib_python PROPERTY OUTPUT_NAME ${JIPLIB_PYTHON_LIB_NAME})
-endif(${CMAKE_VERSION} VERSION_LESS "3.8.0")
+    SOURCES "${JIPLIB_I}"
+)
 
-SET_SOURCE_FILES_PROPERTIES(${JIPLIB_I} PROPERTIES SWIG_FLAGS "-W2")
-TARGET_LINK_LIBRARIES(jiplib_python ${Python_LIBRARIES} ${JIPLIB_LIB_NAME} ${Boost_LIBRARIES})
+if(NOT TARGET jiplib_python)
+    message(FATAL_ERROR "Critical Error: jiplib_python target was not created. Check if JIPLIB_I is defined.")
+endif()
 
-if(BUILD_WITH_PYTHON)
-  SET(PYTHON_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/python)
-  SET(JIPLIB_INIT ${PYTHON_SOURCE_DIR}/__init__.py)
-
-  if(CREATE_WHEEL)
-    MESSAGE(STATUS "creating python wheel: ${CREATE_WHEEL}")
-    MESSAGE(STATUS "PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}")
-    MESSAGE(STATUS "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
-    MESSAGE(STATUS "CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}")
-    MESSAGE(STATUS "CMAKE_CURRENT_BINARY_DIR: ${CMAKE_CURRENT_BINARY_DIR}")
-    MESSAGE(STATUS "CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR}")
-    MESSAGE(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
-    SET(WHEEL_DIR ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME})
-
-    # add_custom_command(TARGET ${JIPLIB_LIB_NAME}
-    add_custom_command(TARGET jiplib_python
-      POST_BUILD
-      COMMAND mkdir -p ${WHEEL_DIR}
-      COMMAND cp ${JIPLIB_INIT} ${WHEEL_DIR}
-      COMMAND cp ${PYTHON_SOURCE_DIR}/setup.py ${CMAKE_CURRENT_BINARY_DIR}
-      COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/README.md ${WHEEL_DIR}
-      COMMAND cp ${CMAKE_BINARY_DIR}/_${JIPLIB_LIB_NAME}.so ${WHEEL_DIR}
-      COMMAND cp ${CMAKE_BINARY_DIR}/lib${JIPLIB_LIB_NAME}.so.${JIPLIB_VERSION_MAJOR} ${WHEEL_DIR}
-      COMMAND cp ${MIALLIB_LIBRARIES}.${MIALLIB_VERSION_MAJOR} ${WHEEL_DIR}
-      COMMAND cp ${CMAKE_BINARY_DIR}/${JIPLIB_LIB_NAME}.py ${WHEEL_DIR}
-      COMMAND cp ${PROJECT_SOURCE_DIR}/README.md ${WHEEL_DIR}
-      COMMAND ${Python_EXECUTABLE} -m pip wheel ${CMAKE_CURRENT_BINARY_DIR}
-      COMMAND rm -rf ${WHEEL_DIR}
-    )
-  endif(CREATE_WHEEL)
-endif(BUILD_WITH_PYTHON)
 
-########## INSTALL ##########
-INSTALL(TARGETS ${JIPLIB_LIB_NAME}
-  LIBRARY
-  DESTINATION ${CMAKE_INSTALL_LIBDIR}
-  COMPONENT libraries
-  PUBLIC_HEADER
-  DESTINATION include/${JIPLIB_LIB_NAME}
-  COMPONENT headers
-  )
+message(STATUS "${PROJECT_SOURCE_DIR}/external/miallib/core/c")
+if(TARGET miallib::miallib)
+    get_target_property(MIALLIB_INCLUDES miallib::miallib INTERFACE_INCLUDE_DIRECTORIES)
+elseif(TARGET miallib)
+    get_target_property(MIALLIB_INCLUDES miallib INTERFACE_INCLUDE_DIRECTORIES)
+else()
+    message(WARNING "Target miallib not found")
+endif()
 
-INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/jiplib.pc
-        DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
+# Update the SWIG properties
+set_property(TARGET jiplib_python PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE)
+#Add only the "internal" generated paths that aren't in targets
+# Usually, SWIG needs the directory where the generated .cxx files live
+set_property(TARGET jiplib_python APPEND PROPERTY
+    SWIG_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}"
 )
-INSTALL(CODE
-  "execute_process(COMMAND ${Python_EXECUTABLE} -m pip install ${_pip_args} ${CMAKE_CURRENT_BINARY_DIR}/jiplib-${JIPLIB_VERSION}-py3-none-any.whl --force-reinstall)"
-  COMPONENT wheels
-  )
+# To fix the GDAL version warning, we can pre-define the version for SWIG
+# Convert CMake GDAL variables into a format SWIG understands
+math(EXPR GDAL_VERSION_NUM_CALC "${GDAL_VERSION_MAJOR} * 1000000 + ${GDAL_VERSION_MINOR} * 10000")
+
+set_property(TARGET jiplib_python APPEND PROPERTY
+    SWIG_FLAGS
+    "-DGDAL_VERSION_NUM=${GDAL_VERSION_NUM_CALC}"
+)
+# Set the output name so 'import jiplib' works
+# This keeps the internal target name unique while the file name stays 'jiplib'
+set_target_properties(jiplib_python PROPERTIES
+    OUTPUT_NAME "jiplib"
+    PREFIX "_"
+)
+
+target_link_libraries(jiplib_python
+    PRIVATE
+    jiplib
+    Python::Module
+    Python::NumPy
+)
+set(JIPLIB_PYTHON_LIB_NAME ${JIPLIB_PYTHON_TARGET})
+
+set_target_properties(jiplib PROPERTIES OUTPUT_NAME "jiplib")
+
+# Installation (Crucial for Wheels) ---
+include(GNUInstallDirs)
+
+set_target_properties(jiplib_python PROPERTIES INSTALL_RPATH "$ORIGIN")


=====================================
cmake/modules/FindGSL.cmake deleted
=====================================
@@ -1,130 +0,0 @@
-## 
-## Try to find gnu scientific library GSL  
-## (see http://www.gnu.org/software/gsl/)
-## Once run this will define: 
-## 
-## GSL_FOUND       = system has GSL lib
-##
-## GSL_LIBRARIES   = full path to the libraries
-##    on Unix/Linux with additional linker flags from "gsl-config --libs"
-## 
-## CMAKE_GSL_CXX_FLAGS  = Unix compiler flags for GSL, essentially "`gsl-config --cxxflags`"
-##
-## GSL_INCLUDE_DIR      = where to find headers 
-##
-## GSL_LINK_DIRECTORIES = link directories, useful for rpath on Unix
-## GSL_EXE_LINKER_FLAGS = rpath on Unix
-##
-## Felix Woelk 07/2004
-## minor corrections Jan Woetzel
-##
-## www.mip.informatik.uni-kiel.de
-## --------------------------------
-##
-
-
-IF(WIN32)
-
-  SET(GSL_MINGW_PREFIX "c:/msys/local" )
-  SET(GSL_MSVC_PREFIX "$ENV{LIB_DIR}")
-  FIND_LIBRARY(GSL_LIB gsl PATHS 
-    ${GSL_MINGW_PREFIX}/lib 
-    ${GSL_MSVC_PREFIX}/lib
-    )
-  #MSVC version of the lib is just called 'cblas'
-  FIND_LIBRARY(GSLCBLAS_LIB gslcblas cblas PATHS 
-    ${GSL_MINGW_PREFIX}/lib 
-    ${GSL_MSVC_PREFIX}/lib
-    )
-
-  FIND_PATH(GSL_INCLUDE_DIR gsl/gsl_blas.h 
-    ${GSL_MINGW_PREFIX}/include 
-    ${GSL_MSVC_PREFIX}/include
-    )
-
-  IF (GSL_LIB AND GSLCBLAS_LIB)
-    SET (GSL_LIBRARIES ${GSL_LIB} ${GSLCBLAS_LIB})
-  ENDIF (GSL_LIB AND GSLCBLAS_LIB)
-  
-ELSE(WIN32)
-  IF(UNIX) 
-    SET(GSL_CONFIG_PREFER_PATH "$ENV{GSL_HOME}/bin" CACHE STRING "preferred path to GSL (gsl-config)")
-    FIND_PROGRAM(GSL_CONFIG gsl-config
-      ${GSL_CONFIG_PREFER_PATH}
-      $ENV{LIB_DIR}/bin
-      /usr/local/bin/
-      /usr/bin/
-      )
-    # MESSAGE("DBG GSL_CONFIG ${GSL_CONFIG}")
-    
-    IF (GSL_CONFIG) 
-      # set CXXFLAGS to be fed into CXX_FLAGS by the user:
-      SET(GSL_CXX_FLAGS "`${GSL_CONFIG} --cflags`")
-      
-      # set INCLUDE_DIRS to prefix+include
-      EXEC_PROGRAM(${GSL_CONFIG}
-        ARGS --prefix
-        OUTPUT_VARIABLE GSL_PREFIX)
-      SET(GSL_INCLUDE_DIR ${GSL_PREFIX}/include CACHE STRING INTERNAL)
-
-      # set link libraries and link flags
-      EXEC_PROGRAM(${GSL_CONFIG}
-          ARGS --libs
-          OUTPUT_VARIABLE GSL_LIBRARIES)
-      
-      ## extract link dirs for rpath  
-      EXEC_PROGRAM(${GSL_CONFIG}
-        ARGS --libs
-        OUTPUT_VARIABLE GSL_CONFIG_LIBS )
-
-      ## split off the link dirs (for rpath)
-      ## use regular expression to match wildcard equivalent "-L*<endchar>"
-      ## with <endchar> is a space or a semicolon
-      STRING(REGEX MATCHALL "[-][L]([^ ;])+" 
-        GSL_LINK_DIRECTORIES_WITH_PREFIX 
-        "${GSL_CONFIG_LIBS}" )
-        #      MESSAGE("DBG  GSL_LINK_DIRECTORIES_WITH_PREFIX=${GSL_LINK_DIRECTORIES_WITH_PREFIX}")
-
-      ## remove prefix -L because we need the pure directory for LINK_DIRECTORIES
-      
-      IF (GSL_LINK_DIRECTORIES_WITH_PREFIX)
-        STRING(REGEX REPLACE "[-][L]" "" GSL_LINK_DIRECTORIES ${GSL_LINK_DIRECTORIES_WITH_PREFIX} )
-      ENDIF (GSL_LINK_DIRECTORIES_WITH_PREFIX)
-      SET(GSL_EXE_LINKER_FLAGS "-Wl,-rpath,${GSL_LINK_DIRECTORIES}" CACHE STRING INTERNAL)
-      #      MESSAGE("DBG  GSL_LINK_DIRECTORIES=${GSL_LINK_DIRECTORIES}")
-      #      MESSAGE("DBG  GSL_EXE_LINKER_FLAGS=${GSL_EXE_LINKER_FLAGS}")
-
-      #      ADD_DEFINITIONS("-DHAVE_GSL")
-      #      SET(GSL_DEFINITIONS "-DHAVE_GSL")
-      MARK_AS_ADVANCED(
-        GSL_CXX_FLAGS
-        GSL_INCLUDE_DIR
-        GSL_LIBRARIES
-        GSL_LINK_DIRECTORIES
-        GSL_DEFINITIONS
-      )
-      
-    ELSE(GSL_CONFIG)
-
-      IF (GSL_FIND_REQUIRED)
-         MESSAGE(FATAL_ERROR "Could not find gsl-config. Please set it manually. GSL_CONFIG=${GSL_CONFIG}")
-      ELSE (GSL_FIND_REQUIRED)
-         MESSAGE(STATUS "Could not find GSL")
-         # TODO: Avoid cmake complaints if GSL is not found
-      ENDIF (GSL_FIND_REQUIRED)
-
-    ENDIF(GSL_CONFIG)
-
-  ENDIF(UNIX)
-ENDIF(WIN32)
-
-
-IF(GSL_LIBRARIES)
-  IF(GSL_INCLUDE_DIR OR GSL_CXX_FLAGS)
-
-    SET(GSL_FOUND 1)
-    
-    MESSAGE(STATUS "Using GSL from ${GSL_PREFIX}")
-
-  ENDIF(GSL_INCLUDE_DIR OR GSL_CXX_FLAGS)
-ENDIF(GSL_LIBRARIES)


=====================================
doc/conf.py
=====================================
@@ -67,9 +67,9 @@ author = u'Pieter Kempeneers and Pierre Soille'
 # built documents.
 #
 # The short X.Y version.
-version = u'1.1.7'
+version = u'1.2.0'
 # The full version, including alpha/beta/rc tags.
-release = u'1.1.7'
+release = u'1.2.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.


=====================================
src/apps/AppFactory.h
=====================================
@@ -32,8 +32,8 @@ along with jiplib.  If not, see <https://www.gnu.org/licenses/>.
 #include "gdal_priv.h"
 #include "base/typeconversion.h"
 //#include "config.h"
-#include "json/value.h"
-#include "json/json.h"
+#include <json/value.h>
+#include <json/json.h>
 
 namespace app
 {


=====================================
src/imageclasses/Jim.cc
=====================================
@@ -30,6 +30,7 @@ along with jiplib.  If not, see <https://www.gnu.org/licenses/>.
 #include "VectorOgr.h"
 #include "base/Optionjl.h"
 #include "algorithms/StatFactory.h"
+#include "Json_compat.h"
 
 using namespace std;
 //Forgetting to place these commands will show itself as an ugly segmentation fault (crash) as soon as any C-API subroutine is actually called
@@ -69,7 +70,7 @@ size_t Jim::getDataTypeSizeBytes(int band) const {
       std::string errorString="Error: data type not supported";
       throw(errorString);
     }
-    return(static_cast<size_t>(GDALGetDataTypeSize(getGDALDataType(band))>>3));
+    return static_cast<size_t>(GDALGetDataTypeSizeBytes(getGDALDataType(band)));
   }
   }
 #else
@@ -78,7 +79,7 @@ size_t Jim::getDataTypeSizeBytes(int band) const {
       std::string errorString="Error: data type not supported";
       throw(errorString);
     }
-    return(static_cast<size_t>(GDALGetDataTypeSize(getGDALDataType(band))>>3));
+    return static_cast<size_t>(GDALGetDataTypeSizeBytes(getGDALDataType(band)));
 #endif
 }
 
@@ -1026,7 +1027,11 @@ void Jim::getGeoTransform(vector<double>& gt) const{
 /**
  * @return the metadata of this data set in C style string format (const version)
  **/
+#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3, 13, 0)
+CSLConstList Jim::getMetadata() const
+#else
 char** Jim::getMetadata() const
+#endif
 {
   if(m_gds){
     if(m_gds->GetMetadata()!=NULL)
@@ -1045,7 +1050,11 @@ char** Jim::getMetadata() const
 void Jim::getMetadata(std::list<std::string>& metadata) const
 {
   if(m_gds){
+#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3, 13, 0)
+    CSLConstList cmetadata=m_gds->GetMetadata();
+#else
     char** cmetadata=m_gds->GetMetadata();
+#endif
     while(*cmetadata!=NULL){
       metadata.push_back(*(cmetadata));
       ++cmetadata;
@@ -1494,7 +1503,11 @@ CPLErr Jim::registerDriver()
       s << "FileOpenError (" << m_imageType << ")";
       throw(s.str());
     }
+#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3, 13, 0)
+    CSLConstList papszMetadata;
+#else
     char **papszMetadata;
+#endif
     papszMetadata = poDriver->GetMetadata();
     //todo: try and catch if CREATE is not supported (as in PNG)
     if( ! CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE )){
@@ -2120,7 +2133,11 @@ CPLErr Jim::open(app::AppFactory &app){
     GDALRasterBand *poBand;//we will fetch the first band to obtain the gds metadata
 
     if(m_gds){
+#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3, 13, 0)
+      CSLConstList papszMetadata;
+#else
       char **papszMetadata;
+#endif
       papszMetadata = m_gds->GetMetadata("SUBDATASETS");
       vector<string> LayersAll;
       if( papszMetadata ){
@@ -3333,32 +3350,44 @@ void Jim::setData(double value, double ulx, double uly, double lrx, double lry,
 }
 
 ///Create a JSON string from a Jim image
-std::string Jim::jim2json(){
-  Json::Value custom;
-  custom["size"]=static_cast<int>(1);
-  int iimg=0;
-  Json::Value image;
-  image["path"]=getFileName();
-  std::string wktString=getProjectionRef();
-  std::string key("EPSG");
-  std::size_t foundEPSG=wktString.rfind(key);
-  std::string fromEPSG=wktString.substr(foundEPSG);//EPSG","32633"]]'
-  std::size_t foundFirstDigit=fromEPSG.find_first_of("0123456789");
-  std::size_t foundLastDigit=fromEPSG.find_last_of("0123456789");
-  std::string epsgString=fromEPSG.substr(foundFirstDigit,foundLastDigit-foundFirstDigit+1);
-  image["epsg"]=atoi(epsgString.c_str());
-  std::ostringstream os;
-  os << iimg++;
-  custom["0"]=image;
-
-  Json::StreamWriterBuilder builder;
-  builder["indentation"] = "";  // assume default for comments is None
-  std::string str = Json::writeString(builder, custom);
-  return(str);
-  //deprecated:
-  // Json::Value custom; // population is left as an exercise for the reader
-  // std::string str = Json::FastWriter().write(custom);
-  // return(str);
+std::string Jim::jim2json() {
+    Json::Value custom;
+    
+    // 1. Handle Json::Value using our centralized helper
+    json_util::get_member(custom, "size") = static_cast<int>(1);
+    
+    int iimg = 0;
+    Json::Value image;
+    json_util::get_member(image, "path") = getFileName();
+
+    std::string wktString = getProjectionRef();
+    std::string key("EPSG");
+    std::size_t foundEPSG = wktString.rfind(key);
+    
+    if (foundEPSG != std::string::npos) {
+        std::string fromEPSG = wktString.substr(foundEPSG);
+        std::size_t foundFirstDigit = fromEPSG.find_first_of("0123456789");
+        std::size_t foundLastDigit = fromEPSG.find_last_of("0123456789");
+        
+        if (foundFirstDigit != std::string::npos) {
+            std::string epsgString = fromEPSG.substr(foundFirstDigit, foundLastDigit - foundFirstDigit + 1);
+            try {
+                json_util::get_member(image, "epsg") = std::stoi(epsgString);
+            } catch (...) {
+                // Fallback if stoi fails on malformed strings
+                json_util::get_member(image, "epsg") = 0;
+            }
+        }
+    }
+
+    // Use the helper for the index key "0"
+    json_util::get_member(custom, "0") = image;
+
+    // 2. Handle StreamWriterBuilder
+    // This is the specific source of your StreamWriterBuilderixERKSs error.
+    Json::StreamWriterBuilder builder;
+    builder[Json::String("indentation")] = "";
+    return Json::writeString(builder, custom);
 }
 
 std::shared_ptr<Jim> Jim::clone(bool copyData) {
@@ -3623,7 +3652,6 @@ CPLErr Jim::copyData(void* data, int band){
   memcpy(static_cast<uint_least8_t*>(data),static_cast<uint_least8_t*>(m_data[band]),getDataTypeSizeBytes()*nrOfCol()*m_blockSize*nrOfPlane());
   m_begin[band]=0;
   m_end[band]=nrOfRow();
-  // memcpy(data,m_data[band],(GDALGetDataTypeSize(getDataType())>>3)*nrOfCol()*m_blockSize);
   return(CE_None);
 };
 


=====================================
src/imageclasses/Jim.h
=====================================
@@ -234,7 +234,7 @@ static std::size_t getDataTypeSizeBytes(const std::string &typeString){
       std::string errorString="Error: data type not supported";
       throw(errorString);
     }
-    return(static_cast<std::size_t>(GDALGetDataTypeSize(static_cast<GDALDataType>(typeInt))>>3));
+    return static_cast<std::size_t>(GDALGetDataTypeSizeBytes(static_cast<GDALDataType>(typeInt)));
   }
   }
 }
@@ -640,7 +640,11 @@ class Jim : public std::enable_shared_from_this<Jim>
   //Get a pointer to the GDAL dataset
   GDALDataset* getDataset(){return m_gds;};
   ///Get the metadata of this dataset
+#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3, 13, 0)
+  CSLConstList getMetadata() const;
+#else
   char** getMetadata() const;
+#endif
   // Get the metadata of this dataset in the form of a list of strings (const version)
   void getMetadata(std::list<std::string>& metadata) const;
   ///Get the image description from the driver of this dataset
@@ -1755,8 +1759,8 @@ template<typename T> CPLErr Jim::readDataBlock(std::vector<T>& buffer, int minCo
             returnValue=readNewBlock(irow,band);
         }
         int index=(irow-m_begin[band])*nrOfCol();
-        int minindex=(index+minCol);//*(GDALGetDataTypeSize(getDataType())>>3);
-        int maxindex=(index+maxCol);//*(GDALGetDataTypeSize(getDataType())>>3);
+        int minindex=(index+minCol);
+        int maxindex=(index+maxCol);
 
         for(index=minindex;index<=maxindex;++index,++bufit){
           double dvalue=0;
@@ -1850,8 +1854,8 @@ template<typename T> CPLErr Jim::readDataBlock3D(std::vector<T>& buffer, std::si
         }
         /* int index=(irow-m_begin[band])*nrOfCol(); */
         std::size_t index=(plane*nrOfRow()*nrOfCol())+(irow-m_begin[band])*nrOfCol();
-        std::size_t minindex=(index+minCol);//*(GDALGetDataTypeSize(getDataType())>>3);
-        std::size_t maxindex=(index+maxCol);//*(GDALGetDataTypeSize(getDataType())>>3);
+        std::size_t minindex=(index+minCol);
+        std::size_t maxindex=(index+maxCol);
 
         for(index=minindex;index<=maxindex;++index,++bufit){
           double dvalue=0;


=====================================
src/imageclasses/JimList.cc
=====================================
@@ -28,6 +28,7 @@ along with jiplib.  If not, see <https://www.gnu.org/licenses/>.
 #include "algorithms/Egcs.h"
 #include "apps/AppFactory.h"
 #include "JimList.h"
+#include "Json_compat.h"
 
 //todo: namespace jiplib
 using namespace std;
@@ -59,93 +60,135 @@ JimList::JimList(unsigned int theSize){
 }
 
 ///constructor using a json string coming from a custom colllection
-JimList& JimList::open(const std::string& strjson){
-  Json::Value custom;
-  std::istringstream sin(strjson);
-  sin >> custom;
-  // Json::Reader reader;
-  // bool parsedSuccess=reader.parse(strjson,custom,false);
-  // if(parsedSuccess){
-  for(int iimg=0;iimg<custom["size"].asInt();++iimg){
-    std::ostringstream os;
-    os << iimg;
-    Json::Value image=custom[os.str()];
-    std::string filename=image["path"].asString();
-    //todo: open without reading?
-    app::AppFactory theApp;
-    theApp.setLongOption("filename",filename);
-    std::shared_ptr<Jim> theImage=Jim::createImg(theApp);
-    pushImage(theImage);
-  }
-  // }
-  return(*this);
+JimList& JimList::open(const std::string& strjson) {
+    Json::Value custom;
+    std::istringstream sin(strjson);
+    
+    // Modern JsonCpp uses operators or CharReader, but sin >> custom 
+    // is generally well-supported across versions.
+    sin >> custom;
+
+    // 1. Robustly access the "size" member
+    int size = 0;
+    try {
+        size = json_util::get_member(custom, "size").asInt();
+    } catch (...) {
+        // Handle cases where "size" might be missing or not an int
+        return *this; 
+    }
+
+    for (int iimg = 0; iimg < size; ++iimg) {
+        // 2. Convert index to string safely
+        std::string indexKey = std::to_string(iimg);
+        
+        // 3. Access the image object using the helper
+        Json::Value image = json_util::get_member(custom, indexKey);
+        
+        // 4. Access the "path" member using the helper
+        std::string filename = json_util::get_member(image, "path").asString();
+
+        if (!filename.empty()) {
+            app::AppFactory theApp;
+            theApp.setLongOption("filename", filename);
+            
+            try {
+                std::shared_ptr<Jim> theImage = Jim::createImg(theApp);
+                pushImage(theImage);
+            } catch (const std::exception& e) {
+                // Log or handle individual image load failures 
+                // to prevent one bad path from crashing the whole list
+            }
+        }
+    }
+    
+    return *this;
 }
 
-JimList& JimList::open(app::AppFactory& theApp){
-  Optionjl<std::string> json_opt("json", "json", "The json object");
-  bool doProcess;//stop process when program was invoked with help option (-h --help)
-  try{
-    doProcess=json_opt.retrieveOption(theApp);
-  }
-  catch(std::string predefinedString){
-    std::cout << predefinedString << std::endl;
-  }
-  if(!doProcess){
-    std::cout << std::endl;
-    std::ostringstream helpStream;
-    helpStream << "exception thrown due to help info";
-    throw(helpStream.str());//help was invoked, stop processing
-  }
+JimList& JimList::open(app::AppFactory& theApp) {
+    Optionjl<std::string> json_opt("json", "json", "The json object");
+    bool doProcess = true;
 
-  std::vector<std::string> badKeys;
-  theApp.badKeys(badKeys);
-  if(badKeys.size()){
-    std::ostringstream errorStream;
-    if(badKeys.size()>1)
-      errorStream << "Error: unknown keys: ";
-    else
-      errorStream << "Error: unknown key: ";
-    for(int ikey=0;ikey<badKeys.size();++ikey){
-      errorStream << badKeys[ikey] << " ";
+    try {
+        doProcess = json_opt.retrieveOption(theApp);
     }
-    errorStream << std::endl;
-    throw(errorStream.str());
-  }
-  if(json_opt.empty()){
-    std::string errorString="Error: json string is empty";
-    throw(errorString);
-  }
-  return(open(json_opt[0]));
-  // JimList(std::string(""));
+    catch (const std::string& predefinedString) {
+        std::cout << predefinedString << std::endl;
+    }
+    catch (const std::exception& e) {
+        std::cerr << "Standard exception: " << e.what() << std::endl;
+    }
+
+    if (!doProcess) {
+        std::cout << std::endl;
+        // Using runtime_error is more robust for Python/C++ boundary
+        throw std::runtime_error("exception thrown due to help info");
+    }
+
+    std::vector<std::string> badKeys;
+    theApp.badKeys(badKeys);
+    if (!badKeys.empty()) {
+        std::ostringstream errorStream;
+        errorStream << "Error: unknown key" << (badKeys.size() > 1 ? "s: " : ": ");
+
+        for (const auto& key : badKeys) {
+            errorStream << key << " ";
+        }
+        errorStream << std::endl;
+        throw std::runtime_error(errorStream.str());
+    }
+
+    if (json_opt.empty()) {
+        throw std::runtime_error("Error: json string is empty");
+    }
+
+    // This calls your newly robust open(const std::string&)
+    return open(json_opt[0]);
 }
 
-std::string JimList::jl2json(){
-  Json::Value custom;
-  custom["size"]=static_cast<int>(size());
-  int iimg=0;
-  for(std::list<std::shared_ptr<Jim> >::iterator lit=begin();lit!=end();++lit){
-    Json::Value image;
-    image["path"]=(*lit)->getFileName();
-    std::string wktString=(*lit)->getProjectionRef();
-    std::string key("EPSG");
-    std::size_t foundEPSG=wktString.rfind(key);
-    std::string fromEPSG=wktString.substr(foundEPSG);//EPSG","32633"]]'
-    std::size_t foundFirstDigit=fromEPSG.find_first_of("0123456789");
-    std::size_t foundLastDigit=fromEPSG.find_last_of("0123456789");
-    std::string epsgString=fromEPSG.substr(foundFirstDigit,foundLastDigit-foundFirstDigit+1);
-    image["epsg"]=atoi(epsgString.c_str());
-    std::ostringstream os;
-    os << iimg++;
-    custom[os.str()]=image;
-  }
-  Json::StreamWriterBuilder builder;
-  builder["indentation"] = "";  // assume default for comments is None
-  std::string str = Json::writeString(builder, custom);
-  return(str);
-  //deprecated:
-  // Json::FastWriter fastWriter;
-  // return(fastWriter.write(custom));
+std::string JimList::jl2json() {
+    Json::Value custom;
+
+    // 1. Set global size using helper
+    json_util::get_member(custom, "size") = static_cast<int>(size());
+
+    int iimg = 0;
+    // Using a modern range-based loop if your list supports it,
+    // otherwise sticking to the iterator for compatibility.
+    for (auto lit = begin(); lit != end(); ++lit) {
+        Json::Value image;
+
+        // 2. Access "path" safely
+        json_util::get_member(image, "path") = (*lit)->getFileName();
+
+        std::string wktString = (*lit)->getProjectionRef();
+        std::string key("EPSG");
+        std::size_t foundEPSG = wktString.rfind(key);
+
+        // Robustness: Check if EPSG was actually found to avoid npos crashes
+        if (foundEPSG != std::string::npos) {
+            std::string fromEPSG = wktString.substr(foundEPSG);
+            std::size_t foundFirstDigit = fromEPSG.find_first_of("0123456789");
+            std::size_t foundLastDigit = fromEPSG.find_last_of("0123456789");
+
+            if (foundFirstDigit != std::string::npos && foundLastDigit != std::string::npos) {
+                std::string epsgString = fromEPSG.substr(foundFirstDigit, foundLastDigit - foundFirstDigit + 1);
+                // 3. Access "epsg" safely
+                json_util::get_member(image, "epsg") = std::stoi(epsgString);
+            }
+        }
+
+        // 4. Use to_string and helper for the dynamic image keys ("0", "1", etc.)
+        std::string indexKey = std::to_string(iimg++);
+        json_util::get_member(custom, indexKey) = image;
+    }
+
+    // 5. Handle StreamWriterBuilder specifically
+    Json::StreamWriterBuilder builder;
+    builder[Json::String("indentation")] = "";
+
+    return Json::writeString(builder, custom);
 }
+
 JimList& JimList::selectGeo(double ulx, double uly, double lrx, double lry){
   /* std::vector<std::shared_ptr<Jim>>::iterator it=begin(); */
   std::list<std::shared_ptr<Jim>>::iterator it=begin();


=====================================
src/imageclasses/Json_compat.cc
=====================================
@@ -0,0 +1,13 @@
+#include "Json_compat.h"
+
+namespace json_util {
+
+Json::Value& get_member(Json::Value& node, const std::string& key) {
+    return node[key];
+}
+
+Json::Value& get_member(Json::Value& node, const char* key) {
+    return node[key];
+}
+
+}


=====================================
src/imageclasses/Json_compat.h
=====================================
@@ -0,0 +1,20 @@
+#ifndef JIPLIB_JSON_COMPAT_H
+#define JIPLIB_JSON_COMPAT_H
+
+#if __cplusplus >= 201703L
+    #include <string_view>
+    #define HAS_STRING_VIEW 1
+#else
+    #define HAS_STRING_VIEW 0
+#endif
+
+#include <json/json.h>
+#include <string>
+
+namespace json_util {
+    // Returns a reference to the member, compatible with various JsonCpp versions
+    Json::Value& get_member(Json::Value& node, const std::string& key);
+    Json::Value& get_member(Json::Value& node, const char* key);
+}
+
+#endif


=====================================
src/imageclasses/VectorOgr.cc
=====================================
@@ -485,7 +485,12 @@ OGRErr VectorOgr::pushLayer(const std::string& layername, const OGRSpatialRefere
     throw(errorString);
   }
   //if no constraints on the types geometry to be written: use wkbUnknown
-  m_layer.push_back(m_gds->CreateLayer(layername.c_str(), theSRS, geometryType ,papszOptions));
+  OGRSpatialReference* srsCopy = theSRS ? theSRS->Clone() : nullptr;
+  m_layer.push_back(m_gds->CreateLayer(layername.c_str(), srsCopy, geometryType, papszOptions));
+  if (srsCopy) {
+    srsCopy->Release();
+  }
+
   m_features.resize(m_layer.size());
   if(!m_layer.back()){
     std::string errorString="Open failed";
@@ -564,7 +569,7 @@ std::shared_ptr<VectorOgr> VectorOgr::intersect(OGRPolygon *pGeom, app::AppFacto
     std::ostringstream errorStream;
     errorStream << "Error: failed to intersect" << std::endl;
     std::cerr << errorStream.str() << std::endl;
-    throw(errorStream);
+    throw(errorStream.str());
   }
   return(ogrWriter);
 }
@@ -575,7 +580,7 @@ std::shared_ptr<VectorOgr> VectorOgr::intersect(const Jim& aJim, app::AppFactory
     std::ostringstream errorStream;
     errorStream << "Error: failed to intersect" << std::endl;
     std::cerr << errorStream.str() << std::endl;
-    throw(errorStream);
+    throw(errorStream.str());
   }
   return(ogrWriter);
 }


=====================================
src/imageclasses/fun2method_errortype.py
=====================================
@@ -1,6 +1,6 @@
 # first 20161111 by Pierre.Soille at jrc.ec.europa.eu
 
-def fun2method(inputfile, outputfile_basename):
+def fun2method(inputfile, outputfile_basename, json_path):
     """converts MIALib C function declarations into JIPLib C++ methods (outputfile_basename.cc file) and C++ method declarations (outputfile_basename.h file).  Currently only convert desctuctive functions, i.e., ERROR_TYPE functions, with IMAGE * as first argument (IMAGE ** not yet taken into account).
 
     :param inputfile: string for input file containing extern declarations
@@ -12,10 +12,15 @@ def fun2method(inputfile, outputfile_basename):
 
     import re
     import json
+    import sys 
+    import os
+    with open(json_path, 'r') as f:
+        old2newDic = json.load(f)
+
     # for writing a dictionary in json file
     #j son.dump(old2NewDict, open("text.txt",'w'))
     # reading dictionary in json file
-    old2newDic = json.load(open("old2NewNames.json"))
+    #old2newDic = json.load(open("old2NewNames.json"))
 
     ifp=open(inputfile, 'r')
 
@@ -197,23 +202,27 @@ import sys, getopt
 def main(argv):
    inputfile="miallib_errortype"
    outputfile="fun2method_errortype"
+   json_path = "old2NewNames.json"
    try:
-      opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="])
+       opts, args = getopt.getopt(argv,"hi:o:j:",["ifile=","ofile=", "json="])
    except getopt.GetoptError:
-      print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+      print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
       sys.exit(2)
    for opt, arg in opts:
       if opt == '-h':
-         print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+         print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
          sys.exit()
       elif opt in ("-i", "--ifile"):
          inputfile = arg
       elif opt in ("-o", "--ofile"):
          outputfile = arg
+      elif opt in ("-j", "--json"):
+         json_path = arg
    print('Input file is "', inputfile)
    print('Output file is "', outputfile)
+   print('JSON file is "', json_path)
 
-   fun2method(inputfile, outputfile)
+   fun2method(inputfile, outputfile, json_path)
 
 if __name__ == "__main__":
    main(sys.argv[1:])


=====================================
src/imageclasses/fun2method_errortype_d.py
=====================================
@@ -1,7 +1,6 @@
 # first 20161111 by Pierre.Soille at jrc.ec.europa.eu
 
-
-def fun2method(inputfile, outputfile_basename):
+def fun2method(inputfile, outputfile_basename, json_path):
     """converts MIALib C function declarations into JIPLib C++ methods (outputfile_basename.cc file) and C++ method declarations (outputfile_basename.h file).  Currently only convert desctuctive functions, i.e., ERROR_TYPE functions, with IMAGE * as first argument (IMAGE ** not yet taken into account).
 
     :param inputfile: string for input file containing extern declarations
@@ -13,7 +12,12 @@ def fun2method(inputfile, outputfile_basename):
 
     import re
     import json
-    old2newDic = json.load(open("old2NewNames.json"))
+    import sys
+    import os
+    with open(json_path, 'r') as f:
+        old2newDic = json.load(f)
+
+    #old2newDic = json.load(open("old2NewNames.json"))
 
     ifp=open(inputfile, 'r')
 
@@ -186,23 +190,27 @@ import sys, getopt
 def main(argv):
    inputfile="miallib_errortype"
    outputfile="fun2method_errortype_d"
+   json_path = "old2NewNames.json"
    try:
-      opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="])
+       opts, args = getopt.getopt(argv,"hi:o:j:",["ifile=","ofile=", "json="])
    except getopt.GetoptError:
-      print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+      print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
       sys.exit(2)
    for opt, arg in opts:
       if opt == '-h':
-         print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+         print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
          sys.exit()
       elif opt in ("-i", "--ifile"):
          inputfile = arg
       elif opt in ("-o", "--ofile"):
          outputfile = arg
+      elif opt in ("-j", "--json"):
+         json_path = arg
    print('Input file is "', inputfile)
    print('Output file is "', outputfile)
+   print('JSON file is "', json_path)
 
-   fun2method(inputfile, outputfile)
+   fun2method(inputfile, outputfile, json_path)
 
 if __name__ == "__main__":
    main(sys.argv[1:])
@@ -210,6 +218,7 @@ if __name__ == "__main__":
 
 
 
+
 # cat /home/soillpi/workstation/jip/mia//core/c/miallib_*.h | grep '^extern ERROR'  > miallib_error_type
 # cat /home/soillpi/work/jip20170201/mia//core/c/miallib_*.h | grep '^extern ERROR'  > miallib_error_type
 # cat /usr/local/include/miallib/miallib_*.h | grep '^extern ERROR'  > miallib_error_type


=====================================
src/imageclasses/fun2method_errortype_d_nm.py
=====================================
@@ -1,6 +1,6 @@
 # first 20190808 by pieter.kempeneers at jrc.ec.europa.eu
 
-def fun2method(inputfile, outputfile_basename):
+def fun2method(inputfile, outputfile_basename, json_path):
     """converts MIALib C function declarations into JIPLib C++ methods (outputfile_basename.cc file) and C++ method declarations (outputfile_basename.h file). Convert desctuctive functions that do not support multi-band processing.
 
     :param inputfile: string for input file containing extern declarations
@@ -12,7 +12,11 @@ def fun2method(inputfile, outputfile_basename):
 
     import re
     import json
-    old2newDic = json.load(open("old2NewNames.json"))
+    import sys
+    import os
+    with open(json_path, 'r') as f:
+        old2newDic = json.load(f)
+    #old2newDic = json.load(open("old2NewNames.json"))
 
     ifp=open(inputfile, 'r')
 
@@ -163,23 +167,27 @@ import sys, getopt
 def main(argv):
    inputfile="miallib_errortype_nm"
    outputfile="fun2method_errortype_d_nm"
+   json_path = "old2NewNames.json"
    try:
-      opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="])
+       opts, args = getopt.getopt(argv,"hi:o:j:",["ifile=","ofile=", "json="])
    except getopt.GetoptError:
-      print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+      print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
       sys.exit(2)
    for opt, arg in opts:
       if opt == '-h':
-         print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+         print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
          sys.exit()
       elif opt in ("-i", "--ifile"):
          inputfile = arg
       elif opt in ("-o", "--ofile"):
          outputfile = arg
+      elif opt in ("-j", "--json"):
+         json_path = arg
    print('Input file is "', inputfile)
    print('Output file is "', outputfile)
+   print('JSON file is "', json_path)
 
-   fun2method(inputfile, outputfile)
+   fun2method(inputfile, outputfile, json_path)
 
 if __name__ == "__main__":
    main(sys.argv[1:])
@@ -187,6 +195,7 @@ if __name__ == "__main__":
 
 
 
+
 # cat /home/soillpi/workstation/jip/mia//core/c/miallib_*.h | grep '^extern ERROR'  > miallib_error_type_nm
 # cat /home/soillpi/work/jip20170201/mia//core/c/miallib_*.h | grep '^extern ERROR'  > miallib_error_type_nm
 # cat /usr/local/include/miallib/miallib_*.h | grep '^extern ERROR'  > miallib_error_type_nm


=====================================
src/imageclasses/fun2method_errortype_nd.py
=====================================
@@ -1,8 +1,7 @@
 # first 20161111 by Pierre.Soille at jrc.ec.europa.eu
 # 20170216 Pieter Kempeneers: adapted for functions that do not modify the input image
 
-
-def fun2method(inputfile, outputfile_basename):
+def fun2method(inputfile, outputfile_basename, json_path):
     """converts MIALib C function declarations into JIPLib C++ methods (outputfile_basename.cc file) and C++ method declarations (outputfile_basename.h file).  Currently only convert desctuctive functions, i.e., ERROR_TYPE functions, with IMAGE * as first argument (IMAGE ** not yet taken into account).
 
     :param inputfile: string for input file containing extern declarations
@@ -14,7 +13,12 @@ def fun2method(inputfile, outputfile_basename):
 
     import re
     import json
-    old2newDic = json.load(open("old2NewNames.json"))
+    import sys 
+    import os
+    with open(json_path, 'r') as f:
+        old2newDic = json.load(f)
+
+    #old2newDic = json.load(open("old2NewNames.json"))
 
     ifp=open(inputfile, 'r')
 
@@ -174,23 +178,27 @@ import sys, getopt
 def main(argv):
    inputfile="miallib_errortype_nd"
    outputfile="fun2method_errortype_nd"
+   json_path = "old2NewNames.json"
    try:
-      opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="])
+       opts, args = getopt.getopt(argv,"hi:o:j:",["ifile=","ofile=", "json="])
    except getopt.GetoptError:
-      print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+      print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
       sys.exit(2)
    for opt, arg in opts:
       if opt == '-h':
-         print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+         print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
          sys.exit()
       elif opt in ("-i", "--ifile"):
          inputfile = arg
       elif opt in ("-o", "--ofile"):
          outputfile = arg
+      elif opt in ("-j", "--json"):
+         json_path = arg
    print('Input file is "', inputfile)
    print('Output file is "', outputfile)
+   print('JSON file is "', json_path)
 
-   fun2method(inputfile, outputfile)
+   fun2method(inputfile, outputfile, json_path)
 
 if __name__ == "__main__":
    main(sys.argv[1:])


=====================================
src/imageclasses/fun2method_errortype_nm.py
=====================================
@@ -1,6 +1,6 @@
 # first 20190808 by pieter.kempeneers at jrc.ec.europa.eu
 
-def fun2method(inputfile, outputfile_basename):
+def fun2method(inputfile, outputfile_basename, json_path):
     """converts MIALib C function declarations into JIPLib C++ methods (outputfile_basename.cc file) and C++ method declarations (outputfile_basename.h file). Convert desctuctive functions that do not support multi-band processing.
 
     :param inputfile: string for input file containing extern declarations
@@ -12,10 +12,15 @@ def fun2method(inputfile, outputfile_basename):
 
     import re
     import json
+    import sys 
+    import os
+    with open(json_path, 'r') as f:
+        old2newDic = json.load(f)
+
     # for writing a dictionary in json file
     #j son.dump(old2NewDict, open("text.txt",'w'))
     # reading dictionary in json file
-    old2newDic = json.load(open("old2NewNames.json"))
+    #old2newDic = json.load(open("old2NewNames.json"))
 
     ifp=open(inputfile, 'r')
 
@@ -177,23 +182,27 @@ import sys, getopt
 def main(argv):
    inputfile="miallib_errortype_nm"
    outputfile="fun2method_errortype_nm"
+   json_path = "old2NewNames.json"
    try:
-      opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="])
+       opts, args = getopt.getopt(argv,"hi:o:j:",["ifile=","ofile=", "json="])
    except getopt.GetoptError:
-      print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+      print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
       sys.exit(2)
    for opt, arg in opts:
       if opt == '-h':
-         print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+         print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
          sys.exit()
       elif opt in ("-i", "--ifile"):
          inputfile = arg
       elif opt in ("-o", "--ofile"):
          outputfile = arg
+      elif opt in ("-j", "--json"):
+         json_path = arg
    print('Input file is "', inputfile)
    print('Output file is "', outputfile)
+   print('JSON file is "', json_path)
 
-   fun2method(inputfile, outputfile)
+   fun2method(inputfile, outputfile, json_path)
 
 if __name__ == "__main__":
    main(sys.argv[1:])


=====================================
src/imageclasses/fun2method_imagelisttype.py
=====================================
@@ -1,7 +1,6 @@
 # first 20172403 by pieter.kempeneers at ec.europa.eu
 
-
-def fun2method(inputfile, outputfile_basename):
+def fun2method(inputfile, outputfile_basename, json_path):
     """converts MIALib C function declarations into JIPLib C++ methods (outputfile_basename.cc file) and C++ method declarations (outputfile_basename.h file).  Currently only convert desctuctive functions, i.e., ERROR_TYPE functions, with IMAGE * as first argument (IMAGE ** not yet taken into account).
 
     :param inputfile: string for input file containing extern declarations
@@ -13,7 +12,12 @@ def fun2method(inputfile, outputfile_basename):
 
     import re
     import json
-    old2newDic = json.load(open("old2NewNames.json"))
+    import sys 
+    import os
+    with open(json_path, 'r') as f:
+        old2newDic = json.load(f)
+
+    #old2newDic = json.load(open("old2NewNames.json"))
 
     ifp=open(inputfile, 'r')
 
@@ -179,23 +183,27 @@ import sys, getopt
 def main(argv):
    inputfile="miallib_imagelisttype"
    outputfile="fun2method_imagelisttype"
+   json_path = "old2NewNames.json"
    try:
-      opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="])
+       opts, args = getopt.getopt(argv,"hi:o:j:",["ifile=","ofile=", "json="])
    except getopt.GetoptError:
-      print('fun2method_imagelisttype.py -i <inputfile> -o <outputfilebasename>')
+      print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
       sys.exit(2)
    for opt, arg in opts:
       if opt == '-h':
-         print('fun2method_imagelisttype.py -i <inputfile> -o <outputfilebasename>')
+         print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
          sys.exit()
       elif opt in ("-i", "--ifile"):
          inputfile = arg
       elif opt in ("-o", "--ofile"):
          outputfile = arg
+      elif opt in ("-j", "--json"):
+         json_path = arg
    print('Input file is "', inputfile)
    print('Output file is "', outputfile)
+   print('JSON file is "', json_path)
 
-   fun2method(inputfile, outputfile)
+   fun2method(inputfile, outputfile, json_path)
 
 if __name__ == "__main__":
    main(sys.argv[1:])


=====================================
src/imageclasses/fun2method_imagetype.py
=====================================
@@ -1,7 +1,6 @@
 # first 20161111 by Pierre.Soille at jrc.ec.europa.eu
 
-
-def fun2method(inputfile, outputfile_basename):
+def fun2method(inputfile, outputfile_basename, json_path):
     """converts MIALib C function declarations into JIPLib C++ methods (outputfile_basename.cc file) and C++ method declarations (outputfile_basename.h file).  Currently only convert desctuctive functions, i.e., ERROR_TYPE functions, with IMAGE * as first argument (IMAGE ** not yet taken into account).
 
     :param inputfile: string for input file containing extern declarations
@@ -13,7 +12,13 @@ def fun2method(inputfile, outputfile_basename):
 
     import re
     import json
-    old2newDic = json.load(open("old2NewNames.json"))
+    import sys 
+    import os
+    #json_path = sys.argv[3] # or adjust based on your arg parsing
+    with open(json_path, 'r') as f:
+        old2newDic = json.load(f)
+
+    #old2newDic = json.load(open("old2NewNames.json"))
 
     ifp=open(inputfile, 'r')
 
@@ -178,23 +183,27 @@ import sys, getopt
 def main(argv):
    inputfile="miallib_imagetype"
    outputfile="fun2method_imagetype"
+   json_path = "old2NewNames.json"
    try:
-      opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="])
+       opts, args = getopt.getopt(argv,"hi:o:j:",["ifile=","ofile=", "json="])
    except getopt.GetoptError:
-      print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+      print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
       sys.exit(2)
    for opt, arg in opts:
       if opt == '-h':
-         print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+         print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
          sys.exit()
       elif opt in ("-i", "--ifile"):
          inputfile = arg
       elif opt in ("-o", "--ofile"):
          outputfile = arg
+      elif opt in ("-j", "--json"):
+         json_path = arg
    print('Input file is "', inputfile)
    print('Output file is "', outputfile)
+   print('JSON file is "', json_path)
 
-   fun2method(inputfile, outputfile)
+   fun2method(inputfile, outputfile, json_path)
 
 if __name__ == "__main__":
    main(sys.argv[1:])


=====================================
src/imageclasses/fun2method_imagetype_jimlist.py
=====================================
@@ -1,7 +1,6 @@
 # first 20170830 by pieter.kempeneers at ec.europa.eu
 
-
-def fun2method(inputfile, outputfile_basename):
+def fun2method(inputfile, outputfile_basename, json_path):
     """converts MIALib C function declarations into JIPLib C++ methods (outputfile_basename.cc file) and C++ method declarations (outputfile_basename.h file).  Currently only convert desctuctive functions, i.e., ERROR_TYPE functions, with IMAGE ** as first argument
 
     :param inputfile: string for input file containing extern declarations
@@ -13,7 +12,12 @@ def fun2method(inputfile, outputfile_basename):
 
     import re
     import json
-    old2newDic = json.load(open("old2NewNames.json"))
+    import sys 
+    import os
+    with open(json_path, 'r') as f:
+        old2newDic = json.load(f)
+
+    #old2newDic = json.load(open("old2NewNames.json"))
 
     ifp=open(inputfile, 'r')
 
@@ -179,23 +183,27 @@ import sys, getopt
 def main(argv):
    inputfile="miallib_imagetype"
    outputfile="fun2method_imagetype_jimlist"
+   json_path = "old2NewNames.json"
    try:
-      opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="])
+       opts, args = getopt.getopt(argv,"hi:o:j:",["ifile=","ofile=", "json="])
    except getopt.GetoptError:
-      print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+      print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
       sys.exit(2)
    for opt, arg in opts:
       if opt == '-h':
-         print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+         print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
          sys.exit()
       elif opt in ("-i", "--ifile"):
          inputfile = arg
       elif opt in ("-o", "--ofile"):
          outputfile = arg
+      elif opt in ("-j", "--json"):
+         json_path = arg
    print('Input file is "', inputfile)
    print('Output file is "', outputfile)
+   print('JSON file is "', json_path)
 
-   fun2method(inputfile, outputfile)
+   fun2method(inputfile, outputfile, json_path)
 
 if __name__ == "__main__":
    main(sys.argv[1:])


=====================================
src/imageclasses/fun2method_imagetype_multi.py
=====================================
@@ -1,7 +1,6 @@
 # first 20170830 by pieter.kempeneers at ec.europa.eu
 
-
-def fun2method(inputfile, outputfile_basename):
+def fun2method(inputfile, outputfile_basename, json_path):
     """converts MIALib C function declarations into JIPLib C++ methods (outputfile_basename.cc file) and C++ method declarations (outputfile_basename.h file).  Currently only convert desctuctive functions, i.e., ERROR_TYPE functions, with IMAGE ** as first argument
 
     :param inputfile: string for input file containing extern declarations
@@ -13,7 +12,12 @@ def fun2method(inputfile, outputfile_basename):
 
     import re
     import json
-    old2newDic = json.load(open("old2NewNames.json"))
+    import sys 
+    import os
+    with open(json_path, 'r') as f:
+        old2newDic = json.load(f)
+
+    #old2newDic = json.load(open("old2NewNames.json"))
 
     ifp=open(inputfile, 'r')
 
@@ -177,23 +181,27 @@ import sys, getopt
 def main(argv):
    inputfile="miallib_imagetype"
    outputfile="fun2method_imagetype_multi"
+   json_path = "old2NewNames.json"
    try:
-      opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="])
+       opts, args = getopt.getopt(argv,"hi:o:j:",["ifile=","ofile=", "json="])
    except getopt.GetoptError:
-      print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+      print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
       sys.exit(2)
    for opt, arg in opts:
       if opt == '-h':
-         print('fun2method.py -i <inputfile> -o <outputfilebasename>')
+         print('fun2method.py -i <inputfile> -o <outputfilebasename> -j <json_path>')
          sys.exit()
       elif opt in ("-i", "--ifile"):
          inputfile = arg
       elif opt in ("-o", "--ofile"):
          outputfile = arg
+      elif opt in ("-j", "--json"):
+         json_path = arg
    print('Input file is "', inputfile)
    print('Output file is "', outputfile)
+   print('JSON file is "', json_path)
 
-   fun2method(inputfile, outputfile)
+   fun2method(inputfile, outputfile, json_path)
 
 if __name__ == "__main__":
    main(sys.argv[1:])


=====================================
src/imageclasses/jlextractimg_lib.h
=====================================
@@ -21,6 +21,10 @@ along with jiplib.  If not, see <https://www.gnu.org/licenses/>.
 #ifndef _JLEXTRACTIMG_LIB_H_
 #define _JLEXTRACTIMG_LIB_H_
 
+#include <random>
+#if JIPLIB_PROCESS_IN_PARALLEL == 1
+    #include <omp.h>
+#endif
 #include "imageclasses/Jim.h"
 #include "imageclasses/VectorOgr.h"
 #include "apps/AppFactory.h"
@@ -276,23 +280,42 @@ template<typename T> void Jim::extractImg_t(Jim& classReader, VectorOgr& ogrWrit
     if(threshold_opt[0]!=100){
       //todo (optimization): if selection is small, better select random sample than shuffle all...
 #if JIPLIB_PROCESS_IN_PARALLEL == 1
-#pragma omp parallel for
-#else
-#endif
-      for(unsigned short iclass=0;iclass<nclass;++iclass){
-        if(verbose_opt[0]){
-          if(nvalid[iclass]){
-            std::cout << "nvalid[" << iclass << "]: " << nvalid[iclass] << std::endl;
-            std::cout << "ninvalid[" << iclass << "]: " << ninvalid[iclass] << std::endl;
+#pragma omp parallel
+      {
+        // Each thread gets its own generator instance, seeded uniquely
+        // We use thread ID to ensure each thread shuffles differently
+        std::random_device rd;
+        std::mt19937 g(rd() ^ omp_get_thread_num()); 
+    
+        #pragma omp for
+        for(unsigned short iclass=0; iclass<nclass; ++iclass) {
+          if(verbose_opt[0]){
+            if(nvalid[iclass]){
+              std::cout << "nvalid[" << iclass << "]: " << nvalid[iclass] << std::endl;
+              std::cout << "ninvalid[" << iclass << "]: " << ninvalid[iclass] << std::endl;
+            }
+          }
+          if(sample[iclass].size()) {
+            std::shuffle(sample[iclass].begin(), sample[iclass].end(), g);
           }
         }
-        if(sample[iclass].size()){
+      }
+#else
+      // Serial fallback
+      std::random_device rd;
+      std::mt19937 g(rd());
+      for(unsigned short iclass=0; iclass<nclass; ++iclass) {
           if(verbose_opt[0]){
-            std::cout << "random shuffle class " << iclass << " with size " << sample[iclass].size() << std::endl;
+            if(nvalid[iclass]){
+              std::cout << "nvalid[" << iclass << "]: " << nvalid[iclass] << std::endl;
+              std::cout << "ninvalid[" << iclass << "]: " << ninvalid[iclass] << std::endl;
+            }
+          }
+          if(sample[iclass].size()) {
+              std::shuffle(sample[iclass].begin(), sample[iclass].end(), g);
           }
-          std::random_shuffle(sample[iclass].begin(), sample[iclass].end());
-        }
       }
+#endif
     }
 
     size_t fid=0;//unique field identifier


=====================================
src/imageclasses/jlstat_lib.cc
=====================================
@@ -924,7 +924,7 @@ std::multimap<std::string,std::string> JimList::getStats(AppFactory& app){
       for(int inodata=0;inodata<nodata_opt.size();++inodata){
         if(!inodata){
           getImage(0)->GDALSetNoDataValue(nodata_opt[0],band_opt[0]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
-          getImage(1)->GDALSetNoDataValue(nodata_opt[0]),band_opt[1];//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
+          getImage(1)->GDALSetNoDataValue(nodata_opt[0],band_opt[1]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
         }
         getImage(0)->pushNoDataValue(nodata_opt[inodata]);
         getImage(1)->pushNoDataValue(nodata_opt[inodata]);
@@ -971,7 +971,7 @@ std::multimap<std::string,std::string> JimList::getStats(AppFactory& app){
       for(int inodata=0;inodata<nodata_opt.size();++inodata){
         if(!inodata){
           getImage(0)->GDALSetNoDataValue(nodata_opt[0],band_opt[0]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
-          getImage(1)->GDALSetNoDataValue(nodata_opt[0]),band_opt[1];//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
+          getImage(1)->GDALSetNoDataValue(nodata_opt[0],band_opt[1]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
         }
         getImage(0)->pushNoDataValue(nodata_opt[inodata]);
         getImage(1)->pushNoDataValue(nodata_opt[inodata]);
@@ -1018,7 +1018,7 @@ std::multimap<std::string,std::string> JimList::getStats(AppFactory& app){
       for(int inodata=0;inodata<nodata_opt.size();++inodata){
         if(!inodata){
           getImage(0)->GDALSetNoDataValue(nodata_opt[0],band_opt[0]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
-          getImage(1)->GDALSetNoDataValue(nodata_opt[0]),band_opt[1];//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
+          getImage(1)->GDALSetNoDataValue(nodata_opt[0],band_opt[1]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
         }
         getImage(0)->pushNoDataValue(nodata_opt[inodata]);
         getImage(1)->pushNoDataValue(nodata_opt[inodata]);
@@ -1065,7 +1065,7 @@ std::multimap<std::string,std::string> JimList::getStats(AppFactory& app){
       for(int inodata=0;inodata<nodata_opt.size();++inodata){
         if(!inodata){
           getImage(0)->GDALSetNoDataValue(nodata_opt[0],band_opt[0]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
-          getImage(1)->GDALSetNoDataValue(nodata_opt[0]),band_opt[1];//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
+          getImage(1)->GDALSetNoDataValue(nodata_opt[0],band_opt[1]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
         }
         getImage(0)->pushNoDataValue(nodata_opt[inodata]);
         getImage(1)->pushNoDataValue(nodata_opt[inodata]);
@@ -1104,7 +1104,7 @@ std::multimap<std::string,std::string> JimList::getStats(AppFactory& app){
       for(int inodata=0;inodata<nodata_opt.size();++inodata){
         if(!inodata){
           getImage(0)->GDALSetNoDataValue(nodata_opt[0],band_opt[0]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
-          getImage(1)->GDALSetNoDataValue(nodata_opt[0]),band_opt[1];//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
+          getImage(1)->GDALSetNoDataValue(nodata_opt[0],band_opt[1]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
         }
         getImage(0)->pushNoDataValue(nodata_opt[inodata]);
         getImage(1)->pushNoDataValue(nodata_opt[inodata]);


=====================================
src/python/__init__.py
=====================================
@@ -23,4 +23,4 @@ from __future__ import absolute_import
 from .jiplib import *
 
 
-__version__ = '1.1.7'
+__version__ = '1.2.0'


=====================================
src/python/setup.py
=====================================
@@ -27,7 +27,7 @@ from setuptools import find_packages
 
 setup(
     name='jiplib',
-    version='1.1.7',
+    version='1.2.0',
     author='Pieter Kempeneers',
     author_email='pieter.kempeneers at ec.europa.eu',
     url='https://jeodpp.jrc.ec.europa.eu/apps/gitlab/JIPlib/jiplib',



View it on GitLab: https://salsa.debian.org/debian-gis-team/jeolib-jiplib/-/commit/72afd06fff73bcdad8170b7e91a8dce6723aaf2f

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/jeolib-jiplib/-/commit/72afd06fff73bcdad8170b7e91a8dce6723aaf2f
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20260724/b4aa7d52/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list