├── CMakeLists.txt ├── Doxyfile.in ├── README.md ├── cmake └── LibOctDataConfig.cmake ├── cmake_module ├── GetGitRevisionDescription.cmake └── GetGitRevisionDescription.cmake.in ├── licence.txt ├── main.cpp └── octdata ├── buildconstants.cpp.in ├── buildconstants.h ├── datastruct ├── analysegrid.cpp ├── analysegrid.h ├── bscan.cpp ├── bscan.h ├── coordslo.h ├── date.cpp ├── date.h ├── objectwrapper.h ├── oct.cpp ├── oct.h ├── patient.cpp ├── patient.h ├── segmentationlines.cpp ├── segmentationlines.h ├── series.cpp ├── series.h ├── sloimage.cpp ├── sloimage.h ├── study.h └── substructure_template.h ├── export ├── cirrus_raw │ ├── cirrusrawexport.cpp │ └── cirrusrawexport.h ├── cvbin │ ├── cvbinoctwrite.cpp │ └── cvbinoctwrite.h └── xoct │ ├── xoctwrite.cpp │ └── xoctwrite.h ├── filereader ├── filereader.cpp ├── filereader.h ├── filestreamdircet.cpp ├── filestreamdircet.h ├── filestreamgzip.cpp └── filestreamgzip.h ├── filereadoptions.cpp ├── filereadoptions.h ├── filewriteoptions.cpp ├── filewriteoptions.h ├── import ├── cirrus_raw │ ├── cirrus_rawread.cpp │ └── cirrus_rawread.h ├── cvbin │ ├── cvbinread.cpp │ └── cvbinread.h ├── dicom │ ├── dicomread.cpp │ └── dicomread.h ├── gipl │ ├── giplread.cpp │ └── giplread.h ├── he_e2e │ ├── he_e2eread.cpp │ ├── he_e2eread.h │ ├── he_gray_transform.cpp │ └── he_gray_transform.h ├── he_vol │ ├── volread.cpp │ └── volread.h ├── he_xml │ ├── he_xmlread.cpp │ └── he_xmlread.h ├── oct │ ├── octfileread.cpp │ └── octfileread.h ├── octfilereader.cpp ├── octfilereader.h ├── platform_helper.h ├── tiffstack │ ├── tiffstackread.cpp │ └── tiffstackread.h ├── topcon │ ├── readjpeg2k.cpp │ ├── readjpeg2k.h │ ├── topcondata.cpp │ ├── topcondata.h │ ├── topconread.cpp │ └── topconread.h └── xoct │ ├── xoctread.cpp │ └── xoctread.h ├── octdata_packhelper.h ├── octextension.h ├── octfileread.cpp └── octfileread.h /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) 2 | project(liboctdata) 3 | include(GenerateExportHeader) 4 | 5 | set( CMAKE_CXX_STANDARD 11 ) 6 | 7 | # set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 8 | # set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 9 | 10 | 11 | set(liboctdata_VERSION 1.0.0) 12 | set(CMAKE_DEBUG_POSTFIX "-d") 13 | 14 | 15 | # 16 | # Build options 17 | # 18 | option(BUILD_WITH_SUPPORT_HE_E2E "build support for nativ heidelberg spectralis format (E2E, SDB)" ON) 19 | option(BUILD_WITH_SUPPORT_HE_VOL "build support for heidelberg spectralis vol format" ON) 20 | option(BUILD_WITH_SUPPORT_HE_XML "build support for heidelberg spectralis xml export" ON) 21 | option(BUILD_WITH_SUPPORT_DICOM "build support for dicom format (cirrus, experimental)" OFF) 22 | option(BUILD_WITH_SUPPORT_TIFFSTACK "build support for tiffstack" ON) 23 | option(BUILD_WITH_SUPPORT_CVBIN "build support for cvbin import" ON) 24 | option(BUILD_WITH_SUPPORT_XOCT "build support for xoct import" ON) 25 | option(BUILD_WITH_SUPPORT_CI_RAW "build support for cirrus raw files" ON) 26 | option(BUILD_WITH_SUPPORT_OCT_FILE "build support for oct format" ON) 27 | option(BUILD_WITH_SUPPORT_TOPCON "build support for topcon format" ON) 28 | option(BUILD_WITH_SUPPORT_GIPL "build support for gipl format" ON) 29 | option(BUILD_WITH_ZLIB "build the programms with ZLIB" ON) 30 | 31 | 32 | # General build config 33 | set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel.") 34 | 35 | set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake_module/) 36 | 37 | 38 | find_package(OctCppFramework REQUIRED) 39 | 40 | 41 | if(${WIN32}) 42 | # set(Boost_DEBUG ON) 43 | # set(Boost_LIB_PREFIX "libboost") 44 | else() 45 | ADD_DEFINITIONS(-DBOOST_LOG_DYN_LINK) 46 | endif() 47 | 48 | 49 | 50 | find_package(Boost 1.40 COMPONENTS filesystem system locale log serialization REQUIRED) 51 | find_package(OpenCV REQUIRED) 52 | string(TIMESTAMP CMAKE_CONFIGURE_TIME "%Y-%m-%dT%H:%M:%SZ" UTC) 53 | 54 | 55 | include(GetGitRevisionDescription) 56 | get_git_head_revision(GIT_REFSPEC GIT_SHA1) 57 | 58 | 59 | if(BUILD_WITH_SUPPORT_CVBIN) 60 | list(APPEND import_srcs import/cvbin) 61 | add_definitions(-DCVBIN_SUPPORT) 62 | endif() 63 | 64 | if(BUILD_WITH_SUPPORT_DICOM) 65 | find_package(DCMTK REQUIRED) 66 | find_package(OpenJPEG) 67 | list(APPEND import_srcs import/dicom) 68 | include_directories(SYSTEM ${DCMTK_INCLUDE_DIRS}) 69 | 70 | add_definitions(-DDICOM_SUPPORT) 71 | 72 | if(DEFINED OpenJPEG_FOUND) 73 | add_definitions(-DDICOM_JPEG2K_SUPPORT) 74 | endif() 75 | endif() 76 | 77 | 78 | if(BUILD_WITH_SUPPORT_CI_RAW) 79 | list(APPEND import_srcs import/cirrus_raw) 80 | add_definitions(-DCIRRUS_RAW_SUPPORT) 81 | endif() 82 | 83 | 84 | if(BUILD_WITH_SUPPORT_HE_E2E) 85 | find_package(LibE2E REQUIRED) 86 | list(APPEND import_srcs import/he_e2e) 87 | 88 | add_definitions(-DHE_E2E_SUPPORT) 89 | endif() 90 | 91 | 92 | if(BUILD_WITH_SUPPORT_HE_VOL) 93 | list(APPEND import_srcs import/he_vol) 94 | 95 | add_definitions(-DHE_VOL_SUPPORT) 96 | endif() 97 | 98 | if(BUILD_WITH_SUPPORT_OCT_FILE) 99 | list(APPEND import_srcs import/oct) 100 | 101 | add_definitions(-DOCT_FILE_SUPPORT) 102 | endif() 103 | 104 | if(BUILD_WITH_SUPPORT_TOPCON) 105 | find_package(OpenJPEG REQUIRED) 106 | if(DEFINED OpenJPEG_FOUND) 107 | add_definitions(-DDICOM_JPEG2K_SUPPORT) 108 | list(APPEND import_srcs import/topcon) 109 | add_definitions(-DTOPCON_FILE_SUPPORT) 110 | include_directories(SYSTEM ${OPENJPEG_INCLUDE_DIRS}) 111 | message(${OPENJPEG_INCLUDE_DIRS}) 112 | endif() 113 | endif() 114 | 115 | if(BUILD_WITH_SUPPORT_GIPL) 116 | list(APPEND import_srcs import/gipl) 117 | 118 | add_definitions(-DGIPL_SUPPORT) 119 | endif() 120 | 121 | if(BUILD_WITH_SUPPORT_HE_XML) 122 | list(APPEND import_srcs import/he_xml) 123 | 124 | add_definitions(-DHE_XML_SUPPORT) 125 | endif() 126 | 127 | 128 | if(BUILD_WITH_SUPPORT_TIFFSTACK) 129 | find_package(TIFF REQUIRED) 130 | list(APPEND import_srcs import/tiffstack) 131 | 132 | add_definitions(-DTIFFSTACK_SUPPORT) 133 | endif() 134 | 135 | if(BUILD_WITH_SUPPORT_XOCT) 136 | if(!BUILD_WITH_ZLIB) 137 | message(FATAL_ERROR, "xoct need zlib") 138 | endif() 139 | list(APPEND import_srcs import/xoct) 140 | 141 | add_definitions(-DXOCT_SUPPORT) 142 | endif() 143 | 144 | if(BUILD_WITH_ZLIB) 145 | find_package(ZLIB REQUIRED) 146 | include_directories(${ZLIB_INCLUDE_DIRS}) 147 | add_definitions(-DWITH_ZLIB) 148 | endif() 149 | 150 | 151 | if(NOT CMAKE_BUILD_TYPE) 152 | set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) 153 | endif(NOT CMAKE_BUILD_TYPE) 154 | 155 | add_definitions(-DNOCRYPT) # no crypt in zip 156 | 157 | include_directories(SYSTEM ${CMAKE_BINARY_DIR}) 158 | include_directories(${CMAKE_SOURCE_DIR}/octdata/) 159 | include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) 160 | include_directories(SYSTEM ${TIFF_INCLUDE_DIRS}) 161 | include_directories(${OpenCV_INCLUDE_DIRS}) 162 | 163 | if(CMAKE_COMPILER_IS_GNUCXX) 164 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra -Wunreachable-code -Werror -Wconversion -Wold-style-cast") ## -Weverything 165 | set(CMAKE_CFLAGS "${CMAKE_CFLAGS} -fPIC") 166 | 167 | if(${WIN32}) 168 | set(CMAKE_CXX_FLAGS "-mno-ms-bitfields -static -static-libstdc++ ${CMAKE_CXX_FLAGS}") 169 | endif() 170 | endif() 171 | 172 | 173 | file(GLOB liboctdata_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/octdata/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/octdata/**/*.cpp") 174 | 175 | configure_file("${CMAKE_CURRENT_SOURCE_DIR}/octdata/buildconstants.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/buildconstants.cpp" @ONLY) 176 | list(APPEND liboctdata_SRCS "${CMAKE_CURRENT_BINARY_DIR}/buildconstants.cpp") 177 | 178 | 179 | set(srcs_directories datastruct ${import_srcs} "export/cvbin" "export/cirrus_raw" "export/xoct") 180 | foreach(loop_var ${srcs_directories}) 181 | file(GLOB sources_base "${CMAKE_CURRENT_SOURCE_DIR}/octdata/${loop_var}/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/octdata/${loop_var}/*.c") 182 | list(APPEND liboctdata_SRCS ${sources} ${sources_base}) 183 | endforeach(loop_var) 184 | 185 | 186 | # hack for qtcreator (show header files) 187 | FILE(GLOB_RECURSE includefiles "octdata/*.h") 188 | add_custom_target(headers SOURCES ${includefiles}) 189 | 190 | 191 | add_library(octdata SHARED ${liboctdata_SRCS}) 192 | 193 | 194 | IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" ) 195 | SET_TARGET_PROPERTIES(octdata PROPERTIES COMPILE_FLAGS "-fPIC") 196 | ENDIF( CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" ) 197 | 198 | 199 | # add a target to generate API documentation with Doxygen 200 | # find_package(Doxygen) 201 | # if(DOXYGEN_FOUND) 202 | # configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) 203 | # add_custom_target(doc 204 | # ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 205 | # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 206 | # COMMENT "Generating API documentation with Doxygen" VERBATIM 207 | # ) 208 | # endif(DOXYGEN_FOUND) 209 | 210 | 211 | if(DEFINED DCMTK_FOUND) 212 | add_definitions(-DUSE_DCMTK) 213 | target_link_libraries(octdata PRIVATE ${DCMTK_LIBRARIES}) 214 | endif() 215 | 216 | target_link_libraries(octdata PRIVATE ${OPENJPEG_LIBRARIES} ${TIFF_LIBRARIES} ${OpenCV_LIBRARIES} ${Boost_LIBRARIES} ${ZLIB_LIBRARIES}) 217 | 218 | target_link_libraries(octdata PRIVATE OctCppFramework::oct_cpp_framework) 219 | if(BUILD_WITH_SUPPORT_HE_E2E) 220 | target_link_libraries(octdata PRIVATE LibE2E::libe2e) 221 | endif() 222 | 223 | 224 | 225 | GENERATE_EXPORT_HEADER(octdata # generates the export header shared_EXPORTS.h automatically 226 | BASE_NAME octdata 227 | EXPORT_MACRO_NAME Octdata_EXPORTS 228 | EXPORT_FILE_NAME octdata_EXPORTS.h 229 | STATIC_DEFINE SHARED_EXPORTS_BUILT_AS_STATIC) 230 | 231 | 232 | add_definitions(-DOCTDATA_EXPORT) 233 | 234 | add_executable(liboctdata_test main.cpp) 235 | target_link_libraries(liboctdata_test octdata ${OpenCV_LIBRARIES} ) 236 | 237 | 238 | 239 | set_property(TARGET octdata PROPERTY VERSION ${liboctdata_VERSION}) 240 | set_property(TARGET octdata PROPERTY SOVERSION 1) 241 | set_property(TARGET octdata PROPERTY INTERFACE_liboctdata_MAJOR_VERSION 1) 242 | set_property(TARGET octdata APPEND PROPERTY COMPATIBLE_INTERFACE_STRING liboctdata_MAJOR_VERSION) 243 | 244 | install(TARGETS octdata EXPORT LibOctDataTargets 245 | LIBRARY DESTINATION lib 246 | ARCHIVE DESTINATION lib 247 | RUNTIME DESTINATION bin 248 | INCLUDES DESTINATION include 249 | ) 250 | 251 | file(GLOB liboctdata_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/octdata/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/octdata/datastruct/*.h") 252 | install( 253 | FILES 254 | ${liboctdata_HEADERS} 255 | "${CMAKE_CURRENT_BINARY_DIR}/octdata_export.h" 256 | DESTINATION 257 | include 258 | COMPONENT 259 | Devel 260 | ) 261 | 262 | include(CMakePackageConfigHelpers) 263 | write_basic_package_version_file( 264 | "${CMAKE_CURRENT_BINARY_DIR}/liboctdata/LibOctDataConfigVersion.cmake" 265 | VERSION ${liboctdata_VERSION} 266 | COMPATIBILITY AnyNewerVersion 267 | ) 268 | 269 | export(EXPORT LibOctDataTargets 270 | FILE "${CMAKE_CURRENT_BINARY_DIR}/liboctdata/LibOctDataTargets.cmake" 271 | NAMESPACE LibOctData:: 272 | ) 273 | configure_file(cmake/LibOctDataConfig.cmake 274 | "${CMAKE_CURRENT_BINARY_DIR}/liboctdata/LibOctDataConfig.cmake" 275 | COPY_ONLY 276 | ) 277 | 278 | target_include_directories( 279 | octdata PUBLIC 280 | "$" 281 | "$" 282 | ) 283 | 284 | set(ConfigPackageLocation lib/cmake/liboctdata) 285 | 286 | install(EXPORT LibOctDataTargets 287 | FILE 288 | LibOctDataTargets.cmake 289 | NAMESPACE 290 | LibOctData:: 291 | DESTINATION 292 | ${ConfigPackageLocation} 293 | ) 294 | install( 295 | FILES 296 | cmake/LibOctDataConfig.cmake 297 | "${CMAKE_CURRENT_BINARY_DIR}/liboctdata/LibOctDataConfigVersion.cmake" 298 | DESTINATION 299 | ${ConfigPackageLocation} 300 | COMPONENT 301 | Devel 302 | ) 303 | 304 | export(PACKAGE LibOctData) 305 | -------------------------------------------------------------------------------- /Doxyfile.in: -------------------------------------------------------------------------------- 1 | INPUT = @CMAKE_CURRENT_SOURCE_DIR@/octdata/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LibOctData 2 | 3 | a library for reading different OCT file formats 4 | 5 | It supports the following formats 6 | 7 | * Heidelberg Engineering Xml File (xml + tiff) 8 | * Heidelberg Engineering Raw File (vol) 9 | * nativ Heidelberg Engineering format (E2E, sdb) (with LibE2E) 10 | * Topcon (fda) (thanks to the uoct project for documentation) 11 | * Bioptigen Oct file (OCT) 12 | * Cirrus Dicom (dicom) (highly experimental, mostly with huge artefacts in the images) 13 | * Cirrus IMG export files (img) 14 | * Guys Image Processing Lab Format (gipl) 15 | * Tiff-Stack (tiff) 16 | 17 | and the own defined formats (with export support) 18 | 19 | * XOCT (xml metadata with images (mostly png) in a zip file) 20 | * octbin (simple binary format for easy handling with matlab/octave) 21 | 22 | Note that the most some file formats are reverse engineered and we have no guarantee that the information from the import are correct. 23 | 24 | ## License 25 | 26 | This project is licensed under the LGPL3 License - see [license.txt](license.txt) file for details 27 | 28 | ## Build 29 | 30 | for build instructions see the readme from the OCT-Marker project -------------------------------------------------------------------------------- /cmake/LibOctDataConfig.cmake: -------------------------------------------------------------------------------- 1 | include("${CMAKE_CURRENT_BINARY_DIR}/liboctdata/LibOctDataTargets.cmake") 2 | -------------------------------------------------------------------------------- /cmake_module/GetGitRevisionDescription.cmake: -------------------------------------------------------------------------------- 1 | # - Returns a version string from Git 2 | # 3 | # These functions force a re-configure on each git commit so that you can 4 | # trust the values of the variables in your build system. 5 | # 6 | # get_git_head_revision( [ ...]) 7 | # 8 | # Returns the refspec and sha hash of the current head revision 9 | # 10 | # git_describe( [ ...]) 11 | # 12 | # Returns the results of git describe on the source tree, and adjusting 13 | # the output so that it tests false if an error occurs. 14 | # 15 | # git_get_exact_tag( [ ...]) 16 | # 17 | # Returns the results of git describe --exact-match on the source tree, 18 | # and adjusting the output so that it tests false if there was no exact 19 | # matching tag. 20 | # 21 | # Requires CMake 2.6 or newer (uses the 'function' command) 22 | # 23 | # Original Author: 24 | # 2009-2010 Ryan Pavlik 25 | # http://academic.cleardefinition.com 26 | # Iowa State University HCI Graduate Program/VRAC 27 | # 28 | # Copyright Iowa State University 2009-2010. 29 | # Distributed under the Boost Software License, Version 1.0. 30 | # (See accompanying file LICENSE_1_0.txt or copy at 31 | # http://www.boost.org/LICENSE_1_0.txt) 32 | 33 | if(__get_git_revision_description) 34 | return() 35 | endif() 36 | set(__get_git_revision_description YES) 37 | 38 | # We must run the following at "include" time, not at function call time, 39 | # to find the path to this module rather than the path to a calling list file 40 | get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) 41 | 42 | function(get_git_head_revision _refspecvar _hashvar) 43 | set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") 44 | set(GIT_DIR "${GIT_PARENT_DIR}/.git") 45 | while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories 46 | set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") 47 | get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) 48 | if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) 49 | # We have reached the root directory, we are not in git 50 | set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) 51 | set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) 52 | return() 53 | endif() 54 | set(GIT_DIR "${GIT_PARENT_DIR}/.git") 55 | endwhile() 56 | # check if this is a submodule 57 | if(NOT IS_DIRECTORY ${GIT_DIR}) 58 | file(READ ${GIT_DIR} submodule) 59 | string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) 60 | get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) 61 | get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) 62 | endif() 63 | set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") 64 | if(NOT EXISTS "${GIT_DATA}") 65 | file(MAKE_DIRECTORY "${GIT_DATA}") 66 | endif() 67 | 68 | if(NOT EXISTS "${GIT_DIR}/HEAD") 69 | return() 70 | endif() 71 | set(HEAD_FILE "${GIT_DATA}/HEAD") 72 | configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) 73 | 74 | configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" 75 | "${GIT_DATA}/grabRef.cmake" 76 | @ONLY) 77 | include("${GIT_DATA}/grabRef.cmake") 78 | 79 | set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) 80 | set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) 81 | endfunction() 82 | 83 | function(git_describe _var) 84 | if(NOT GIT_FOUND) 85 | find_package(Git QUIET) 86 | endif() 87 | get_git_head_revision(refspec hash) 88 | if(NOT GIT_FOUND) 89 | set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) 90 | return() 91 | endif() 92 | if(NOT hash) 93 | set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) 94 | return() 95 | endif() 96 | 97 | # TODO sanitize 98 | #if((${ARGN}" MATCHES "&&") OR 99 | # (ARGN MATCHES "||") OR 100 | # (ARGN MATCHES "\\;")) 101 | # message("Please report the following error to the project!") 102 | # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") 103 | #endif() 104 | 105 | #message(STATUS "Arguments to execute_process: ${ARGN}") 106 | 107 | execute_process(COMMAND 108 | "${GIT_EXECUTABLE}" 109 | describe 110 | ${hash} 111 | ${ARGN} 112 | WORKING_DIRECTORY 113 | "${CMAKE_CURRENT_SOURCE_DIR}" 114 | RESULT_VARIABLE 115 | res 116 | OUTPUT_VARIABLE 117 | out 118 | ERROR_QUIET 119 | OUTPUT_STRIP_TRAILING_WHITESPACE) 120 | if(NOT res EQUAL 0) 121 | set(out "${out}-${res}-NOTFOUND") 122 | endif() 123 | 124 | set(${_var} "${out}" PARENT_SCOPE) 125 | endfunction() 126 | 127 | function(git_get_exact_tag _var) 128 | git_describe(out --exact-match ${ARGN}) 129 | set(${_var} "${out}" PARENT_SCOPE) 130 | endfunction() 131 | -------------------------------------------------------------------------------- /cmake_module/GetGitRevisionDescription.cmake.in: -------------------------------------------------------------------------------- 1 | # 2 | # Internal file for GetGitRevisionDescription.cmake 3 | # 4 | # Requires CMake 2.6 or newer (uses the 'function' command) 5 | # 6 | # Original Author: 7 | # 2009-2010 Ryan Pavlik 8 | # http://academic.cleardefinition.com 9 | # Iowa State University HCI Graduate Program/VRAC 10 | # 11 | # Copyright Iowa State University 2009-2010. 12 | # Distributed under the Boost Software License, Version 1.0. 13 | # (See accompanying file LICENSE_1_0.txt or copy at 14 | # http://www.boost.org/LICENSE_1_0.txt) 15 | 16 | set(HEAD_HASH) 17 | 18 | file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) 19 | 20 | string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) 21 | if(HEAD_CONTENTS MATCHES "ref") 22 | # named branch 23 | string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") 24 | if(EXISTS "@GIT_DIR@/${HEAD_REF}") 25 | configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) 26 | else() 27 | configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) 28 | file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) 29 | if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") 30 | set(HEAD_HASH "${CMAKE_MATCH_1}") 31 | endif() 32 | endif() 33 | else() 34 | # detached HEAD 35 | configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) 36 | endif() 37 | 38 | if(NOT HEAD_HASH) 39 | file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) 40 | string(STRIP "${HEAD_HASH}" HEAD_HASH) 41 | endif() 42 | -------------------------------------------------------------------------------- /licence.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | const char* filename = "test_stack.tif"; 8 | 9 | std::cout << "open: " << filename << std::endl; 10 | 11 | OctData::OCT oct = OctData::OctFileRead::openFile(filename); 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /octdata/buildconstants.cpp.in: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | 19 | #include 20 | 21 | namespace OctData 22 | { 23 | 24 | const char BuildConstants::gitSha1 [] = "@GIT_SHA1@"; 25 | const char BuildConstants::buildTyp [] = "@CMAKE_BUILD_TYPE@"; 26 | const char BuildConstants::buildTime [] = __TIME__; 27 | const char BuildConstants::buildDate [] = __DATE__; 28 | const char BuildConstants::compiler [] = "@CMAKE_CXX_COMPILER@"; 29 | const char BuildConstants::compilerId [] = "@CMAKE_CXX_COMPILER_ID@"; 30 | const char BuildConstants::compilerVersion[] = "@CMAKE_CXX_COMPILER_VERSION@"; 31 | const char BuildConstants::configureTime [] = "@CMAKE_CONFIGURE_TIME@"; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /octdata/buildconstants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | namespace OctData 21 | { 22 | 23 | struct BuildConstants 24 | { 25 | static const char gitSha1[]; 26 | static const char buildTyp[]; 27 | static const char buildDate[]; 28 | static const char buildTime[]; 29 | static const char compiler[]; 30 | static const char compilerId[]; 31 | static const char compilerVersion[]; 32 | static const char configureTime []; 33 | }; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /octdata/datastruct/analysegrid.cpp: -------------------------------------------------------------------------------- 1 | #include "analysegrid.h" 2 | 3 | 4 | -------------------------------------------------------------------------------- /octdata/datastruct/analysegrid.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | #include"coordslo.h" 23 | 24 | namespace OctData 25 | { 26 | class AnalyseGrid 27 | { 28 | CoordSLOmm center; 29 | std::vector diametersMM; 30 | 31 | 32 | template 33 | static void callSubset(T& getSet, ParameterSet& p, const std::string& name) 34 | { 35 | T subSetGetSet = getSet.subSet(name); 36 | p.getSetParameter(subSetGetSet); 37 | } 38 | 39 | template 40 | static void getSetParameter(T& getSet, ParameterSet& p) 41 | { 42 | callSubset(getSet, p.center, "center"); 43 | getSet("diametersMM", p.diametersMM); 44 | } 45 | public: 46 | const CoordSLOmm& getCenter() const { return center; } 47 | const std::vector& getDiametersMM() const { return diametersMM; } 48 | 49 | void setCenter(const CoordSLOmm& c) { center = c; } 50 | void addDiameterMM(double diameter) { diametersMM.push_back(diameter); } 51 | 52 | 53 | template void getSetParameter(T& getSet) { getSetParameter(getSet, *this); } 54 | template void getSetParameter(T& getSet) const { getSetParameter(getSet, *this); } 55 | }; 56 | 57 | } 58 | -------------------------------------------------------------------------------- /octdata/datastruct/bscan.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "bscan.h" 19 | 20 | #define _USE_MATH_DEFINES 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | 27 | namespace OctData 28 | { 29 | 30 | BScan::BScan(const cv::Mat& img, const BScan::Data& data) 31 | : image (new cv::Mat(img)) 32 | , angioImage(new cv::Mat) 33 | , rawImage (new cv::Mat) 34 | , data (data) 35 | { 36 | 37 | } 38 | 39 | BScan::~BScan() 40 | { 41 | delete image; 42 | delete angioImage; 43 | delete rawImage; 44 | } 45 | 46 | int BScan::getWidth() const 47 | { 48 | return image->cols; 49 | } 50 | 51 | int BScan::getHeight() const 52 | { 53 | return image->rows; 54 | } 55 | 56 | void BScan::setRawImage(const cv::Mat& img) 57 | { 58 | *rawImage = img; 59 | } 60 | 61 | void BScan::setAngioImage(const cv::Mat& img) 62 | { 63 | *angioImage = img; 64 | } 65 | 66 | OctData::CoordSLOmm calcCirclePos(const OctData::CoordSLOmm& center, const OctData::CoordSLOmm& start, double frac, bool clockwise) 67 | { 68 | if(!clockwise) 69 | frac = 1-frac; 70 | 71 | const double radius = center.abs(start); 72 | const double ratio = start.getX() - center.getX(); 73 | const double nullAngle = acos( ratio/radius )/M_PI/2; 74 | 75 | frac += nullAngle; 76 | frac *= 2*M_PI; 77 | 78 | const double posX = cos(frac)*radius + center.getX(); 79 | const double posY = sin(frac)*radius + center.getY(); 80 | 81 | return OctData::CoordSLOmm(posX, posY); 82 | } 83 | 84 | 85 | 86 | const OctData::CoordSLOmm OctData::BScan::getFracPos(double frac) const 87 | { 88 | switch(getBScanType()) 89 | { 90 | case BScanType::Circle: 91 | return calcCirclePos(getCenter(), getStart(), frac, getClockwiseRot()); 92 | break; 93 | case BScanType::Line: 94 | return getStart()*(1-frac) + getEnd()*(frac); // TODO: falsche Richtung? 95 | break; 96 | case BScanType::Unknown: 97 | break; 98 | } 99 | return OctData::CoordSLOmm(); 100 | } 101 | 102 | const OctData::CoordSLOmm OctData::BScan::getAscanPos(std::size_t ascan) const 103 | { 104 | const std::size_t bscanWidth = getWidth(); 105 | 106 | if(ascan >= bscanWidth && bscanWidth > 1) 107 | throw std::out_of_range("ascan number greater than bscan width"); 108 | 109 | const double frac = static_cast(ascan)/static_cast(bscanWidth-1); 110 | return getFracPos(frac); 111 | } 112 | 113 | template<> void BScan::BScanTypeEnumWrapper::toString() 114 | { 115 | switch(obj) 116 | { 117 | case BScan::BScanType::Circle: std::string::operator=("Circle"); break; 118 | case BScan::BScanType::Line : std::string::operator=("Line" ); break; 119 | case BScan::BScanType::Unknown: 120 | break; 121 | } 122 | } 123 | template<> void BScan::BScanTypeEnumWrapper::fromString() 124 | { 125 | if(*this == "Circle") obj = BScan::BScanType::Circle; 126 | else if(*this == "Line" ) obj = BScan::BScanType::Line ; 127 | else obj = BScan::BScanType::Unknown; 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /octdata/datastruct/bscan.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include "coordslo.h" 23 | #include "date.h" 24 | #include "segmentationlines.h" 25 | 26 | namespace cv { class Mat; } 27 | 28 | 29 | #ifdef OCTDATA_EXPORT 30 | #include "octdata_EXPORTS.h" 31 | #else 32 | #define Octdata_EXPORTS 33 | #endif 34 | 35 | 36 | namespace OctData 37 | { 38 | 39 | // GCL IPL INL OPL ELM PR1 PR2 RPE BM 40 | class Octdata_EXPORTS BScan 41 | { 42 | public: 43 | enum class BScanType { Unknown, Line, Circle }; 44 | 45 | typedef ObjectWrapper BScanTypeEnumWrapper; 46 | 47 | struct Data 48 | { 49 | std::string filename; 50 | 51 | 52 | int numAverage = 0; 53 | double imageQuality = 0; 54 | double scanAngle = 0; 55 | Date acquisitionTime; 56 | /* 57 | bool positionWithinTolerance ; 58 | bool edi ;*/ 59 | 60 | BScanType bscanType = BScanType::Line; 61 | ScaleFactor scaleFactor; 62 | CoordSLOmm start ; 63 | CoordSLOmm end ; 64 | CoordSLOmm center ; 65 | bool clockwiseRotation = false; 66 | 67 | Segmentationlines segmentationslines; 68 | Segmentationlines::Segmentline& getSegmentLine(Segmentationlines::SegmentlineType i) 69 | { return segmentationslines.getSegmentLine(i); } 70 | const Segmentationlines::Segmentline& getSegmentLine(Segmentationlines::SegmentlineType i) const 71 | { return segmentationslines.getSegmentLine(i); } 72 | }; 73 | 74 | // BScan(); 75 | BScan(const cv::Mat& img, const BScan::Data& data); 76 | ~BScan(); 77 | 78 | BScan(const BScan& other) = delete; 79 | BScan& operator=(const BScan& other) = delete; 80 | 81 | const cv::Mat& getImage() const { return *image ; } 82 | const cv::Mat& getAngioImage() const { return *angioImage ; } 83 | const cv::Mat& getRawImage() const { return *rawImage ; } 84 | 85 | void setRawImage(const cv::Mat& img); 86 | void setAngioImage(const cv::Mat& img); 87 | 88 | 89 | const std::string getFilename() const { return data.filename ; } 90 | 91 | int getNumAverage() const { return data.numAverage ; } 92 | double getImageQuality() const { return data.imageQuality ; } 93 | double getScanAngle () const { return data.scanAngle ; } 94 | Date getAcquisitionTime() const { return data.acquisitionTime ; } 95 | 96 | // bool getPositionWithinTolerance() const { return data.positionWithinTolerance; } 97 | // bool getEdi() const { return data.edi ; } 98 | 99 | BScanType getBScanType() const { return data.bscanType ; } 100 | const ScaleFactor& getScaleFactor() const { return data.scaleFactor ; } 101 | const CoordSLOmm& getStart() const { return data.start ; } 102 | const CoordSLOmm& getEnd() const { return data.end ; } 103 | const CoordSLOmm& getCenter() const { return data.center ; } 104 | bool getClockwiseRot() const { return data.clockwiseRotation ; } 105 | 106 | const CoordSLOmm getAscanPos(std::size_t ascan) const; 107 | const CoordSLOmm getFracPos(double frac) const; 108 | 109 | 110 | static std::size_t getNumSegmentLine() { return Segmentationlines::getSegmentlineTypes().size(); } 111 | const Segmentationlines::Segmentline& getSegmentLine(Segmentationlines::SegmentlineType i) const 112 | { return data.getSegmentLine(i); } 113 | 114 | const Segmentationlines& getSegmentLines() const { return data.segmentationslines; } 115 | 116 | int getWidth() const; 117 | int getHeight() const; 118 | 119 | 120 | template void getSetParameter(T& getSet) { getSetParameter(getSet, *this); } 121 | template void getSetParameter(T& getSet) const { getSetParameter(getSet, *this); } 122 | 123 | 124 | private: 125 | cv::Mat* image = nullptr; 126 | cv::Mat* angioImage = nullptr; 127 | cv::Mat* rawImage = nullptr; 128 | Data data; 129 | 130 | 131 | template 132 | static void callSubset(T& getSet, ParameterSet& p, const std::string& name) 133 | { 134 | T subSetGetSet = getSet.subSet(name); 135 | p.getSetParameter(subSetGetSet); 136 | } 137 | 138 | template 139 | static void getSetParameter(T& getSet, ParameterSet& p) 140 | { 141 | BScanTypeEnumWrapper bscanTypeWrapper (p.data.bscanType); 142 | 143 | 144 | DateWrapper acquisitionTimeWrapper(p.data.acquisitionTime); 145 | 146 | getSet("numAverage" , p.data.numAverage ); 147 | getSet("clockwiseRotation", p.data.clockwiseRotation ); 148 | getSet("imageQuality" , p.data.imageQuality ); 149 | getSet("scanAngle" , p.data.scanAngle ); 150 | getSet("acquisitionTime" , static_cast(acquisitionTimeWrapper)); 151 | getSet("bscanType" , static_cast(bscanTypeWrapper) ); 152 | 153 | callSubset(getSet, p.data.scaleFactor, "scaleFactor"); 154 | callSubset(getSet, p.data.start , "start_mm" ); 155 | callSubset(getSet, p.data.end , "end_mm" ); 156 | callSubset(getSet, p.data.center , "center_mm" ); 157 | } 158 | 159 | }; 160 | } 161 | -------------------------------------------------------------------------------- /octdata/datastruct/coordslo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | namespace OctData 24 | { 25 | class CoordSLOmm; 26 | 27 | class ScaleFactor 28 | { 29 | double x; 30 | double y; 31 | double z = 0; 32 | 33 | template 34 | static void getSetParameter(T& getSet, ParameterSet& p) 35 | { 36 | getSet("x", p.x); 37 | getSet("y", p.y); 38 | getSet("z", p.z); 39 | } 40 | 41 | public: 42 | ScaleFactor(double x, double y, double z = 0) : x(x), y(y), z(z) 43 | {} 44 | explicit ScaleFactor(double factor) : x(factor), y(factor) {} 45 | ScaleFactor() : x(1), y(1) {} 46 | 47 | double getX() const { return x; } 48 | double getY() const { return y; } 49 | double getZ() const { return z; } 50 | 51 | ScaleFactor operator* (double factor) const { return ScaleFactor(x*factor, y*factor, z*factor); } 52 | ScaleFactor& operator*=(double factor) { x *= factor; y *= factor; z*= factor; return *this; } 53 | 54 | void print(std::ostream& stream) const { stream << "(" << x << " | " << y << " | " << z << ")"; } 55 | 56 | template void getSetParameter(T& getSet) { getSetParameter(getSet, *this); } 57 | template void getSetParameter(T& getSet) const { getSetParameter(getSet, *this); } 58 | }; 59 | inline std::ostream& operator<<(std::ostream& stream, const ScaleFactor& obj) { obj.print(stream); return stream; } 60 | 61 | class CoordSLOpx 62 | { 63 | double x; 64 | double y; 65 | 66 | template 67 | static void getSetParameter(T& getSet, ParameterSet& p) 68 | { 69 | getSet("x", p.x); 70 | getSet("y", p.y); 71 | } 72 | 73 | public: 74 | CoordSLOpx(double x, double y) : x(x), y(y) {} 75 | CoordSLOpx() : x(0), y(0) {} 76 | 77 | int getX() const { return static_cast(std::round(x)); } 78 | int getY() const { return static_cast(std::round(y)); } 79 | 80 | 81 | double getXf() const { return x; } 82 | double getYf() const { return y; } 83 | 84 | CoordSLOpx operator+(const CoordSLOpx& o) const { return CoordSLOpx(x+o.x , y+o.y ); } 85 | CoordSLOpx operator*(double factor) const { return CoordSLOpx(x*factor, y*factor); } 86 | CoordSLOpx operator-(const CoordSLOpx& v) const { return CoordSLOpx(x-v.x , y-v.y ); } 87 | 88 | double operator*(const CoordSLOpx& v) const { return x*v.x + y*v.y; } 89 | double normquadrat() const { return x*x + y*y; } 90 | 91 | double absQuad(const CoordSLOpx& o) const { return (x-o.x)*(x-o.x) + (y-o.y)*(y-o.y); } 92 | double abs(const CoordSLOpx& o) const { return std::sqrt(absQuad(o)); } 93 | 94 | void print(std::ostream& stream) const { stream << "(" << x << " | " << y << ")"; } 95 | 96 | CoordSLOmm operator/(const ScaleFactor& factor) const; 97 | 98 | template void getSetParameter(T& getSet) { getSetParameter(getSet, *this); } 99 | template void getSetParameter(T& getSet) const { getSetParameter(getSet, *this); } 100 | }; 101 | 102 | inline std::ostream& operator<<(std::ostream& stream, const CoordSLOpx& obj) { obj.print(stream); return stream; } 103 | 104 | 105 | class CoordSLOmm 106 | { 107 | double x; 108 | double y; 109 | 110 | bool set = false; 111 | 112 | template 113 | static void getSetParameter(T& getSet, ParameterSet& p) 114 | { 115 | getSet("x" , p.x ); 116 | getSet("y" , p.y ); 117 | getSet("set", p.set); 118 | } 119 | 120 | public: 121 | CoordSLOmm(double x, double y) : x(x), y(y), set(true) {} 122 | CoordSLOmm() : x(0), y(0) {} 123 | 124 | double getX() const { return x; } 125 | double getY() const { return y; } 126 | 127 | CoordSLOpx operator*(const ScaleFactor& factor) const { return CoordSLOpx(x/factor.getX(), y/factor.getY()); } 128 | 129 | CoordSLOmm operator+(const CoordSLOmm& o) const { return CoordSLOmm(x+o.x , y+o.y ); } 130 | CoordSLOmm operator*(double factor) const { return CoordSLOmm(x*factor, y*factor); } 131 | CoordSLOmm operator-(const CoordSLOmm& v) const { return CoordSLOmm(x-v.x , y-v.y ); } 132 | 133 | double abs(const CoordSLOmm& o) const { return std::sqrt((x-o.x)*(x-o.x) + (y-o.y)*(y-o.y)); } 134 | 135 | operator bool() const { return set; } 136 | 137 | template void getSetParameter(T& getSet) { getSetParameter(getSet, *this); } 138 | template void getSetParameter(T& getSet) const { getSetParameter(getSet, *this); } 139 | }; 140 | 141 | 142 | class CoordTransform 143 | { 144 | double a11 = 1.; 145 | double a12 = 0.; 146 | double a21 = 0.; 147 | double a22 = 1.; 148 | 149 | double b1 = 0.; 150 | double b2 = 0.; 151 | 152 | template 153 | static void getSetParameter(T& getSet, ParameterSet& p) 154 | { 155 | getSet("a11", p.a11); 156 | getSet("a12", p.a12); 157 | getSet("a21", p.a21); 158 | getSet("a22", p.a22); 159 | 160 | getSet("b1" , p.b1 ); 161 | getSet("b2" , p.b2 ); 162 | } 163 | public: 164 | CoordTransform() = default; 165 | CoordTransform(double a11, double a12, double a21, double a22, double b1, double b2) 166 | : a11(a11) 167 | , a12(a12) 168 | , a21(a21) 169 | , a22(a22) 170 | , b1 (b1 ) 171 | , b2 (b2 ) 172 | {} 173 | 174 | CoordSLOmm operator*(const CoordSLOmm& mm) const { return CoordSLOmm(a11*mm.getX() + a12*mm.getY() + b1, a21*mm.getX() + a22*mm.getY() + b2); } 175 | CoordSLOpx operator*(const CoordSLOpx& px) const { return CoordSLOpx(a11*px.getXf() + a12*px.getYf() + b1, a21*px.getXf() + a22*px.getYf() + b2); } 176 | 177 | template void getSetParameter(T& getSet) { getSetParameter(getSet, *this); } 178 | template void getSetParameter(T& getSet) const { getSetParameter(getSet, *this); } 179 | 180 | CoordTransform inv() const 181 | { 182 | double det = a11*a22 - a12*a21; 183 | if(det < 1e-7) 184 | return CoordTransform(); 185 | double invDet = 1./det; 186 | return CoordTransform( a22*invDet 187 | , -a12*invDet 188 | , -a21*invDet 189 | , a11*invDet 190 | , -b1 191 | , -b2); 192 | } 193 | }; 194 | 195 | 196 | 197 | inline CoordSLOmm CoordSLOpx::operator/(const ScaleFactor& factor) const { return CoordSLOmm(x*factor.getX(), y*factor.getY()); } 198 | } 199 | -------------------------------------------------------------------------------- /octdata/datastruct/date.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "date.h" 19 | 20 | #include 21 | // #include 22 | // #include 23 | 24 | #ifdef _MSC_VER 25 | #define timegm _mkgmtime 26 | #endif 27 | 28 | namespace 29 | { 30 | const long long windowsTicksToUnixFactor = 10000000; 31 | const long long secToUnixEpechFromWindowsTicks = 11644473600LL; 32 | } 33 | 34 | 35 | 36 | namespace OctData 37 | { 38 | Date::TimeCollection Date::conviertWindowsTicks(long long windowsTicks) 39 | { 40 | TimeCollection time; 41 | time.unixtime = (windowsTicks/windowsTicksToUnixFactor - secToUnixEpechFromWindowsTicks); 42 | time.ms = static_cast((windowsTicks/(windowsTicksToUnixFactor/1000) - secToUnixEpechFromWindowsTicks*1000) - static_cast(time.unixtime)*1000); 43 | return time; 44 | } 45 | 46 | Date::TimeCollection Date::convertWindowsTimeFormat(double wintime) 47 | { 48 | TimeCollection time; 49 | time.unixtime = static_cast((wintime - 25569)*60*60*24); 50 | time.ms = static_cast((wintime - 25569)*60*60*24*1000 - std::floor((wintime - 25569)*60*60*24*1000)); 51 | return time; 52 | } 53 | 54 | void Date::decodeUnixTime() 55 | { 56 | struct tm* ti = gmtime(&unixtime); 57 | if(ti == nullptr) 58 | return; 59 | timeinfo = *ti; 60 | decoded = true; 61 | } 62 | 63 | Date::TimeCollection Date::convertTime(int year, int month, int day, int hour, int min, double sec, bool withTime) 64 | { 65 | struct tm timeinfo{}; 66 | 67 | timeinfo.tm_year = year - 1900; 68 | timeinfo.tm_mon = month - 1; 69 | timeinfo.tm_mday = day; 70 | if(withTime) 71 | { 72 | timeinfo.tm_hour = hour; 73 | timeinfo.tm_min = min; 74 | timeinfo.tm_sec = static_cast(sec); 75 | } 76 | 77 | TimeCollection time; 78 | time.unixtime = timegm(&timeinfo); 79 | time.ms = static_cast((sec - std::floor(sec))*1000); 80 | return time; 81 | } 82 | 83 | void Date::decodeString(const std::string& str) 84 | { 85 | unixtime = 0; 86 | decodeUnixTime(); 87 | decoded = false; 88 | 89 | if(str.empty() || str == "-") 90 | return; 91 | 92 | std::istringstream datesstring(str); 93 | 94 | int year = -1; 95 | int month = -1; 96 | int day = -1; 97 | char trenner; 98 | datesstring >> year >> trenner >> month >> trenner >> day; 99 | if(day < 0) 100 | return; 101 | 102 | decoded = true; 103 | setYear(year); 104 | setMonth(month); 105 | setDay(day); 106 | 107 | int hour = -1; 108 | int min = -1; 109 | int sec = -1; 110 | datesstring >> hour >> trenner >> min >> trenner >> sec; 111 | if(sec < 0) 112 | return; 113 | 114 | setHour(hour); 115 | setMin(min); 116 | setSec(sec); 117 | 118 | int ms = -1; 119 | datesstring >> trenner >> ms; 120 | if(trenner == '.' && ms > 0) 121 | setMs(ms); 122 | } 123 | 124 | 125 | template<> void DateWrapper::toString() 126 | { 127 | if(!obj.isEmpty()) 128 | std::string::operator=(obj.timeDateStr()); 129 | } 130 | 131 | 132 | template<> void DateWrapper::fromString() 133 | { 134 | if(!empty()) 135 | obj.decodeString(*this); 136 | } 137 | 138 | 139 | 140 | } 141 | -------------------------------------------------------------------------------- /octdata/datastruct/date.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include"objectwrapper.h" 29 | 30 | namespace OctData 31 | { 32 | class Date 33 | { 34 | struct TimeCollection 35 | { 36 | time_t unixtime = 0; 37 | int ms = 0; 38 | }; 39 | 40 | time_t unixtime; 41 | struct tm timeinfo; 42 | bool decoded = false; 43 | int millisecunds = 0; 44 | 45 | 46 | static TimeCollection conviertWindowsTicks(long long windowsTicks); 47 | static TimeCollection convertWindowsTimeFormat(double wintime); 48 | static TimeCollection convertTime(int year, int month, int day, int hour, int min, double sec, bool withTime); 49 | void decodeUnixTime(); 50 | 51 | explicit Date(time_t unixtime) : unixtime(unixtime) { decodeUnixTime(); } 52 | explicit Date(const TimeCollection& time) 53 | : unixtime (time.unixtime) 54 | , millisecunds(time.ms) 55 | { 56 | decodeUnixTime(); 57 | } 58 | public: 59 | Date() : unixtime() { } 60 | 61 | static Date fromWindowsTicks(uint64_t ticks) { return Date(conviertWindowsTicks(ticks)); } 62 | static Date fromWindowsTimeFormat(double t) { return Date(convertWindowsTimeFormat(t)); } 63 | static Date fromUnixTime(time_t unixtime) { return Date(unixtime); } 64 | static Date fromDate(int year, int month, int day) { return Date(convertTime(year, month, day, 0, 0, 0, false)); } 65 | static Date fromTime(int year, int month, int day, int hour, int min, double sec) 66 | { return Date(convertTime(year, month, day, hour, min, sec, true)); } 67 | 68 | int day () const { return timeinfo.tm_mday ; } 69 | int month() const { return timeinfo.tm_mon + 1 ; } 70 | int year () const { return timeinfo.tm_year + 1900; } 71 | int hour () const { return timeinfo.tm_hour ; } 72 | int min () const { return timeinfo.tm_min ; } 73 | int sec () const { return timeinfo.tm_sec ; } 74 | int ms () const { return millisecunds ; } 75 | 76 | 77 | void setDay (int value) { timeinfo.tm_mday = value ; } 78 | void setMonth(int value) { timeinfo.tm_mon = value - 1 ; } 79 | void setYear (int value) { timeinfo.tm_year = value - 1900; } 80 | void setHour (int value) { timeinfo.tm_hour = value ; } 81 | void setMin (int value) { timeinfo.tm_min = value ; } 82 | void setSec (int value) { timeinfo.tm_sec = value ; } 83 | void setMs (int value) { millisecunds = value ; } 84 | void setDateAsValid() { decoded = true; } 85 | 86 | bool isEmpty() const { return !decoded; } 87 | 88 | std::string str(char trenner = '.') const; 89 | std::string strTime(char timeTrenner = ':') const; 90 | std::string strUsDate(char trenner = ':') const; 91 | std::string timeDateStr(char datetrenner = '.', char timeTrenner = ':', bool showMs = false) const; 92 | 93 | void decodeString(const std::string& str); 94 | 95 | void print(std::ostream& stream) const { stream << timeDateStr(); } 96 | }; 97 | 98 | 99 | inline std::string Date::str(char trenner) const 100 | { 101 | if(!decoded) 102 | return "-"; 103 | 104 | std::ostringstream datesstring; 105 | datesstring << year() << trenner << std::setw(2) << std::setfill('0') << month() << trenner << std::setw(2) << day(); 106 | return datesstring.str(); 107 | } 108 | 109 | inline std::string Date::strUsDate(char trenner) const 110 | { 111 | if(!decoded) 112 | return "-"; 113 | 114 | std::ostringstream datesstring; 115 | datesstring << std::setw(2) << std::setfill('0') << month() << trenner << std::setw(2) << day() << trenner << year(); 116 | return datesstring.str(); 117 | } 118 | 119 | inline std::string Date::strTime(char timeTrenner) const 120 | { 121 | if(!decoded) 122 | return "-"; 123 | 124 | std::ostringstream datesstring; 125 | datesstring << hour() << timeTrenner << std::setw(2) << min() << timeTrenner << std::setw(2) << sec(); 126 | return datesstring.str(); 127 | } 128 | 129 | inline std::string Date::timeDateStr(char datetrenner, char timeTrenner, bool showMs) const 130 | { 131 | if(!decoded) 132 | return "-"; 133 | 134 | std::ostringstream datesstring; 135 | datesstring << year() << datetrenner << std::setw(2) << std::setfill('0') << month() << datetrenner << std::setw(2) << day(); 136 | datesstring << " "; 137 | datesstring << hour() << timeTrenner << std::setw(2) << min() << timeTrenner << std::setw(2) << sec(); 138 | if(showMs) 139 | datesstring << '.' << std::setw(3) << ms(); 140 | 141 | return datesstring.str(); 142 | } 143 | 144 | inline std::ostream& operator<<(std::ostream& stream, const Date& obj) { obj.print(stream); return stream; } 145 | 146 | typedef ObjectWrapper DateWrapper; 147 | } 148 | 149 | 150 | -------------------------------------------------------------------------------- /octdata/datastruct/objectwrapper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #ifdef OCTDATA_EXPORT 21 | #include "octdata_EXPORTS.h" 22 | #else 23 | #define Octdata_EXPORTS 24 | #endif 25 | 26 | 27 | #include 28 | 29 | namespace OctData 30 | { 31 | template 32 | class ObjectWrapper : public std::string 33 | { 34 | T constObj; // temporary for const usage 35 | T& obj; 36 | 37 | Octdata_EXPORTS void toString(); 38 | Octdata_EXPORTS void fromString(); 39 | 40 | public: 41 | ObjectWrapper(const T& o) 42 | : constObj(o) 43 | , obj(constObj) 44 | { toString(); } 45 | 46 | ObjectWrapper(T& o) 47 | : obj(o) 48 | { toString(); } 49 | 50 | ~ObjectWrapper() 51 | { 52 | if(&constObj != &obj) 53 | fromString(); 54 | } 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /octdata/datastruct/oct.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "oct.h" 19 | 20 | namespace OctData 21 | { 22 | void OCT::findSeries(const OctData::Series* const seriesReq, const OctData::Patient*& pat, const OctData::Study*& study) const 23 | { 24 | pat = nullptr; 25 | study = nullptr; 26 | 27 | if(seriesReq == nullptr) 28 | return; 29 | 30 | // Search series 31 | for(const OCT::SubstructurePair& patientPair : *this) 32 | { 33 | const Patient* actPatient = patientPair.second; 34 | for(const Patient::SubstructurePair& studyPair : *actPatient) 35 | { 36 | const Study* actStudy = studyPair.second; 37 | for(const Study::SubstructurePair& seriesPair : *actStudy) 38 | { 39 | const Series* series = seriesPair.second; 40 | if(series == seriesReq) 41 | { 42 | pat = actPatient; 43 | study = actStudy; 44 | return; 45 | } 46 | } 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /octdata/datastruct/oct.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "substructure_template.h" 21 | #include "patient.h" 22 | 23 | namespace OctData 24 | { 25 | class OCT : public SubstructureTemplate 26 | { 27 | public: 28 | Octdata_EXPORTS Patient& getInsertId(int id) { return getAndInsert (id) ; } 29 | 30 | Octdata_EXPORTS Patient& getPatient(int patientId) { return getAndInsert (patientId) ; } 31 | Octdata_EXPORTS const Patient& getPatient(int patientId) const { return *(substructureMap.at(patientId)); } 32 | Octdata_EXPORTS void clear() { clearSubstructure(); } 33 | 34 | Octdata_EXPORTS void findSeries(const OctData::Series* series, const OctData::Patient*& pat, const OctData::Study*& study) const; 35 | 36 | 37 | template void getSetParameter(T& /*getSet*/) { } 38 | template void getSetParameter(T& /*getSet*/) const { } 39 | }; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /octdata/datastruct/patient.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include"patient.h" 19 | 20 | 21 | namespace OctData 22 | { 23 | const char* OctData::Patient::getSexName(Sex sex) 24 | { 25 | switch(sex) 26 | { 27 | case Sex::Female : return "Female"; 28 | case Sex::Male : return "Male"; 29 | case Sex::Unknown: return "Unknown"; 30 | } 31 | return "Unknown"; 32 | } 33 | 34 | 35 | 36 | 37 | 38 | template<> void Patient::SexEnumWrapper::toString() 39 | { 40 | switch(obj) 41 | { 42 | case Patient::Sex::Female: std::string::operator=("female"); break; 43 | case Patient::Sex::Male : std::string::operator=("male" ); break; 44 | case Patient::Sex::Unknown: 45 | break; 46 | } 47 | } 48 | 49 | 50 | template<> void Patient::SexEnumWrapper::fromString() 51 | { 52 | if(*this == "female") obj = Patient::Sex::Female; 53 | else if(*this == "male" ) obj = Patient::Sex::Male ; 54 | else obj = Patient::Sex::Unknown; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /octdata/datastruct/patient.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | #include "substructure_template.h" 23 | #include "study.h" 24 | #include "date.h" 25 | 26 | #include"objectwrapper.h" 27 | 28 | namespace OctData 29 | { 30 | class Patient : public SubstructureTemplate 31 | { 32 | public: 33 | explicit Patient(int internalId) : internalId(internalId) {} 34 | 35 | enum class Sex { Unknown, Female, Male}; 36 | typedef ObjectWrapper SexEnumWrapper; 37 | 38 | static const char* getSexName(Sex sex); 39 | const char* getSexName() const { return getSexName(sex); } 40 | 41 | const std::string& getForename () const { return forename ; } 42 | const std::string& getSurname () const { return surname ; } 43 | const std::string& getTitle () const { return title ; } 44 | const std::string& getId () const { return id ; } 45 | Sex getSex () const { return sex ; } 46 | const Date& getBirthdate() const { return birthdate; } 47 | 48 | const std::u16string& getDiagnose() const { return diagnose; } 49 | 50 | 51 | void setForename (const std::string& v) { forename = v ; } 52 | void setSurname (const std::string& v) { surname = v ; } 53 | void setTitle (const std::string& v) { title = v ; } 54 | void setId (const std::string& v) { id = v ; } 55 | void setSex (const Sex v) { sex = v ; } 56 | void setBirthdate(const Date& bd) { birthdate = bd; } 57 | 58 | void setDiagnose (const std::u16string& v) { diagnose = v ; } 59 | 60 | const std::string& getPatientUID() const { return uid; } 61 | void setPatientUID(const std::string& id) { uid = id ; } 62 | const std::string& getAncestry() const { return ancestry; } 63 | void setAncestry (const std::string& v) { ancestry = v ; } 64 | 65 | 66 | Study& getInsertId(int id) { return getAndInsert(id) ; } 67 | 68 | Study& getStudy(int seriesId) { return getAndInsert(seriesId) ; } 69 | const Study& getStudy(int seriesId) const { return *(substructureMap.at(seriesId)); } 70 | 71 | int getInternalId() const { return internalId; } 72 | 73 | 74 | template void getSetParameter(T& getSet) { getSetParameter(getSet, *this); } 75 | template void getSetParameter(T& getSet) const { getSetParameter(getSet, *this); } 76 | 77 | 78 | struct PrintOptions 79 | { 80 | std::ostream& stream; 81 | 82 | PrintOptions(std::ostream& stream) : stream(stream) {} 83 | 84 | template 85 | void operator()(const char* name, const T& value) 86 | { 87 | stream << std::setw(26) << name << " : " << value << '\n'; 88 | } 89 | }; 90 | 91 | void print(std::ostream& stream) const 92 | { 93 | PrintOptions printer(stream); 94 | this->getSetParameter(printer); 95 | } 96 | 97 | private: 98 | const int internalId; 99 | 100 | std::string forename; 101 | std::string surname ; 102 | std::string title ; 103 | std::string id ; 104 | std::string uid ; 105 | std::string ancestry; 106 | 107 | std::u16string diagnose; 108 | 109 | Date birthdate ; 110 | 111 | Sex sex = Sex::Unknown; 112 | 113 | template 114 | static void getSetParameter(T& getSet, ParameterSet& p) 115 | { 116 | SexEnumWrapper sexWrapper(p.sex); 117 | DateWrapper birthDateWrapper(p.birthdate); 118 | 119 | // getSet("internalId", p.internalId ); 120 | getSet("forename" , p.forename ); 121 | getSet("surname" , p.surname ); 122 | getSet("title" , p.title ); 123 | getSet("id" , p.id ); 124 | getSet("uid" , p.uid ); 125 | getSet("ancestry" , p.ancestry ); 126 | getSet("birthdate" , static_cast(birthDateWrapper)); 127 | getSet("sex" , static_cast(sexWrapper) ); 128 | } 129 | 130 | }; 131 | 132 | 133 | 134 | } 135 | -------------------------------------------------------------------------------- /octdata/datastruct/segmentationlines.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "segmentationlines.h" 19 | 20 | namespace OctData 21 | { 22 | 23 | const Segmentationlines::SegLinesTypeList Segmentationlines::segmentlineTypes = 24 | { 25 | { 26 | SegmentlineType::ILM , 27 | SegmentlineType::RNFL, 28 | SegmentlineType::GCL , 29 | SegmentlineType::IPL , 30 | SegmentlineType::INL , 31 | SegmentlineType::OPL , 32 | SegmentlineType::ELM , 33 | SegmentlineType::PR1 , 34 | SegmentlineType::PR2 , 35 | SegmentlineType::RPE , 36 | SegmentlineType::BM , 37 | SegmentlineType::CHO 38 | } 39 | }; 40 | 41 | // ILM, NFL, I3T1, I4T1, I5T1, I6T1, I8T3, I14T1, I15T1, I16T1, BM, NR_OF_ELEMENTS 42 | 43 | const char* Segmentationlines::getSegmentlineName(OctData::Segmentationlines::SegmentlineType type) 44 | { 45 | switch(type) 46 | { 47 | case SegmentlineType::ILM : return "ILM" ; 48 | case SegmentlineType::RNFL: return "RNFL"; 49 | case SegmentlineType::GCL : return "GCL" ; 50 | case SegmentlineType::IPL : return "IPL" ; 51 | case SegmentlineType::INL : return "INL" ; 52 | case SegmentlineType::OPL : return "OPL" ; 53 | case SegmentlineType::ELM : return "ELM" ; 54 | case SegmentlineType::PR1 : return "PR1" ; 55 | case SegmentlineType::PR2 : return "PR2" ; 56 | case SegmentlineType::RPE : return "RPE" ; 57 | case SegmentlineType::BM : return "BM" ; 58 | case SegmentlineType::CHO : return "CHO" ; 59 | } 60 | return "invalid type"; 61 | } 62 | 63 | const Segmentationlines::SegLinesTypeList& Segmentationlines::getSegmentlineTypes() 64 | { return segmentlineTypes; } 65 | } 66 | -------------------------------------------------------------------------------- /octdata/datastruct/segmentationlines.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #ifdef OCTDATA_EXPORT 24 | #include "octdata_EXPORTS.h" 25 | #else 26 | #define Octdata_EXPORTS 27 | #endif 28 | 29 | 30 | namespace OctData 31 | { 32 | 33 | // GCL IPL INL OPL ELM PR1 PR2 RPE BM 34 | class Octdata_EXPORTS Segmentationlines 35 | { 36 | static const std::size_t numSegmentlineType = 12; 37 | public: 38 | enum class SegmentlineType 39 | { 40 | ILM , 41 | RNFL, 42 | GCL , 43 | IPL , 44 | INL , 45 | OPL , 46 | ELM , 47 | PR1 , 48 | PR2 , 49 | RPE , 50 | BM , 51 | CHO 52 | }; 53 | 54 | typedef double SegmentlineDataType; 55 | typedef std::vector Segmentline; 56 | typedef std::array SegLinesTypeList; 57 | 58 | Segmentline& getSegmentLine(SegmentlineType i) { return segmentlines.at(static_cast(i)); } 59 | const Segmentline& getSegmentLine(SegmentlineType i) const { return segmentlines.at(static_cast(i)); } 60 | 61 | static const char* getSegmentlineName(SegmentlineType type); 62 | 63 | static const SegLinesTypeList& getSegmentlineTypes(); 64 | private: 65 | static const SegLinesTypeList segmentlineTypes; 66 | std::array segmentlines; 67 | 68 | }; 69 | 70 | } 71 | -------------------------------------------------------------------------------- /octdata/datastruct/series.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "series.h" 19 | 20 | #include "bscan.h" 21 | #include "sloimage.h" 22 | 23 | #include 24 | 25 | #define _USE_MATH_DEFINES 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | namespace OctData 34 | { 35 | 36 | Series::Series(int internalId) 37 | : internalId(internalId) 38 | , sloImage(new SloImage) 39 | , scanFocus(std::numeric_limits::quiet_NaN()) 40 | { 41 | 42 | } 43 | 44 | 45 | Series::~Series() 46 | { 47 | for(BScan* bscan : bscans) 48 | delete bscan; 49 | 50 | delete sloImage; 51 | } 52 | 53 | void Series::takeBScan(OctData::BScan* bscan) 54 | { 55 | bscans.push_back(bscan); 56 | calculateSLOConvexHull(); 57 | updateCornerCoords(); 58 | } 59 | 60 | const BScan* Series::getBScan(std::size_t pos) const 61 | { 62 | if(pos >= bscans.size()) 63 | return nullptr; 64 | return bscans[pos]; 65 | } 66 | 67 | void Series::takeSloImage(SloImage* slo) 68 | { 69 | if(slo) 70 | { 71 | delete sloImage; 72 | sloImage = slo; 73 | } 74 | } 75 | 76 | 77 | 78 | void Series::updateCornerCoords(const CoordSLOmm& point) 79 | { 80 | double minX = std::min(point.getX(), leftUpper .getX()); 81 | double maxX = std::max(point.getX(), rightLower.getX()); 82 | double minY = std::min(point.getY(), leftUpper .getY()); 83 | double maxY = std::max(point.getY(), rightLower.getY()); 84 | 85 | leftUpper = CoordSLOmm(minX, minY); 86 | rightLower = CoordSLOmm(maxX, maxY); 87 | } 88 | 89 | void Series::updateCornerCoords() 90 | { 91 | BScan* bscan = bscans.back(); 92 | if(!bscan) 93 | return; 94 | 95 | if(bscans.size() == 1) // first scan, init points 96 | { 97 | leftUpper = bscan->getStart(); 98 | rightLower = bscan->getStart(); 99 | } 100 | 101 | switch(bscan->getBScanType()) 102 | { 103 | case BScan::BScanType::Circle: 104 | { 105 | double radius = bscan->getCenter().abs(bscan->getStart()); 106 | updateCornerCoords(bscan->getCenter() + CoordSLOmm( radius, 0)); 107 | updateCornerCoords(bscan->getCenter() + CoordSLOmm(-radius, 0)); 108 | updateCornerCoords(bscan->getCenter() + CoordSLOmm(0, radius)); 109 | updateCornerCoords(bscan->getCenter() + CoordSLOmm(0, -radius)); 110 | break; 111 | } 112 | case BScan::BScanType::Line: 113 | case BScan::BScanType::Unknown: 114 | updateCornerCoords(bscan->getStart()); 115 | updateCornerCoords(bscan->getEnd()); 116 | break; 117 | } 118 | } 119 | 120 | void Series::calculateSLOConvexHull() 121 | { 122 | convexHullSLOBScans.clear(); 123 | 124 | typedef boost::geometry::model::d2::point_xy Point; 125 | typedef boost::geometry::model::polygon Polygon; 126 | typedef std::vector PointsList; 127 | 128 | struct Adder 129 | { 130 | static void addPoint(PointsList& pl, const CoordSLOmm& pt) 131 | { 132 | pl.emplace_back(pt.getX(), pt.getY()); 133 | } 134 | static void addCircle(PointsList& pl, const CoordSLOmm& center, const CoordSLOmm& pt) 135 | { 136 | double radius = center.abs(pt); 137 | for(double alpha = 0; alpha < 2*M_PI; alpha += M_PI/16) 138 | { 139 | CoordSLOmm p = center + CoordSLOmm(sin(alpha)*radius, cos(alpha)*radius); 140 | pl.emplace_back(p.getX(), p.getY()); 141 | } 142 | } 143 | }; 144 | 145 | PointsList points; 146 | for(BScan* bscan : bscans) 147 | { 148 | if(bscan) 149 | { 150 | if(bscan->getCenter()) 151 | Adder::addCircle(points, bscan->getCenter(), bscan->getStart()); 152 | else 153 | { 154 | Adder::addPoint(points, bscan->getStart()); 155 | Adder::addPoint(points, bscan->getEnd()); 156 | } 157 | } 158 | } 159 | 160 | Polygon poly; 161 | boost::geometry::assign_points(poly, points); 162 | 163 | Polygon hull; 164 | boost::geometry::convex_hull(poly, hull); 165 | 166 | // ring is a vector 167 | std::vector const& convexPoints = hull.outer(); 168 | for(const Point&p : convexPoints) 169 | convexHullSLOBScans.emplace_back(p.get<0>(), p.get<1>()); 170 | } 171 | 172 | 173 | template<> void Series::LateralityEnumWrapper::toString() 174 | { 175 | switch(obj) 176 | { 177 | case Series::Laterality::OD: std::string::operator=("OD"); break; 178 | case Series::Laterality::OS: std::string::operator=("OS"); break; 179 | case Series::Laterality::undef: 180 | break; 181 | } 182 | } 183 | template<> void Series::LateralityEnumWrapper::fromString() 184 | { 185 | if(*this == "OD") obj = Series::Laterality::OD; 186 | else if(*this == "OS") obj = Series::Laterality::OS; 187 | else obj = Series::Laterality::undef; 188 | } 189 | 190 | 191 | template<> void Series::ScanPatternEnumWrapper::toString() 192 | { 193 | switch(obj) 194 | { 195 | case Series::ScanPattern::Text : std::string::operator=("Text" ); break; 196 | case Series::ScanPattern::SingleLine : std::string::operator=("SingleLine" ); break; 197 | case Series::ScanPattern::Circular : std::string::operator=("Circular" ); break; 198 | case Series::ScanPattern::Volume : std::string::operator=("Volume" ); break; 199 | case Series::ScanPattern::FastVolume : std::string::operator=("FastVolume" ); break; 200 | case Series::ScanPattern::Radial : std::string::operator=("Radial" ); break; 201 | case Series::ScanPattern::RadialCircles: std::string::operator=("RadialCircles"); break; 202 | case Series::ScanPattern::Unknown: 203 | break; 204 | } 205 | } 206 | template<> void Series::ScanPatternEnumWrapper::fromString() 207 | { 208 | if(*this == "Text" ) obj = Series::ScanPattern::Text ; 209 | else if(*this == "SingleLine" ) obj = Series::ScanPattern::SingleLine ; 210 | else if(*this == "Circular" ) obj = Series::ScanPattern::Circular ; 211 | else if(*this == "Volume" ) obj = Series::ScanPattern::Volume ; 212 | else if(*this == "FastVolume" ) obj = Series::ScanPattern::FastVolume ; 213 | else if(*this == "Radial" ) obj = Series::ScanPattern::Radial ; 214 | else if(*this == "RadialCircles") obj = Series::ScanPattern::RadialCircles ; 215 | else obj = Series::ScanPattern::Unknown; 216 | } 217 | 218 | 219 | 220 | template<> void Series::ExaminedStructureEnumWrapper::toString() 221 | { 222 | switch(obj) 223 | { 224 | case Series::ExaminedStructure::Text : std::string::operator=("Text" ); break; 225 | case Series::ExaminedStructure::ONH : std::string::operator=("ONH" ); break; 226 | case Series::ExaminedStructure::Retina: std::string::operator=("Retina"); break; 227 | case Series::ExaminedStructure::Unknown: 228 | break; 229 | } 230 | } 231 | template<> void Series::ExaminedStructureEnumWrapper::fromString() 232 | { 233 | if(*this == "Text" ) obj = Series::ExaminedStructure::Text ; 234 | else if(*this == "ONH" ) obj = Series::ExaminedStructure::ONH ; 235 | else if(*this == "Retina") obj = Series::ExaminedStructure::Retina; 236 | else obj = Series::ExaminedStructure::Unknown; 237 | } 238 | 239 | 240 | } 241 | -------------------------------------------------------------------------------- /octdata/datastruct/series.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | #include "date.h" 24 | #include "analysegrid.h" 25 | 26 | #include"objectwrapper.h" 27 | 28 | 29 | #ifdef OCTDATA_EXPORT 30 | #include "octdata_EXPORTS.h" 31 | #else 32 | #define Octdata_EXPORTS 33 | #endif 34 | 35 | 36 | 37 | namespace OctData 38 | { 39 | class SloImage; 40 | class BScan; 41 | 42 | class Series 43 | { 44 | Series(const Series&) = delete; 45 | Series& operator=(const Series&) = delete; 46 | 47 | public: 48 | enum class Laterality { undef, OD, OS }; 49 | enum class ScanPattern { Unknown, Text, SingleLine, Circular, Volume, FastVolume, Radial, RadialCircles }; 50 | enum class ExaminedStructure { Unknown, Text, ONH, Retina }; 51 | typedef ObjectWrapper LateralityEnumWrapper ; 52 | typedef ObjectWrapper ScanPatternEnumWrapper ; 53 | typedef ObjectWrapper ExaminedStructureEnumWrapper; 54 | 55 | typedef std::vector BScanList; 56 | typedef std::vector BScanSLOCoordList; 57 | 58 | Octdata_EXPORTS explicit Series(int internalId); 59 | Octdata_EXPORTS ~Series(); 60 | 61 | Octdata_EXPORTS const SloImage& getSloImage() const { return *sloImage; } 62 | Octdata_EXPORTS void takeSloImage(SloImage* sloImage); 63 | 64 | Octdata_EXPORTS const BScanList getBScans() const { return bscans; } 65 | Octdata_EXPORTS const BScan* getBScan(std::size_t pos) const; 66 | Octdata_EXPORTS std::size_t bscanCount() const { return bscans.size(); } 67 | 68 | Octdata_EXPORTS Laterality getLaterality() const { return laterality; } 69 | Octdata_EXPORTS void setLaterality(Laterality l) { laterality = l; } 70 | 71 | Octdata_EXPORTS ScanPattern getScanPattern() const { return scanPattern; } 72 | Octdata_EXPORTS void setScanPattern(ScanPattern p) { scanPattern = p; } 73 | Octdata_EXPORTS const std::string& getScanPatternText() const { return scanPatternText; } 74 | Octdata_EXPORTS void setScanPatternText(const std::string& str){ scanPatternText = str; } 75 | 76 | Octdata_EXPORTS ExaminedStructure getExaminedStructure() const { return examinedStructure; } 77 | Octdata_EXPORTS void setExaminedStructure(ExaminedStructure p) { examinedStructure = p; } 78 | Octdata_EXPORTS const std::string& getExaminedStructureText() const 79 | { return examinedStructureText; } 80 | Octdata_EXPORTS void setExaminedStructureText(const std::string& str) 81 | { examinedStructureText = str; } 82 | 83 | Octdata_EXPORTS void setScanDate(const Date& time) { scanDate = time; } 84 | 85 | Octdata_EXPORTS const Date& getScanDate() const { return scanDate; } 86 | 87 | Octdata_EXPORTS void setSeriesUID(const std::string& uid) { seriesUID = uid; } 88 | Octdata_EXPORTS const std::string& getSeriesUID() const { return seriesUID; } 89 | 90 | Octdata_EXPORTS void setRefSeriesUID(const std::string& uid) { refSeriesID = uid; } 91 | Octdata_EXPORTS const std::string& getRefSeriesUID() const { return refSeriesID; } 92 | 93 | Octdata_EXPORTS void setScanFocus(double focus) { scanFocus = focus; } 94 | Octdata_EXPORTS double getScanFocus() const { return scanFocus; } 95 | 96 | Octdata_EXPORTS void takeBScan(BScan* bscan); 97 | 98 | Octdata_EXPORTS void setDescription(const std::string& text) { description = text; } 99 | Octdata_EXPORTS const std::string& getDescription() const { return description; } 100 | 101 | Octdata_EXPORTS int getInternalId() const { return internalId; } 102 | 103 | Octdata_EXPORTS AnalyseGrid& getAnalyseGrid() { return analyseGrid; } 104 | Octdata_EXPORTS const AnalyseGrid& getAnalyseGrid() const { return analyseGrid; } 105 | 106 | Octdata_EXPORTS const BScanSLOCoordList& getConvexHull() const { return convexHullSLOBScans; } 107 | Octdata_EXPORTS const CoordSLOmm& getLeftUpperCoord() const { return leftUpper; } 108 | Octdata_EXPORTS const CoordSLOmm& getRightLowerCoord() const { return rightLower; } 109 | 110 | 111 | template void getSetParameter(T& getSet) { getSetParameter(getSet, *this); } 112 | template void getSetParameter(T& getSet) const { getSetParameter(getSet, *this); } 113 | 114 | private: 115 | const int internalId; 116 | 117 | SloImage* sloImage = nullptr; 118 | std::string seriesUID; 119 | std::string refSeriesID; 120 | double scanFocus; 121 | 122 | ScanPattern scanPattern = ScanPattern::Unknown; 123 | std::string scanPatternText; 124 | 125 | ExaminedStructure examinedStructure = ExaminedStructure::Unknown; 126 | std::string examinedStructureText; 127 | 128 | Laterality laterality = Laterality::undef; 129 | Date scanDate; 130 | 131 | std::string description; 132 | 133 | BScanList bscans; 134 | 135 | AnalyseGrid analyseGrid; 136 | 137 | BScanSLOCoordList convexHullSLOBScans; 138 | CoordSLOmm leftUpper; 139 | CoordSLOmm rightLower; 140 | void calculateSLOConvexHull(); 141 | void updateCornerCoords(); 142 | void updateCornerCoords(const CoordSLOmm& point); 143 | 144 | 145 | template 146 | static void callSubset(T& getSet, ParameterSet& p, const std::string& name) 147 | { 148 | T subSetGetSet = getSet.subSet(name); 149 | p.getSetParameter(subSetGetSet); 150 | } 151 | 152 | 153 | template 154 | static void getSetParameter(T& getSet, ParameterSet& p) 155 | { 156 | LateralityEnumWrapper lateralityWrapper (p.laterality ); 157 | ScanPatternEnumWrapper scanPatternWrapper (p.scanPattern ); 158 | ExaminedStructureEnumWrapper examinedStructureWrapper(p.examinedStructure); 159 | 160 | 161 | DateWrapper scanDateWrapper(p.scanDate); 162 | 163 | getSet("seriesUID" , p.seriesUID ); 164 | getSet("refSeriesID" , p.refSeriesID ); 165 | getSet("scanFocus" , p.scanFocus ); 166 | getSet("scanPatternText" , p.scanPatternText ); 167 | getSet("examinedStructureText", p.examinedStructureText ); 168 | getSet("description" , p.description ); 169 | getSet("scanDate" , static_cast(scanDateWrapper )); 170 | getSet("laterality" , static_cast(lateralityWrapper )); 171 | getSet("scanPattern" , static_cast(scanPatternWrapper )); 172 | getSet("examinedStructure" , static_cast(examinedStructureWrapper)); 173 | 174 | callSubset(getSet, p.analyseGrid, "analyseGrid"); 175 | } 176 | 177 | }; 178 | 179 | } 180 | -------------------------------------------------------------------------------- /octdata/datastruct/sloimage.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "sloimage.h" 19 | 20 | 21 | #include 22 | 23 | 24 | namespace OctData 25 | { 26 | SloImage::SloImage() 27 | : image(new cv::Mat) 28 | { 29 | 30 | } 31 | 32 | 33 | SloImage::~SloImage() 34 | { 35 | delete image; 36 | } 37 | 38 | 39 | void SloImage::setImage(const cv::Mat& image) 40 | { 41 | *(this->image) = image; 42 | } 43 | 44 | int SloImage::getHeight() const 45 | { 46 | if(image) 47 | return image->rows; 48 | return 0; 49 | } 50 | 51 | int SloImage::getWidth() const 52 | { 53 | if(image) 54 | return image->cols; 55 | return 0; 56 | } 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /octdata/datastruct/sloimage.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "coordslo.h" 21 | 22 | namespace cv { class Mat; } 23 | 24 | 25 | 26 | #ifdef OCTDATA_EXPORT 27 | #include "octdata_EXPORTS.h" 28 | #else 29 | #define Octdata_EXPORTS 30 | #endif 31 | 32 | namespace OctData 33 | { 34 | class SloImage 35 | { 36 | cv::Mat* image = nullptr; 37 | // std::string filename; 38 | 39 | ScaleFactor scaleFactor; 40 | CoordSLOpx shift; 41 | CoordTransform transform; 42 | 43 | int numAverage = 0 ; 44 | int imageQuality = 0 ; 45 | 46 | template 47 | static void callSubset(T& getSet, ParameterSet& p, const std::string& name) 48 | { 49 | T subSetGetSet = getSet.subSet(name); 50 | p.getSetParameter(subSetGetSet); 51 | } 52 | 53 | template 54 | static void getSetParameter(T& getSet, ParameterSet& p) 55 | { 56 | getSet("numAverage" , p.numAverage ); 57 | getSet("imageQuality", p.imageQuality); 58 | 59 | callSubset(getSet, p.scaleFactor, "scaleFactor"); 60 | callSubset(getSet, p.shift , "shift_px" ); 61 | callSubset(getSet, p.transform , "transform" ); 62 | } 63 | 64 | public: 65 | Octdata_EXPORTS SloImage(); 66 | Octdata_EXPORTS ~SloImage(); 67 | 68 | SloImage(const SloImage& other) = delete; 69 | SloImage& operator=(const SloImage& other) = delete; 70 | 71 | const cv::Mat& getImage() const { return *image ; } 72 | Octdata_EXPORTS void setImage(const cv::Mat& image); 73 | 74 | // const std::string& getFilename() const { return filename ; } 75 | // void setFilename(const std::string& s) { filename = s ; } 76 | 77 | const ScaleFactor& getScaleFactor() const { return scaleFactor ; } 78 | const CoordSLOpx& getShift() const { return shift ; } 79 | const CoordTransform& getTransform() const { return transform ; } 80 | void setScaleFactor(const ScaleFactor& f) { scaleFactor = f ; } 81 | void setShift (const CoordSLOpx& s) { shift = s ; } 82 | void setTransform (const CoordTransform& t) { transform = t ; } 83 | 84 | int getNumAverage() const { return numAverage ; } 85 | int getImageQuality() const { return imageQuality ; } 86 | 87 | bool hasImage() const { return image ; } 88 | Octdata_EXPORTS int getWidth() const; 89 | Octdata_EXPORTS int getHeight() const; 90 | 91 | template void getSetParameter(T& getSet) { getSetParameter(getSet, *this); } 92 | template void getSetParameter(T& getSet) const { getSetParameter(getSet, *this); } 93 | }; 94 | } 95 | -------------------------------------------------------------------------------- /octdata/datastruct/study.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "substructure_template.h" 21 | #include "series.h" 22 | 23 | namespace OctData 24 | { 25 | class Study : public SubstructureTemplate 26 | { 27 | std::string studyUID ; 28 | std::string studyName ; 29 | std::string studyOperator; 30 | Date studyDate ; 31 | const int internalId ; 32 | 33 | template 34 | static void getSetParameter(T& getSet, ParameterSet& p) 35 | { 36 | DateWrapper studyDateWrapper(p.studyDate); 37 | 38 | getSet("studyUID" , p.studyUID ); 39 | getSet("studyName" , p.studyName ); 40 | getSet("studyOperator", p.studyOperator ); 41 | getSet("studyDate" , static_cast(studyDateWrapper)); 42 | // getSet("internalId" , p.internalId ); 43 | } 44 | 45 | public: 46 | explicit Study(int internalId) : internalId(internalId) {} 47 | 48 | Series& getInsertId(int id) { return getAndInsert(id) ; } 49 | 50 | Series& getSeries(int seriesId) { return getAndInsert (seriesId) ; } 51 | const Series& getSeries(int seriesId) const { return *(substructureMap.at(seriesId)); } 52 | 53 | const std::string& getStudyUID() const { return studyUID; } 54 | void setStudyUID(const std::string& uid) { studyUID = uid; } 55 | 56 | 57 | const std::string& getStudyName() const { return studyName; } 58 | void setStudyName(const std::string& name) { studyName = name; } 59 | 60 | 61 | const std::string& getStudyOperator() const { return studyOperator; } 62 | const Date& getStudyDate() const { return studyDate ; } 63 | 64 | void setStudyOperator(const std::string& s) { studyOperator = s; } 65 | void setStudyDate (const Date& d) { studyDate = d; } 66 | 67 | int getInternalId() const { return internalId; } 68 | 69 | 70 | template void getSetParameter(T& getSet) { getSetParameter(getSet, *this); } 71 | template void getSetParameter(T& getSet) const { getSetParameter(getSet, *this); } 72 | }; 73 | 74 | } 75 | -------------------------------------------------------------------------------- /octdata/datastruct/substructure_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | 23 | #ifdef OCTDATA_EXPORT 24 | #include "octdata_EXPORTS.h" 25 | #else 26 | #define Octdata_EXPORTS 27 | #endif 28 | 29 | namespace OctData 30 | { 31 | 32 | template 33 | class SubstructureTemplate 34 | { 35 | SubstructureTemplate(const SubstructureTemplate&) = delete; 36 | SubstructureTemplate& operator=(const SubstructureTemplate&) = delete; 37 | public: 38 | Octdata_EXPORTS SubstructureTemplate() = default; 39 | Octdata_EXPORTS SubstructureTemplate(SubstructureTemplate&& o) { swapSubstructure(o); } 40 | 41 | SubstructureTemplate& operator=(SubstructureTemplate&& o) { swapSubstructure(o); return *this; } 42 | 43 | typedef Type SubstructureType; 44 | typedef std::pair SubstructurePair; 45 | typedef std::map SubstructureMap; 46 | typedef typename SubstructureMap::iterator SubstructureIterator; 47 | typedef typename SubstructureMap::const_iterator SubstructureCIterator; 48 | 49 | Octdata_EXPORTS std::size_t subStructureElements() const { return substructureMap.size(); } 50 | 51 | Octdata_EXPORTS SubstructureCIterator begin() const { return substructureMap.begin(); } 52 | Octdata_EXPORTS SubstructureCIterator end() const { return substructureMap.end(); } 53 | Octdata_EXPORTS SubstructureIterator begin() { return substructureMap.begin(); } 54 | Octdata_EXPORTS SubstructureIterator end() { return substructureMap.end(); } 55 | Octdata_EXPORTS std::size_t size() const { return substructureMap.size(); } 56 | 57 | protected: 58 | void swapSubstructure(SubstructureTemplate& d) { substructureMap.swap(d.substructureMap); } 59 | 60 | virtual ~SubstructureTemplate() 61 | { 62 | for(SubstructurePair obj : substructureMap) 63 | delete obj.second; 64 | } 65 | 66 | Type& getAndInsert(IndexType id) 67 | { 68 | SubstructureIterator it = substructureMap.find(id); 69 | if(it == substructureMap.end()) 70 | { 71 | std::pair pit = substructureMap.emplace(id, new Type(id)); 72 | if(pit.second == false) 73 | throw "SubstructureTemplate pit.second == false"; 74 | return *((pit.first)->second); 75 | } 76 | return *(it->second); 77 | }; 78 | 79 | void clearSubstructure() 80 | { 81 | for(SubstructurePair obj : substructureMap) 82 | delete obj.second; 83 | substructureMap.clear(); 84 | } 85 | 86 | 87 | SubstructureMap substructureMap; 88 | }; 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /octdata/export/cirrus_raw/cirrusrawexport.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "cirrusrawexport.h" 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | 43 | namespace bfs = boost::filesystem; 44 | 45 | 46 | namespace OctData 47 | { 48 | namespace 49 | { 50 | void writeFliped(const cv::Mat& bscan, uint8_t* dest, std::size_t sizeX, std::size_t sizeY) 51 | { 52 | if(bscan.type() != cv::DataType::type || bscan.channels() != 1) 53 | return; 54 | 55 | if(bscan.cols != static_cast(sizeX)) BOOST_LOG_TRIVIAL(warning) << "CirrusRawExport: cols != sizeX " << bscan.cols << " != " << sizeX; 56 | if(bscan.rows != static_cast(sizeY)) BOOST_LOG_TRIVIAL(warning) << "CirrusRawExport: cols != sizeX " << bscan.rows << " != " << sizeY; 57 | 58 | const int cols = std::min(bscan.cols, static_cast(sizeX)); 59 | const int rows = std::min(bscan.rows, static_cast(sizeY)); 60 | 61 | for(int r = 0; r < rows; ++r) 62 | { 63 | const uint8_t* sourceIt = bscan.ptr(r); 64 | uint8_t* destIt = dest+(rows-r)*sizeX; 65 | for(int c = 0; c < cols; ++c) 66 | { 67 | --destIt; 68 | *destIt = *sourceIt; 69 | ++sourceIt; 70 | } 71 | } 72 | } 73 | 74 | inline std::string avoidEmptyString(const std::string& str) 75 | { 76 | if(str.empty()) 77 | return "undef"; 78 | return str; 79 | } 80 | } 81 | 82 | bool CirrusRawExport::writeFile(const boost::filesystem::path& file, const OctData::OCT& oct, const OctData::FileWriteOptions& opt) 83 | { 84 | OCT::SubstructureCIterator pat = oct.begin(); 85 | const Patient* p = pat->second; 86 | if(!p) 87 | return false; 88 | 89 | Patient::SubstructureCIterator study = p->begin(); 90 | const Study* s = study->second; 91 | if(!s) 92 | return false; 93 | 94 | Study::SubstructureCIterator series = s->begin(); 95 | const Series* ser = series->second; 96 | 97 | if(!ser) 98 | return false; 99 | 100 | return writeFile(file, oct, *p, *s, *ser, opt); 101 | } 102 | 103 | 104 | bool CirrusRawExport::writeFile(const boost::filesystem::path& file 105 | , const OCT& /*oct*/ 106 | , const Patient& pat 107 | , const Study& study 108 | , const Series& series 109 | , const FileWriteOptions& /*opt*/) 110 | { 111 | // P1270HZ_Optic Disc Cube 200x200_9-21-2010_11-42-13_OS_sn0415_cube_raw.img 112 | 113 | const BScan* bscan = series.getBScan(0); 114 | if(!bscan) 115 | return false; 116 | 117 | const std::size_t cubeSizeX = bscan->getImage().cols; 118 | const std::size_t cubeSizeY = bscan->getImage().rows; 119 | const std::size_t cubeSizeZ = series.bscanCount(); 120 | 121 | Series::Laterality eyeSide = series.getLaterality(); 122 | Series::LateralityEnumWrapper lateralityWrapper(eyeSide); 123 | 124 | Date date = series.getScanDate(); 125 | if(date.isEmpty()) 126 | date = study.getStudyDate(); 127 | if(date.isEmpty()) 128 | date = Date::fromUnixTime(0); 129 | 130 | const std::string patient_id = avoidEmptyString(pat.getId()); 131 | std::string scantype = ""; 132 | const std::string scan_date1 = avoidEmptyString(date.strUsDate('-')); 133 | const std::string scan_date2 = avoidEmptyString(date.strTime('-') ); 134 | std::string eye_side = avoidEmptyString(static_cast(lateralityWrapper)); 135 | const std::string sn = "sn1234"; 136 | std::string cube = ""; 137 | const std::string filetype = "raw"; 138 | 139 | switch(series.getExaminedStructure()) 140 | { 141 | case Series::ExaminedStructure::ONH: 142 | scantype += "Optic Disc"; 143 | break; 144 | case Series::ExaminedStructure::Retina: 145 | scantype += "Macular"; 146 | break; 147 | case Series::ExaminedStructure::Text: 148 | scantype += series.getExaminedStructureText(); 149 | break; 150 | case Series::ExaminedStructure::Unknown: 151 | scantype += "Unknown"; 152 | break; 153 | } 154 | 155 | scantype += " "; 156 | 157 | Series::ScanPattern scanPattern = series.getScanPattern(); 158 | switch(series.getScanPattern()) 159 | { 160 | case Series::ScanPattern::Volume: 161 | case Series::ScanPattern::FastVolume: 162 | scantype += "Cube"; 163 | cube = "cube"; 164 | break; 165 | case Series::ScanPattern::Text: 166 | scantype += series.getScanPatternText(); 167 | cube = series.getScanPatternText(); 168 | break; 169 | default: 170 | { 171 | Series::ScanPatternEnumWrapper scanpatternWrapper(scanPattern); 172 | scantype += static_cast(scanpatternWrapper); 173 | cube = static_cast(scanpatternWrapper); 174 | } 175 | } 176 | 177 | scantype += " "; 178 | scantype += boost::lexical_cast(cubeSizeX) + "x" + boost::lexical_cast(cubeSizeZ); 179 | 180 | std::string filename = patient_id + '_' 181 | + scantype + '_' 182 | + scan_date1 + '_' 183 | + scan_date2 + '_' 184 | + eye_side + '_' 185 | + sn + '_' 186 | + cube + '_' 187 | + filetype + ".img"; 188 | 189 | bfs::path exportpath = file.branch_path() / filename; 190 | 191 | std::ofstream stream(exportpath.generic_string(), std::ios_base::binary); 192 | 193 | std::unique_ptr cache(new uint8_t[cubeSizeX*cubeSizeY*cubeSizeZ]); 194 | uint8_t* cacheIt = cache.get(); 195 | 196 | const OctData::Series::BScanList& bscans = series.getBScans(); 197 | OctData::Series::BScanList::const_reverse_iterator beginIt = bscans.crbegin(); 198 | const OctData::Series::BScanList::const_reverse_iterator endIt = bscans.crend(); 199 | 200 | // OctData::Series::BScanList::const_iterator beginIt = bscans.cbegin(); 201 | // const OctData::Series::BScanList::const_iterator endIt = bscans.cend(); 202 | 203 | while(endIt != beginIt) 204 | { 205 | if(*beginIt) 206 | writeFliped((*beginIt)->getImage(), cacheIt, cubeSizeX, cubeSizeY); 207 | 208 | cacheIt += cubeSizeX*cubeSizeY; 209 | ++beginIt; 210 | } 211 | 212 | stream.write(reinterpret_cast(cache.get()), cubeSizeX*cubeSizeY*cubeSizeZ); 213 | 214 | 215 | return true; 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /octdata/export/cirrus_raw/cirrusrawexport.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | namespace boost { namespace filesystem { class path; } } 21 | 22 | 23 | namespace OctData 24 | { 25 | class OCT; 26 | class Study; 27 | class Series; 28 | class Patient; 29 | class FileWriteOptions; 30 | 31 | class CirrusRawExport 32 | { 33 | public: 34 | static bool writeFile(const boost::filesystem::path& file, const OCT& oct, const FileWriteOptions& opt); 35 | static bool writeFile(const boost::filesystem::path& file, const OCT& oct, const Patient& pat, const Study& study, const Series& series, const FileWriteOptions& opt); 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /octdata/export/cvbin/cvbinoctwrite.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "cvbinoctwrite.h" 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | 43 | namespace bfs = boost::filesystem; 44 | 45 | 46 | namespace OctData 47 | { 48 | namespace 49 | { 50 | // general export methods 51 | void writeSlo(CppFW::CVMatTree& sloNode, const SloImage& slo) 52 | { 53 | CppFW::SetToCVMatTree sloWriter(sloNode); 54 | slo.getSetParameter(sloWriter); 55 | sloNode.getDirNode("img").getMat() = slo.getImage(); 56 | } 57 | 58 | void writeImage(CppFW::CVMatTree& tree, const cv::Mat& image, const std::string& nodeName) 59 | { 60 | if(image.empty()) 61 | return; 62 | 63 | CppFW::CVMatTree& imgNode = tree.getDirNode(nodeName); 64 | imgNode.getMat() = image; 65 | } 66 | 67 | void writeBScan(CppFW::CVMatTree& seriesNode, const BScan* bscan) 68 | { 69 | if(!bscan) 70 | return; 71 | 72 | CppFW::CVMatTree& bscanNode = seriesNode.newListNode(); 73 | writeImage(bscanNode, bscan->getImage() , "img" ); 74 | writeImage(bscanNode, bscan->getAngioImage(), "angioImg"); 75 | 76 | CppFW::CVMatTree& bscanDataNode = bscanNode.getDirNode("data"); 77 | CppFW::SetToCVMatTree bscanWriter(bscanDataNode); 78 | bscan->getSetParameter(bscanWriter); 79 | 80 | CppFW::CVMatTree& bscanSegNode = bscanNode.getDirNode("segmentations"); 81 | 82 | for(OctData::Segmentationlines::SegmentlineType type : OctData::Segmentationlines::getSegmentlineTypes()) 83 | { 84 | const Segmentationlines::Segmentline& seg = bscan->getSegmentLine(type); 85 | if(!seg.empty()) 86 | bscanSegNode.getDirNode(Segmentationlines::getSegmentlineName(type)).getMat() = cv::Mat(1, static_cast(seg.size()), cv::DataType::type, const_cast(seg.data())).clone(); 87 | } 88 | } 89 | 90 | // deep file format (support many scans per file, tree structure) 91 | template 92 | bool writeStructure(CppFW::CVMatTree& tree, const S& structure) 93 | { 94 | bool result = true; 95 | CppFW::CVMatTree& dataNode = tree.getDirNode("data"); 96 | // CppFW::CVMatTree& subNodeList = tree.getDirNode("Sub"); // TODO 97 | CppFW::SetToCVMatTree structureWriter(dataNode); 98 | structure.getSetParameter(structureWriter); 99 | 100 | for(typename S::SubstructurePair const& subStructPair : structure) 101 | { 102 | CppFW::CVMatTree& subNode = tree.getDirNode("id_" + boost::lexical_cast(subStructPair.first)); 103 | result &= writeStructure(subNode, *subStructPair.second); 104 | } 105 | return result; 106 | } 107 | 108 | 109 | template<> 110 | bool writeStructure(CppFW::CVMatTree& tree, const Series& series) 111 | { 112 | CppFW::CVMatTree& seriesDataNode = tree.getDirNode("data"); 113 | CppFW::SetToCVMatTree seriesWriter(seriesDataNode); 114 | series.getSetParameter(seriesWriter); 115 | 116 | 117 | writeSlo(tree.getDirNode("slo"), series.getSloImage()); 118 | 119 | CppFW::CVMatTree& seriesNode = tree.getDirNode("bscans"); 120 | 121 | for(BScan* bscan : series.getBScans()) 122 | writeBScan(seriesNode, bscan); 123 | 124 | return true; 125 | } 126 | 127 | 128 | // flat file format (only one scan per file) 129 | bool writeFlatFile(CppFW::CVMatTree& octtree, const Patient& pat, const Study& study, const Series& series) 130 | { 131 | CppFW::CVMatTree& patDataNode = octtree.getDirNode("patientData"); 132 | CppFW::CVMatTree& studyDataNode = octtree.getDirNode("studyData" ); 133 | CppFW::CVMatTree& seriesDataNode = octtree.getDirNode("seriesData" ); 134 | 135 | CppFW::CVMatTreeExtra::setCvScalar(patDataNode , "ID", pat .getInternalId()); 136 | CppFW::CVMatTreeExtra::setCvScalar(studyDataNode , "ID", study .getInternalId()); 137 | CppFW::CVMatTreeExtra::setCvScalar(seriesDataNode, "ID", series.getInternalId()); 138 | 139 | CppFW::SetToCVMatTree patientWriter(patDataNode); 140 | pat.getSetParameter(patientWriter); 141 | 142 | CppFW::SetToCVMatTree studyWriter(studyDataNode); 143 | study.getSetParameter(studyWriter); 144 | 145 | CppFW::SetToCVMatTree seriesWriter(seriesDataNode); 146 | series.getSetParameter(seriesWriter); 147 | 148 | writeSlo(octtree.getDirNode("slo"), series.getSloImage()); 149 | 150 | CppFW::CVMatTree& seriesNode = octtree.getDirNode("serie"); 151 | for(BScan* bscan : series.getBScans()) 152 | writeBScan(seriesNode, bscan); 153 | 154 | return true; 155 | } 156 | 157 | bool writeFlatFile(CppFW::CVMatTree& octtree, const OCT& oct) 158 | { 159 | OCT::SubstructureCIterator pat = oct.begin(); 160 | const Patient* p = pat->second; 161 | if(!p) 162 | return false; 163 | 164 | Patient::SubstructureCIterator study = p->begin(); 165 | const Study* s = study->second; 166 | if(!s) 167 | return false; 168 | 169 | Study::SubstructureCIterator series = s->begin(); 170 | const Series* ser = series->second; 171 | 172 | if(!ser) 173 | return false; 174 | 175 | return writeFlatFile(octtree, *p, *s, *ser); 176 | } 177 | 178 | } 179 | 180 | void setStringOpt(CppFW::CVMatTree& tree, const char* nodeName, const std::string& value) 181 | { 182 | if(!value.empty()) 183 | tree.getDirNode(nodeName).getString() = value; 184 | } 185 | 186 | bool CvBinOctWrite::writeFile(const boost::filesystem::path& file, const OCT& oct, const FileWriteOptions& opt) 187 | { 188 | CppFW::CVMatTree octtree; 189 | 190 | bool result; 191 | if(opt.octBinFlat) 192 | result = writeFlatFile(octtree, oct); 193 | else 194 | result = writeStructure(octtree, oct); 195 | 196 | // if(result) 197 | result &= CppFW::CVMatTreeStructBin::writeBin(file.generic_string(), octtree); 198 | 199 | return result; 200 | } 201 | 202 | } 203 | -------------------------------------------------------------------------------- /octdata/export/cvbin/cvbinoctwrite.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | namespace boost { namespace filesystem { class path; } } 21 | 22 | 23 | namespace OctData 24 | { 25 | class OCT; 26 | class Study; 27 | class Series; 28 | class Patient; 29 | class FileWriteOptions; 30 | 31 | class CvBinOctWrite 32 | { 33 | public: 34 | 35 | static bool writeFile(const boost::filesystem::path& file, const OCT& oct, const FileWriteOptions& opt); 36 | }; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /octdata/export/xoct/xoctwrite.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "xoctwrite.h" 19 | 20 | #include 21 | 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | #include 33 | 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include 42 | 43 | namespace bpt = boost::property_tree; 44 | 45 | 46 | 47 | namespace OctData 48 | { 49 | namespace 50 | { 51 | class SetToPTree 52 | { 53 | bpt::ptree& tree; 54 | public: 55 | SetToPTree(bpt::ptree& tree) : tree(tree) {} 56 | 57 | template 58 | void operator()(const std::string& name, const T& value) 59 | { 60 | tree.add(name, value); 61 | } 62 | 63 | template 64 | void operator()(const std::string& name, const std::vector& value) 65 | { 66 | std::ostringstream sstream; 67 | for(const T& val : value) 68 | sstream << val << ' '; 69 | tree.add(name, sstream.str()); 70 | } 71 | 72 | void operator()(const std::string& name, const std::string& value) 73 | { 74 | if(value.empty()) 75 | return; 76 | tree.add(name, value); 77 | } 78 | 79 | SetToPTree subSet(const std::string& name) 80 | { 81 | return SetToPTree(tree.add(name, "")); 82 | } 83 | }; 84 | 85 | template 86 | std::string getSubStructureName() 87 | { 88 | std::string name = boost::typeindex::type_id().pretty_name(); 89 | std::size_t namePos = name.rfind(':'); 90 | if(namePos > 0) 91 | ++namePos; 92 | return name.substr(namePos, name.size() - namePos); 93 | } 94 | 95 | class XOctWritter 96 | { 97 | CppFW::ZipCpp& zipfile; 98 | // const OctData::FileWriteOptions& opt; 99 | std::string imageExtention; 100 | bool compressImage = false; 101 | public: 102 | XOctWritter(CppFW::ZipCpp& zipfile 103 | , const OctData::FileWriteOptions& opt) 104 | : zipfile(zipfile) 105 | // , opt(opt) 106 | { 107 | switch(opt.xoctImageFormat) 108 | { 109 | case FileWriteOptions::XoctImageFormat::png: 110 | imageExtention = ".png"; 111 | break; 112 | case FileWriteOptions::XoctImageFormat::tiff: 113 | imageExtention = ".tiff"; 114 | break; 115 | case FileWriteOptions::XoctImageFormat::zippedBMP: 116 | compressImage = true; 117 | // [[fallthrough]]; 118 | case FileWriteOptions::XoctImageFormat::bmp: 119 | imageExtention = ".bmp"; 120 | break; 121 | } 122 | } 123 | 124 | void writeImage(bpt::ptree& node, const cv::Mat& image, const std::string& filename, const std::string& imageName) 125 | { 126 | if(image.empty()) 127 | return; 128 | 129 | std::vector buffer; 130 | cv::imencode(imageExtention, image, buffer); 131 | zipfile.addFile(filename, buffer.data(), buffer.size(), compressImage); 132 | node.add(imageName, filename); 133 | } 134 | 135 | void writeXml(const std::string& filename, bpt::ptree& xmlTree) 136 | { 137 | std::stringstream stream; 138 | bpt::write_xml(stream, xmlTree, bpt::xml_writer_make_settings('\t', 1u)); 139 | std::string xmlString = stream.str(); 140 | zipfile.addFile(filename, xmlString.data(), static_cast(xmlString.size())); 141 | } 142 | 143 | 144 | template 145 | void writeParameter(bpt::ptree& tree, const S& structure) 146 | { 147 | bpt::ptree& dataNode = tree.add("data", ""); 148 | SetToPTree parameterWriter(dataNode); 149 | structure.getSetParameter(parameterWriter); 150 | } 151 | 152 | // general export methods 153 | void writeSlo(bpt::ptree& sloNode, const SloImage& slo, const std::string& dataPath) 154 | { 155 | writeParameter(sloNode, slo); 156 | writeImage(sloNode, slo.getImage(), dataPath + "slo" + imageExtention, "image"); 157 | } 158 | 159 | 160 | void writeSegmentation(bpt::ptree& segNode, const Segmentationlines& seglines) 161 | { 162 | SetToPTree set(segNode); 163 | for(OctData::Segmentationlines::SegmentlineType type : OctData::Segmentationlines::getSegmentlineTypes()) 164 | { 165 | const Segmentationlines::Segmentline& seg = seglines.getSegmentLine(type); 166 | if(!seg.empty()) 167 | set(Segmentationlines::getSegmentlineName(type), seg); 168 | } 169 | } 170 | 171 | 172 | void writeBScan(bpt::ptree& seriesNode, const BScan* bscan, std::size_t bscanNum, const std::string& dataPath) 173 | { 174 | if(!bscan) 175 | return; 176 | 177 | std::string numString = boost::lexical_cast(bscanNum); 178 | 179 | bpt::ptree& bscanNode = seriesNode.add("BScan", ""); 180 | writeParameter(bscanNode, *bscan); 181 | writeImage(bscanNode, bscan->getImage() , dataPath + "bscan_" + numString + imageExtention, "image" ); 182 | writeImage(bscanNode, bscan->getAngioImage(), dataPath + "bscanAngio_" + numString + imageExtention, "angioImage"); 183 | 184 | 185 | bpt::ptree seglinesTree; 186 | writeSegmentation(seglinesTree.add("LayerSegmentation", ""), bscan->getSegmentLines()); 187 | 188 | std::string segmentationFile = dataPath + "segmentation_" + numString + ".xml"; 189 | writeXml(segmentationFile, seglinesTree); 190 | bscanNode.add("LayerSegmentationFile", segmentationFile); 191 | } 192 | 193 | template 194 | class SubStrutureFileWriter 195 | { 196 | XOctWritter& parent; 197 | bool writeFiles; 198 | bpt::ptree& mainTree; 199 | std::unique_ptr subTree; 200 | const std::string& dataPath; 201 | std::string subTreeFilename; 202 | 203 | void finishSubTree() 204 | { 205 | if(!writeFiles || !subTree || subTreeFilename.empty()) 206 | return; 207 | 208 | parent.writeXml(subTreeFilename, *subTree); 209 | } 210 | 211 | public: 212 | SubStrutureFileWriter(XOctWritter& parent, bpt::ptree& mainTree, const std::string& dataPath, const S& structure) 213 | : parent(parent) 214 | , writeFiles(structure.size() > 1) 215 | , mainTree(mainTree) 216 | , dataPath(dataPath) 217 | { } 218 | 219 | ~SubStrutureFileWriter() 220 | { 221 | finishSubTree(); 222 | } 223 | 224 | 225 | bpt::ptree& getTree(const std::string& nameId, const std::size_t id) 226 | { 227 | const std::string structureName = getSubStructureName(); 228 | bpt::ptree& subNode = mainTree.add(structureName, ""); 229 | subNode.add("id", boost::lexical_cast(id)); 230 | 231 | if(writeFiles) 232 | { 233 | finishSubTree(); 234 | subTreeFilename = dataPath + nameId + ".xml"; 235 | subNode.add("filename", subTreeFilename); 236 | subTree.reset(new bpt::ptree); 237 | 238 | bpt::ptree& newTree = subTree->add(structureName, ""); 239 | newTree.add("id", boost::lexical_cast(id)); 240 | return newTree; 241 | } 242 | else 243 | { 244 | return subNode; 245 | } 246 | } 247 | }; 248 | 249 | template 250 | bool writeStructure(bpt::ptree& tree, const std::string& dataPath, const S& structure) 251 | { 252 | bool result = true; 253 | writeParameter(tree, structure); 254 | 255 | SubStrutureFileWriter writer(*this, tree, dataPath, structure); 256 | 257 | for(typename S::SubstructurePair const& subStructPair : structure) 258 | { 259 | const std::string structureName = getSubStructureName(); 260 | const std::string structureNameId = structureName + '_' + boost::lexical_cast(subStructPair.first); 261 | 262 | bpt::ptree& subNode = writer.getTree(structureNameId, subStructPair.first); 263 | // bpt::ptree& subNode = tree.add(structureName, ""); 264 | // subNode.add("id", boost::lexical_cast(subStructPair.first)); 265 | 266 | std::string subDataPath = dataPath + structureNameId + '/'; 267 | result &= writeStructure(subNode, subDataPath, *subStructPair.second); 268 | } 269 | return result; 270 | } 271 | 272 | }; 273 | 274 | template<> 275 | bool XOctWritter::writeStructure(bpt::ptree& tree, const std::string& dataPath, const Series& series) 276 | { 277 | writeParameter(tree, series); 278 | writeSlo(tree.add("slo", ""), series.getSloImage(), dataPath); 279 | 280 | std::size_t bscanNum = 0; 281 | for(BScan* bscan : series.getBScans()) 282 | writeBScan(tree, bscan, bscanNum++, dataPath); 283 | 284 | return true; 285 | } 286 | } 287 | 288 | 289 | 290 | bool XOctWrite::writeFile(const boost::filesystem::path& file, const OctData::OCT& oct, const OctData::FileWriteOptions& opt) 291 | { 292 | CppFW::ZipCpp zipfile(file.generic_string()); 293 | 294 | bpt::ptree xmlTree; 295 | std::string dataPath; 296 | 297 | XOctWritter writter(zipfile, opt); 298 | 299 | bpt::ptree& octTree = xmlTree.add("XOCT", ""); 300 | if(!writter.writeStructure(octTree, dataPath, oct)) 301 | return false; 302 | 303 | writter.writeXml("xoct.xml", xmlTree); 304 | 305 | return true; 306 | } 307 | } 308 | -------------------------------------------------------------------------------- /octdata/export/xoct/xoctwrite.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | namespace boost { namespace filesystem { class path; } } 21 | 22 | 23 | namespace OctData 24 | { 25 | class OCT; 26 | class Study; 27 | class Series; 28 | class Patient; 29 | class FileWriteOptions; 30 | 31 | class XOctWrite 32 | { 33 | public: 34 | static bool writeFile(const boost::filesystem::path& file, const OCT& oct, const FileWriteOptions& opt); 35 | }; 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /octdata/filereader/filereader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "filereader.h" 19 | 20 | #include 21 | 22 | #include"filestreamdircet.h" 23 | #include"filestreamgzip.h" 24 | #include 25 | 26 | namespace bfs = boost::filesystem; 27 | 28 | namespace OctData 29 | { 30 | 31 | FileReader::FileReader(const boost::filesystem::path& filepath) 32 | : filepath(filepath) 33 | { 34 | const boost::filesystem::path ext = filepath.extension(); 35 | if(filepath.extension() == ".gz") 36 | { 37 | compressType = Compressed::gzip; 38 | extension = filepath.stem().extension(); 39 | } 40 | else 41 | { 42 | compressType = Compressed::none; 43 | extension = ext; 44 | } 45 | } 46 | 47 | FileReader::~FileReader() 48 | { 49 | delete fileStream; 50 | } 51 | 52 | bool OctData::FileReader::openFile() 53 | { 54 | delete fileStream; 55 | fileStream = nullptr; 56 | switch(compressType) 57 | { 58 | case Compressed::none: 59 | fileStream = new FileStreamDircet(filepath); 60 | break; 61 | case Compressed::gzip: 62 | #ifdef WITH_ZLIB 63 | fileStream = new FileStreamGZip(filepath); 64 | #endif 65 | break; 66 | } 67 | return fileStream != nullptr; 68 | } 69 | 70 | std::size_t FileReader::file_size() const 71 | { 72 | if(filesize == 0) 73 | { 74 | switch(compressType) 75 | { 76 | case Compressed::none: 77 | filesize = bfs::file_size(filepath); 78 | break; 79 | case Compressed::gzip: 80 | std::ifstream stream(filepathConv(filepath), std::ios::binary | std::ios::in); 81 | stream.seekg(-4, std::ios_base::end); 82 | unsigned int size; 83 | stream.read(reinterpret_cast(&size), sizeof(size)); 84 | boost::endian::little_to_native_inplace(size); 85 | filesize = size; 86 | break; 87 | } 88 | } 89 | 90 | return filesize; 91 | } 92 | 93 | 94 | 95 | 96 | } 97 | -------------------------------------------------------------------------------- /octdata/filereader/filereader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | 28 | #include 29 | 30 | namespace OctData 31 | { 32 | class FileStreamInterface 33 | { 34 | public: 35 | FileStreamInterface() {}; 36 | virtual ~FileStreamInterface() {}; 37 | 38 | virtual std::streamsize read(char* dest, std::streamsize size) = 0; 39 | virtual void seekg(std::streamoff pos) = 0; 40 | 41 | virtual bool good() const = 0; 42 | }; 43 | 44 | class FileReader 45 | { 46 | enum class Compressed { none, gzip }; 47 | 48 | const boost::filesystem::path filepath; 49 | boost::filesystem::path extension; 50 | 51 | mutable std::size_t filesize = 0; 52 | 53 | Compressed compressType; 54 | 55 | FileStreamInterface* fileStream = nullptr; 56 | 57 | template 58 | void readFStreamBigInt(T* dest, std::size_t num, std::true_type) 59 | { 60 | fileStream->read(reinterpret_cast(dest), sizeof(T)*num); 61 | for(std::size_t i = 0; i(&value))); } 67 | void convertFloatType(double& value) { boost::endian::big_to_native_inplace(*(reinterpret_cast(&value))); } 68 | 69 | template 70 | void readFStreamBigInt(T* dest, std::size_t num, std::false_type) // TODO: correct endian for floating types 71 | { 72 | readFStream(dest, num); 73 | for(std::size_t i = 0; iseekg(pos); } 88 | bool good() const { return fileStream->good(); } 89 | std::size_t file_size() const; 90 | 91 | 92 | template 93 | void readFStream(T* dest, std::size_t num = 1) { fileStream->read(reinterpret_cast(dest), sizeof(T)*num); } 94 | 95 | template 96 | void readFStreamBig(T* dest, std::size_t num = 1) { readFStreamBigInt(dest, num, std::is_integral()); } 97 | 98 | 99 | void readString(std::string& dest, std::size_t num = 1) 100 | { 101 | dest.resize(num); 102 | fileStream->read(const_cast(dest.data()), sizeof(std::string::value_type)*num); // TODO: c++17: remove const_cast 103 | } 104 | 105 | 106 | template 107 | void readCVImage(cv::Mat& image, std::size_t sizeX, std::size_t sizeY) 108 | { 109 | image = cv::Mat(static_cast(sizeX), static_cast(sizeY), cv::DataType::type); 110 | 111 | const std::size_t num = sizeX*sizeY; 112 | fileStream->read(reinterpret_cast(image.data), sizeof(T)*num); 113 | // stream.read(reinterpret_cast(image.data), num*sizeof(T)); 114 | } 115 | }; 116 | } 117 | -------------------------------------------------------------------------------- /octdata/filereader/filestreamdircet.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "filestreamdircet.h" 19 | 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | #include 26 | 27 | #include 28 | namespace bfs = boost::filesystem; 29 | 30 | namespace OctData 31 | { 32 | 33 | FileStreamDircet::FileStreamDircet(const boost::filesystem::path& filepath) 34 | { 35 | stream.open(filepathConv(filepath), std::ios::binary | std::ios::in); 36 | if(!stream.good()) 37 | { 38 | BOOST_LOG_TRIVIAL(error) << "Can't open file stream " << filepathConv(filepath); 39 | throw("Can't open file stream"); // TODO 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /octdata/filereader/filestreamdircet.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "filereader.h" 21 | #include 22 | 23 | namespace OctData 24 | { 25 | 26 | class FileStreamDircet : public FileStreamInterface 27 | { 28 | std::fstream stream; 29 | public: 30 | FileStreamDircet(const boost::filesystem::path& filepath); 31 | 32 | 33 | virtual std::streamsize read(char* dest, std::streamsize size) override 34 | { stream.read(dest, size); return size; } 35 | virtual void seekg(std::streamoff pos) override { stream.seekg(pos); } 36 | 37 | bool good() const override { return stream.good(); } 38 | 39 | }; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /octdata/filereader/filestreamgzip.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "filestreamgzip.h" 19 | 20 | 21 | #ifdef WITH_ZLIB 22 | 23 | namespace OctData 24 | { 25 | 26 | FileStreamGZip::FileStreamGZip(const boost::filesystem::path& filepath) 27 | { 28 | file = gzopen(filepath.generic_string().c_str(), "r"); 29 | gzbuffer(file, 128*1024); 30 | } 31 | 32 | FileStreamGZip::~FileStreamGZip() 33 | { 34 | gzclose(file); 35 | }; 36 | 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /octdata/filereader/filestreamgzip.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #ifdef WITH_ZLIB 21 | 22 | #include "filereader.h" 23 | #include 24 | 25 | 26 | namespace OctData 27 | { 28 | 29 | class FileStreamGZip : public FileStreamInterface 30 | { 31 | gzFile file; 32 | public: 33 | FileStreamGZip(const boost::filesystem::path& filepath); 34 | virtual ~FileStreamGZip(); 35 | 36 | 37 | virtual std::streamsize read(char* dest, std::streamsize size) override 38 | { return gzread(file, dest, static_cast(size)); } 39 | virtual void seekg(std::streamoff pos) override { gzseek(file, pos, SEEK_SET); } 40 | virtual bool good() const override { return !gzeof(file); } 41 | }; 42 | 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /octdata/filereadoptions.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include"filereadoptions.h" 19 | 20 | 21 | namespace OctData 22 | { 23 | template<> void FileReadOptions::E2eGrayTransformEnumWrapper::toString() 24 | { 25 | switch(obj) 26 | { 27 | case FileReadOptions::E2eGrayTransform::nativ: std::string::operator=("nativ"); break; 28 | case FileReadOptions::E2eGrayTransform::xml : std::string::operator=("xml" ); break; 29 | case FileReadOptions::E2eGrayTransform::vol : std::string::operator=("vol" ); break; 30 | case FileReadOptions::E2eGrayTransform::u16 : std::string::operator=("u16" ); break; 31 | } 32 | } 33 | 34 | template<> void FileReadOptions::E2eGrayTransformEnumWrapper::fromString() 35 | { 36 | if(*this == "nativ") obj = FileReadOptions::E2eGrayTransform::nativ; 37 | else if(*this == "xml" ) obj = FileReadOptions::E2eGrayTransform::xml; 38 | else if(*this == "vol" ) obj = FileReadOptions::E2eGrayTransform::vol; 39 | else if(*this == "u16" ) obj = FileReadOptions::E2eGrayTransform::u16; 40 | else obj = FileReadOptions::E2eGrayTransform::xml; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /octdata/filereadoptions.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include"datastruct/objectwrapper.h" 22 | 23 | namespace OctData 24 | { 25 | class FileReadOptions 26 | { 27 | public: 28 | enum class E2eGrayTransform { nativ, xml, vol, u16 }; 29 | typedef ObjectWrapper E2eGrayTransformEnumWrapper; 30 | 31 | bool fillEmptyPixelWhite = true; 32 | bool registerBScanns = true; 33 | bool rotateSlo = false; 34 | 35 | bool holdRawData = false; 36 | bool loadRefFiles = true; 37 | bool readBScans = true; 38 | 39 | bool dumpFileParts = false; 40 | 41 | E2eGrayTransform e2eGray = E2eGrayTransform::xml; 42 | 43 | std::string libPath; 44 | 45 | template void getSetParameter(T& getSet) { getSetParameter(getSet, *this); } 46 | template void getSetParameter(T& getSet) const { getSetParameter(getSet, *this); } 47 | 48 | private: 49 | template 50 | static void getSetParameter(T& getSet, ParameterSet& p) 51 | { 52 | E2eGrayTransformEnumWrapper e2eGrayWrapper(p.e2eGray); 53 | 54 | getSet("fillEmptyPixelWhite", p.fillEmptyPixelWhite ); 55 | getSet("registerBScanns" , p.registerBScanns ); 56 | getSet("rotateSlo" , p.rotateSlo ); 57 | getSet("holdRawData" , p.holdRawData ); 58 | getSet("loadRefFiles" , p.loadRefFiles ); 59 | getSet("readBScans" , p.readBScans ); 60 | getSet("e2eGrayTransform" , static_cast(e2eGrayWrapper)); 61 | } 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /octdata/filewriteoptions.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | 19 | #include"filewriteoptions.h" 20 | 21 | 22 | namespace OctData 23 | { 24 | template<> void FileWriteOptions::XoctImageFormatEnumWrapper::toString() 25 | { 26 | switch(obj) 27 | { 28 | case FileWriteOptions::XoctImageFormat::png : std::string::operator=("png" ); break; 29 | case FileWriteOptions::XoctImageFormat::tiff : std::string::operator=("tiff" ); break; 30 | case FileWriteOptions::XoctImageFormat::bmp : std::string::operator=("bmp" ); break; 31 | case FileWriteOptions::XoctImageFormat::zippedBMP: std::string::operator=("zippedBMP"); break; 32 | } 33 | } 34 | 35 | template<> void FileWriteOptions::XoctImageFormatEnumWrapper::fromString() 36 | { 37 | if(*this == "png" ) obj = FileWriteOptions::XoctImageFormat::png ; 38 | else if(*this == "tiff" ) obj = FileWriteOptions::XoctImageFormat::tiff ; 39 | else if(*this == "bmp" ) obj = FileWriteOptions::XoctImageFormat::bmp ; 40 | else if(*this == "zippedBMP") obj = FileWriteOptions::XoctImageFormat::zippedBMP; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /octdata/filewriteoptions.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include"datastruct/objectwrapper.h" 22 | 23 | 24 | namespace OctData 25 | { 26 | class FileWriteOptions 27 | { 28 | public: 29 | enum class XoctImageFormat { png, tiff, bmp, zippedBMP }; 30 | typedef ObjectWrapper XoctImageFormatEnumWrapper; 31 | 32 | 33 | bool octBinFlat = false; 34 | XoctImageFormat xoctImageFormat = XoctImageFormat::png; 35 | 36 | 37 | template void getSetParameter(T& getSet) { getSetParameter(getSet, *this); } 38 | template void getSetParameter(T& getSet) const { getSetParameter(getSet, *this); } 39 | 40 | private: 41 | template 42 | static void getSetParameter(T& getSet, ParameterSet& p) 43 | { 44 | XoctImageFormatEnumWrapper xoctImageFormat(p.xoctImageFormat); 45 | 46 | getSet("octBinFlat" , p.octBinFlat ); 47 | getSet("xoctImageFormat", static_cast(xoctImageFormat)); 48 | } 49 | }; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /octdata/import/cirrus_raw/cirrus_rawread.cpp: -------------------------------------------------------------------------------- 1 | #include "cirrus_rawread.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | #include 23 | 24 | namespace bfs = boost::filesystem; 25 | 26 | 27 | namespace 28 | { 29 | template 30 | void readCVImage(std::istream& stream, cv::Mat& image, std::size_t sizeX, std::size_t sizeY) 31 | { 32 | image = cv::Mat(static_cast(sizeX), static_cast(sizeY), cv::DataType::type); 33 | std::size_t num = sizeX*sizeY; 34 | stream.read(reinterpret_cast(image.data), num*sizeof(T)); 35 | } 36 | } 37 | 38 | 39 | namespace OctData 40 | { 41 | CirrusRawRead::CirrusRawRead() 42 | : OctFileReader(OctExtension{".img", ".img.gz", "Cirrus img files"}) 43 | { 44 | 45 | } 46 | 47 | bool CirrusRawRead::readFile(FileReader& filereader, OCT& oct, const FileReadOptions& /*op*/, CppFW::Callback* callback) 48 | { 49 | const boost::filesystem::path& file = filereader.getFilepath(); 50 | 51 | if(filereader.getExtension() != ".img") 52 | return false; 53 | 54 | BOOST_LOG_TRIVIAL(trace) << "Try to open OCT file as cirrus img"; 55 | 56 | if(!filereader.openFile()) 57 | { 58 | BOOST_LOG_TRIVIAL(error) << "Can't open cirrus img file " << filereader.getFilepath().generic_string(); 59 | return false; 60 | } 61 | /* 62 | if(file.extension() != ".img") 63 | return false; 64 | 65 | if(!bfs::exists(file)) 66 | return false; 67 | */ 68 | 69 | bool debug = false; 70 | 71 | // split filename in elements 72 | std::vector elements; 73 | std::string filenameString = filereader.getFilepath().filename().generic_string(); 74 | boost::split(elements, filenameString, boost::is_any_of("_"), boost::token_compress_on); 75 | 76 | if(debug) 77 | std::cout << "elements.size(): " << elements.size() << std::endl; 78 | 79 | if(elements.size() != 8) 80 | { 81 | BOOST_LOG_TRIVIAL(error) << "Can't open cirrus img file: false number of filename metadata " << elements.size() << " != 8"; 82 | for(const std::string& ele : elements) 83 | BOOST_LOG_TRIVIAL(error) << "Metadata: " << ele; 84 | return false; 85 | } 86 | 87 | const std::string& patient_id = elements.at(0); 88 | const std::string& scantype = elements.at(1); 89 | const std::string& scan_date1 = elements.at(2); 90 | const std::string& scan_date2 = elements.at(3); 91 | const std::string& eye_side = elements.at(4); 92 | const std::string& sn = elements.at(5); 93 | const std::string& cube = elements.at(6); 94 | const std::string& filetype = elements.at(7); 95 | 96 | if(debug) 97 | { 98 | std::cout << "patient_id: " << patient_id << std::endl; 99 | std::cout << "scantype : " << scantype << std::endl; 100 | std::cout << "scan_date1: " << scan_date1 << std::endl; 101 | std::cout << "scan_date2: " << scan_date2 << std::endl; 102 | std::cout << "eye_side : " << eye_side << std::endl; 103 | std::cout << "sn : " << sn << std::endl; 104 | std::cout << "cube : " << cube << std::endl; 105 | std::cout << "filetype : " << filetype << std::endl; 106 | } 107 | 108 | if(filetype.substr(0, 7) != "raw.img" && filetype.substr(0, 5) != "z.img") 109 | { 110 | BOOST_LOG_TRIVIAL(error) << "wring filetype (not raw.img or z.img): " << filetype.substr(0, 7); 111 | return false; 112 | } 113 | 114 | 115 | // split scantype in elements to find the scan size 116 | std::vector scantypeElements; 117 | boost::split(scantypeElements, scantype, boost::is_any_of(" "), boost::token_compress_on); 118 | 119 | if(debug) 120 | std::cout << "scantypeElements.size(): " << scantypeElements.size() << std::endl; 121 | if(scantypeElements.size() < 2) 122 | { 123 | BOOST_LOG_TRIVIAL(error) << "wrong format of scantype (type volsize) : " << scantype; 124 | return false; 125 | } 126 | 127 | std::vector scanSizeElements; 128 | const std::string& vol_size = scantypeElements.at(scantypeElements.size()-1); 129 | boost::split(scanSizeElements, vol_size, boost::is_any_of("x"), boost::token_compress_on); 130 | if(scanSizeElements.size() != 2) 131 | { 132 | BOOST_LOG_TRIVIAL(error) << "wrong format of scan size : " << vol_size; 133 | return false; 134 | } 135 | 136 | std::size_t volSizeX = boost::lexical_cast(scanSizeElements[0]); 137 | std::size_t volSizeY = boost::lexical_cast(scanSizeElements[1]); 138 | 139 | if(debug) 140 | std::cout << "vol_size " << volSizeX << " : " << volSizeY << std::endl; 141 | 142 | // TODO: 143 | /* 144 | if strcmp(cube,'hidef') 145 | num_bscan = 2; 146 | if strcmp(vol_info.scan_type,'Macular') 147 | num_ascan = 1024; 148 | elseif strcmp(vol_info.scan_type,'Optic Disc') 149 | num_ascan = 1000; 150 | end 151 | end 152 | */ 153 | 154 | // std::size_t filesize = bfs::file_size(file); 155 | std::size_t filesize = filereader.file_size(); 156 | std::size_t volSizeZ = filesize / volSizeX /volSizeY; 157 | 158 | const double cubeSizeX = 6; 159 | const double cubeSizeY = 6; 160 | const double cubeSizeZ = 2; 161 | 162 | const double scaleX = cubeSizeX/static_cast(volSizeX); 163 | const double scaleY = cubeSizeY/static_cast(volSizeY); 164 | const double scaleZ = cubeSizeZ/static_cast(volSizeZ); 165 | 166 | ScaleFactor sf(scaleX, scaleY, scaleZ); 167 | 168 | // // std::fstream stream(file.generic_string(), std::ios::binary | std::ios::in); 169 | // if(!stream.good()) 170 | // return false; 171 | 172 | Patient& pat = oct.getPatient(0); 173 | Series& series = pat.getStudy(0).getSeries(0); 174 | 175 | std::vector bscanList; 176 | 177 | BScan::Data data; 178 | data.scaleFactor = sf; 179 | for(std::size_t i = 0; icallback(static_cast(i)/static_cast(volSizeY))) 184 | break; 185 | } 186 | 187 | cv::Mat bscanImage; 188 | // readCVImage(stream, bscanImage, volSizeZ, volSizeX); 189 | filereader.readCVImage(bscanImage, volSizeZ, volSizeX); 190 | cv::flip(bscanImage, bscanImage, -1); 191 | 192 | bscanList.push_back(new BScan(bscanImage, data)); 193 | } 194 | 195 | for(std::vector::reverse_iterator it = bscanList.rbegin(); it != bscanList.rend(); ++it) 196 | series.takeBScan(*it); 197 | 198 | //------------ 199 | // load slo 200 | //------------ 201 | std::string fileString = file.generic_string(); 202 | std::size_t found = fileString.find_last_of("_"); 203 | found = fileString.find_last_of("_", found-1); 204 | std::string baseFilename = fileString.substr(0, found); 205 | 206 | bfs::path slofile(baseFilename + "_lslo.bin"); 207 | std::cout << slofile.generic_string() << std::endl; 208 | if(!bfs::exists(slofile)) 209 | return true; // bscans loaded successfull 210 | 211 | std::fstream streamSlo(slofile.generic_string(), std::ios::binary | std::ios::in); 212 | if(!streamSlo.good()) 213 | return true; // bscans loaded successfull 214 | 215 | cv::Mat sloImage; 216 | std::size_t filesizeSlo = bfs::file_size(slofile); 217 | 218 | std::size_t sloWidth = 512; 219 | readCVImage(streamSlo, sloImage, sloWidth, filesizeSlo/sloWidth); 220 | SloImage* slo = new SloImage; 221 | slo->setImage(sloImage); 222 | series.takeSloImage(slo); 223 | 224 | if(debug) 225 | std::cout << "slo: " << sloWidth << " x " << (filesizeSlo/sloWidth) << std::endl; 226 | return true; 227 | } 228 | 229 | 230 | } 231 | -------------------------------------------------------------------------------- /octdata/import/cirrus_raw/cirrus_rawread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../octfilereader.h" 4 | 5 | namespace OctData 6 | { 7 | class FileReadOptions; 8 | 9 | /** 10 | * hidef scan consists of 2 orthogonal bscans intersecting in the center of 11 | * the volume. The first is in the y direction (across B-scans), the second 12 | * is in the x direction (aligned with the center B-scan). Unfortunately, 13 | * they are not in good alignment with the volumetric data 14 | */ 15 | class CirrusRawRead : public OctFileReader 16 | { 17 | public: 18 | CirrusRawRead(); 19 | 20 | virtual bool readFile(FileReader& filereader, OCT& oct, const FileReadOptions& op, CppFW::Callback* callback) override; 21 | }; 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /octdata/import/cvbin/cvbinread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "../octfilereader.h" 5 | 6 | namespace OctData 7 | { 8 | class CvBinRead : public OctFileReader 9 | { 10 | public: 11 | CvBinRead(); 12 | 13 | virtual bool readFile(FileReader& filereader, OCT& oct, const FileReadOptions& op, CppFW::Callback* callback) override; 14 | }; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /octdata/import/dicom/dicomread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../octfilereader.h" 5 | 6 | #include 7 | 8 | namespace OctData 9 | { 10 | class FileReadOptions; 11 | 12 | class DicomRead : public OctFileReader 13 | { 14 | bool readDicomDir(const boost::filesystem::path& file, OCT& oct); 15 | public: 16 | DicomRead(); 17 | 18 | virtual bool readFile(FileReader& filereader, OCT& oct, const FileReadOptions& op, CppFW::Callback* callback) override; 19 | }; 20 | 21 | } 22 | 23 | -------------------------------------------------------------------------------- /octdata/import/gipl/giplread.cpp: -------------------------------------------------------------------------------- 1 | #include "giplread.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace bfs = boost::filesystem; 8 | 9 | #include 10 | 11 | #include 12 | 13 | #include "../platform_helper.h" 14 | #include "../../octdata_packhelper.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | 23 | #include 24 | 25 | 26 | // GIPL magic number 27 | const unsigned GIPL_MAGIC1 = 719555000; 28 | const unsigned GIPL_MAGIC2 = 4026526128U; 29 | 30 | // GIPL header size 31 | #define GIPL_HEADERSIZE 256 32 | 33 | // GIPL filter types 34 | #define GIPL_BINARY 1 35 | #define GIPL_CHAR 7 36 | #define GIPL_U_CHAR 8 37 | #define GIPL_U_SHORT 15 38 | #define GIPL_SHORT 16 39 | #define GIPL_U_INT 31 40 | #define GIPL_INT 32 41 | #define GIPL_FLOAT 64 42 | #define GIPL_DOUBLE 65 43 | #define GIPL_C_SHORT 144 44 | #define GIPL_C_INT 160 45 | #define GIPL_C_FLOAT 192 46 | #define GIPL_C_DOUBLE 193 47 | 48 | 49 | namespace OctData 50 | { 51 | 52 | namespace 53 | { 54 | template 55 | void readFStream(std::istream& stream, T* dest, std::size_t num = 1) 56 | { 57 | stream.read(reinterpret_cast(dest), sizeof(T)*num); 58 | } 59 | 60 | class PrintObj 61 | { 62 | std::ostream& stream; 63 | public: 64 | PrintObj(std::ostream& stream) : stream(stream) {} 65 | 66 | template 67 | void op(const char* name, const P& value, std::size_t /*size*/) 68 | { 69 | stream << name << ": " << value << std::endl; 70 | } 71 | 72 | template 73 | void op(const char* name, const P* value, std::size_t size) 74 | { 75 | stream << name << ": "; 76 | for(std::size_t i = 0; i < size; ++i) 77 | stream << value[i] << "; "; 78 | stream << std::endl; 79 | } 80 | }; 81 | 82 | class ReadFromStream 83 | { 84 | FileReader& filereader; 85 | 86 | template 87 | void readOb(T& v, std::size_t size) 88 | { 89 | filereader.readFStreamBig(&v, size); 90 | } 91 | 92 | template 93 | void readOb(T* v, std::size_t size) 94 | { 95 | filereader.readFStreamBig(v, size); 96 | } 97 | 98 | public: 99 | ReadFromStream(FileReader& filereader) : filereader(filereader) {} 100 | 101 | template 102 | void op(const char* /*name*/, P& value, std::size_t size) 103 | { 104 | readOb(value, size); 105 | } 106 | }; 107 | template<> void ReadFromStream::readOb(std::string& v, std::size_t size) { filereader.readString(v, size); } 108 | 109 | } 110 | 111 | void GIPLRead::GiplHeader::print(std::ostream& stream) const 112 | { 113 | PrintObj p(stream); 114 | getSetParameter(p, *this); 115 | } 116 | 117 | void GIPLRead::GiplHeader::readInfo(FileReader& filereader) 118 | { 119 | ReadFromStream r(filereader); 120 | getSetParameter(r, *this); 121 | } 122 | 123 | struct ReadUInt8 124 | { 125 | static void readImg(FileReader& filereader, cv::Mat& image, std::size_t sizeX, std::size_t sizeY) { filereader.readCVImage(image, sizeY, sizeX); } 126 | static void convertImage(cv::Mat& /*image*/) {} 127 | }; 128 | struct ReadUInt16 129 | { 130 | double maxVal = 1; 131 | 132 | void readImg(FileReader& filereader, cv::Mat& image, std::size_t sizeX, std::size_t sizeY) 133 | { 134 | filereader.readCVImage(image, sizeY, sizeX); 135 | auto imgIt = image.begin(); 136 | auto imgItEnd = image.end (); 137 | 138 | for(;imgIt != imgItEnd; ++imgIt) 139 | boost::endian::big_to_native_inplace(*imgIt); 140 | 141 | double min, max; 142 | cv::minMaxLoc(image, &min, &max); 143 | if(max > maxVal) 144 | maxVal = max; 145 | // tmpImg.convertTo(image, cv::DataType::type, 1./4.); 146 | } 147 | 148 | void convertImage(cv::Mat& image) 149 | { 150 | image.convertTo(image, cv::DataType::type, 256./maxVal); 151 | } 152 | }; 153 | 154 | template 155 | void readBScans(FileReader& filereader, Series& series, const OctData::FileReadOptions& op, const GIPLRead::GiplHeader& giplHeader, CppFW::Callback* callback, T reader) 156 | { 157 | const std::size_t sizeX = giplHeader.getSizeX(); 158 | const std::size_t sizeY = giplHeader.getSizeY(); 159 | const std::size_t numBScans = giplHeader.getSizeZ(); 160 | 161 | std::vector bscanTemp; 162 | bscanTemp.reserve(numBScans); 163 | 164 | for(std::size_t numBscan = 0; numBscancallback(static_cast(numBscan)/static_cast(numBScans)); 168 | 169 | cv::Mat bscanImage; 170 | reader.readImg(filereader, bscanImage, sizeX, sizeY); 171 | // filereader.readCVImage(bscanImage, sizeY, sizeX); 172 | 173 | bscanTemp.push_back(bscanImage); 174 | } 175 | 176 | for(cv::Mat& bscanImage : bscanTemp) 177 | { 178 | reader.convertImage(bscanImage); 179 | 180 | BScan::Data bscanData; 181 | BScan* bscan = new BScan(bscanImage, bscanData); 182 | if(op.holdRawData) 183 | bscan->setRawImage(bscanImage); 184 | series.takeBScan(bscan); 185 | } 186 | } 187 | 188 | bool GIPLRead::readFile(FileReader& filereader, OctData::OCT& oct, const OctData::FileReadOptions& op, CppFW::Callback* callback) 189 | { 190 | if(filereader.getExtension() != ".gipl") 191 | return false; 192 | 193 | const std::string filename = filereader.getFilepath().generic_string(); 194 | BOOST_LOG_TRIVIAL(trace) << "Try to open OCT file as gpil"; 195 | 196 | 197 | if(!filereader.openFile()) 198 | { 199 | BOOST_LOG_TRIVIAL(error) << "Can't open vol file " << filename; 200 | return false; 201 | } 202 | 203 | BOOST_LOG_TRIVIAL(debug) << "open " << filename << " as gpil file"; 204 | 205 | 206 | GiplHeader giplHeader; 207 | giplHeader.readInfo(filereader); 208 | giplHeader.print(std::cout); 209 | if(!giplHeader.numberCheck()) 210 | { 211 | BOOST_LOG_TRIVIAL(error) << "Can't open vol file " << filename; 212 | return false; 213 | } 214 | 215 | 216 | if(giplHeader.getType() != GIPLFilterType::typeId 217 | && giplHeader.getType() != GIPLFilterType::typeId) 218 | { 219 | BOOST_LOG_TRIVIAL(error) << "Non supported format (only uint8 and uint16 supported) " << giplHeader.getType(); 220 | return false; 221 | } 222 | 223 | filereader.seekg(GIPL_HEADERSIZE); 224 | 225 | 226 | Patient& pat = oct.getPatient(1); 227 | Study& study = pat.getStudy(1); 228 | Series& series = study.getSeries(1); // TODO 229 | 230 | switch(giplHeader.getType()) 231 | { 232 | case GIPLFilterType::typeId: readBScans(filereader, series, op, giplHeader, callback, ReadUInt8 ()); break; 233 | case GIPLFilterType::typeId: readBScans(filereader, series, op, giplHeader, callback, ReadUInt16()); break; 234 | } 235 | 236 | return true; 237 | } 238 | 239 | 240 | GIPLRead::GIPLRead() 241 | : OctFileReader(OctExtension{".gipl", ".gipl.gz", "Guys Image Processing Lab Format"}) 242 | { 243 | } 244 | 245 | 246 | } 247 | -------------------------------------------------------------------------------- /octdata/import/gipl/giplread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "../octfilereader.h" 5 | 6 | namespace OctData 7 | { 8 | template struct GIPLFilterType; 9 | template<> struct GIPLFilterType{ constexpr static const int typeId = 8 ; }; 10 | template<> struct GIPLFilterType{ constexpr static const int typeId = 15; }; 11 | 12 | class FileReader; 13 | 14 | class GIPLRead : public OctFileReader 15 | { 16 | public: 17 | class GiplHeader 18 | { 19 | public: 20 | struct RawData 21 | { 22 | uint16_t sizes [ 4]; 23 | uint16_t image_type ; 24 | float scales [ 4]; 25 | std::string patient ; 26 | float matrix [20]; 27 | uint8_t orientation ; 28 | uint8_t par2 ; 29 | double voxmin ; 30 | double voxmax ; 31 | double origin [ 4]; 32 | float pixval_offset ; 33 | float pixval_cal ; 34 | float interslicegap ; 35 | float user_def2 ; 36 | uint32_t magic_number ; 37 | }; 38 | 39 | GiplHeader() = default; 40 | GiplHeader(const RawData& data) : header(data) {} 41 | 42 | uint16_t getSizeX () const { return header.sizes[0] ; } 43 | uint16_t getSizeY () const { return header.sizes[1] ; } 44 | uint16_t getSizeZ () const { return header.sizes[2] ; } 45 | uint16_t getType () const { return header.image_type; } 46 | 47 | void print(std::ostream& stream) const; 48 | void readInfo(FileReader& filereader); 49 | bool numberCheck() const 50 | { 51 | return header.magic_number == giplMagicNumber; 52 | } 53 | 54 | template 55 | void writeHeader(T& writer) const 56 | { 57 | getSetParameter(writer, *this); 58 | } 59 | 60 | constexpr static const uint32_t giplMagicNumber = 4026526128; 61 | 62 | private: 63 | RawData header; 64 | 65 | template 66 | static void getSetParameter(T& getset, VI& data) 67 | { 68 | getset.template op("sizes ", data.header.sizes , 4); 69 | getset.template op("image_type ", data.header.image_type , 1); 70 | getset.template op("scales ", data.header.scales , 4); 71 | getset.template op("patient ", data.header.patient ,80); 72 | getset.template op("matrix ", data.header.matrix ,20); 73 | getset.template op("orientation ", data.header.orientation , 1); 74 | getset.template op("par2 ", data.header.par2 , 1); 75 | getset.template op("voxmin ", data.header.voxmin , 1); 76 | getset.template op("voxmax ", data.header.voxmax , 1); 77 | getset.template op("origin ", data.header.origin , 4); 78 | getset.template op("pixval_offset", data.header.pixval_offset, 1); 79 | getset.template op("pixval_cal ", data.header.pixval_cal , 1); 80 | getset.template op("interslicegap", data.header.interslicegap, 1); 81 | getset.template op("user_def2 ", data.header.user_def2 , 1); 82 | getset.template op("magic_number ", data.header.magic_number , 1); 83 | } 84 | }; 85 | 86 | GIPLRead(); 87 | 88 | virtual bool readFile(FileReader& filereader, OCT& oct, const FileReadOptions& op, CppFW::Callback* callback) override; 89 | }; 90 | } 91 | 92 | -------------------------------------------------------------------------------- /octdata/import/he_e2e/he_e2eread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "../octfilereader.h" 5 | 6 | #include 7 | 8 | namespace OctData 9 | { 10 | class FileReadOptions; 11 | 12 | class HeE2ERead : public OctFileReader 13 | { 14 | public: 15 | HeE2ERead(); 16 | 17 | virtual bool readFile(FileReader& filereader, OCT& oct, const FileReadOptions& op, CppFW::Callback* callback) override; 18 | 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /octdata/import/he_e2e/he_gray_transform.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace OctData 7 | { 8 | 9 | class HeGrayTransformXml 10 | { 11 | uint8_t* lutXML = nullptr; 12 | 13 | HeGrayTransformXml(); 14 | ~HeGrayTransformXml() { delete[] lutXML; } 15 | 16 | HeGrayTransformXml(const HeGrayTransformXml&) = delete; 17 | HeGrayTransformXml& operator=(const HeGrayTransformXml&) = delete; 18 | 19 | public: 20 | static HeGrayTransformXml& getInstance() { static HeGrayTransformXml instance; return instance; } 21 | static uint8_t getXmlValue(uint16_t val); 22 | 23 | uint8_t getValue(uint16_t val) const { return lutXML[val]; } 24 | 25 | }; 26 | 27 | class HeGrayTransformVol 28 | { 29 | uint8_t* lutVol = nullptr; 30 | 31 | HeGrayTransformVol(); 32 | ~HeGrayTransformVol() { delete[] lutVol; } 33 | 34 | HeGrayTransformVol(const HeGrayTransformVol&) = delete; 35 | HeGrayTransformVol& operator=(const HeGrayTransformVol&) = delete; 36 | 37 | public: 38 | static HeGrayTransformVol& getInstance() { static HeGrayTransformVol instance; return instance; } 39 | static uint8_t getVolValue(uint16_t val) 40 | { 41 | const double fitVal1 = 2.38423154996781e-07; 42 | const double fitVal2 = 6.78813958074898e-04; 43 | const double fitVal3 = 4.07055468750000e+04; 44 | 45 | double tmpVal = fitVal1*std::exp((static_cast(val) - fitVal3)*fitVal2); 46 | if(tmpVal > 1.) 47 | tmpVal = 1.; 48 | tmpVal = std::pow(tmpVal, 0.25); 49 | 50 | return static_cast(tmpVal * 255); 51 | } 52 | 53 | uint8_t getValue(uint16_t val) const { return lutVol[val]; } 54 | }; 55 | 56 | class HeGrayTransformUFloat16 57 | { 58 | uint8_t* lut = nullptr; 59 | 60 | HeGrayTransformUFloat16(); 61 | ~HeGrayTransformUFloat16() { delete[] lut; } 62 | 63 | HeGrayTransformUFloat16(const HeGrayTransformXml&) = delete; 64 | HeGrayTransformUFloat16& operator=(const HeGrayTransformXml&) = delete; 65 | 66 | public: 67 | static HeGrayTransformUFloat16& getInstance() { static HeGrayTransformUFloat16 instance; return instance; } 68 | static uint8_t getUint8Value(uint16_t val); 69 | static double getDoubleValue(uint16_t val); 70 | 71 | uint8_t getValue(uint16_t val) const { return lut[val]; } 72 | 73 | }; 74 | 75 | } 76 | -------------------------------------------------------------------------------- /octdata/import/he_vol/volread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "../octfilereader.h" 5 | 6 | namespace OctData 7 | { 8 | class VOLRead : public OctFileReader 9 | { 10 | public: 11 | VOLRead(); 12 | 13 | virtual bool readFile(FileReader& filereader, OCT& oct, const FileReadOptions& op, CppFW::Callback* callback) override; 14 | }; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /octdata/import/he_xml/he_xmlread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "../octfilereader.h" 5 | 6 | #include 7 | 8 | namespace OctData 9 | { 10 | class FileReadOptions; 11 | 12 | class HeXmlRead : public OctFileReader 13 | { 14 | boost::filesystem::path xmlFilename; 15 | boost::filesystem::path xmlPath; 16 | 17 | public: 18 | HeXmlRead(); 19 | 20 | virtual bool readFile(FileReader& filereader, OCT& oct, const FileReadOptions& op, CppFW::Callback* callback) override; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /octdata/import/oct/octfileread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "../octfilereader.h" 5 | 6 | namespace OctData 7 | { 8 | class OctFileFormatRead : public OctFileReader 9 | { 10 | public: 11 | OctFileFormatRead(); 12 | 13 | virtual bool readFile(FileReader& filereader, OCT& oct, const FileReadOptions& op, CppFW::Callback* callback) override; 14 | }; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /octdata/import/octfilereader.cpp: -------------------------------------------------------------------------------- 1 | #include "octfilereader.h" 2 | 3 | #include "../octfileread.h" 4 | 5 | 6 | #include "he_vol/volread.h" 7 | #include "he_xml/he_xmlread.h" 8 | #include "oct/octfileread.h" 9 | #include "topcon/topconread.h" 10 | #include "cirrus_raw/cirrus_rawread.h" 11 | #include "dicom/dicomread.h" 12 | #include "he_e2e/he_e2eread.h" 13 | #include "tiffstack/tiffstackread.h" 14 | #include "cvbin/cvbinread.h" 15 | #include "gipl/giplread.h" 16 | #include "xoct/xoctread.h" 17 | 18 | namespace OctData 19 | { 20 | OctFileReader::OctFileReader() 21 | { } 22 | 23 | OctFileReader::OctFileReader(const OctExtension& ext) 24 | { 25 | extList.push_back(ext); 26 | } 27 | 28 | OctFileReader::OctFileReader(const OctExtensionsList& extList) 29 | : extList(extList) 30 | { 31 | } 32 | 33 | OctFileReader::~OctFileReader() 34 | { 35 | 36 | } 37 | 38 | void OctFileReader::registerReaders(OctFileRead& fileRead) 39 | { 40 | #ifdef HE_VOL_SUPPORT 41 | fileRead.registerFileRead(new VOLRead); 42 | #endif 43 | #ifdef HE_XML_SUPPORT 44 | fileRead.registerFileRead(new HeXmlRead); 45 | #endif 46 | #ifdef CIRRUS_RAW_SUPPORT 47 | fileRead.registerFileRead(new CirrusRawRead); 48 | #endif 49 | #ifdef DICOM_SUPPORT 50 | fileRead.registerFileRead(new DicomRead); 51 | #endif 52 | #ifdef HE_E2E_SUPPORT 53 | fileRead.registerFileRead(new HeE2ERead); 54 | #endif 55 | #ifdef TIFFSTACK_SUPPORT 56 | fileRead.registerFileRead(new TiffStackRead); 57 | #endif 58 | #ifdef CVBIN_SUPPORT 59 | fileRead.registerFileRead(new CvBinRead); 60 | #endif 61 | #ifdef OCT_FILE_SUPPORT 62 | fileRead.registerFileRead(new OctFileFormatRead); 63 | #endif 64 | #ifdef TOPCON_FILE_SUPPORT 65 | fileRead.registerFileRead(new TopconFileFormatRead); 66 | #endif 67 | #ifdef GIPL_SUPPORT 68 | fileRead.registerFileRead(new GIPLRead); 69 | #endif 70 | #ifdef XOCT_SUPPORT 71 | fileRead.registerFileRead(new XOctRead); 72 | #endif 73 | } 74 | 75 | } 76 | 77 | -------------------------------------------------------------------------------- /octdata/import/octfilereader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../octextension.h" 4 | 5 | namespace CppFW { class Callback; } 6 | 7 | namespace OctData 8 | { 9 | class FileReadOptions; 10 | class OctFileRead; 11 | class OCT; 12 | class FileReader; 13 | 14 | class OctFileReader 15 | { 16 | OctExtensionsList extList; 17 | 18 | public: 19 | OctFileReader(); 20 | explicit OctFileReader(const OctExtension& ext); 21 | explicit OctFileReader(const OctExtensionsList& ext); 22 | 23 | virtual ~OctFileReader(); 24 | virtual bool readFile(FileReader& filereader, OCT& oct, const FileReadOptions& op, CppFW::Callback* callback) = 0; 25 | const OctExtensionsList& getExtentsions() const { return extList; } 26 | 27 | static void registerReaders(OctFileRead& fileRead); 28 | }; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /octdata/import/platform_helper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | 9 | #include 10 | 11 | #if BOOST_OS_WINDOWS 12 | #include 13 | 14 | typedef std::wstring FileString; 15 | 16 | inline std::wstring filenameConv(const std::string& utf_str) 17 | { 18 | std::wstring_convert> converter; 19 | return converter.from_bytes(utf_str); 20 | } 21 | 22 | inline std::wstring filepathConv(const boost::filesystem::path& file) 23 | { 24 | return file.generic_wstring(); 25 | } 26 | #else 27 | 28 | typedef std::string FileString; 29 | 30 | inline const std::string& filenameConv(const std::string& utf_str) { return utf_str; } 31 | inline const std::string& filepathConv(const boost::filesystem::path& file) 32 | { 33 | return file.generic_string(); 34 | } 35 | 36 | #endif 37 | 38 | 39 | inline std::string convertUTF16StringToUTF8(const std::u16string& u16) 40 | { 41 | #if BOOST_COMP_MSVC == false 42 | static std::wstring_convert, char16_t> converter; 43 | return converter.to_bytes(u16); 44 | #else 45 | static std::wstring_convert> convert; 46 | std::wstring wstr(u16.begin(), u16.end()); 47 | return convert.to_bytes(wstr); 48 | #endif 49 | } 50 | -------------------------------------------------------------------------------- /octdata/import/tiffstack/tiffstackread.cpp: -------------------------------------------------------------------------------- 1 | #include "tiffstackread.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | // #include 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | namespace bfs = boost::filesystem; 23 | 24 | namespace OctData 25 | { 26 | 27 | TiffStackRead::TiffStackRead() 28 | : OctFileReader(OctExtension{".tiff", ".tif", "Tiff stack"}) 29 | { 30 | } 31 | 32 | bool TiffStackRead::readFile(FileReader& filereader, OCT& oct, const FileReadOptions& /*op*/, CppFW::Callback* /*callback*/) 33 | { 34 | const boost::filesystem::path& file = filereader.getFilepath(); 35 | 36 | if(file.extension() != ".tiff" && file.extension() != ".tif") 37 | return false; 38 | 39 | if(!bfs::exists(file)) 40 | return false; 41 | 42 | BOOST_LOG_TRIVIAL(trace) << "Try to open OCT file as tiff stack"; 43 | 44 | int dircount = 0; 45 | 46 | TIFF* tif = TIFFOpen(file.generic_string().c_str(), "r"); 47 | if(tif) 48 | { 49 | Patient& pat = oct .getPatient(1); 50 | Study & study = pat .getStudy(1); 51 | Series & series = study.getSeries(1); 52 | 53 | // http://www.libtiff.org/man/TIFFGetField.3t.html 54 | 55 | uint32 imageWidth, imageLength; 56 | // uint32 tileWidth, tileLength; 57 | 58 | do { 59 | TIFFGetField(tif, TIFFTAG_IMAGEWIDTH , &imageWidth ); 60 | TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageLength); 61 | 62 | BScan::Data bscanData; 63 | 64 | cv::Mat bscanImage(imageLength, imageWidth, CV_MAKETYPE(cv::DataType::type, 4)); 65 | if(TIFFReadRGBAImageOriented(tif, imageWidth, imageLength, bscanImage.ptr(0), ORIENTATION_TOPLEFT, 0) != 0) 66 | cv::cvtColor(bscanImage, bscanImage, CV_BGR2GRAY); 67 | else 68 | bscanImage = cv::Mat(); 69 | 70 | BScan* bscan = new BScan(bscanImage, bscanData); 71 | series.takeBScan(bscan); 72 | 73 | ++dircount; 74 | } while(TIFFReadDirectory(tif)); 75 | 76 | TIFFClose(tif); 77 | } 78 | 79 | BOOST_LOG_TRIVIAL(debug) << "read tiff stack \"" << file.generic_string() << "\" finished"; 80 | return dircount>0; 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /octdata/import/tiffstack/tiffstackread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "../octfilereader.h" 5 | 6 | namespace OctData 7 | { 8 | class TiffStackRead : public OctFileReader 9 | { 10 | public: 11 | TiffStackRead(); 12 | 13 | virtual bool readFile(FileReader& filereader, OCT& oct, const FileReadOptions& op, CppFW::Callback* callback) override; 14 | }; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /octdata/import/topcon/readjpeg2k.h: -------------------------------------------------------------------------------- 1 | #ifndef READJPEG2K_H 2 | #define READJPEG2K_H 3 | 4 | #include 5 | #include 6 | 7 | typedef void* opj_stream_t; 8 | 9 | namespace cv { class Mat; } 10 | 11 | class ReadJPEG2K 12 | { 13 | void* memoryStream; 14 | 15 | opj_stream_t* opjStreamCreateDefaultMemoryStream(const char* data, std::size_t dataSize); 16 | 17 | void* imageVoid = nullptr; 18 | 19 | template 20 | bool copyMatrix(cv::Mat& matrix, bool flip); 21 | 22 | public: 23 | ReadJPEG2K(); 24 | ~ReadJPEG2K(); 25 | 26 | 27 | bool openJpeg(const char* data, std::size_t dataSize); 28 | 29 | bool getImage(cv::Mat& image, bool flip); 30 | 31 | }; 32 | 33 | #endif // READJPEG2K_H 34 | -------------------------------------------------------------------------------- /octdata/import/topcon/topcondata.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include"topcondata.h" 6 | namespace 7 | { 8 | 9 | void applyParamScan(TopconData& data) 10 | { 11 | if(data.bscanList.size() == 0) 12 | return; 13 | 14 | const double resYmm = data.scanParameter.scanSizeYmm/static_cast(data.bscanList.size()); 15 | const double resZmm = data.scanParameter.resZum/1000; 16 | for(TopconData::BScanPair& bscan : data.bscanList) 17 | { 18 | double resXmm = data.scanParameter.scanSizeXmm/static_cast(bscan.image.cols); 19 | switch(bscan.data.bscanType) 20 | { 21 | case OctData::BScan::BScanType::Circle: bscan.data.scaleFactor = OctData::ScaleFactor(resXmm*M_PI, resYmm, resZmm); break; 22 | case OctData::BScan::BScanType::Line : bscan.data.scaleFactor = OctData::ScaleFactor(resXmm , resYmm, resZmm); break; 23 | case OctData::BScan::BScanType::Unknown: break; 24 | } 25 | } 26 | } 27 | 28 | 29 | void applyRegistInfoVol(const TopconData::ScanParameter& parameter, TopconData::BScanPair& bscan, double pos) 30 | { 31 | bscan.data.start = OctData::CoordSLOmm(0 , parameter.scanSizeYmm*pos); 32 | bscan.data.end = OctData::CoordSLOmm(parameter.scanSizeXmm, parameter.scanSizeYmm*pos); 33 | } 34 | void applyRegistInfoCircle(const TopconData::ScanParameter& parameter, TopconData::BScanPair& bscan) 35 | { 36 | bscan.data.start = OctData::CoordSLOmm(parameter.scanSizeXmm/2., 0); 37 | bscan.data.center = OctData::CoordSLOmm(0 , 0); 38 | } 39 | 40 | void applyBscanCoords(TopconData& data) 41 | { 42 | TopconData::BScanList& list = data.bscanList; 43 | 44 | const std::size_t numBScans = list.size(); 45 | 46 | std::size_t bscanNum = 0; 47 | for(TopconData::BScanPair& bscan : list) 48 | { 49 | double pos = static_cast(bscanNum)/static_cast(numBScans); 50 | switch(bscan.data.bscanType) 51 | { 52 | case OctData::BScan::BScanType::Circle : applyRegistInfoCircle(data.scanParameter, bscan); break; 53 | case OctData::BScan::BScanType::Line : applyRegistInfoVol (data.scanParameter, bscan, pos); break; 54 | case OctData::BScan::BScanType::Unknown: break; 55 | } 56 | 57 | ++bscanNum; 58 | } 59 | } 60 | 61 | void applySloDataRect(TopconData& data, TopconData::SloData& sloData) 62 | { 63 | const double scanSloSizeXpx = sloData.registData.maxX - sloData.registData.minX; 64 | const double scanSloSizeYpx = sloData.registData.maxY - sloData.registData.minY; 65 | 66 | const TopconData::ScanParameter& parameter = data.scanParameter; 67 | 68 | double sloScaleX = parameter.scanSizeXmm/scanSloSizeXpx; 69 | double sloScaleY = parameter.scanSizeYmm/scanSloSizeYpx; 70 | 71 | sloData.sloImage->setScaleFactor(OctData::ScaleFactor(sloScaleX, sloScaleY)); 72 | sloData.sloImage->setShift(OctData::CoordSLOpx(sloData.registData.minX, sloData.registData.minY)); 73 | 74 | } 75 | void applySloDataCircle(TopconData& data, TopconData::SloData& sloData) 76 | { 77 | const double scanSloSizePx = sloData.registData.radius; 78 | 79 | const TopconData::ScanParameter& parameter = data.scanParameter; 80 | 81 | double sloScaleX = parameter.scanSizeXmm/scanSloSizePx; 82 | double sloScaleY = parameter.scanSizeXmm/scanSloSizePx; 83 | 84 | sloData.sloImage->setScaleFactor(OctData::ScaleFactor(sloScaleX, sloScaleY)); 85 | sloData.sloImage->setShift(OctData::CoordSLOpx(sloData.registData.centerX, sloData.registData.centerY)); 86 | } 87 | 88 | void applySloData(TopconData& data, TopconData::SloData& sloData) 89 | { 90 | switch(data.series.getScanPattern()) 91 | { 92 | case OctData::Series::ScanPattern::Circular: applySloDataCircle(data, sloData); break; 93 | case OctData::Series::ScanPattern::Volume : applySloDataRect (data, sloData); break; 94 | default: break; 95 | } 96 | data.series.takeSloImage(sloData.sloImage); 97 | } 98 | } 99 | 100 | 101 | TopconData::TopconData(OctData::OCT& oct) 102 | : oct (oct) 103 | , pat (oct.getPatient (1)) 104 | , study (pat.getStudy (1)) 105 | , series(study.getSeries(1)) 106 | { 107 | } 108 | 109 | 110 | 111 | void TopconData::transferData2Series() 112 | { 113 | if(sloFundus.sloImage) applySloData(*this, sloFundus); 114 | else if(sloTRC .sloImage) applySloData(*this, sloTRC ); 115 | 116 | applyParamScan(*this); 117 | applyBscanCoords(*this); 118 | 119 | for(BScanPair& pair : bscanList) 120 | { 121 | OctData::BScan::Data bscanData; 122 | OctData::BScan* bscan = new OctData::BScan(pair.image, pair.data); 123 | 124 | series.takeBScan(bscan); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /octdata/import/topcon/topcondata.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | 11 | 12 | struct TopconData 13 | { 14 | TopconData(OctData::OCT& oct); 15 | ~TopconData() { transferData2Series(); } 16 | 17 | void transferData2Series(); 18 | 19 | struct BScanPair 20 | { 21 | cv::Mat image; 22 | OctData::BScan::Data data; 23 | }; 24 | 25 | struct ScanParameter 26 | { 27 | double scanSizeXmm = 0; 28 | double scanSizeYmm = 0; 29 | double resZum = 0; 30 | }; 31 | 32 | typedef std::vector BScanList; 33 | 34 | 35 | class SloRegistData 36 | { 37 | public: 38 | double maxX = 0; 39 | double maxY = 0; 40 | double minX = 0; 41 | double minY = 0; 42 | 43 | double centerX = 0; 44 | double centerY = 0; 45 | double radius = 1; 46 | 47 | 48 | SloRegistData() = default; 49 | 50 | SloRegistData(uint32_t v[4]) 51 | : maxX(v[2]) 52 | , maxY(v[3]) 53 | , minX(v[0]) 54 | , minY(v[1]) 55 | , centerX(v[0]) 56 | , centerY(v[1]) 57 | , radius(v[2]) 58 | {} 59 | }; 60 | 61 | struct SloData 62 | { 63 | OctData::SloImage* sloImage = nullptr; 64 | SloRegistData registData; 65 | }; 66 | 67 | 68 | BScanList bscanList; 69 | SloData sloData; 70 | ScanParameter scanParameter; 71 | 72 | OctData::OCT& oct ; 73 | OctData::Patient& pat ; 74 | OctData::Study& study ; 75 | OctData::Series& series; 76 | 77 | SloData sloFundus; 78 | SloData sloTRC ; 79 | }; 80 | 81 | -------------------------------------------------------------------------------- /octdata/import/topcon/topconread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "../octfilereader.h" 5 | 6 | namespace OctData 7 | { 8 | class TopconFileFormatRead : public OctFileReader 9 | { 10 | public: 11 | TopconFileFormatRead(); 12 | 13 | virtual bool readFile(FileReader& filereader, OCT& oct, const FileReadOptions& op, CppFW::Callback* callback) override; 14 | }; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /octdata/import/xoct/xoctread.cpp: -------------------------------------------------------------------------------- 1 | #include "xoctread.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | namespace bfs = boost::filesystem; 34 | namespace bpt = boost::property_tree; 35 | namespace bip = boost::interprocess; 36 | namespace qi = boost::spirit::qi; 37 | 38 | namespace OctData 39 | { 40 | namespace 41 | { 42 | 43 | class GetFromPTree 44 | { 45 | const bpt::ptree* tree; 46 | 47 | template 48 | void unserializeVector(const std::string& str, std::vector& vec) 49 | { 50 | std::istringstream sstream(str); 51 | T tmp; 52 | while(sstream.good()) 53 | { 54 | sstream >> tmp; 55 | vec.push_back(tmp); 56 | } 57 | } 58 | 59 | public: 60 | GetFromPTree(const bpt::ptree& tree) : tree(&tree) {} 61 | GetFromPTree(const bpt::ptree* tree) : tree(tree) {} 62 | 63 | template 64 | void operator()(const std::string& name, T& value) 65 | { 66 | if(tree) 67 | { 68 | boost::optional t = tree->get_optional(name); 69 | if(t) 70 | value = std::move(*t); 71 | } 72 | } 73 | 74 | template 75 | void operator()(const std::string& name, std::vector& value) 76 | { 77 | value.clear(); 78 | if(tree) 79 | { 80 | boost::optional t = tree->get_optional(name); 81 | if(t) 82 | unserializeVector(*t, value); 83 | } 84 | } 85 | 86 | GetFromPTree subSet(const std::string& name) 87 | { 88 | if(tree) 89 | { 90 | boost::optional subTree = tree->get_child_optional(name); 91 | if(subTree) 92 | return GetFromPTree(*subTree); 93 | } 94 | return GetFromPTree(nullptr); 95 | } 96 | }; 97 | 98 | template<> 99 | void GetFromPTree::unserializeVector(const std::string& str, std::vector& vec) 100 | { 101 | std::string::const_iterator f(str.begin()), l(str.end()); 102 | qi::parse(f,l,qi::double_ % ' ',vec); 103 | } 104 | // template<> 105 | // void GetFromPTree::unserializeVector(const std::string& str, std::vector& vec) 106 | // { 107 | // std::string::const_iterator f(str.begin()), l(str.end()); 108 | // qi::parse(f,l,qi::float_ % ' ',vec); 109 | // } 110 | 111 | 112 | template 113 | void readDataNode(const bpt::ptree& tree, S& structure) 114 | { 115 | boost::optional dataNode = tree.get_child_optional("data"); 116 | if(dataNode) 117 | { 118 | GetFromPTree structureReader(*dataNode); 119 | structure.getSetParameter(structureReader); 120 | } 121 | } 122 | 123 | bpt::ptree readXml(CppFW::UnzipCpp& zipfile, const std::string& filename) 124 | { 125 | bpt::ptree xmlTree; 126 | std::vector xmlRaw = zipfile.readFile(filename); 127 | bip::bufferstream input_stream(xmlRaw.data(), xmlRaw.size()); 128 | bpt::read_xml(input_stream, xmlTree); 129 | return xmlTree; 130 | } 131 | 132 | // general import methods 133 | cv::Mat readImage(const bpt::ptree& tree, CppFW::UnzipCpp& zipfile, const std::string& imageStr) 134 | { 135 | const boost::optional imagePath = tree.get_optional(imageStr); 136 | if(imagePath) 137 | { 138 | const std::vector imageContent = zipfile.readFile(*imagePath); 139 | if(imageContent.size() > 0) 140 | return cv::imdecode(imageContent, cv::IMREAD_UNCHANGED); 141 | } 142 | return cv::Mat(); 143 | } 144 | 145 | SloImage* readSlo(const bpt::ptree& sloNode, CppFW::UnzipCpp& zipfile) 146 | { 147 | cv::Mat sloImage = readImage(sloNode, zipfile, "image"); 148 | if(sloImage.empty()) 149 | return nullptr; 150 | 151 | SloImage* slo = new SloImage(); 152 | slo->setImage(sloImage); 153 | readDataNode(sloNode, *slo); 154 | return slo; 155 | } 156 | 157 | void readSegmentation(const bpt::ptree& segNode, Segmentationlines& seglines) 158 | { 159 | GetFromPTree get(segNode); 160 | for(OctData::Segmentationlines::SegmentlineType type : OctData::Segmentationlines::getSegmentlineTypes()) 161 | { 162 | Segmentationlines::Segmentline& seg = seglines.getSegmentLine(type); 163 | get(Segmentationlines::getSegmentlineName(type), seg); 164 | } 165 | } 166 | 167 | BScan* readBScan(const bpt::ptree& bscanNode, CppFW::UnzipCpp& zipfile) 168 | { 169 | cv::Mat bscanImg = readImage(bscanNode, zipfile, "image"); 170 | if(bscanImg.empty()) 171 | return nullptr; 172 | 173 | cv::Mat imageAngio = readImage(bscanNode, zipfile, "angioImage"); 174 | 175 | BScan::Data bscanData; 176 | try// seglines 177 | { 178 | std::string layerSegmentationPath = bscanNode.get("LayerSegmentationFile"); 179 | bpt::ptree xmlTree = readXml(zipfile, layerSegmentationPath); 180 | bpt::ptree segNode = xmlTree.get_child("LayerSegmentation"); 181 | readSegmentation(segNode, bscanData.segmentationslines); 182 | } 183 | catch(...) {} 184 | 185 | BScan* bscan = new BScan(bscanImg, bscanData); 186 | 187 | if(!imageAngio.empty()) 188 | bscan->setAngioImage(imageAngio); 189 | 190 | readDataNode(bscanNode, *bscan); 191 | return bscan; 192 | } 193 | 194 | bool readBScanList(const bpt::ptree seriesNode, CppFW::UnzipCpp& zipfile, Series& series, CppFW::Callback* callback) 195 | { 196 | const std::size_t numBScan = seriesNode.count("BScan"); 197 | CppFW::CallbackStepper bscanCallbackStepper(callback, numBScan); 198 | 199 | for(const std::pair& subTreePair : seriesNode) 200 | { 201 | // std::this_thread::sleep_for(std::chrono::milliseconds(50)); 202 | if(subTreePair.first != "BScan") 203 | continue; 204 | 205 | if(++bscanCallbackStepper == false) 206 | return false; 207 | 208 | BScan* bscan = readBScan(subTreePair.second, zipfile); 209 | if(bscan) 210 | series.takeBScan(bscan); 211 | } 212 | return true; 213 | } 214 | 215 | 216 | template 217 | std::string getSubStructureName() 218 | { 219 | std::string name = boost::typeindex::type_id().pretty_name(); 220 | std::size_t namePos = name.rfind(':'); 221 | if(namePos > 0) 222 | ++namePos; 223 | return name.substr(namePos, name.size() - namePos); 224 | } 225 | 226 | 227 | template 228 | bool readStructure(const bpt::ptree& tree, CppFW::UnzipCpp& zipfile, S& structure, const OctData::FileReadOptions& op, CppFW::Callback* callback) 229 | { 230 | static const std::string subStructureName = getSubStructureName(); 231 | 232 | const std::size_t numSubStructure = tree.count(subStructureName); 233 | CppFW::CallbackSubTaskCreator bscanCallbackCreator(callback, numSubStructure); 234 | 235 | bool result = true; 236 | readDataNode(tree, structure); 237 | 238 | for(const std::pair& subTreePair : tree) 239 | { 240 | if(subTreePair.first != subStructureName) 241 | continue; 242 | 243 | const bpt::ptree& subTreeNode = subTreePair.second; 244 | const int id = subTreeNode.get("id", 1); 245 | CppFW::Callback subCallback = bscanCallbackCreator.getSubTaskCallback(); 246 | 247 | boost::optional filenameSub(subTreeNode.get_optional("filename")); 248 | if(filenameSub) 249 | { 250 | bpt::ptree subFileTree = readXml(zipfile, *filenameSub); 251 | boost::optional subFileTreeNode = subFileTree.get_child_optional(subStructureName); 252 | if(subFileTreeNode) 253 | result &= readStructure(*subFileTreeNode, zipfile, structure.getInsertId(id), op, &subCallback); 254 | else 255 | result = false; 256 | } 257 | else 258 | result &= readStructure(subTreeNode, zipfile, structure.getInsertId(id), op, &subCallback); 259 | } 260 | return result; 261 | } 262 | 263 | 264 | template<> 265 | bool readStructure(const bpt::ptree& tree, CppFW::UnzipCpp& zipfile, Series& series, const OctData::FileReadOptions& op, CppFW::Callback* callback) 266 | { 267 | readDataNode(tree, series); 268 | 269 | boost::optional sloNode = tree.get_child_optional("slo"); 270 | if(sloNode) 271 | series.takeSloImage(readSlo(*sloNode, zipfile)); 272 | 273 | if(op.readBScans) 274 | return readBScanList(tree, zipfile, series, callback); 275 | else 276 | return true; 277 | } 278 | } 279 | 280 | XOctRead::XOctRead() 281 | : OctFileReader(OctExtension(".xoct", "XOct format")) 282 | { 283 | } 284 | 285 | bool OctData::XOctRead::readFile(OctData::FileReader& filereader, OctData::OCT& oct, const OctData::FileReadOptions& op, CppFW::Callback* callback) 286 | { 287 | const boost::filesystem::path& file = filereader.getFilepath(); 288 | if(file.extension() != ".xoct") 289 | return false; 290 | 291 | BOOST_LOG_TRIVIAL(trace) << "Try to open OCT file as xoct"; 292 | 293 | CppFW::UnzipCpp zipfile(file.generic_string()); 294 | 295 | bpt::ptree xmlTree = readXml(zipfile, "xoct.xml"); 296 | 297 | if(callback) 298 | callback->callback(0.01); 299 | 300 | boost::optional xoctTree = xmlTree.get_child_optional("XOCT"); 301 | 302 | if(xoctTree) 303 | return readStructure(*xoctTree, zipfile, oct, op, callback); 304 | else 305 | { 306 | BOOST_LOG_TRIVIAL(error) << "XOCT node in xml not found"; 307 | return false; 308 | } 309 | } 310 | 311 | } 312 | -------------------------------------------------------------------------------- /octdata/import/xoct/xoctread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "../octfilereader.h" 5 | 6 | namespace OctData 7 | { 8 | class XOctRead : public OctFileReader 9 | { 10 | public: 11 | XOctRead(); 12 | 13 | virtual bool readFile(FileReader& filereader, OCT& oct, const FileReadOptions& op, CppFW::Callback* callback) override; 14 | }; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /octdata/octdata_packhelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | // https://stackoverflow.com/questions/2989810/which-cross-platform-preprocessor-defines-win32-or-win32-or-win32 5 | 6 | #if BOOST_COMP_GNUC || BOOST_COMP_CLANG 7 | #define PACKSTRUCT( __Declaration__ ) __Declaration__ __attribute__((__packed__)) 8 | #elif BOOST_COMP_MSVC 9 | #define PACKSTRUCT( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) 10 | #else 11 | #error "unhandled compiler for packing struct" 12 | #endif 13 | 14 | 15 | -------------------------------------------------------------------------------- /octdata/octextension.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | namespace OctData 27 | { 28 | class OctExtension 29 | { 30 | static std::string toLower(const std::string& str) 31 | { 32 | std::string lowerCaseStr = str; 33 | std::transform(lowerCaseStr.begin(), lowerCaseStr.end(), lowerCaseStr.begin(), ::tolower); 34 | return lowerCaseStr; 35 | } 36 | public: 37 | typedef std::vector ExtList; 38 | 39 | OctExtension() = default; 40 | 41 | OctExtension(const std::string& ext, const std::string& name) 42 | : extensions(1) 43 | , name(name) 44 | , extensionsLowerCase(1) 45 | { 46 | extensions.at(0) = ext; 47 | extensionsLowerCase.at(0) = toLower(ext); 48 | } 49 | 50 | explicit OctExtension(const std::initializer_list& seq) 51 | : extensions(seq.size()-1) 52 | , extensionsLowerCase(seq.size()-1) 53 | { 54 | std::initializer_list::const_iterator srcIt = seq.begin(); 55 | ExtList::iterator destIt = extensions.begin(); 56 | ExtList::iterator destLowerIt = extensionsLowerCase.begin(); 57 | 58 | for(std::size_t i=0; i extLength) 80 | { 81 | if(str == lowerCaseName.substr(fileLength-extLength, extLength)) 82 | return true; 83 | } 84 | } 85 | return false; 86 | } 87 | 88 | 89 | ExtList extensions; 90 | std::string name; 91 | private: 92 | ExtList extensionsLowerCase; 93 | }; 94 | 95 | 96 | class OctExtensionsList : public std::vector 97 | { 98 | public: 99 | OctExtensionsList() = default; 100 | OctExtensionsList(const std::initializer_list& list) : std::vector(list) {}; 101 | 102 | 103 | bool matchWithFile(const std::string& filename) const 104 | { 105 | for(const OctExtension& ext : *this) 106 | if(ext.matchWithFile(filename)) 107 | return true; 108 | return false; 109 | } 110 | }; 111 | } 112 | -------------------------------------------------------------------------------- /octdata/octfileread.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "octfileread.h" 19 | 20 | #include 21 | #include "import/octfilereader.h" 22 | #include "filereadoptions.h" 23 | #include "filewriteoptions.h" 24 | 25 | #include 26 | 27 | #include "buildconstants.h" 28 | 29 | #include 30 | 31 | #include 32 | namespace bfs = boost::filesystem; 33 | 34 | #include 35 | 36 | #include "import/platform_helper.h" 37 | #include 38 | #include 39 | #include 40 | 41 | namespace OctData 42 | { 43 | OctFileRead::OctFileRead() 44 | { 45 | BOOST_LOG_TRIVIAL(info) << "OctData: Build Type : " << BuildConstants::buildTyp; 46 | BOOST_LOG_TRIVIAL(info) << "OctData: Git Hash : " << BuildConstants::gitSha1; 47 | BOOST_LOG_TRIVIAL(info) << "OctData: Build Date : " << BuildConstants::buildDate; 48 | BOOST_LOG_TRIVIAL(info) << "OctData: Build Time : " << BuildConstants::buildTime; 49 | BOOST_LOG_TRIVIAL(info) << "OctData: Compiler Id : " << BuildConstants::compilerId; 50 | BOOST_LOG_TRIVIAL(info) << "OctData: Compiler Version: " << BuildConstants::compilerVersion; 51 | BOOST_LOG_TRIVIAL(info) << "OctData: OpenCV Version : " << CV_VERSION ; // cv::getBuildInformation(); 52 | 53 | OctFileReader::registerReaders(*this); // TODO: serch better implementation 54 | } 55 | 56 | 57 | OctFileRead::~OctFileRead() 58 | { 59 | for(OctFileReader* reader : fileReaders) 60 | delete reader; 61 | } 62 | 63 | 64 | OCT OctFileRead::openFile(const std::string& filename, CppFW::Callback* callback) 65 | { 66 | return getInstance().openFilePrivat(filename, FileReadOptions(), callback); 67 | } 68 | 69 | OCT OctFileRead::openFile(const std::string& filename, const FileReadOptions& op, CppFW::Callback* callback) 70 | { 71 | return getInstance().openFilePrivat(filename, op, callback); 72 | } 73 | 74 | OCT OctFileRead::openFile(const boost::filesystem::path& filename, const FileReadOptions& op, CppFW::Callback* callback) 75 | { 76 | return getInstance().openFilePrivat(filename, op, callback); 77 | } 78 | 79 | 80 | 81 | OCT OctFileRead::openFilePrivat(const std::string& filename, const FileReadOptions& op, CppFW::Callback* callback) 82 | { 83 | bfs::path file(filenameConv(filename)); 84 | return openFilePrivat(file, op, callback); 85 | } 86 | 87 | 88 | 89 | bool OctFileRead::openFileFromExt(OCT& oct, FileReader& filereader, const FileReadOptions& op, CppFW::Callback* callback) 90 | { 91 | std::string filename = filereader.getFilepath().generic_string(); 92 | for(OctFileReader* reader : fileReaders) 93 | { 94 | if(reader->getExtentsions().matchWithFile(filename)) 95 | { 96 | if(reader->readFile(filereader, oct, op, callback)) 97 | return true; 98 | oct.clear(); 99 | } 100 | } 101 | return false; 102 | } 103 | 104 | bool OctFileRead::tryOpenFile(OCT& oct, FileReader& filereader, const FileReadOptions& op, CppFW::Callback* callback) 105 | { 106 | for(OctFileReader* reader : fileReaders) 107 | { 108 | if(reader->readFile(filereader, oct, op, callback)) 109 | return true; 110 | oct.clear(); 111 | } 112 | return false; 113 | } 114 | 115 | OCT OctFileRead::openFilePrivat(const boost::filesystem::path& file, const FileReadOptions& op, CppFW::Callback* callback) 116 | { 117 | FileReader filereader(file); 118 | OctData::OCT oct; 119 | 120 | if(bfs::exists(file)) 121 | { 122 | if(!openFileFromExt(oct, filereader, op, callback)) 123 | tryOpenFile(oct, filereader, op, callback); 124 | } 125 | else 126 | BOOST_LOG_TRIVIAL(error) << "file " << file.generic_string() << " not exists"; 127 | 128 | return oct; 129 | } 130 | 131 | // used by friend class OctFileReader 132 | void OctFileRead::registerFileRead(OctFileReader* reader) 133 | { 134 | if(!reader) 135 | return; 136 | 137 | const OctExtensionsList& extList = reader->getExtentsions(); 138 | 139 | for(const OctExtension& ext : extList) 140 | { 141 | BOOST_LOG_TRIVIAL(info) << "OctData: register reader for " << ext.name; 142 | extensions.push_back(ext); 143 | } 144 | 145 | fileReaders.push_back(reader); 146 | } 147 | 148 | const OctExtensionsList& OctFileRead::supportedExtensions() 149 | { 150 | return getInstance().extensions; 151 | } 152 | 153 | bool OctFileRead::isLoadable(const std::string& filename) 154 | { 155 | 156 | for(const OctExtension& supportedExtension : getInstance().extensions) 157 | if(supportedExtension.matchWithFile(filename)) 158 | return true; 159 | return false; 160 | } 161 | 162 | 163 | bool OctFileRead::writeFile(const std::string& filename, const OCT& octdata) 164 | { 165 | return getInstance().writeFilePrivat(filename, octdata, FileWriteOptions()); 166 | } 167 | 168 | bool OctFileRead::writeFile(const std::string& filename, const OCT& octdata, const FileWriteOptions& opt) 169 | { 170 | return getInstance().writeFilePrivat(filename, octdata, opt); 171 | } 172 | 173 | bool OctFileRead::writeFile(const bfs::path& filepath, const OCT& octdata, const FileWriteOptions& opt) 174 | { 175 | return getInstance().writeFilePrivat(filepath, octdata, opt); 176 | } 177 | 178 | 179 | bool OctFileRead::writeFilePrivat(const bfs::path& filepath, const OCT& octdata, const FileWriteOptions& opt) 180 | { 181 | if(filepath.extension() == ".img") 182 | return CirrusRawExport::writeFile(filepath, octdata, opt); 183 | if(filepath.extension() == ".xoct") 184 | return XOctWrite::writeFile(filepath, octdata, opt); 185 | return CvBinOctWrite::writeFile(filepath, octdata, opt); 186 | } 187 | 188 | } 189 | 190 | 191 | -------------------------------------------------------------------------------- /octdata/octfileread.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Kay Gawlik 3 | * 4 | * This program is free software: you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation, either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #include "octextension.h" 24 | 25 | #ifdef OCTDATA_EXPORT 26 | #include "octdata_EXPORTS.h" 27 | #else 28 | #define Octdata_EXPORTS 29 | #endif 30 | 31 | namespace boost { namespace filesystem { class path; } } 32 | 33 | namespace CppFW { class Callback; } 34 | 35 | namespace OctData 36 | { 37 | class OCT; 38 | class OctFileReader; 39 | class FileReadOptions; 40 | class FileWriteOptions; 41 | class OctExtensionsList; 42 | class FileReader; 43 | 44 | class OctFileRead 45 | { 46 | friend class OctFileReader; 47 | public: 48 | Octdata_EXPORTS static OctFileRead& getInstance() { static OctFileRead instance; return instance; } 49 | 50 | Octdata_EXPORTS static const OctExtensionsList& supportedExtensions(); 51 | Octdata_EXPORTS static OCT openFile(const std::string& filename, const FileReadOptions& op, CppFW::Callback* callback = nullptr); 52 | Octdata_EXPORTS static OCT openFile(const boost::filesystem::path& filename, const FileReadOptions& op, CppFW::Callback* callback = nullptr); 53 | Octdata_EXPORTS static OCT openFile(const std::string& filename, CppFW::Callback* callback = nullptr); 54 | 55 | Octdata_EXPORTS static bool isLoadable(const std::string& filename); 56 | 57 | Octdata_EXPORTS static bool writeFile(const std::string& filename, const OCT& octdata); 58 | Octdata_EXPORTS static bool writeFile(const std::string& filename, const OCT& octdata, const FileWriteOptions& opt); 59 | Octdata_EXPORTS static bool writeFile(const boost::filesystem::path& filepath, const OCT& octdata, const FileWriteOptions& opt); 60 | 61 | private: 62 | OctFileRead(); 63 | ~OctFileRead(); 64 | 65 | void registerFileRead(OctFileReader* reader); 66 | OCT openFilePrivat(const std::string& filename, const FileReadOptions& op, CppFW::Callback* callback); 67 | OCT openFilePrivat(const boost::filesystem::path& file, const FileReadOptions& op, CppFW::Callback* callback); 68 | 69 | bool writeFilePrivat(const boost::filesystem::path& filepath, const OCT& octdata, const FileWriteOptions& opt); 70 | 71 | bool openFileFromExt(OCT& oct, FileReader& filename, const FileReadOptions& op, CppFW::Callback* callback); 72 | bool tryOpenFile(OCT& oct, FileReader& filename, const FileReadOptions& op, CppFW::Callback* callback); 73 | 74 | OctExtensionsList extensions; 75 | 76 | std::vector fileReaders; 77 | }; 78 | 79 | } 80 | 81 | --------------------------------------------------------------------------------