pax_global_header00006660000000000000000000000064144535677040014531gustar00rootroot0000000000000052 comment=101c745e847a5de4a1e569a94368ce2027198598 lensfun-0.3.4/000077500000000000000000000000001445356770400132075ustar00rootroot00000000000000lensfun-0.3.4/CMakeLists.txt000066400000000000000000000241361445356770400157550ustar00rootroot00000000000000# require at least cmake 2.8.12 CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12 FATAL_ERROR ) # path for helper modules set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_SOURCE_DIR}/cmake/modules") GET_FILENAME_COMPONENT(SOURCE_BASE_DIR ${CMAKE_SOURCE_DIR} PATH CACHE) # global setup project(lensfun C CXX) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) IF (MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") ELSE() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wformat-security") ENDIF() # version SET(VERSION_MAJOR 0) SET(VERSION_MINOR 3) SET(VERSION_MICRO 4) SET(VERSION_BUGFIX 0) SET(VERSION_API 1) # This is the version of the *shipped* database, which is not necessarily the # highest version number supported SET(LENSFUN_DB_VERSION 1) # check if some include are available INCLUDE(CheckIncludeFiles) CHECK_INCLUDE_FILES(regex.h HAVE_REGEX_H) CHECK_INCLUDE_FILES(endian.h HAVE_ENDIAN_H) # set include directories INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include/lensfun) IF(NOT HAVE_REGEX_H) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include/regex) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/libs/regex) ENDIF() IF(CMAKE_SYSTEM_PROCESSOR MATCHES "[XxIi][0-9]?86|[Aa][Mm][Dd]64") SET(X86_ON ON) else() SET(X86_ON OFF) ENDIF() # options controlling the build process OPTION(BUILD_STATIC "Build static library" OFF) OPTION(BUILD_WITH_MSVC_STATIC_RUNTIME "Build using static MSVC runtime" OFF) OPTION(BUILD_TESTS "Build test suite" OFF) OPTION(BUILD_LENSTOOL "Build the lenstool (requires libpng)" OFF) OPTION(BUILD_FOR_SSE "Build with support for SSE" ${X86_ON}) OPTION(BUILD_FOR_SSE2 "Build with support for SSE2" ${X86_ON}) OPTION(BUILD_DOC "Build documentation with doxygen" OFF) OPTION(INSTALL_PYTHON_MODULE "Install Python module for the helper scripts" ON) OPTION(INSTALL_HELPER_SCRIPTS "Install various helper scripts" ON) IF(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build, options are: Debug, Release" FORCE ) ENDIF() # place all .exe and .dll files in same folder to avoid issues with tests IF(WIN32) SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) ENDIF() # set local install prefix on windows IF(WIN32 AND CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) SET(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/install" CACHE PATH "Install prefix for Lensfun" FORCE) ENDIF() # overwrite some folders before GNUInstallDirs is loaded IF (WIN32 AND NOT DEFINED CMAKE_INSTALL_DATAROOTDIR) SET(CMAKE_INSTALL_DATAROOTDIR "$ENV{ALLUSERSPROFILE}" CACHE PATH "read-only architecture-independent data root (share)") ENDIF() # get standard GNU install directories for the current platform INCLUDE(GNUInstallDirs) IF(NOT DEFINED CMAKE_INSTALL_DATAROOTDIR) SET(CMAKE_INSTALL_DATAROOTDIR "share" CACHE PATH "read-only architecture-independent data root (share)") ENDIF() IF (WIN32) SET(LENSFUN_WINDOWS_DATADIR ${CMAKE_INSTALL_DATAROOTDIR}/lensfun CACHE PATH "Directory for library data files. This should be relative to the location where the lensfun.dll will be installed.") ENDIF() IF(BUILD_FOR_SSE) SET(VECTORIZATION_SSE 1) IF(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") SET(VECTORIZATION_SSE_FLAGS "-msse") ENDIF() ENDIF() IF(BUILD_FOR_SSE2) SET(VECTORIZATION_SSE2 1) IF(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") SET(VECTORIZATION_SSE2_FLAGS "-msse2") ENDIF() ENDIF() IF(WIN32) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/libs/getopt) # base path for searching for glib on windows IF(NOT GLIB2_BASE_DIR) SET(GLIB2_BASE_DIR "${SOURCE_BASE_DIR}/glib-2.28.1" CACHE STRING "Base path of glib2 dir." FORCE) ENDIF() # install glib dll on windows next to lensfun.dll IF (GLIB2_DLL) INSTALL(FILES ${GLIB2_DLL} DESTINATION ${CMAKE_INSTALL_BINDIR}) ENDIF() ENDIF() IF (BUILD_TESTS) # automatic tests need at least glib version 2.40 # NOTE: must be one of the macros listed in https://developer.gnome.org/glib/stable/glib-Version-Information.html SET(LENSFUN_GLIB_REQUIREMENT_MACRO "GLIB_VERSION_2_40") FIND_PACKAGE(GLIB2 REQUIRED) ELSE() SET(LENSFUN_GLIB_REQUIREMENT_MACRO "GLIB_VERSION_2_26") FIND_PACKAGE(GLIB2 REQUIRED) ENDIF() INCLUDE_DIRECTORIES(SYSTEM ${GLIB2_INCLUDE_DIRS}) LINK_DIRECTORIES(${GLIB2_LIBRARY_DIRS}) IF(BUILD_STATIC) ADD_DEFINITIONS(-DCONF_LENSFUN_STATIC) ENDIF() # some windows and MSVC specific settings IF(WIN32) IF (MSVC) IF(BUILD_WITH_MSVC_STATIC_RUNTIME) # compile everything for the static C runtime FOREACH(TYPE C CXX) # makefiles use blank configuration FOREACH(CFG "_DEBUG" "_MINSIZEREL" "_RELEASE" "_RELWITHDEBINFO") SET(NEW_FLAGS "${CMAKE_${TYPE}_FLAGS${CFG}}") # fix up static libc flags STRING(REPLACE "/MD" "/MT" NEW_FLAGS "${NEW_FLAGS}") # *FORCE* to override whats already placed into the cache SET(CMAKE_${TYPE}_FLAGS${CFG} "${NEW_FLAGS}" CACHE STRING "CMAKE_${TYPE}_FLAGS${CFG} (overwritten to ensure static build)" FORCE) ENDFOREACH(CFG) ENDFOREACH(TYPE) # link only with the static C runtime !! THIS IS A MUST !! SET(NEW_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") # ensure that the flags are not duplicaated on subsequent runs STRING(REPLACE " /NODEFAULTLIB:\"MSVCRT.lib\" /NODEFAULTLIB:\"MSVCRTd.lib\"" "" NEW_FLAGS "${NEW_FLAGS}") # note that flag names (NODEFAULTLIB) etc.) are case sensitive SET(CMAKE_EXE_LINKER_FLAGS "${NEW_FLAGS} /NODEFAULTLIB:\"MSVCRT.lib\" /NODEFAULTLIB:\"MSVCRTd.lib\"" CACHE STRING "for MSVC" FORCE ) ENDIF() ENDIF(MSVC) ENDIF(WIN32) # create config.h file CONFIGURE_FILE(include/lensfun/config.h.in.cmake ${CMAKE_BINARY_DIR}/config.h) # create lensfun.h file CONFIGURE_FILE(include/lensfun/lensfun.h.in ${CMAKE_BINARY_DIR}/lensfun.h @ONLY) # include libs ADD_SUBDIRECTORY(libs) # build the test suite IF(BUILD_TESTS) enable_testing() ADD_SUBDIRECTORY(tests) ENDIF() # apps subdir IF(BUILD_LENSTOOL) FIND_PACKAGE(PNG REQUIRED) ENDIF() ADD_SUBDIRECTORY(apps) # install include files INSTALL(FILES ${CMAKE_BINARY_DIR}/lensfun.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/lensfun) IF(NOT HAVE_REGEX_H) INSTALL(FILES include/regex/regex.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/regex) ENDIF() # install db files FILE(GLOB DATABASE_FILES data/db/*.xml) INSTALL(FILES ${DATABASE_FILES} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/lensfun/version_${LENSFUN_DB_VERSION}) INSTALL(FILES data/db/timestamp.txt DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/lensfun/version_${LENSFUN_DB_VERSION}) FILE(GLOB DATABASE_DTD data/db/*.dtd data/db/*.xsd) INSTALL(FILES ${DATABASE_DTD} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/lensfun/version_${LENSFUN_DB_VERSION}) # build documentation IF(BUILD_DOC) ADD_SUBDIRECTORY(docs) ENDIF() IF(WIN32 AND NOT BUILD_STATIC) FIND_FILE(GLIB2_DLL NAMES glib-2.0-0.dll glib-2.dll glib-2-vs9.dll PATHS "${GLIB2_BASE_DIR}/bin" NO_SYSTEM_ENVIRONMENT_PATH) INSTALL(FILES ${GLIB2_DLL} DESTINATION ${CMAKE_INSTALL_BINDIR}) ENDIF() # print some information MESSAGE(STATUS "-------------------------------------------------------------------------------------") MESSAGE(STATUS "Building Lensfun ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO}.${VERSION_BUGFIX}") MESSAGE(STATUS "-------------------------------------------------------------------------------------") IF(BUILD_STATIC) MESSAGE(STATUS "Build as static library") ELSE() MESSAGE(STATUS "Build as dynamic/shared library") ENDIF() MESSAGE(STATUS "Build type: ${CMAKE_BUILD_TYPE}") MESSAGE(STATUS "Build doc: ${BUILD_DOC}") MESSAGE(STATUS "Build test suite: ${BUILD_TESTS}") MESSAGE(STATUS "Build lenstool: ${BUILD_LENSTOOL}") MESSAGE(STATUS "Build with support for SSE: ${BUILD_FOR_SSE}") MESSAGE(STATUS "Build with support for SSE2: ${BUILD_FOR_SSE2}") MESSAGE(STATUS "Install helper scripts: ${INSTALL_HELPER_SCRIPTS}") MESSAGE(STATUS "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}") MESSAGE(STATUS "\nUsing: ") MESSAGE(STATUS "GLIB2 include dir: ${GLIB2_INCLUDE_DIRS}") MESSAGE(STATUS "GLIB2 library: ${GLIB2_LIBRARIES}") IF(GLIB2_DLL) MESSAGE(STATUS "GLIB2 DLL: ${GLIB2_DLL}") ENDIF() IF(BUILD_LENSTOOL) MESSAGE(STATUS "libpng include dir: ${PNG_INCLUDE_DIRS}") MESSAGE(STATUS "libpng lib: ${PNG_LIBRARIES}") MESSAGE(STATUS "zlib include dir: ${ZLIB_INCLUDE_DIRS}") MESSAGE(STATUS "zlib lib: ${ZLIB_LIBRARIES}") ENDIF() # Package # This needs some testing, in particular for right package naming for different # package managers and distributions. Debian works fine. SET(CPACK_PACKAGE_NAME "lensfun") SET(CPACK_PACKAGE_VERSION_MAJOR "${VERSION_MAJOR}") SET(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}") SET(CPACK_PACKAGE_VERSION_PATCH "${VERSION_MICRO}.${VERSION_BUGFIX}") SET(CPACK_PACKAGE_INSTALL_DIRECTORY "CMake ${V_MAJOR}.${V_MINOR}") SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO}.${VERSION_BUGFIX}") SET(CPACK_SOURCE_GENERATOR "TGZ;TBZ2") SET(CPACK_PACKAGE_CONTACT "zap@homelink.ru") SET(CPACK_SET_DESTDIR "ON") IF(BUILD_AUXFUN) SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libglib2.0-0 (>=2.0.0), libpng (>=1.0), zlib (>=1.0)") ELSE() SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libglib2.0-0 (>=2.0.0)") ENDIF() IF(CPACK_BINARY_DEB) # workaround to set correct debian package name SET(CPACK_DEBIAN_PACKAGE_NAME "liblensfun${VERSION_API}") STRING(TOLOWER "${CPACK_DEBIAN_PACKAGE_NAME}" CPACK_PACKAGE_NAME_LOWERCASE) FIND_PROGRAM(DPKG_PROGRAM dpkg DOC "dpkg program of Debian-based systems") if(DPKG_PROGRAM) EXECUTE_PROCESS( COMMAND ${DPKG_PROGRAM} --print-architecture OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE ) SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME_LOWERCASE}_${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO}.${VERSION_BUGFIX}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") else(DPKG_PROGRAM) SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME_LOWERCASE}_${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO}.${VERSION_BUGFIX}_${CMAKE_SYSTEM_NAME}") endif(DPKG_PROGRAM) ENDIF(CPACK_BINARY_DEB) INCLUDE(CPack) lensfun-0.3.4/ChangeLog000066400000000000000000001345611445356770400147730ustar00rootroot00000000000000======================================= 0.3.4-rc1 --> 0.3.4 (2023-07-12) ======================================= Includes all new cameras and lenses up to master commit 645bfdd5df50da92023a4f9158b0717ebcc47e81 (Wed Jul 12 18:45:25 2023 +0200) New cameras (19): * Canon EOS 200D II * Canon EOS M50 Mark II * Canon EOS R8 * Fujifilm GFX100S * Fujifilm GFX 50S * Fujifilm X-S20 * Leica Camera AG Leica M11 Monochrom * Leica Camera AG Leica Q3 * Nikon Corporation Z 8 * Olympus Corporation E-M10 III S * Panasonic DC-GH5M2 * Panasonic DC-S5M2 * Panasonic DMC-FZ330 * Panasonic DMC-GF8 * Ricoh Imaging Company, Ltd. KP * Sony Alpha 6700 * Sony FX3 * Sony FX30 * Sony ZV-E1 New lenses (50): * Canon Canon EF 28-80mm f/3.5-5.6 USM * Canon Canon EF 70-210mm f/4 * Canon Canon RF 24-70mm F2.8L IS USM * Fujifilm GF110mmF2 R LM WR * Fujifilm GF23mmF4 R LM WR * Fujifilm XF 23mm f/1.4 R LM WR * Fujifilm XF 90mm f/2 R LM WR * Leica Camera AG APO-SUMMICRON-SL 1:2/50 ASPH. * Leica Camera AG VARIO-ELMARIT-SL 1:2.8/24-70 ASPH. * Meike Meike 28mm f/2.8 * Meike Meike 50mm F1.2 * Nikon Nikkor AF 10.5mm f/2.8G DX ED Fisheye * Nikon Nikkor AF-S 400mm f/2.8G ED + converter TC-14EIII * Nikon Nikkor AF-S 400mm f/2.8G ED + converter TC-20EIII * Nikon NIKKOR Z 100-400mm f/4.5-5.6 VR S * Nikon NIKKOR Z 50mm f/1.2 S * Olympus Olympus M.Zuiko Digital ED 12-200mm f/3.5-6.3 * Olympus Olympus M.Zuiko Digital ED 12-45mm f/4.0 Pro * Olympus Olympus M.Zuiko Digital ED 30mm f/3.5 Macro * Olympus Olympus M.Zuiko Digital ED 40-150mm F2.8 Pro * Panasonic Lumix G Vario 100-300mm F4-5.6 II Power O.I.S. * Pentax HD PENTAX-DA* 11-18mm f/2.8 ED DC AW * Pentax HD PENTAX DA* 16-50mm f/2.8 ED PLM AW * Pentax HD Pentax-D FA* 70-200mm f/2.8 ED DC AW * Pentax smc PENTAX-F 35-80mm f/4-5.6 * Samsung Samsung NX 16-50mm f/2-2.8 S * Samsung Samsung NX 50-150mm F2.8 S * Samsung Samsung NX-M 9-27mm f/3.5-5.6 ED OIS * Samsung Samsung NX-M 9mm f/3.5 ED * Sigma 100-400mm F5-6.3 DG OS HSM | C * Sigma 105mm F2.8 DG DN MACRO | Art 020 * Sigma 70-200mm F2.8 DG OS HSM | S * Sigma Sigma 60-600mm F4.5-6.3 DG OS HSM | Sports 018 + 1.4x ext. * Sony E 11mm f/1.8 * Sony E 16-55mm f/2.8 G * Sony E 70-350mm f/4.5-6.3 G OSS * Sony FE 14mm f/1.8 GM * Sony FE 200-600mm f/5.6-6.3 G OSS * Sony FE 20-70mm f/4 G * Sony FE 20mm f/1.8 G * Sony FE 24-70mm f/2.8 GM II * Sony FE 24mm f/1.4 GM * Sony FE 28-60mm f/4-5.6 * Sony FE 35mm f/1.4 GM (SEL35F14GM) * Sony FE 35mm f/1.8 * Sony FE 40mm f/2.5 G * Sony FE 50mm f/1.2 GM * Sony FE 50mm f/2.8 Macro * Sony FE 50mm f/2.8 Macro * Yongnuo Yongnuo YN 50mm f/1.8 II ======================================= 0.3.3 --> 0.3.4-rc1 (2023-01-01) ======================================= Includes all new cameras and lenses up to master commit ec9412d27d5fa8f377848a59c768b12c243cb80d (Wed Dec 28 16:24:48 2022 +0100) Changes / bugfixes (4): * Fix C++11 issues to enable compilation with Clang (#1954) * Port apps/setup.py from Python distutils (deprecated) to setuptools (#1956) * CMake: Bump CMake minimum version to 2.8.12 (#1958) * CMake: Numerous backports from master (#1959) New cameras (54): * Canon Canon PowerShot G9 X Mark II * Canon EOS M6 Mark II * Canon EOS R10 * Canon EOS R3 * Canon EOS R6 Mark II * Canon EOS R7 * Canon PowerShot G7 X Mark III (3:2) * DJI Air 2S * Fujifilm GFX 100S * Fujifilm XF10 * Fujifilm X-H2 * Fujifilm X-H2S * Fujifilm X-T30 II * Fujifilm X-T5 * Hasselblad DJI Mavic 3 * Leica Camera AG Digilux 3 * Leica Camera AG Leica C-Lux (Typ 1546) * Leica Camera AG Leica M10 * Leica Camera AG Leica M10 Monochrom * Leica Camera AG Leica M10-P * Leica Camera AG Leica M10-R * Leica Camera AG Leica M11 * Leica Camera AG Leica M Monochrom (Typ 246) * Leica Camera AG Leica M (Typ 240) * Leica Camera AG Leica Q2 * Leica Camera AG Leica Q2 Mono * Leica Camera AG Leica SL2 * Leica Camera AG Leica SL2-S * Leica Camera AG M9 Digital Camera * Leica D-LUX2 * Leica D-LUX 3 * Leica D-LUX 4 * Nikon Corporation Z 30 * OM Digital Solutions OM-1 * OM Digital Solutions OM-5 * Panasonic DC-G100 * Panasonic DC-G110 * Panasonic DC-GH5S * Panasonic DC-GH6 * Panasonic DC-GX7MK3 * Panasonic DC-S1H * Panasonic DC-TZ220 * Panasonic DC-ZS220 * Panasonic DMC-FZ2000 * Panasonic DMC-FZ2500 * Panasonic DMC-ZS110 * Ricoh Imaging Company, Ltd. K-3 III * Ricoh Imaging Company, Ltd. Ricoh GR IIIx * Samsung Galaxy S21 * Sony Alpha 7R IIIA * Sony Alpha 7R IV A * Sony Alpha 7R V * Sony RX0 * Sony ZV-E10 New lenses (140): * Canon Canon EF 28mm f/2.8 * Canon Canon EF 35-105mm f/3.5-4.5 * Canon Canon EF 75-300mm F4-5.6 III * Canon Canon EF 85mm f/1.4L IS USM * Canon Canon EF-M 32mm f/1.4 STM * Canon Canon RF 100-400mm F5.6-8 IS USM * Canon Canon RF 100mm F2.8L Macro IS USM * Canon Canon RF 14-35mm F4 L IS USM * Canon Canon RF 15-35mm F2.8L IS USM * Canon Canon RF 16mm F2.8 STM * Canon Canon RF 35mm F1.8 MACRO IS STM * Canon Canon RF 800mm F11 IS STM * Canon Canon RF-S 18-150mm F3.5-6.3 IS STM * DJI FC3411 fixed lens * Fujifilm XF 10-24mm f/4 R OIS WR * Fujifilm XF10 & compatibles (Standard) * Fujifilm XF 33mm f/1.4 R LM WR * Hasselblad fixed lens * Kipon Elegant 35mm F/2.4 * Leica Camera AG Elmarit-M 28mm f/2.8 ASPH * Leica Camera AG Elmarit-M 90mm f/2.8 * Leica Camera AG Elmarit-TL 1:2.8/18 ASPH. * LEICA CAMERA AG fixed lens * LEICA CAMERA AG fixed lens * Leica Camera AG Summicron-M 1:2/28 ASPH. * Leica Camera AG Summicron-M 50mm f/2 * Leica Camera AG Summicron TL 1:2 23 ASPH. * Leica Camera AG Summilux-TL 1:1.4/35 ASPH. * Leica fixed lens * Meyer Optik Görlitz Meyer Optik Görlitz 3.5/30mm * Minolta Minolta AF 50mm f/1.7 * Minolta Minolta AF 70-210mm f/4 Macro * Mitakon Mitakon Speedmaster 50mm f/0.95 III * Nikon Nikkor AF 18-35mm f/3.5-4.5D IF-ED * Nikon Nikkor AF-S 600mm f/4E FL ED VR + converter TC-14EIII * Nikon Nikkor AI-S 135mm f/3.5 * Nikon NIKKOR Z 24-120mm f/4 S * Nikon NIKKOR Z 28-75mm f/2.8 * Nikon NIKKOR Z MC 105mm f/2.8 VR S * Nikon Nikkor Z MC 50mm f/2.8 * Nikon Nikon AF-S Nikkor 500mm f/5.6E PF ED VR * Nikon Nikon AF-S Nikkor 600mm f/4E FL ED VR * Nikon Nikon AF-S VR Nikkor 400mm f/2.8G ED * Nikon Nikon AF-S VR Zoom-Nikkor 200-400mm f/4G IF-ED * Nikon Nikon AF-S VR Zoom-Nikkor 70-200mm f/2.8G IF-ED * Nikon Nikon AF Zoom-Nikkor 70-210mm f/4 * Nikon Nikon Zoom-NIKKOR Auto 43-86mm F3.5 * Olympus Olympus M.Zuiko Digital ED 8-25mm f/4.0 PRO * OM Digital Solutions OM 20mm F1.4 * Panasonic Leica DG Macro-Elmarit 45mm f/2.8 * Panasonic Leica DG Summilux 15mm f/1.7 Asph. * Panasonic Leica DG Summilux 25mm f/1.4 Asph. * Panasonic Leica DG Summilux 25mm f/1.4 II * Panasonic Leica DG Summilux 9mm f/1.7 * Panasonic Leica DG Vario-Elmarit 12-60mm f/2.8-4.0 Asph. Power OIS * Panasonic Leica DG Vario-Elmarit 50-200 mm F2.8-4 Asph OIS * Panasonic Leica D Summilux 25mm F1.4 Asph. * Panasonic Leica D Vario-Elmar 14-150mm f/3.5-5.6 Asph. OIS * Panasonic Lumix G Vario 14-140mm f/3.5-5.6 Asph. II Power OIS * Panasonic Lumix G Vario 14-140mm f/3.5-5.6 Asph. Power OIS * Panasonic Lumix G Vario 45-200mm f/4.0-5.6 II power OIS * Panasonic Lumix G Vario 45-200mm f/4.0-5.6 Mega OIS * Panasonic Lumix G X Vario 12-35mm f/2.8 II * Panasonic LUMIX G X VARIO 35-100 mm f/2.8 II Power OIS * Panasonic Lumix G X Vario 35-100mm f/2.8 Power OIS * Panasonic LUMIX S 16-35/F4 * Panasonic Lumix S 20-60/F3.5-5.6 * Panasonic Lumix S 24/F1.8 * Panasonic Lumix S 50/F1.8 * Panasonic LUMIX S 70-300/F4.5-5.6 * Panasonic Lumix S 85/F1.8 * Pentacon Pentacon electric 2.8/29mm * Pentax HD PENTAX-DA* 11-18mm F2.8 ED DC AW * Pentax smc PENTAX-F 35-80mm F4-5.6 * Ricoh imaging company, ltd. fixed lens * Rollei Rollei Rolleinar MC f/2.8 28mm * Rollei Rollei Rolleinar MC f/4 21mm * Samsung Samsung Galaxy S21 ultrawide * Samsung Samsung NX 50-200mm f/4-5.6 * Samyang Samyang AF 12mm f/2.0 * Samyang Samyang AF 18mm f/2.8 * Samyang Samyang AF 24mm f/1.8 * Samyang Samyang AF 35mm f/1.8 * Samyang Samyang AF 45mm f/1.8 * Samyang Samyang AF 75mm f/1.8 * Samyang Samyang AF 85mm f/1.4 * Samyang Samyang XP 10mm f/3.5 * Sigma 16-28mm F2.8 DG DN | Contemporary 022 * Sigma 20mm F2 DG DN | Contemporary 022 * Sigma 24-70mm F2.8 DG DN | Art 019 * Sigma 24mm F2 DG DN | Contemporary 021 * Sigma 28-70mm F2.8 DG DN | Contemporary 021 * Sigma 35mm F2 DG DN | Contemporary 020 * Sigma 45mm F2.8 DG DN | Contemporary 019 * Sigma 65mm F2 DG DN | Contemporary 020 * Sigma 90mm F2.8 DG DN | Contemporary 021 * Sigma Sigma 105 mm F1.4 DG HSM Art * Sigma Sigma 16mm f/1.4 DC DN Contemporary * Sigma Sigma 24mm f/1.4 DG HSM | A * Sigma Sigma 40mm F1.4 DG HSM | Art * Sigma Sigma 56 mm F1.4 DC DN | C 018 * Sigma Sigma 56mm F1.4 DC DN | C 018 * Sigma Sigma 60-600mm F4.5-6.3 DG OS HSM | Sports 018 * Sony E 11mm F1.8 * Sony FE 14mm F1.8 GM * Sony FE 40mm F2.5 G * Sony FE 50mm F1.2 GM * Sony FE 50mm F2.8 Macro * Sony FE 50mm F2.8 Macro * Sony Sony 85mm F2.8 SAM (SAL85F28) * Tamron 18-300mm F3.5-6.3 DiIII-A VC VXD B061X * Tamron E 24mm F2.8 * Tamron TAMRON 100-400mm F/4.5-6.3 Di VC USD A035 * Tamron Tamron 11-20 mm F2.8 Di III-A RXD (B060) * Tamron Tamron 150-500mm F5-6.7 Di III VC VXD * Tamron Tamron 16-300mm f/3.5-6.3 Di II VC PZD Macro B016 * Tamron Tamron 16-300mm f/3.5-6.3 Di II VC PZD Macro B016 * Tamron Tamron 17-35mm f/2.8-4 Di OSD (A037) * Tamron Tamron 35-150mm f/2.8-4 Di VC OSD (A043) * Tamron Tamron SP 45mm F/1.8 Di VC USD * Tamron Tamron SP AF 150-600mm F/5-6.3 Di VC USD G2 (A022) * Tokina Tokina atx-i 11-16mm F2.8 CF * Tokina Tokina AT-X M35 PRO DX (AF 35mm f/2.8 Macro) * TTArtisan TTArtisan APS-C 23mm F1.4 * Venus Laowa 17mm f/1.8 C-Dreamer * Voigtländer 15mm F4,5 Super Wide Heliar aspherical III * Voigtländer Voigtlander APO-LANTHAR 50mm F2 Aspherical * Voigtländer Voigtlander Color Skopar 20mm F3.5 SLII Aspherical * Voigtländer Voigtländer HELIAR-HYPER WIDE 10mm F5.6 * Voigtländer Voigtländer Nokton 25mm f/0.95 Type II * Zeiss Carl Zeiss Jena 135mm f/3.5 * Zeiss Carl Zeiss Jena Flektogon 4/20mm * Zeiss Carl Zeiss Planar T* 1,4/50 ZF.2 * Zeiss Carl Zeiss Sonnar T* 135mm F1.8 ZA (SAL135F18Z) * Zeiss Distagon 18mm f/4 * Zeiss Distagon 28mm f/2.8 MMJ * Zeiss Makro-Planar T* 2/100 * Zeiss Planar 50mm f/1.7 AEJ * Zeiss Sonnar 85mm f/2.8 AEJ * Zeiss Touit 2.8/12 ======================================= 0.3.3-rc1 --> 0.3.3 (2022-02-22) ======================================= Includes all new cameras and lenses up to commit 75f41548ba6bb2a02de215f3b3512afc418c2c5b (Tue Feb 22 17:11:53 2022 +0000) New lenses (8): * Canon RF 100-500mm F4.5-7.1L IS USM * SAMYANG AF 18mm F2.8 * 18-50mm F2.8 DC DN | Contemporary 021 * Tamron E 70-180mm F2.8 * Tamron E 35mm F2.8 F053 * Canon EF28mm f/2.8 * Carl Zeiss Planar T* 1,4/50 ZF.2 * Carl Zeiss Distagon T* 3,5/18 ZF.2 Updated lenses (3): * Canon RF 24-105mm F4L IS USM * Canon RF 70-200mm F2.8L IS USM * Sony FE 24mm f/2.8 G ======================================= 0.3.2 --> 0.3.3-rc1 (2022-02-20) ======================================= Release candiate for a new maintenance release for the 0.3.x branch. Includes all new cameras and lenses up to commit 10e037729cf8261385cf87c674cda16ce7388e6a (Sun Feb 20 01:36:15 2022 +0100) * Static lfXX::Create() and lfXX:Destroy() methods of various Lensfun classe are now marked as deprecated. C++ new/delete syntax should be used instead. * CMAKE: glib > 2.26 is now only required when tests are being build. * CMAKE: various fixes (paths, OS compatibility) New cameras (346): * Apple iPhone XS * Canon EOS-1D X Mark II * Canon EOS 2000D * Canon EOS 200D * Canon EOS 250D * Canon EOS 4000D * Canon EOS 5D Mark IV * Canon EOS 5DS * Canon EOS 5DS R * Canon EOS 6D Mark II * Canon EOS 77D * Canon EOS 8000D * Canon EOS 800D * Canon EOS 850D * Canon EOS 9000D * Canon EOS 90D * Canon EOS KISS M * Canon EOS Kiss X10i * Canon EOS Kiss X8i * Canon EOS Kiss X9 * Canon EOS Kiss X90 * Canon EOS Kiss X9i * Canon EOS M10 * Canon EOS M100 * Canon EOS M200 * Canon EOS M5 * Canon EOS M50 * Canon EOS M6 * Canon EOS R * Canon EOS R5 * Canon EOS R6 * Canon EOS Rebel SL2 * Canon EOS Rebel SL3 * Canon EOS Rebel T100 * Canon EOS Rebel T6 * Canon EOS Rebel T6i * Canon EOS Rebel T6s * Canon EOS Rebel T7 * Canon EOS Rebel T7i * Canon EOS Rebel T8i * Canon EOS RP * Canon IXUS 95 IS * Canon Powershot A1200 * Canon PowerShot A490 * Canon PowerShot A495 * Canon PowerShot G16 * Canon PowerShot G1 X Mark III * Canon PowerShot G3 X * Canon PowerShot G5 X * Canon PowerShot G5 X Mark II * Canon PowerShot G7 X Mark II * Canon PowerShot G9 X * Canon PowerShot SD1100 IS * Canon PowerShot SX10 IS * Canon PowerShot SX160 IS * Canon PowerShot SX240 HS * Canon PowerShot SX30 IS * Canon Powershot SX50 HS * Canon Powershot SX60 HS * Canon PowerShot SX700 HS * Canon PowerShot SX710 HS * DJI FC6310 * DJI Mavic Air FC2103 * DJI Mavic Pro FC220 * DJI Phantom 3 Pro FC300X * Eastman Kodak Company Kodak CX7525 * Fujifilm GFX 50R * Fujifilm X100F * Fujifilm X100V * Fujifilm X70 * Fujifilm X-A3 * Fujifilm X-A5 * Fujifilm X-A7 * Fujifilm X-E2S * Fujifilm X-E3 * Fujifilm X-E4 * Fujifilm X-H1 * Fujifilm X-Pro2 * Fujifilm X-Pro3 * Fujifilm X-S1 * Fujifilm X-S10 * Fujifilm X-T10 * Fujifilm X-T100 * Fujifilm X-T2 * Fujifilm X-T20 * Fujifilm X-T3 * Fujifilm X-T30 * Fujifilm X-T4 * GitUp Git2 * GoPro HERO4 Black * GoPro HERO5 Black * Hasselblad DJI Mavic 2 Pro * Honor 6A * Huawei P10 Lite * Huawei P20 Pro * Huawei P30 Pro * Leica CL * LEICA Q2 * Leica Q (Typ 116) * Leica SL (Typ 601) * Leica TL * Leica TL2 * Leica T (Typ 701) * Leica M (Typ 240) * Leica X Vario (Typ 107) * Microsoft Lumia 950 * Microsoft Lumia 950 XL * Nikon Coolpix P340 * Nikon Coolpix P7800 * Nikon Corporation Coolpix A * Nikon Corporation Coolpix P1000 * Nikon Corporation D3400 * Nikon Corporation D3500 * Nikon Corporation D5 * Nikon Corporation D500 * Nikon Corporation D5600 * Nikon Corporation D6 * Nikon Corporation D7500 * Nikon Corporation D780 * Nikon Corporation D850 * Nikon Corporation Z 5 * Nikon Corporation Z 50 * Nikon Corporation Z 6 * Nikon Corporation Z 6II * Nikon Corporation Z 7 * Nikon Corporation Z 7II * Nikon Corporation Z 9 * Nikon Corporation Z fc * Nokia Lumia 1520 * Olympus Corporation E-M10 II * Olympus Corporation E-M10 III * Olympus Corporation E-M10 IV * Olympus Corporation E-M1MarkIII * Olympus Corporation E-M5MarkIII * Olympus Corporation E-PL8 * Olympus Corporation E-PL9 * Olympus Corporation Tough TG-1 * Olympus Corporation Tough TG-2 * Olympus Corporation Tough TG-3 * Olympus Corporation Tough TG-4 * Olympus Corporation Tough TG-5 * Olympus Corporation Tough TG-6 * Olympus Imaging Corp. E-M1MarkII * Olympus Imaging Corp. PEN-F * Panasonic DC-FZ10002 * Panasonic DC-G9 * Panasonic DC-G90 * Panasonic DC-G91 * Panasonic DC-G95 * Panasonic DC-G99 * Panasonic DC-GH5 * Panasonic DC-GX800 * Panasonic DC-GX880 * Panasonic DC-GX9 * Panasonic DC-LX100M2 * Panasonic DC-S1 * Panasonic DC-S1R * Panasonic DC-S5 * Panasonic DC-TZ200 * Panasonic DC-TZ202 * Panasonic DC-TZ90 * Panasonic DC-ZS200 * Panasonic DMC-FZ100 * Panasonic DMC-FZ300 * Panasonic DMC-FZ40 * Panasonic DMC-FZ45 * Panasonic DMC-G7 * Panasonic DMC-G70 * Panasonic DMC-G80 * Panasonic DMC-G81 * Panasonic DMC-G85 * Panasonic DMC-GX8 * Panasonic DMC-GX80 * Panasonic DMC-GX85 * Panasonic DMC-LX10 * Panasonic DMC-LX15 * Panasonic DMC-TZ100 * Panasonic DMC-TZ101 * Panasonic DMC-TZ110 * Panasonic DMC-TZ60 * Panasonic DMC-TZ61 * Panasonic DMC-TZ70 * Panasonic DMC-TZ80 * Panasonic DMC-TZ81 * Panasonic DMC-TZ90 * Panasonic DMC-TZ91 * Panasonic DMC-TZ96 * Panasonic DMC-ZS100 * Panasonic DMC-ZS40 * Panasonic DMC-ZS50 * Panasonic DMC-ZS60 * Panasonic DMC-ZS70 * Pentax K-01 * Pentax KP * Ricoh Imaging Company, Ltd. K-1 Mark II * Ricoh Imaging Company, Ltd. K-3 * Ricoh Imaging Company, Ltd. K-3 II * Ricoh Imaging Company, Ltd. K-70 * Ricoh Imaging Company, Ltd. K-S1 * Ricoh Imaging Company, Ltd. K-S2 * Ricoh Imaging Company, Ltd. Ricoh GR III * Samsung Galaxy Note 8 * Samsung Galaxy S7 * Samsung Galaxy S8 * Samsung Galaxy S8 * Sigma fp * Sigma fp L * Sigma sd Quattro * Sony Alpha 1 * Sony Alpha 6100 * Sony Alpha 6300 * Sony Alpha 6400 * Sony Alpha 6500 * Sony Alpha 6600 * Sony Alpha 68 * Sony Alpha 7C * Sony Alpha 7 III * Sony Alpha 7 IV * Sony Alpha 7R II * Sony Alpha 7R III * Sony Alpha 7R IV * Sony Alpha 7S II * Sony Alpha 7S III * Sony Alpha 9 * Sony Alpha 99 II * Sony RX0 II * Sony RX10 * Sony RX100 V * Sony RX100 VA * Sony RX100 VI * Sony RX100 VII * Sony RX10 III * Sony RX10 IV * Sony RX1 R II New lenses (439): * Arsenal MC Volna-3 80mm f/2.8 * Canon EF 100-200mm f/4.5A * Canon EF 100-400mm f/4.5-5.6L IS II USM * Canon EF 100-400mm f/4.5-5.6L IS II USM * Canon EF 100mm f/2.8L Macro IS USM * Canon EF 135mm f/2 L USM * Canon EF 16-35mm f/2.8L III USM * Canon EF 22-55mm f/4-5.6 USM * Canon EF 24-105mm f/3.5-5.6 IS STM * Canon EF 24-105mm f/4L IS II USM * Canon EF 24-105mm f/4L IS II USM * Canon EF 24mm f/1.4L II USM * Canon EF 24mm f/2.8 IS USM * Canon EF 300mm f/4L IS USM * Canon EF 300mm f/4L IS USM + 1.4× ext. * Canon EF 35mm f/1.4L II USM * Canon EF 35mm f/2 IS USM * Canon EF 35mm f/2 IS USM * Canon EF 50mm f/1.8 STM * Canon EF 50mm f/1.8 STM * Canon EF 50mm f/2.5 Compact Macro * Canon EF 70-200mm f/2.8L IS II USM + EF 2× III ext. * Canon EF 70-200mm f/2.8L IS USM * Canon EF 70-200mm f/2.8L IS USM + EF 2× II ext. * Canon EF 70-300mm f/4-5.6L IS USM * Canon EF 80-200mm f/4.5-5.6 * Canon EF85mm f/1.4L IS USM * Canon EF-M 11-22mm f/4-5.6 IS STM * Canon EF-M 15-45mm f/3.5-6.3 IS STM * Canon EF-M 28mm f/3.5 Macro IS STM * Canon EF-M 55-200mm f/4.5-6.3 IS STM * Canon EF-S 18-135mm f/3.5-5.6 IS USM * Canon EF-S 18-55mm f/4-5.6 IS STM * Canon EF-S 55-250mm f/4-5.6 IS II * Canon EF-S 55-250mm f/4-5.6 IS STM * Canon FD 200mm f/2.8 S.S.C. * Canon FD 50mm f/1.4 S.C.C. * Canon FDn 135mm 1:2.8 * Canon FDn 200mm 1:4 * Canon FDn 24mm 1:2.8 * Canon FDn 50mm 1:1.8 * Canon PowerShot SX60 HS & compatibles * Canon RF 24-105mm F4-7.1 IS STM * Canon RF 24-240mm F4-6.3 IS USM * Canon RF 50mm F1.8 STM * Canon RF85mm F1.2L USM * Canon fixed lens, with Tiffen 0.56× converter * Canon fixed lens, with WC-DC58N * Canon RF24-105mm F4 L IS USM * Canon RF70-200mm F2.8 L IS USM * Canon RF85mm F2 MACRO IS STM * Chinon Auto Chinon 35mm f/2.8 * Chinon Chinon 75-205mm f/3.8 * Cosina 24mm 2.0 Macro * Fujifilm GF45mmF2.8 R WR * Fujifilm X100V-lens * Fujifilm X100V-Lens, with TCL-X100 * Fujifilm X100V-Lens, with WCL-X100 * Fujifilm X70 & compatibles (Standard) * Fujifilm XC 15-45mm f/3.5-5.6 OIS PZ * Fujifilm XC 35mm f/2 * Fujifilm XF 100-400mm f/4.5-5.6 R LM OIS WR * Fujifilm XF 100-400mm f/4.5-5.6 R LM OIS WR + 1.4× conv. * Fujifilm XF 10-24mm f/4 R OIS * Fujifilm XF 16-55mm f/2.8 R LM WR * Fujifilm XF 16-80mm f/4 R OIS WR * Fujifilm XF 16mm f/2.8 R WR * Fujifilm XF 18-135mm f/3.5-5.6R LM OIS WR * Fujifilm XF 23mm f/2 R WR * Fujifilm XF 35mm f/2 R WR * Fujifilm XF 50-140mm f/2.8 R LM OIS WR * Fujifilm XF 50mm f/2 R WR * Fujifilm XF 56mm f/1.2 R * Fujifilm XF 70-300mm f/4-5.6 R LM OIS WR * Irix Irix 15mm f/2.4 * KMZ Helios-40 85mm f/1.5 * KMZ Helios-44 58mm 1:2 * KMZ Industar-50-2 3.5/50 * KMZ Jupiter-37AM MC 3.5/135 * KMZ MC Helios-44M-4 58mm 1:2 * KMZ MIR-1B 37mm f/2.8 * KMZ MIR-1B 37mm f/2.8 * Leica Camera AG 28.0mm f/1.7 * LEICA CAMERA AG Summicron TL 1:2 23 ASPH. * LEICA CAMERA AG SUMMILUX 1:1.7/28 ASPH. * LEICA CAMERA AG Summilux-TL 1:1.4/35 ASPH. * Leica Elmarit-M 28mm f/2.8 ASPH * Leica Elmarit-M 90mm f/2.8 * Leica DG Summilux 25mm f/1.4 Asph. * Leica DG Summilux 25mm f/1.4 II * Leica DG Vario-Elmarit 12-60mm f/2.8-4.0 Asph. Power OIS * Leica Summicron-M 50mm f/2 * Meike 25mm f/1.8 * Meike 35mm f/1.7 * Meike 50mm f/2.0 * Meike MK-F 28mm f/2.8 * Minolta AF 100-300mm f/4.5-5.6 APO (D) * Minolta AF 135mm f/2.8 * Minolta AF 17-35mm f/2.8-4 (D) * Minolta AF 28-75mm F2.8 (D) * Minolta AF 50mm f/1.4 * Minolta AF 50mm f/2.8 Macro * Minolta AF 85mm f/1.4G (D) * Minolta AF 24-105mm f/3.5-4.5 (D) * Miranda 28mm f/2.8 MC * MTO MTO-500 500mm f/8 mirror lens * Nikon 1 Nikkor 10mm f/2.8 * Nikon 1 Nikkor AW 10mm f/2.8 * Nikon Nikkor 55mm f/3.5 Micro * Nikon Nikkor AF 105mm f/2D DC * Nikon Nikkor AF 105mm Micro f/2.8D * Nikon Nikkor AF 135mm f/2D DC * Nikon Nikkor AF 180mm f/2.8D IF-ED * Nikon Nikkor AF 24-50mm f/3.3-4.5 * Nikon Nikkor AF 28-70mm f/3.5-4.5D * Nikon NIKKOR AF 300mm f/4 IF-ED * Nikon Nikkor AF 35-70mm f/2.8 * Nikon Nikkor AF 35mm f/2.8 PC “black knob” * Nikon Nikkor AF-P 10-20mm f/4.5-5.6G DX VR * Nikon NIKKOR AF-P 18-55mm f/3.5-5.6G DX VR * Nikon NIKKOR AF-P 70-300mm f/4.5-5.6E ED VR * Nikon NIKKOR AF-P 70-300mm f/4.5-6.3G DX ED VR * Nikon NIKKOR AF-S 16-80mm f/2.8-4E DX ED VR * Nikon NIKKOR AF-S 16-85mm f/3.5-5.6G DX ED VR * Nikon Nikkor AF-S 17-35mm f/2.8D IF-ED * Nikon NIKKOR AF-S 18-300mm f/3.5-5.6G DX ED VR * Nikon Nikkor AF-S 18-35mm f/3.5-4.5G ED * Nikon NIKKOR AF-S 18-55mm f/3.5-5.6G DX VR II * Nikon NIKKOR AF-S 200-500mm f/5.6E ED VR * Nikon NIKKOR AF-S 200-500mm f/5.6E ED VR * Nikon NIKKOR AF-S 20mm f/1.8G ED * Nikon NIKKOR AF-S 24-120mm f/4G ED VR * Nikon NIKKOR AF-S 24-70mm f/2.8E ED VR * Nikon NIKKOR AF-S 24mm f/1.8G ED * Nikon NIKKOR AF-S 28mm f/1.8G * Nikon NIKKOR AF-S 300mm f/4D IF-ED * Nikon NIKKOR AF-S 300mm f/4E PF ED VR * Nikon NIKKOR AF-S 35mm f/1.8G DX * Nikon NIKKOR AF-S 35mm f/1.8G ED * Nikon Nikkor AF-S 40mm f/2.8G DX Micro * Nikon NIKKOR AF-S 50mm f/1.4G * Nikon NIKKOR AF-S 50mm f/1.4G * Nikon NIKKOR AF-S 50mm f/1.8G * Nikon NIKKOR AF-S 50mm f/1.8G * Nikon NIKKOR AF-S 600mm f/4G ED VR * Nikon NIKKOR AF-S 70-200mm f/2.8E FL ED VR * Nikon NIKKOR AF-S 70-200mm f/2.8G ED VR II * Nikon NIKKOR AF-S 70-200mm f/4G IF-ED VR * Nikon NIKKOR AF-S 85mm f/1.4G * Nikon NIKKOR AF-S 85mm f/1.8G * Nikon Nikkor AF-S VR 105mm f/2.8G Micro IF-ED * Nikon Nikkor AI 80-200mm f/4.5 Zoom New * Nikon Nikkor AI-S 105mm f/2.5 * Nikon Nikkor AI-S 135mm f/2 * Nikon Nikkor AI-S 135mm f/2.8 * Nikon Nikkor AI-S 200mm f/4 * Nikon Nikkor AI-S 24mm f/2 * Nikon Nikkor AI-S 28mm f/2 * Nikon Nikkor AI-S 300mm f/4.5 * Nikon Nikkor AI-S 35mm f/2 * Nikon Nikkor AI-S 400mm f/3.5 * Nikon Nikkor AI-S 400mm f/3.5 + TC14B teleconverter * Nikon Nikkor AI-S 500mm f/8 Reflex * Nikon Nikkor AI-S 500mm f/8 Reflex * Nikon Nikkor AI-S 50mm f/1.4 * Nikon Nikkor AI-S 50mm f/1.8 * Nikon Nikkor AI-S 55mm f/2.8 Micro * Nikon Nikkor AI-S 85mm f/2.0 * Nikon NIKKOR Z 14-24mm f/2.8 S * Nikon NIKKOR Z 14-30mm f/4 S * Nikon NIKKOR Z 20mm f/1.8 S * Nikon NIKKOR Z 24-200mm f/4-6.3 VR * Nikon NIKKOR Z 24-70mm f/2.8 S * Nikon NIKKOR Z 24-70mm f/4 S * Nikon NIKKOR Z 35mm f/1.8 S * Nikon NIKKOR Z 40mm f/2 * Nikon NIKKOR Z 50mm f/1.8 S * Nikon NIKKOR Z 70-200mm f/2.8 VR S * Nikon NIKKOR Z 85mm f/1.8 S * Nikon NIKKOR Z DX 16-50mm f/3.5-6.3 VR * Nikon AF-S Nikkor 58mm f/1.4G * Nikon AF-S Nikkor 80-400mm f/4.5-5.6G ED VR * Nikon AF-S VR Nikkor 400mm f_2.8G ED * Nikon AF Zoom-Nikkor 28-105mm f/3.5-4.5D IF * Nikon AF Zoom-Nikkor 28-85mm f/3.5-4.5 * Olympus M.Zuiko Digital ED 12-100mm f/4.0 IS Pro * Olympus M.Zuiko Digital ED 14-150mm f/4.0-5.6 II * Olympus M.Zuiko Digital ED 17mm f/1.2 Pro * Olympus M.Zuiko Digital ED 25mm f/1.2 Pro * Olympus M.Zuiko Digital ED 40-150mm f/2.8 PRO + 1.4× conv. * Olympus M.Zuiko Digital ED 45mm f/1.2 Pro * Olympus M.Zuiko Digital ED 60mm f/2.8 Macro * Olympus M.Zuiko ED 12-200mm f/3.5-6.3 * Olympus M.Zuiko ED 12-45mm f/4.0 Pro * Olympus M.Zuiko ED 30mm f/3.5 Macro * Olympus M.Zuiko ED 40-150mm F2.8 PRO * Olympus Zuiko Digital ED 14-35mm F2.0 SWD * Olympus Zuiko Auto-S 50mm f/1.8 * Opteka 15mm f/4 Wide Macro 1:1 * Panasonic Leica DG Nocticron 42.5mm f/1.2 Asph. Power OIS * Panasonic Leica DG Vario-Elmar 100-400mm f/4.0-6.3 Asph. Power OIS * Panasonic Leica DG Vario-Elmarit 8-18mm f/2.8-4 Asph. * Panasonic Leica DG Vario-Summilux 10-25mm f/1.7 Asph. * Panasonic Lumix G 25mm f/1.7 Asph. * Panasonic Lumix G 42.5mm f/1.7 * Panasonic Lumix G Macro 30mm f/2.8 * Panasonic Lumix G Vario 12-60mm f/3.5-5.6 Asph. Power OIS * Panasonic Lumix G Vario 14-140mm f/3.5-5.6 * Panasonic Lumix G Vario 14-140mm f/3.5-5.6 II * Panasonic Lumix G Vario 35-100mm f/4.0-5.6 Asph. Mega OIS * Panasonic Lumix G X Vario PZ 45-175mm f/4.0-5.6 * Panasonic LUMIX S 20-60/F3.5-5.6 * Pentax-DA 16-85mm f/3.5-5.6 ED DC WR * Pentax-DA 18-50mm f/4-5.6 DC WR RE * Pentax-DA 21mm f/3.2 ED AL Limited * Pentax-DA 55-300mm f/4.5-6.3 ED PLM WR RE * Pentax-DA 55-300mm f/4-5.8 ED WR * Pentax-DA 70mm f/2.4 Limited * Pentax-D FA 150-450mm f/4.5-5.6 ED DC AW * Pentax-D FA 15-30mm f/2.8 ED SDM WR * Pentax-D FA 24-70mm f/2.8 ED SDM WR * Pentax-D FA 28-105mm f/3.5-5.6 ED DC WR * Pentax-D FA 70-200mm f/2.8 ED DC AW * Pentax-F 28-80mm f/3.5-4.5 * Pentax SMC Takumar 50mm f/1.4 * Pentax-A 50mm f/1.4 * Pentax-A 50mm f/1.7 * Pentax-DA 17-70mm f/4 AL [IF] SDM * Pentax-DA 18-250mm f/3.5-6.3 ED AL [IF] * Pentax-DA 35mm f/2.4 AL * Pentax-DA 35mm f/2.8 Macro Limited * Pentax-DA 50mm f/1.8 * Pentax-DA 55-300mm f/4-5.8 ED * PENTAX DA* 60-250mm f/4 IF SDM * Pentax-DA 70mm f/2.4 Limited * Pentax-DA L 18-50mm f/4-5.6 DC WR RE * Pentax-DA L 50-200mm f/4-5.6 ED WR * Pentax-D FA Macro 100mm f/2.8 WR * Pentax-F 28mm f/2.8 * Pentax-FA 28-70mm f/4 AL * Pentax-FA 77mm f/1.8 Limited * Pentax-M 50mm f/1.7 * Pentax Super-Takumar 50mm f/1.4 * Pentax Super-Takumar 55mm f/1.8 * Petri Auto Petri 1:2.8 f=28mm * Samsung S7 wide angle lens cover * Samsung S8 wide angle lens * Samsung SM-G950F * Samyang 10mm f/2.8 ED AS NCS CS * Samyang 12mm f/3.1 VDSLR ED AS NCS Fish-eye * Samyang 135mm f/2 ED UMC * Samyang 16mm f/2.0 ED AS UMC CS * Samyang 20mm f/1.8 ED AS UMC * Samyang 35mm f/1.4 AS UMC * Samyang 85mm f/1.4 IF UMC Aspherical * Samyang AF 12mm F2.0 * Samyang AF 14mm f/2.8 * Samyang AF 24mm F1.8 * Samyang AF 24mm f/2.8 * Samyang AF 35mm f/2.8 * Samyang AF 45mm F1.8 * Samyang AF 85mm F1.4 * Sigma 100-400mm F5-6.3 DG OS HSM | Contemporary 017 * Sigma 105mm F1.4 DG HSM | Art 018 * Sigma 14-24mm F2.8 DG DN | Art 019 * Sigma 30mm f/1.4 DC DN * Sigma 35mm F1.2 DG DN | Art 019 * Sigma 70-200mm F2.8 DG OS HSM | Sports 018 * Sigma 85mm F1.4 DG DN | Art 020 * Sigma 100-300mm f/4 APO EX DG HSM * Sigma 100-300mm f/4 APO EX DG HSM + Kenko Teleplus PRO 300 AF 1.4× DGX ext. * Sigma 10-20mm f/3.5 EX DC HSM * Sigma 105mm f/2.8 EX DG OS HSM Macro * Sigma 12-24mm F4 DG HSM Art * Sigma 14mm f/1.8 DG HSM | A * Sigma 150-600mm f/5-6.3 DG OS HSM | C * Sigma 150-600mm f/5-6.3 DG OS HSM | C * Sigma 150-600mm f/5-6.3 DG OS HSM | C * Sigma 16mm f/1.4 DC DN C * Sigma 16mm f/1.4 DC DN C * Sigma 17-50mm f/2.8 EX DC HSM * Sigma 17-70mm f/2.8-4.5 DC Macro * Sigma 17-70mm f/2.8-4 DC Macro OS HSM | C * Sigma 18-200mm f/3.5-6.3 DC Macro OS HSM * Sigma 18-300mm f/3.5-6.3 DC Macro HSM * Sigma 19mm f/2.8 DN * Sigma 20mm f/1.4 DG HSM | A * Sigma 24mm f/1.4 DG HSM [A] * Sigma 24mm f/2.8 Super Wide II * Sigma 28-70mm f/2.8 AF * Sigma 50-100mm f/1.8 DC HSM Art * Sigma 60mm f/2.8 DN * Sigma 70-300mm f/4-5.6 DG OS * Sigma 70mm f/2.8 EX DG Macro * Sigma 85mm f/1.4 EX DG HSM * Sigma 85mm f/1.4 EX DG HSM * SLR Magic 8mm f/4 * Sony Carl Zeiss Distagon T* 24mm F2 ZA SSM (SAL24F20Z) * Sony E 10-18mm f/4 OSS * Sony E 16-55mm F2.8 G * Sony E 18-135mm f/3.5-5.6 OSS * Sony E 70-350mm F4.5-6.3 G OSS * Sony FE 100-400mm f/4.5-5.6 GM OSS * Sony FE 12-24mm f/4 G * Sony FE 16-35mm f/2.8 GM * Sony FE 16-35mm f/4 ZA OSS * Sony FE 200-600mm F5.6-6.3 G OSS * Sony FE 20mm F1.8 G * Sony FE 24-105mm f/4 G OSS * Sony FE 24-240mm f/3.5-6.3 OSS * Sony FE 24-70mm f/2.8 GM * Sony FE 24mm F1.4 GM * Sony FE 24mm f/2.8 G * Sony FE 35mm F1.4 GM (SEL35F14GM) * Sony FE 35mm f/1.4 ZA * Sony FE 35mm F1.8 * Sony FE 35mm f/2.8 ZA * Sony FE 50mm f/1.8 * Sony FE 50mm f/2.5 G * Sony FE 70-200mm f/2.8 GM OSS * Sony FE 70-200mm f/4 G OSS * Sony FE 70-300mm f/4.5-5.6 G OSS * Sony FE 85mm f/1.4 GM * Sony FE 85mm f/1.8 * Sony 28-75mm F2.8 SAM * Sony 35mm f/1.4 G * Sony 70-300mm f/4.5-5.6 G SSM II * Sony AF 100mm F2.8 Macro * Sony AF 500mm F8 Reflex * Sony AF DT 18-250mm f/3.5-6.3 * Sony Zeiss Planar T* 50mm f/1.4 ZA SSM * Sony Zeiss Vario-Sonnar T* 16-35mm f/2.8 ZA SSM II * Sony Zeiss Vario-Sonnar T* 24-70mm f/2.8 ZA SSM II * Tamron AF 18-200mm f/3.5-6.3 Di II VC * Tamron E 17-28mm F2.8-2.8 * Tamron E 17-70mm F2.8 B070 * Tamron E 18-300mm F3.5-6.3 B061 * Tamron E 28-200mm F2.8-5.6 A071 * Tamron E 28-75mm F2.8-2.8 * Tamron 10-24mm f/3.5-4.5 Di II VC HLD * Tamron 14-150mm f/3.5-5.8 Di III * Tamron 17-35mm F/2.8-4 Di OSD * Tamron 18-400mm f/3.5-6.3 Di II VC HLD (B028) * Tamron 200mm f/3.5 CT-200 BBAR * Tamron 20mm F2.8 Di III OSD M1:2 * Tamron 28-300mm f/3.5-6.3 Di VC PZD * Tamron AF 17-50mm f/2.8 XR Di-II LD (Model A16) * Tamron AF 18-270mm F/3.5-6.3 Di II VC LD Aspherical (IF) Macro * Tamron AF 18-270mm F/3.5-6.3 Di II VC PZD * Tamron SP 15-30mm f/2.8 Di VC USD * Tamron SP 15-30mm f/2.8 Di VC USD G2 (A041) * Tamron SP 24-70mm F/2.8 Di VC USD G2 (A032) * Tamron SP 35mm f/1.4 Di USD * Tamron SP 35mm f/1.8 Di VC USD F012 * Tamron SP 70-200mm F/2.8 Di VC USD G2 * Tamron SP 70-300mm f/4-5.6 Di USD * Tamron SP 70-300mm f/4-5.6 Di VC USD (A005) * Tamron SP 90mm f/2.8 Di VC USD Macro 1:1 * Tamron SP 90mm f/2.8 Di VC USD Macro 1:1 * Tamron SP 90mm F/2.8 Di VC USD Macro 1:1 * Tamron SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical (IF) * Tamron SP AF 28-75mm f/2.8 XR Di (IF) Macro * Tokina E 20mm f/2 * Tokina 17mm f/3.5 AT-X 17 AF Pro * Tokina 17mm f/3.5 RMC II * Tokina AF 100mm f/2.8 AT-X Pro D M100 Macro * Tokina AF 11-20mm f/2.8 AT-X Pro DX * Tokina AF 28-80mm f/2.8 AT-X 280 Pro * Tokina AF 80-200mm f/2.8 AT-X 828 Pro * Tokina AT-X 14-20 F2 PRO DX * Tokina AT-X 24-70mm f/2.8 PRO FX * Tokina ATX-i 11-20mm F2.8 CF * Venus Laowa 12mm f/2.8 Zero-D * Venus Laowa 60mm f/2.8 2X Ultra-Macro * Venus Laowa 7.5mm f/2.0 * Venus Laowa 9mm f/2.8 Zero-D * Viltrox 23mmF1.4XM * Viltrox Viltrox 23mm F1.4 E * Viltrox Viltrox AF 85mm f/1.8 Z * Voigtlander Voigtländer HELIAR-HYPER WIDE 10mm F5.6 * Voigtländer Voigtländer Super Wide-Heliar 15mm f/4.5 III * Yongnuo Yongnuo YN 35mm f/2 * Yongnuo Yongnuo YN 50mm f/1.8 * Zeiss Batis 18mm f/2.8 * Zeiss Batis 25mm f/2 * Zeiss Batis 85mm f/1.8 * Zeiss Carl Zeiss Distagon T* 2/35 ZF.2 * Zeiss Loxia 21mm f/2.8 * Zeiss Loxia 50mm f/2 Planar T* * Zeiss Touit 2.8/50M * Zeiss Zeiss Milvus 1.4/50 * Zeiss Zeiss Otus 85mm f/1.4 * And more... Additional/updated data for: * Canon EF-S 10-22mm f/3.5-4.6 USM * Canon EF 16-35mm f/2.8L USM * Canon EF-S 17-55mm f/2.8 IS USM * Canon EF-S 18-55mm f/3.5-5.6 IS * Canon EF 24-105mm f/4L IS USM * Canon EF 50mm f/1.4 USM * Canon EF 70-300mm f/4.5-5.6 DO IS USM * Canon EF 100-400mm f/4.5-5.6L IS USM * Canon EF 24-70mm f/4L IS USM * Fujifilm XF 23mm f/1.4 R * Fujifilm XF 27mm f/2.8 * Fujifilm XF 35mm f/1.4 R * Fujifilm XF 60mm f/2.4 R Macro * Fujifilm XF 18-55mm f/2.8-4 R LM OIS * Fujifilm XF 55-200mm f/3.5-4.8 R LM OIS * Nikkor AF-S 16-80mm f/2.8-4E DX ED VR * Olympus Zuiko Digital ED 9-18mm f/4.0-5.6 * Olympus Zuiko Digital ED 14-54mm f/2.8-3.5 * Olympus M.Zuiko Digital 25mm f/1.8 * Pentax FA 28mm f/2.8 * Pentax FA 50mm f/1.4 * Samyang 12mm f/2.0 NCS CS * Sigma 8mm f/3.5 EX DG Circular * Sigma 17-50mm f/2.8 EX DC OS HSM * Voigländer Ultron 40mm f/2 SL_II Asph. * Many more... ======================================= 0.3.1 --> 0.3.2 (2015-11-16) ======================================= * Incremented binary version number * Improved vignetting interpolation * Internal code cleanups * Custom install directories can be configured by CMAKE_INSTALL_XXX variables (CMake GNUInstallDirs) * New LENSFUN_WINDOWS_DATADIR CMake variable for better windows compatibility * Support for parallel installation of different database versions New interchangeable lenses: * Canon EF-S 10-18mm f/4.5-5.6 IS STM * Canon EF-S 24mm f/2.8 STM * Canon EF 24-70mm f/4L IS USM * Canon FDn 50mm 1:1.8 * Canon FDn 24mm 1:2.8 * Contax G Planar T* 2/35 * Fujifilm XC 16-50mm f/3.5-5.6 OIS II * Fujifilm XC 50-230mm f/4.5-6.7 OIS II * Leica D Vario-Elmar 14-150mm f/3.5-5.6 Asph. OIS * Minolta MD Rokkor 50mm 1:1.4 * 1 Nikkor 18.5mm f/1.8 * 1 Nikkor 32mm f/1.2 * Nikkor AF-S 20mm f/1.8G ED * Nikon Lens Series E 28mm f/2.8 * Nikon Lens Series E 50mm f/1.8 * Nikkor AF-S 85mm f/1.4G * Nikon Lens Series E 100mm f/2.8 * Nikkor AF 105mm f/2.8D Micro * Nikkor AF-S 300mm f/4E PF ED VR * Olympus M.Zuiko Digital ED 7-14mm f/2.8 Pro * Olympus M.Zuiko Digital ED 8mm f/1.8 Fisheye Pro * Olympus 9mm Body Cap Lens Fisheye * Samyang 12mm f/2.8 Fish-Eye ED AS NCS * Samyang 35mm T1.5 Cine Lens * Sigma 70-300mm F4-5.6 DG Macro * Sony FE 28mm f/2 * Sony FE 24-70mm f/4 ZA OSS * Sony FE 55mm f/1.8 ZA * Tamron 18-200mm f/3.5-6.3 Di III VC * Tamron SP AF 70-200mm f/2.8 Di LD (IF) Macro * Vivitar Series 1 70-210mm 1:3.5 SN 22... * Voigtländer Ultron 40mm f/2 SL-II Aspherical New compact cameras: * AEE MagiCam SD19 (action cam) * Canon IXUS 125 HS * Canon PowerShot G7 X * Canon PowerShot S100 * Canon PowerShot S110 * Canon PowerShot SX130 IS * Canon PowerShot SX510 HS * GoPro HERO4 Silver * GoPro Hero3+ black * LG G4 * Nikon Coolpix P7000 * Panasonic DMC-FZ150 * Panasonic DMC-LF1 * Panasonic DMC-TZ71 * Sony RX100 IV New interchangable lens cameras: * Sony Alpha 7 II * Sony Alpha 77 II * Pentax K-3 II * Pentax K-S1 * Pentax K-S2 * Samsung NX mini Additional/updated data for: * Canon EF-S 18-135mm f/3.5-5.6 IS STM * Canon EF 24mm f/2.8 * Canon EF 24-70mm f/2.8L USM * Canon EF 50mm f/1.8 II * Nikon AF-S Nikkor 18-135mm f/3.5-5.6G DX IF-ED * Nikon AF-S Nikkor 20mm f/1.8G ED * Nikon AF Nikkor 20mm f/2.8D * Nikon AF-S Nikkor 50mm f/1.4G * Nikon AF-S Nikkor 50mm f/1.8G * Nikon AF-S Nikkor 28-300mm f/3.5-5.6G ED VR * Nikon AF-S Zoom-Nikkor 16-35mm f/4G ED VR * Nikon AF DX Fisheye-Nikkor 10.5mm f/2.8G ED * Samsung NX 45mm f/1.8 2D/3D * Sigma 12-24mm f/4.5-5.6 EX DG * Sony DT 16-50mm f/2.8 SSM * smc Pentax-A 28mm 1:2.8 * Sony FE 24-70mm f/4 ZA OSS * Panasonic DMC-LX100 * Canon PowerShot G7 X ======================================= 0.3 --> 0.3.1 (2015-05-10) ======================================= * Improved performance when used with 32-bit float image buffers. * Introduced automated testing. * lensfun-update-data now also works without root privileges * Fixed autoscaling for panoramic and equirectangular projections New interchangeable lenses: * Canon EF 16-35mm f/4L IS USM * Canon EF-S 18-55mm f/3.5-5.6 IS STM * Canon Lens FL 50mm F1.4 * Canon FDn 50mm 1:1.4 (APS-C) * Nikkor AF-S 60mm f/2.8G ED Micro * Canon EF 70-210mm f/3.5-4.5 USM * Canon Lens FL 135mm F3.5 * Canon EF 300mm f/2.8L IS II USM (also with 1.4x and 2.0x converters) * Canon EF 400mm f/5.6L USM (also with 1.4x converter) * Canon EF 500mm f/4L IS II USM (also with 1.4x and 2.0x converters) * Cosina 19-35mm f/3.5-4.5 MC * Fotasy M3517 35mm f/1.7 * Fujifilm TCL-X100 teleconverter (for X100/X100s cameras) * Fujifilm XF 23mm f/1.4 R * Fujifilm XF 60mm f/2.4 R Macro * KMZ MC HELIOS-44M-4 58mm 1:2 * Leica DG Summilux 15mm f/1.7 * Lumix G Vario 12-32 f/3.5-5.6 * Lumix G 14mm f/2.5 II * Minolta MD 35mm 1/2.8 * Minolta AF 35-105mm f/3.5-4.5 * Nikkor AF 10.5mm f/2.8G DX ED Fisheye * Nikkor AF-S 18-55mm f/3.5-5.6G DX VR II * Nikkor AF-S 18-300mm f/3.5-6.3G DX ED VR * Nikkor AI 20mm f/3.5 * Nikkor AF 20-35mm f/2.8D IF * Nikkor AI-S 24mm f/2.8 * Nikkor AF-S 24-120mm f/4G ED VR * Nikkor AF 28mm f/1.4D * Nikkor AF-S 28mm f/1.8G * Nikkor AI-S 28mm f/2.8 * Nikkor AF 28-80mm f/3.3-5.6G * Nikkor AF 28-200mm f/3.5-5.6G IF-ED * Nikkor AI-S 35mm f/2.0 * Nikkor AF 60mm f/2.8D Micro * Nikkor AF-S 70-300mm f/4.5-5.6G VR IF-ED * Olympus M.Zuiko Digital 60mm f/2.8 Macro * HD Pentax-DA 20-40mm f/2.8-4 ED Limited DC WR * smc Pentax-A 28mm 1:2.8 * smc Pentax-DA 18-55mm f/3.5-5.6 AL II * smc Pentax-DA 50mm f/1.8 * smc Pentax-M Macro 1:4 50mm * Ricoh 50mm 1:2.0 * Schneider-Kreuznach Retina-Curtagon 1:4/28mm * Sigma 8mm f/3.5 EX DG Circular (APS-C) * Sony FE 28-70mm f/3.5-5.6 OSS * Tamron SP AF 60mm f/2 Di II LD (IF) Macro * Tamron SP 150-600mm f/5-6.3 Di VC USD * Tokina AF 100mm f/2.8 AT-X Pro D Macro * Voigtländer Skoparex 1:3,4/35 * Voigtländer Color-Skopar X 1:2,8/50 * Zenitar MC 16mm f/2.8 * Carl Zeiss Jena 1Q Biotar 1:2 f=58mm T New interchangable lens cameras: * Canon EOS 7D Mark II * Canon EOS 750D * Canon EOS 760D * Canon EOS M2 * Canon EOS M3 * Fuji X-A2 * Nikon D5500 * Nikon D7200 * Nikon 1 S2 * Nikon 1 V3 * Nikon 1 J5 * Olympus E-5 Mark II * Panasonic DMC-GH4 * Panasonic DMC-GF7 * Samsung NX1 * Samsung NX300M * Samsung NX500 * Sony A5100 New compact cameras: * Canon IXUS 220 HS (CHDK's DNGs) * Canon PowerShot A4000 IS (CHDK's DNGs) * Canon PowerShot G1 X Mark II * Canon PowerShot S95 * DIJ Phantom Vision FC200 * Fujifilm FinePix A370 * Fujifilm X100T * Fujifilm X30 * Fujifilm XQ1 * Olympus E-PL7 * Olympus Stylus 1s * Panasonic FZ1000 * Panasonic DMC-GM5 * Panasonic DMC-LX100 * Ricoh GR * Sony RX100 III Additional/updated data for: * Canon EF-S 10-22mm f/3.5-4.5 USM * Canon TS-E 24mm f/3.5L * Canon EF 24-85mm f/3.5-4.5 USM * Canon EF 50mm f/1.8 * Canon EF 70-200mm f/4L IS USM * Fujifilm XC 16-50mm f/3.5-5.6 OIS * Fujifilm XC 50-230mm f/4.5-6.7 OIS * Nikkor AF 24-85mm f/2.8-4D IF * Nikkor AF 50mm f/1.4D * Nikkor AF 50mm f/1.8D * Nikkor AF-S 55-300mm f/4.5-5.6G DX ED VR * Nikkor AF-S 70-200mm f/2.8G VR IF-ED * Nikkor AF 70-210mm f/4-5.6 * Nikkor AF 80-200mm f/2.8 ED * Nikkor AF 85mm f/1.8 * Olympus M.Zuiko Digital 25mm f/1.8 * Olympus M.Zuiko Digital 60mm f/2.8 Macro * Olympus M.Zuiko Digital ED 75-300mm f/4.8-6.7 II * smc Pentax-DA 18-55mm f/3.5-5.6 AL WR * smc Pentax-M 28mm 1:3.5 * smc Pentax-DA 35mm f/2.4 AL * smc Pentax-A 50mm f/1.7 * Samyang 14mm f/2.8 ED AS IF UMC * Sigma 19mm f/2.8 EX DN * Sigma 50-150mm f/2.8 APO EX DC OS HSM * Sigma 70-200mm f/2.8 EX DG OS HSM * Sigma 105mm f/2.8 EX DG OS HSM Macro * Sony 50mm f/1.4 * Sony E 16-50mm f/3.5-5.6 OSS PZ * Canon PowerShot A640 * Canon PowerShot A720 * Canon PowerShot SX150 * Canon PowerShot SX220 ======================================= 0.2.8 --> 0.3 (2014-09-30) ======================================= * Streamlined the names of Nikkor, Tamron, Tokina, Panasonic, Leica, Olympus, Sony, and Sigma lenses so that auto-detection works better * Fixed names of Sony Coolpix cameras * Comprehensive update of Lensfun's documentation * Lens lists may now be sorted by focal length * The tag is now mandatory for and in the database files * Increased accuracy because APS-C is not anymore assumed to have the crop factor 1.5 (non-Canon) or 1.6 (Canon), but the accurate crop factor of the respective camera * Added command line tool "lensfun-update-data" for updating the database * Added command line tool "lensfun-add-adapter" for managing mount compatibilities * Removed compatibility of Four Third on Micro Four Third * Removed compatibility of Sony Alpha on Sony E * Many bugfixes, especially for the case if sensor sizes of calibration and image to-be-corrected are different * MaxAperture is now the maximal f-stop number one can set on the given lens * Removed non-working implementation of CCI * Made primary keys of the database tables explicit and documented * Replaced field-of-view data with real-focal-length data; marked the FOV API deprecated * Higher accuracy for fisheye <--> rectinilear transformation for lenses with real focal length data * The field-of-view distortion model (FOV1) was removed because it is inherently flawed * Simplified method for finding the database directories; see documentation * Removed old non-CMake build system * Added new cameras New interchangeable lenses: * Canon EF-S 15-85mm f/3.5-5.6 IS USM * Canon EF 16-35mm f/2.8L II USM * Canon EF-S 18-55mm f/3.5-5.6 IS * Canon EF-M 18-55mm f/3.5-5.6 IS STM * Canon EF-S 18-135mm f/3.5-5.6 IS STM * Canon EF-S 18-200mm f/3.5-5.6 IS * Canon EF-M 22mm f/2 STM * Canon EF 24-70mm f/2.8L II USM * Canon EF 28-80mm f/3.5-5.6 USM IV * Canon EF 50mm f/1.8 MkII * Canon EF 50-200mm f/3.5-4.5L * Canon EF-S 55-250mm f/4-5.6 IS * Canon EF 70-300mm f/4-5.6L IS USM * Cosina Cosinon-S 50mm 1:2 * KMZ MC MTO 11CA mirror tele * Leica DG Macro-Elmarit 45mm f/2.8 * Mitakon wide MC f=24mm 1:2.8 * 1 Nikkor AW 11-27.5mm f/3.5-5.6 * Nikkor AI-S 6mm f/2.8 Fisheye * Nikkor AF-S 18-140mm f/3.5-5.6G DX ED VR * Nikkor AF-S 18-200mm f/3.5-5.6G DX VR IF-ED * Nikkor AF-S 24-85 mm f/3.5-4.5G ED VR * Nikkor AI-S 50mm f/1.2 * Nikkor AF-S 50mm f/1.8G * Nikkor AF-S 55-300mm f/4.5-5.6G DX ED VR * Nikkor AF-S 70-200mm f/4G VR IF-ED * Nikkor AF-S 70-300mm f/4.5-5.6G VR IF-ED * Nikkor AF-S VR 105mm f/2.8G IF-ED * Nikkor AF-S 600mm f/4G ED VR * Nikkor AF-S 800mm f/5.6E FL ED VR * Fujian 35mm f/1.7 * Fujifilm XC 16-50mm f/3.5-5.6 OIS * Fujifilm XF 18mm f/2 R * Fujifilm XF 18-55mm f/2.8-4 R LM OIS * Fujifilm XF 27mm f/2.8 * Fujifilm XF 35mm f/1.4 R * Fujifilm XC 50-230mm f/4.5-6.7 OIS * Fujifilm XF 55-200mm f/3.5-4.8 R LM OIS * Olympus M.9-18mm f/4.0-5.6 * Olympus Zuiko Digital ED 12-60mm f/2.8-4.0 SWD * Olympus M.Zuiko Digital 25mm f/1.8 * Olympus M.40-150mm f/4.0-5.6 R * Olympus M.Zuiko Digital ED 75mm f/1.8 * Olympus M.Zuiko Digital 75-300mm f/4.8-6.7 II * Panasonic Lumix G Vario 7-14mm f/4.0 * Panasonic Lumix G Vario 12-35mm f/2.8 * Panasonic Lumix G Vario 14-42mm f/3.5-5.6 II * Panasonic Lumix G Vario 14-45mm f/3.5-5.6 Asph. Mega OIS * Panasonic Lumix G 20mm f/1.7 II * Panasonic Lumix G Vario 35-100mm f/2.8 * Panasonic Lumix G Vario 45-150mm f/4.0-5.6 * Panasonic Lumix G Vario PZ 45-175mm f/4.0-5.6 * Pentacon 50mm f/1.8 auto multi coating * Pentax-DA Fish-Eye 10-17mm f/3.5-4.5 ED IF * Pentax-FA 28mm f/2.8 AL * Pentax-M 28mm 1:3.5 * Pentax-FA 31mm F1.8 AL Limited * Pentax-M 35mm 1:2 * Pentax-A 50mm f/1.7 * Pentax-DA L 55-300mm f/4-5.8 ED * Ricoh XR Rikenon 1:1.4 50mm * Samyang 8mm f/3.5 Fish-Eye CS * Samyang T-S 24mm f/3.5 ED AS UMC * Samsung NX 16-50mm f/3.5-5.6 PZ ED OIS * Samsung Zoom 18-55mm f/3.5-5.6 OIS * Samsung NX 20mm f/2.8 Pancake * Samsung NX 45mm f/1.8 2D/3D * Samyang 12mm f/2.0 NCS CS * Samyang 35mm f/1.4 AS UMC * Samyang 50mm f/1.4 AS UMC (APS-C only) * Sigma 10mm f/2.8 EX DC Fisheye HSM * Sigma 18-35mm f/1.8 DC HSM * Sigma 18-250mm f/3.5-6.3 DC OS MACRO HSM * Sigma 24-70mm f/2.8 IF EX DG HSM * Sigma 24-105mm f/4.0 DG OS HSM [A] * Sigma 17-70mm f/2.8-4 DC Macro OS HSM * Sigma 19mm f/2.8 DN * Sigma 19mm f/2.8 EX DN * Sigma 30mm f/2.8 EX DN * Sigma 50mm f/1.4 DG HSM [A] * Sigma 50-150mm f/2.8 APO EX DC HSM II * Sigma 60mm f/2.8 DN * Sigma 70-200mm f/2.8 EX DG APO OS HSM * Sigma 70-200mm f/2.8 EX DG Macro HSM II * Sigma 80-400mm f/4.5-5.6 EX DG OS * Sigma 100-300mm f/4 APO EX DG HSM * Sigma 105mm f/2.8 EX DG OS HSM Macro * Sigma 180mm f/2.8 EX DG OS HSM APO Macro * Sigma 180mm f/5.6 APO Macro * Sony E 10-18mm f/4 OSS * Sony E 16-70mm f/4 ZA OSS * Sony E PZ 18-105mm f/4 G OSS * Sony DT 18-135mm f/3.5-5.6 SAM * Sony AF DT 35mm f/1.8 SAM * Sony AF DT 50mm f/1.8 SAM * Sony DT 55-300mm f/4.5-5.6 SAM * Tamron SP AF 11-18mm f/4.5-5.6 Di-II LD Aspherical (IF) * Tamron 16-300mm f/3.5-6.3 Di II VC PZD * Tamron 18-200mm f/3.5-6.3 XR Di II LD * Tokina AF 12-28mm f/4 AT-X Pro DX * Tokina AF 16-28mm f/2.8 AT-X Pro SD FX * Tokina 500mm f/8 RMC Mirror Lens * Vivitar 100mm f/3.5 AF Macro * Carl Zeiss Distagon T* 2,8/21 ZE * Carl Zeiss Distagon T* 2,8/21 ZF.2 * Zeiss E 32mm f/1.8 New compact cameras: * Canon PowerShot A640 * Canon PowerShot A720 * Canon PowerShot IXUS 70 * Canon PowerShot S90 * Canon PowerShot S120 * Canon PowerShot SX220 HS * Canon PowerShot SX230 HS * Canon PowerShot SX260 HS * Fujifilm FinePix F770EXR * Fujifilm FinePix HS20EXR * Fujifilm FineFix S5600 * Fujifilm X20 * GoPro Hero HD2 * Kodak CX6330 * Nikon Coolpix S3300 * Nokia Lumia 1020 * Olympus Stylus 1 * Panasonic Lumix DMC-LX7 * Panasonic Lumix DMC-FZ200 * Sony DSC-HX300 * Sony RX100 II * Sony RX100 III Additional/updated data for: * Canon EF-S 18-55mm f/3.5-5.6 IS II * Canon EF 24-70mm f/2.8L II USM * Canon EF 24-105mm f/4L IS USM * Canon EF 50mm f/1.8 MkII * Canon EF 50-200mm f/3.5-4.5L * Canon EF 70-200mm f/2.8L IS II USM * Canon EF 70-200mm f/4L IS USM * Canon EF 85mm f/1.8 USM * Canon EF 100mm f/2.8L Macro IS USM * Nikkor AF-S 10-24mm f/3.5-4.5G DX ED * Nikkor AF-S 16-85mm f/3.5-5.6G DX ED VR * Nikkor AF-S 18-55mm f/3.5-5.6G DX VR * Nikkor AF-S 18-105mm f/3.5-5.6G DX ED VR * Nikkor AF-S 18-200mm f/3.5-5.6G DX VR IF-ED II * Nikkor AF 20mm f/2.8D * Nikkor AF-S 35mm f/1.8G DX * Nikkor AF-S 50mm f/1.4G * Nikkor AF-S 55-300mm f/4.5-5.6G DX ED VR * Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.6 L * Olympus M.Zuiko Digital 17mm f/1.8 * Panasonic Lumix G Vario 45-200mm f/4.0-5.6 Mega OIS * Pentax 01 Standard Prime 8.5 mm f/1.9 AL [IF] * Pentax-DA* 16-50mm f/2.8 ED AL IF SDM * Pentax-DA* 50-135mm f/2.8 ED IF SDM * Pentax-D FA Macro 100mm f/2.8 WR * Samyang 8mm f/2.8 Fisheye * Sigma 8-16mm F4.5-5.6 DC HSM * Sigma 10-20mm f/3.5 EX DC HSM * Sigma 10-20mm f/4-5.6 EX DC HSM * Sigma 15-30mm f/3.5-4.5 EX DG Aspherical * Sigma 30mm f/1.4 EX DC HSM * Sigma 35mm f/1.4 DG HSM * Sigma 50mm f/1.4 EX DG HSM * Sigma 70-200mm f/2.8 EX DG Macro HSM II * Sigma 150mm f/2.8 EX DG APO HSM Macro * Sony RX100 * Sony DT 18-55mm f/3.5-5.6 SAM * Sony E 20mm f/2.8 * Sony AF DT 55-200mm f/4-5.6 SAM * Panasonic Lumix G Vario 14-42 f/3.5-5.6 II * Panasonic Lumix G X Vario PZ 14-42 f/3.5-5.6 * Tamron SP AF 17-50mm f/2.8 ======================================= 0.2.7 --> 0.2.8 (2013-10-20) ======================================= Maintenance release. Most fixes were related to the build system. Interchangeable lens: * Canon EF-S 60mm f/2.8 Macro * Canon EF-S 18-135mm f/3.5-5.6 IS * Canon EF 100mm f/2.8L Macro IS USM * Canon EF 200mm f/2.8L USM * Canon EF 85mm f/1.2L II USM * Canon EF 50mm f/1.2L USM * Canon EF 70-200mm f/2.8L USM * Canon EF 70-200mm f/2.8L IS II USM * Canon FDn 100mm 1:2.8 * Canon FDn 50mm 1:1.4 * Nikkor 24-70mm f/2.8G ED * Nikon AF-S DX VR Zoom-Nikkor 18-55mm f/3.5-5.6G * Nikon AF-S DX Zoom-Nikkor 18-70mm f/3.5-4.5G IF-ED * Nikon AF-S Zoom-Nikkor 14-24mm f/2.8G ED * Nikon AF-S Nikkor 85mm f/1.8G * Zuiko Digital 25mm F2.8 * Zuiko Digital 35mm f/3.5 Macro * Zuiko Digital ED 14-42mm F3.5-5.6 * Zuiko Digital ED 40-150mm F4.0-5.6 * Zuiko Digital ED 9-18mm F4.0-5.6 * smc PENTAX-D FA Macro 100mm F2.8 WR * smc PENTAX-DA 15mm F4 ED AL Limited * smc PENTAX-DA 18-55mm F3.5-5.6 AL WR * smc PENTAX-DA 21mm f/3.2 AL Limited * smc PENTAX-DA 35mm f/2.4 AL * smc PENTAX-FA 43mm F1.9 Limited * smc PENTAX-FA 50mm f/1.4 * smc PENTAX-DA* 50-135mm f/2.8 ED [IF] SDM * SIGMA 8mm f/3.5 EX DG Circular * SIGMA 8-16mm f/4.5-5.6mm DC HSM * SIGMA 10-20mm F4-5.6 EX DC HSM * SIGMA 17-50mm F2.8 EX DC OS HSM * SIGMA 24-60mm F2.8 EX DG * SIGMA E 30mm F2.8 * SIGMA 35mm f/1.4 DG HSM * SIGMA 150mm F2.8 MACRO HSM * SIGMA 150-500mm f/5-6.3 APO DG OS HSM * OLYMPUS M.14-150mm F4.0-5.6 * OLYMPUS M.17mm F1.8 * OLYMPUS M.45mm F1.8 * Leica DG Summilux 25/f1.4 * LUMIX G 14/F2.5 + GWC1 0.79x * LUMIX G VARIO PZ 14-42/F3.5-5.6 * Samsung 16mm f/2.4 * Samyang 7.5mm F/3.5 UMC Fish-eye MFT * Samyang 8mm f/2.8 UMC Fish-eye * Samyang 14mm f/2.8 ED AS IF UMC * Samyang 500mm f/6.3 MC IF Mirror Lens * Sony E 10-18mm F4 OSS * Sony E PZ 16-50mm F3.5-5.6 OS * Sony E 18-200mm F3.5-6.3 OSS * Sony E 18-200mm F3.5-6.3 OSS LE * Sony E 30mm F3.5 Macro * Sony E 35mm F1.8 OSS * Sony DT 16-50mm F2.8 SSM * Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD * Tamron SP AF 90mm f/2.8 (172E) Compact cameras: * Canon PowerShot G11 * Canon PowerShot G1X * Canon PowerShot SX150 IS * Fujifilm X10 * Fujifilm X100S * Panasonic DMC-FZ28 * Panasonic LX7 * SAMSUNG WB2000 compact camera * Sigma DP2 lensfun-0.3.4/README.md000066400000000000000000000133371445356770400144750ustar00rootroot00000000000000WHAT IS IT ---------- The goal of the Lensfun library is to provide a open source database of photographic lenses and their characteristics. In the past there was a effort in this direction (see http://www.epaperpress.com/ptlens/), but then author decided to take the commercial route and the database froze at the last public stage. This database was used as the basement on which Lensfun database grew, thanks to PTLens author which gave his permission for this, while the code was totally rewritten from scratch (and the database was converted to a totally new, XML-based format). The Lensfun library not only provides a way to read the database and search for specific things in it, but also provides a set of algorithms for correcting images based on detailed knowledge of lens properties. Right now Lensfun is designed to correct distortion, transversal (also known as lateral) chromatic aberrations, and vignetting. The interface is defined both using C++ style and plain C. The C interface is a wrapper around the C++ classes. Website: http://lensfun.sourceforge.net/ Sourceforge: http://sourceforge.net/projects/lensfun/ LICENSE ------- The libraries which are part of this package are licensed under the terms of the GNU Lesser General Public License, version 3. Libraries are located under the subdirectory libs/ of the source package. A copy of the license is available in the file lgpl-3.0.txt which can be found in the source archive. You can read it here: http://www.gnu.org/licenses/lgpl-3.0.html The documentation files, including those autogenerated with Doxygen, are covered as well by GNU Lesser General Public License, version 3. Applications which are part of this package are licensed under the terms of the GNU General Public License, version 3. Applications are located under the apps/ subdirectory of the source package. A copy of the license can be found in the file gpl-3.0.txt which can be found in the source archive. You can read it here: http://www.gnu.org/licenses/gpl-3.0.html Also the build system (the contents of the build/ subdirectory plus the ac.py file) is licensed under GPL v3. Test programs and tools are put into public domain, unless explicitly specified otherwise in the header of the source files. Test programs are located under the tests/ subdirectory, and tools are located in tools/. The lens database is licensed under the Creative Commons Attribution-Share Alike 3.0 license. The database is located under the data/ subdirectory of the source package. You can read it here: http://creativecommons.org/licenses/by-sa/ BUILD INSTRUCTIONS ------------------ The build system is based on CMake (http://www.cmake.org/). In order to successfully configure and build the project the following tools are more or less required: - CMake - GNU Make - Doxygen in order to generate the library documentation. - GLib 2.0 and later which is used for low-level I/O and XML parsing. - libpng is required to build and run test programs. First enter the Lensfun root folder and create a build directory. cd lensfun mkdir cmake_build Enter the build directory and run CMake to configure your sources and create the build files cd cmake_build cmake ../ Run make/make install as usual make make install The following CMake options can be set (defaults are upper case): -DCMAKE_BUILD_TYPE=DEBUG|Release select debug or release build mode -DINSTALL_HELPER_SCRIPTS=off|ON install various helper scripts -DCMAKE_INSTALL_PREFIX=/USR/LOCAL install prefix -DBUILD_STATIC=OFF|on build static or shared lib -DBUILD_TESTS=OFF|on build also the test programs -DBUILD_LENSTOOL=OFF|on build Lensfun reference implementation -DBUILD_FOR_SSE=off|ON build with SSE optimisation -DBUILD_FOR_SSE2=off|ON build with SSE2 optimisaiton -DBUILD_DOC=OFF|on build documentation If you want to have more detailed output when running 'make' you can simply add 'VERBOSE=1' to the make command line. You can also build packages with cmake: Add -DCPACK_BINARY_DEB:BOOL=ON or -DCPACK_BINARY_RPM:BOOL=ON to the command line and then "make package". (But this is not extensively tested.) Please note that running cmake again does NOT reset all options to default or reconfigure all variables. To restart with a clean configuration delete all files in your cmake_build folder. If you prefer setting the configuration with a GUI or want to get an extensive overview of all available settings and cache values run cmake-gui. DOCUMENTATION ------------- The end-user documentation for the library can be built by issuing the command: make docs Also you can read it online at any time by pointing your browser to: http://lensfun.sourceforge.net/manual/ The documentation on the site is updated every night from Git, so it always contains the latest info on the library. CREDITS ------- Here goes a full list of people who have contributed to this library: CODE: > Andrew Zabolotny LENS DATA: > Tom Niemann: original open-source ptlens database. THANKS: > Pablo d'Angelo for the idea of a open-source lens database. > > The whole PanoTools team, for all math and knowledge I have borrowed from PanoTools: > > Helmut Dersch - The father of most (all?) open-source panorama creation tools. > Daniel M. German > Kevin Kratzke > Rik Littlefield > Fulvio Senore > Jim Watters > Thomas Rauscher > Pablo d'Angelo (thanks once more :) > Bret McKee > Robert Platt Also I would like to thank the people that made valuable contributions to Lensfun: > Niels Kristian Bech Jensen > Pascal de Bruijn > Thomas Modes > Torsten Bronger And of course great thanks to all the people sending profiles for the database. lensfun-0.3.4/apps/000077500000000000000000000000001445356770400141525ustar00rootroot00000000000000lensfun-0.3.4/apps/CMakeLists.txt000066400000000000000000000032611445356770400167140ustar00rootroot00000000000000IF(WIN32) SET(COMMON_LIBS getopt) ENDIF() IF(BUILD_LENSTOOL) FIND_PACKAGE(PNG REQUIRED) INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${PNG_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) ADD_EXECUTABLE(lenstool lenstool/lenstool.cpp lenstool/image.cpp) TARGET_LINK_LIBRARIES(lenstool lensfun ${COMMON_LIBS} ${PNG_LIBRARY} ${ZLIB_LIBRARY}) INSTALL(TARGETS lenstool DESTINATION ${CMAKE_INSTALL_BINDIR}) ENDIF() IF(INSTALL_HELPER_SCRIPTS) INSTALL(PROGRAMS g-lensfun-update-data lensfun-add-adapter lensfun-update-data DESTINATION ${CMAKE_INSTALL_BINDIR}) ENDIF(INSTALL_HELPER_SCRIPTS) # Inspired by http://bloerg.net/2012/11/10/cmake-and-distutils.html FIND_PROGRAM(PYTHON "python3") IF(PYTHON) SET(SETUP_PY_IN "${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in") SET(SETUP_PY "${CMAKE_CURRENT_BINARY_DIR}/setup.py") SET(DEPS_IN "${CMAKE_CURRENT_SOURCE_DIR}/lensfun/__init__.py.in") SET(DEPS "${CMAKE_CURRENT_BINARY_DIR}/lensfun/__init__.py") SET(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/build/timestamp") CONFIGURE_FILE(${SETUP_PY_IN} ${SETUP_PY}) CONFIGURE_FILE(${DEPS_IN} ${DEPS}) ADD_CUSTOM_COMMAND(OUTPUT ${OUTPUT} COMMAND ${PYTHON} ${SETUP_PY} build COMMAND ${CMAKE_COMMAND} -E touch ${OUTPUT} DEPENDS ${DEPS_IN}) ADD_CUSTOM_TARGET(python-package ALL DEPENDS ${OUTPUT}) IF(NOT DEFINED SETUP_PY_INSTALL_PREFIX) SET(SETUP_PY_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") ENDIF() INSTALL(CODE "execute_process(COMMAND ${PYTHON} ${SETUP_PY} install --prefix=\$ENV{DESTDIR}${SETUP_PY_INSTALL_PREFIX})") ENDIF(PYTHON) lensfun-0.3.4/apps/g-lensfun-update-data000077500000000000000000000001411445356770400201610ustar00rootroot00000000000000#!/usr/bin/env sh lensfun-update-data if [ $? -eq 2 ] ; then gksudo lensfun-update-data fi lensfun-0.3.4/apps/lensfun-add-adapter000077500000000000000000000271271445356770400177270ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- """This program allows the user to add further mount compatibilities to his Lensfun configuration. This way, the number of default mount compatibilities can be kept low, while users who own adapters can add those to their local installation. Especially mirrorless systems can use all SLR lenses, so the lens lists to choose from would become very long. The program can be used non-interactively (passing arguments on the command line) and interactively, where the program asks you questions and takes your input. For example, you own a Sony NEX-7 and have bought an adapter to use A-mount lenses with it. Thus, you start this program. The program asks for a camera model name. You enter "NEX-7". Then, you get a list of possible mounts, together with numbers. In this list, it says:: 32) Sony Alpha So, you enter "32 ". That's it. Lensfun now offers also A-mount lenses for E-mount cameras (all, by the way, not only for the NEX-7). Diagnostics: Status code 0 -- successful 1 -- invalid command line arguments 2 -- invalid input in interactive mode The program writes its output to ``~/.local/share/lensfun/_mounts.xml``. Any former mount configuration in that file is preserved. Since it can be assumed that this file will not change its format often (in particular, not with every new Lensfun DB version), this file is deliberately not put in a versioned sub-directory. As a positive side-effect of this, the user is not forced to move this file once a new Lensfun DB version comes out. """ import os, sys, argparse, glob from xml.etree import ElementTree import lensfun local_xml_filepath = os.path.join(lensfun.user_local_db_path, "_mounts.xml") os.makedirs(os.path.dirname(local_xml_filepath), exist_ok=True) parser = argparse.ArgumentParser(description="Add mount compatibilities (adapters) to Lensfun's database.") parser.add_argument("--maker", help="Exact camera manufacturer name.") parser.add_argument("--model", help="Exact camera model name.") parser.add_argument("--mount", help="Exact mount name to add as an adapter for camera mount.") parser.add_argument("--remove-local-mount-config", action="store_true", help="Remove all local changes to the mount compatibility configuration made through this program.") args = parser.parse_args() if args.maker and not args.model or args.model and not args.maker: print("ERROR: The options --maker and --camera must be passed together.") sys.exit(1) if args.remove_local_mount_config: if args.maker or args.model or args.mount: print("ERROR: If the option --remove-local-mount-config is given, it must be the only one.") sys.exit(1) def default_name(element, tag_name): """Returns the untranslated string in the tag `tag_name`, which is a sub-element of `element`. This is useful if you need the e.g. definitive model name of a camera in order to use it as a key. """ for child in element.findall(tag_name): if "lang" not in child.attrib: return child.text def fancy_name(element, tag_name): """Returns the English version of the string in the tag `tag_name`, which is a sub-element of `element`. If not available, take the untranslated version. """ for child in element.findall(tag_name): if child.attrib.get("lang") == "en": return child.text return default_name(element, tag_name) def normalize_camera_name(name): return name.lower().translate(str.maketrans("", "", " ,.:-+*/()[]")) def indent(root, level=0): """Pretty-print an XML tree by indentation.""" i = "\n" + level * " " if len(root): if not root.text or not root.text.strip(): root.text = i + " " if not root.tail or not root.tail.strip(): root.tail = i for root in root: indent(root, level + 1) if not root.tail or not root.tail.strip(): root.tail = i else: if level and (not root.tail or not root.tail.strip()): root.tail = i class Mount: """Normally, all data structures in this program are just strings or mappings or lists of strings. Even compatibility mounts are only represented by their name. However, for the main list of mounts, we have to store more of them. Therefore, this is a class. """ def __init__(self, name, fixed_lens=False): self.name, self.fixed_lens = name, fixed_lens self.compatible_mounts = set() def __str__(self): return self.name def read_database(): """Read the database of Lensfun. Note that also the local configuration – including the ``_mounts.xml`` file – is read. It returns the cameras as a mapping from the (maker, model) tuple to the mount object, the `makers_and_models` mapping which maps so-called “loose” camera names to (maker, model) tuples, and the mounts as a mapping from mount names to `Mount` objects. “Loose” camera names are brutally normalised to that partial string matching can be easily done against user input. In particular, everything is lowercase and all punctuation and spacing is removed. """ cameras = {} makers_and_models = {} mounts = {} paths = lensfun.get_database_directories() for path in paths: for filepath in glob.glob(os.path.join(path, "*.xml")): filename = os.path.basename(filepath) tree = ElementTree.parse(filepath) for mount in tree.findall("mount"): name = default_name(mount, "name") try: fixed_lens = mounts[name].fixed_lens except KeyError: fixed_lens = filename.startswith("compact") or name in ["olympusE10"] mounts[name] = Mount(name, fixed_lens) for compatible_mount in mount.findall("compat"): mounts[name].compatible_mounts.add(compatible_mount.text) for camera in tree.findall("camera"): loose_name = normalize_camera_name(fancy_name(camera, "maker") + fancy_name(camera, "model")) maker_and_model = default_name(camera, "maker"), default_name(camera, "model") makers_and_models[loose_name] = maker_and_model mount = default_name(camera, "mount") cameras[maker_and_model] = mount mounts.setdefault(mount, Mount(mount, filename.startswith("compact") or mount in ["olympusE10"])) for maker_and_model, mount_name in cameras.items(): cameras[maker_and_model] = mounts[mount_name] return mounts, makers_and_models, cameras def find_mount_groups(mounts): """A “mount group” is a set of mount names that are fully compatible to every other one in the group. This way, we can offer the user to add all Nikon lenses in one go to their camera mount, no matter whether the Nikon lens is Nikon F, Nikon F AI-S, etc. Remember that mount compatibilities are not transitive in Lensfun. """ groups = set() for mount in mounts.values(): if mount.name != "Generic": mutually_compatibles = {mount.name} for compatible_mount in mount.compatible_mounts: try: reverse_compatibles = mounts[compatible_mount].compatible_mounts except KeyError: continue if compatible_mount != "Generic" and mount.name in reverse_compatibles: mutually_compatibles.add(compatible_mount) if len(mutually_compatibles) > 1: groups.add(frozenset(mutually_compatibles)) return groups def find_to_mount(cameras, makers_and_models): """The `to_mount` is the camera mount, i.e. the mount *to* which we want to adapt. """ if args.model: try: return cameras[args.maker, args.model] except KeyError: print("ERROR: Camera model not found in database.") sys.exit(1) else: camera_name = normalize_camera_name(input("Enter camera model name (or part of it): ")) hits = [] for loose_name, maker_and_model in makers_and_models.items(): if camera_name in loose_name: hits.append(maker_and_model) if not hits: print("ERROR: No cameras with this name found.") sys.exit(2) elif len(hits) > 1: hits.sort() for i, maker_and_model in enumerate(hits, 1): print("{:3d}) {} {}".format(i, *maker_and_model)) try: number = int(input("Enter number: ")) maker_and_model = hits[number - 1] except (ValueError, IndexError, EOFError): print("ERROR: Invalid input.") sys.exit(2) else: maker_and_model = hits[0] return cameras[maker_and_model] def find_from_mounts(mounts, groups, to_mount): """The `from_mount` is the lenses' mount, i.e. the mount *from* which we want to adapt. It may be a set of mounts in case of a mount group. """ if args.mount: if args.mount not in mounts: print("ERROR: Mount name not found in database.") sys.exit(1) return {args.mount} else: from_candidates = [] for from_candidate in [(mount.name, {mount.name}) for mount in mounts.values() if not mount.fixed_lens] + \ [(", ".join(sorted(group)) + " (all together)", group) for group in groups]: for mount in from_candidate[1]: if mount not in to_mount.compatible_mounts | {to_mount.name}: break else: continue from_candidates.append(from_candidate) from_candidates.sort() for i, mount_data in enumerate(from_candidates, 1): print("{:3d}) {}".format(i, mount_data[0])) try: number = int(input("Enter number: ")) from_mounts = from_candidates[number - 1][1] except (ValueError, IndexError, EOFError): print("ERROR: Invalid input.") sys.exit(2) return from_mounts def write_xml_file(to_mount, from_mounts, mounts): """We write the ``_mounts.xml`` file rather non-invasive, i.e. we touch only the mount we want to change. Either we change it, or we add it. """ try: tree = ElementTree.parse(local_xml_filepath) except (OSError, ElementTree.ParseError): tree = ElementTree.ElementTree(ElementTree.Element("lensdatabase")) for mount in tree.findall("mount"): if default_name(mount, "name") == to_mount.name: for compatible_mount in mount.findall("compat"): mount.remove(compatible_mount) break else: mount = ElementTree.SubElement(tree.getroot(), "mount") ElementTree.SubElement(mount, "name").text = to_mount.name for compatible_mount in sorted(to_mount.compatible_mounts): ElementTree.SubElement(mount, "compat").text = compatible_mount indent(tree.getroot()) tree.write(local_xml_filepath) if args.remove_local_mount_config: try: os.remove(local_xml_filepath) except OSError: pass else: mounts, makers_and_models, cameras = read_database() mount_groups = find_mount_groups(mounts) to_mount = find_to_mount(cameras, makers_and_models) if to_mount.fixed_lens: from_mounts = {"Generic"} else: from_mounts = find_from_mounts(mounts, mount_groups, to_mount) to_mount.compatible_mounts.update(from_mounts) write_xml_file(to_mount, from_mounts, mounts) print("Made {} lenses mountable to {}.".format(" / ".join(from_mounts), to_mount)) lensfun-0.3.4/apps/lensfun-update-data000077500000000000000000000136041445356770400177450ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- """This program fetches the latest version of the Lensfun database from the Internet and places it on the local system. This way, the user can update the database conveniently. Unfortunately, we have to take into account that the Git database may have a too new format for the locally installed Lensfun. Then, it may fetch backports of the database from other URLs. This program must be called with root privileges. It stores the new database in `/var/lib/lensfun-updates`. The repository of databases resides at a base URL. Below that URL, there is the file versions.json. It contains a list with three elements. The first is the database timestamp, the second is a list of available version numbers, and the third is a list of strings which represents further alternative base URLs to look at. So, the file may contain the following:: [1386797501, [1, 2, 3], ["http://wilson.bronger.org/"]] All URLs must end with a slash. For every version number, there must be a file called version_.tar.bz2. So in our case, there must be the files :: version_1.tar.bz2 version_2.tar.bz2 version_3.tar.bz2 in the same directory as versions.json. These tar balls contain the Lensfun database with the given timestamp and version. The timestamps are the number of seconds since the Epoch as an int. Diagnostics: Status code 0 -- successfully installed updates 1 -- no newer upstream database found for last installed Lensfun 3 -- no location was responsive; maybe network problems """ import urllib.request, shutil, sys, os, time, calendar, tarfile, json, glob import lensfun database_version = lensfun.get_database_version() lensfun_updates_dir = lensfun.system_db_update_path if os.name == "posix" and os.geteuid() != 0: lensfun_updates_dir = os.path.join(lensfun.user_local_db_path, "updates") print("Info: root privileges needed for updating the system database.") print("Info: updating user DB in '%s'" % lensfun_updates_dir) def seconds_since_epoch(): return calendar.timegm(time.gmtime()) def detect_local_timestamp(version): if version == database_version: return lensfun.get_core_database()[0] def detect_single_timestamp(path): try: return int(open(os.path.join(path, "version_{}".format(version), "timestamp.txt")).read()) except (FileNotFoundError, ValueError): return 0 directory_candidates = {"/usr/share/lensfun", "/usr/local/share/lensfun", lensfun.system_db_path, lensfun.system_db_update_path, os.path.join(lensfun.user_local_db_path, "updates")} return max(map(detect_single_timestamp, directory_candidates)) class Location: def __init__(self, base_url, version, timestamp): self.base_url, self.version, self.timestamp = base_url, version, timestamp def __lt__(self, other): return self.timestamp < other.timestamp def extract(self, directory): tar = tarfile.open(fileobj=urllib.request.urlopen(self.base_url + "version_{}.tar.bz2".format(self.version)), mode="r|*") tar.extractall(directory) tar.close() def detect_local_database_versions(): versions = {database_version} directories = set(glob.glob("/usr/share/lensfun/version_*") + glob.glob("/usr/local/share/lensfun/version_*") + glob.glob(os.path.join(lensfun.system_db_path, "version_*"))) for directory in directories: if os.path.isdir(directory): try: versions.add(int(directory.partition("version_")[2])) except ValueError: pass return versions local_database_versions = detect_local_database_versions() locations = {version: set() for version in local_database_versions} local_timestamps = {version: detect_local_timestamp(version) for version in local_database_versions} seen_urls = set() at_least_one_responsive_location = False def read_location(base_url): global at_least_one_responsive_location if base_url not in seen_urls and len(seen_urls) < 50: seen_urls.add(base_url) print("Reading {} …".format(base_url + "versions.json")) try: response = urllib.request.urlopen(base_url + "versions.json") except (urllib.error.HTTPError, urllib.error.URLError, ValueError) as e: print(" Error: URL could not be opened, skipping: " + str(e)) else: try: timestamp, versions, alternatives = json.loads(response.read().decode("utf-8")) except ValueError: print(" Error: Invalid data received.") else: at_least_one_responsive_location = True versions = set(versions) & set(locations) for version in versions: if timestamp > local_timestamps[version]: locations[version].add(Location(base_url, version, timestamp)) for base_url in alternatives: read_location(base_url) read_location("http://lensfun.sourceforge.net/db/") read_location("http://wilson.bronger.org/lensfun-db/") if not at_least_one_responsive_location: print("Fatal: No location was responsive. Network down?") sys.exit(3) elif not locations[database_version]: print("Info: No newer database was found for last installed Lensfun.") sys.exit(1) for version, location_list in locations.items(): try: best_location = max(location_list) except ValueError: continue updates_dir = os.path.join(lensfun_updates_dir, "version_{}".format(version)) shutil.rmtree(updates_dir, ignore_errors=True) os.makedirs(updates_dir) best_location.extract(updates_dir) open(os.path.join(updates_dir, "timestamp.txt"), "w").write(str(best_location.timestamp)) print("Successfully updated the database in " + updates_dir + ".") lensfun-0.3.4/apps/lensfun/000077500000000000000000000000001445356770400156245ustar00rootroot00000000000000lensfun-0.3.4/apps/lensfun/__init__.py.in000066400000000000000000000065241445356770400203510ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- """The Lensfun Python package. It provides common functionality for Python scripts that want to find or read the Lensfun database. :var user_local_db_path: absolute path to the Lensfun DB of the current user. :var system_db_update_path: absolute path to the local but system-wide update of the Lensfun DB. :vartype user_local_db_path: str :vartype system_db_update_path: str """ import os user_local_db_path = os.path.join( os.environ.get("XDG_DATA_HOME", os.path.expanduser("~/.local/share")), "lensfun") system_db_path = os.path.join("${CMAKE_INSTALL_FULL_DATAROOTDIR}", "lensfun") system_db_update_path = os.path.join("/", "${CMAKE_INSTALL_LOCALSTATEDIR}", "lib", "lensfun-updates") def get_database_version(): """Returns the database version of the installed Lensfun. Note that if multiple versions of Lensfun are installed, the returned version number refers to the one that was installed together with the Python scripts. :return: the version number of Lensfun's database :rtype: int """ return ${LENSFUN_DB_VERSION} def get_core_database(): """Finds the upstream (core) database. The core database is the database installed with Lensfun, or downloaded by “lensfun-update-data”. :return: the timestamp of the local core database and its path; if no core database is found, it returns ``(0, None)`` :rtype: int, str """ def get_timestamp(path): try: return int(open(os.path.join(path, "timestamp.txt")).read()) except (FileNotFoundError, PermissionError, ValueError): return 0 versioned_subdir = "version_{}".format(get_database_version()) db_path_candidates = {system_db_update_path, os.path.join(user_local_db_path, "updates"), system_db_path} newest_path = None newest_timestamp = 0 for path in db_path_candidates: path = os.path.join(path, versioned_subdir) timestamp = get_timestamp(path) if timestamp > newest_timestamp: newest_timestamp = timestamp newest_path = path return newest_timestamp, newest_path def get_database_directories(): """Returns the directories containing Lensfun databases. The list returned should be iterated over to realise proper overriding of database entries. Thus, later entries take higher precedence over earlier entries. Note that if multiple versions of Lensfun are installed, the returned list refers to the one that was installed together with the Python scripts. Also note that Lensfun databases consist only of the files in a particular directory, and do not include automatically all files in sub-directories as well. All returned paths are guaranteed to exist, however, they may contain no database files or at least no ones readable to the current user. :return: list with paths to Lensfun databases :rtype: list of str """ versioned_subdir = "version_{}".format(get_database_version()) core_database_path = get_core_database()[1] paths = [core_database_path] if core_database_path else [] for path in (user_local_db_path, os.path.join(user_local_db_path, versioned_subdir)): if os.path.isdir(path): paths.append(path) return paths lensfun-0.3.4/apps/lenstool/000077500000000000000000000000001445356770400160115ustar00rootroot00000000000000lensfun-0.3.4/apps/lenstool/auxfun.h000066400000000000000000000044231445356770400174730ustar00rootroot00000000000000#ifndef __LENSTOOL_AUXFUN_H__ #define __LENSTOOL_AUXFUN_H__ // atof() with sanity checks static float _atof (const char *s) { char *end = NULL; float r = strtof (s, &end); if (end && *end) { g_print ("ERROR: Invalid number `%s', parsed as %g\n", s, r); g_print ("Use your locale-specific number format (e.g. ',' or '.' etc)\n"); exit (-1); } return r; } static bool smartstreq (const char *str, const char *pattern) { const char *src = str; while (*src) { char cs = toupper (*src++); char cp = toupper (*pattern++); if (!cs) return (src != str); if (!cp) return false; if (cs != cp) return false; } return true; } static void PrintCamera (const lfCamera *camera, const lfDatabase *ldb) { g_print (" %s / %s %s%s%s\n", lf_mlstr_get (camera->Maker), lf_mlstr_get (camera->Model), camera->Variant ? "(" : "", camera->Variant ? lf_mlstr_get (camera->Variant) : "", camera->Variant ? ")" : ""); g_print (" |- Mount: %s\n", lf_db_mount_name (ldb, camera->Mount)); g_print (" |- Crop factor: %g\n", camera->CropFactor); } static void PrintLens (const lfLens *lens, const lfDatabase *ldb) { g_print (" %s / %s\n", lf_mlstr_get (lens->Maker), lf_mlstr_get (lens->Model)); g_print (" |- Crop factor: %g\n", lens->CropFactor); g_print (" |- Aspect ratio: %g\n", lens->AspectRatio); if (lens->MinFocal != lens->MaxFocal) g_print (" |- Focal: %g-%gmm\n", lens->MinFocal, lens->MaxFocal); else g_print (" |- Focal: %gmm\n", lens->MinFocal); g_print (" |- Min-Aperture: f/%g\n", lens->MinAperture); g_print (" |- Center: %g,%g\n", lens->CenterX, lens->CenterY); g_print (" |- Compatible mounts: "); if (lens->Mounts) for (int j = 0; lens->Mounts [j]; j++) g_print ("%s, ", lf_db_mount_name (ldb, lens->Mounts [j])); g_print ("\n"); g_print (" |- Calibration data: "); if (lens->CalibTCA) g_print ("tca, "); if (lens->CalibVignetting) g_print ("vign, "); if (lens->CalibDistortion) g_print ("dist,"); g_print ("\n"); } #endif lensfun-0.3.4/apps/lenstool/image.cpp000066400000000000000000000514431445356770400176060ustar00rootroot00000000000000/* Miscelaneous image manipulations Copyright (C) 2001 by Andrew Zabolotny */ #include "image.h" #include #include #include #include #ifdef _MSC_VER #define _USE_MATH_DEFINES #include float rint (float x) { return floor (x + 0.5f); } float trunc (float x) { return (((x) < 0) ? ceil ((x)) : floor ((x))); } #define unlink _unlink #else #include #include #endif // A support of 3 gives an overall sharper looking image, but // it is a) slower b) gives more sharpening artefacts #define LANCZOS_SUPPORT 2 // Lanczos kernel is precomputed in a table with this resolution // The value below seems to be enough for HQ upscaling up to eight times #define LANCZOS_TABLE_RES 256 template static inline T square (T x) { return x * x; } float *Image::lanczos_func = NULL; int Image::lanczos_func_use = 0; Image::Image () : file (NULL), lanczos_func_in_use (false), image (NULL) { } Image::~Image () { Close (); Free (); } bool Image::Open (const char *fName) { file = fopen (fName, "rb"); if (!file) return false; fseek (file, 0, SEEK_END); filesize = ftell (file); fseek (file, 0, SEEK_SET); return true; } void Image::Close () { if (file) { fclose (file); file = NULL; } } void Image::Free () { delete [] image; image = NULL; if (lanczos_func_in_use && !--lanczos_func_use) { delete [] lanczos_func; lanczos_func = NULL; lanczos_func_in_use = false; } } bool Image::LoadPNG () { png_structp png; png_infop info; size_t rowbytes, exp_rowbytes; png_bytep *row_pointers; Free (); png = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) return false; info = png_create_info_struct (png); if (!info) { png_destroy_read_struct (&png, (png_infopp) NULL, (png_infopp) NULL); png = NULL; return false; } png_init_io (png, file); if (setjmp (png_jmpbuf(png))) // If we get here, we had a problem reading the file goto nomem; png_read_info (png, info); // Get picture info png_uint_32 Width, Height; int bit_depth, color_type; png_get_IHDR (png, info, &Width, &Height, &bit_depth, &color_type, NULL, NULL, NULL); if (bit_depth > 8) // tell libpng to strip 16 bit/color files down to 8 bits/color png_set_strip_16 (png); else if (bit_depth < 8) // Expand pictures with less than 8bpp to 8bpp png_set_packing (png); switch (color_type) { case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_GRAY_ALPHA: png_set_gray_to_rgb (png); break; case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb (png); break; case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: break; default: goto nomem; } // If there is no alpha information, fill with 0xff if (!(color_type & PNG_COLOR_MASK_ALPHA)) { // Expand paletted or RGB images with transparency to full alpha // channels so the data will be available as RGBA quartets. if (png_get_valid (png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha (png); else png_set_filler (png, 0xff, PNG_FILLER_AFTER); } // Update structure with the above settings png_read_update_info (png, info); // Allocate the memory to hold the image image = new RGBpixel [(width = Width) * (height = Height)]; if (!image) goto nomem; exp_rowbytes = Width * sizeof (RGBpixel); rowbytes = png_get_rowbytes (png, info); if (rowbytes != exp_rowbytes) goto nomem; // Yuck! Something went wrong! row_pointers = new png_bytep [Height]; if (!row_pointers || setjmp (png_jmpbuf(png))) // Set a new exception handler { delete [] row_pointers; nomem: png_destroy_read_struct (&png, &info, (png_infopp) NULL); Free (); return false; } for (png_uint_32 row = 0; row < Height; row++) row_pointers [row] = ((png_bytep)image) + row * rowbytes; // Read image data png_read_image (png, row_pointers); // read rest of file, and get additional chunks in info_ptr png_read_end (png, (png_infop)NULL); // Free the row pointers array that is not needed anymore delete [] row_pointers; png_destroy_read_struct (&png, &info, (png_infopp) NULL); return true; } static inline int isqr (int x) { return x * x; } bool Image::SavePNG (const char *fName) { /* Remove the file in the case it exists and it is a link */ unlink (fName); /* open the file */ FILE *fp = fopen (fName, "wb"); if (fp == NULL) return false; png_structp png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) { error1: fclose (fp); return false; } /* Allocate/initialize the image information data. */ png_infop info = png_create_info_struct (png); if (info == NULL) { error2: png_destroy_write_struct (&png, &info); goto error1; } /* Catch processing errors */ if (setjmp(png_jmpbuf(png))) /* If we get here, we had a problem writing the file */ goto error2; /* Set up the output function */ png_init_io (png, fp); /* Set the image information here. Width and height are up to 2^31, * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED */ int colortype, rowlen, bits; colortype = PNG_COLOR_TYPE_RGB_ALPHA; rowlen = width * sizeof (RGBpixel); bits = 8; png_set_IHDR (png, info, width, height, bits, colortype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* if we are dealing with a color image then */ png_color_8 sig_bit; memset (&sig_bit, 0, sizeof (sig_bit)); sig_bit.red = 8; sig_bit.green = 8; sig_bit.blue = 8; /* if the image has an alpha channel then */ if (colortype & PNG_COLOR_MASK_ALPHA) sig_bit.alpha = bits; png_set_sBIT (png, info, &sig_bit); /* Write the file header information. */ png_write_info (png, info); /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into * RGB (4 channels -> 3 channels). The second parameter is not used. */ if (!(colortype & PNG_COLOR_MASK_ALPHA)) png_set_filler (png, 0, PNG_FILLER_AFTER); /* The easiest way to write the image (you may have a different memory * layout, however, so choose what fits your needs best). You need to * use the first method if you aren't handling interlacing yourself. */ png_bytep *row_pointers = new png_bytep [height]; unsigned char *ImageData = (unsigned char *)image; for (unsigned i = 0; i < height; i++) row_pointers [i] = ImageData + i * rowlen; /* One of the following output methods is REQUIRED */ png_write_image (png, row_pointers); /* It is REQUIRED to call this to finish writing the rest of the file */ png_write_end (png, info); /* clean up after the write, and free any memory allocated */ png_destroy_write_struct (&png, &info); /* Free the row pointers */ delete [] row_pointers; /* close the file */ fclose (fp); /* that's it */ return true; } void Image::Resize (unsigned newwidth, unsigned newheight) { Free (); image = new RGBpixel [(width = newwidth) * (height = newheight)]; } void Image::InitInterpolation (InterpolationMethod method) { switch (method) { case I_NEAREST: fGetR = GetR_n; fGetG = GetG_n; fGetB = GetB_n; fGet = Get_n; break; case I_BILINEAR: fGetR = GetR_b; fGetG = GetG_b; fGetB = GetB_b; fGet = Get_b; break; case I_LANCZOS: fGetR = GetR_l; fGetG = GetG_l; fGetB = GetB_l; fGet = Get_l; if (!lanczos_func) { // Precompute the function for faster interpolation lanczos_func = new float [LANCZOS_SUPPORT * LANCZOS_SUPPORT * LANCZOS_TABLE_RES]; for (int i = 0; i < LANCZOS_SUPPORT * LANCZOS_SUPPORT * LANCZOS_TABLE_RES; i++) { float d = sqrt (float (i) / LANCZOS_TABLE_RES); if (d == 0.0) lanczos_func [i] = 1.0; else lanczos_func [i] = (LANCZOS_SUPPORT * sin (M_PI * d) * sin ((M_PI / LANCZOS_SUPPORT) * d)) / (M_PI * M_PI * d * d); } } if (!lanczos_func_in_use) { lanczos_func_in_use = true; lanczos_func_use++; } break; } } // --- // Nearest interpolation // --- // unsigned char Image::GetR_n (Image *This, float x, float y) { unsigned xi = unsigned (x + 0.5); unsigned yi = unsigned (y + 0.5); if (xi >= This->width || yi >= This->height) return 0; RGBpixel *p = This->image + yi * This->width + xi; return p->red; } unsigned char Image::GetG_n (Image *This, float x, float y) { unsigned xi = unsigned (x + 0.5); unsigned yi = unsigned (y + 0.5); if (xi >= This->width || yi >= This->height) return 0; RGBpixel *p = This->image + yi * This->width + xi; return p->green; } unsigned char Image::GetB_n (Image *This, float x, float y) { unsigned xi = unsigned (x + 0.5); unsigned yi = unsigned (y + 0.5); if (xi >= This->width || yi >= This->height) return 0; RGBpixel *p = This->image + yi * This->width + xi; return p->blue; } void Image::Get_n (Image *This, RGBpixel &out, float x, float y) { unsigned xi = unsigned (x + 0.5); unsigned yi = unsigned (y + 0.5); if (xi >= This->width || yi >= This->height) return; RGBpixel *p = This->image + yi * This->width + xi; out = *p; } // --- // Bi-linear interpolation // --- // unsigned char Image::GetR_b (Image *This, float x, float y) { // linear interpolation unsigned xi = unsigned (x); unsigned yi = unsigned (y); if (xi >= This->width || yi >= This->height) return 0; unsigned dx = unsigned ((x - trunc (x)) * 256); unsigned dy = unsigned ((y - trunc (y)) * 256); RGBpixel *p0 = This->image + yi * This->width + xi; RGBpixel *p1 = p0 + This->width; unsigned k1, k2; k1 = 256 * p0 [0].red + dx * (int (p0 [1].red ) - int (p0 [0].red )); k2 = 256 * p1 [0].red + dx * (int (p1 [1].red ) - int (p1 [0].red )); return (256 * k1 + dy * (k2 - k1)) >> 16; } unsigned char Image::GetG_b (Image *This, float x, float y) { // linear interpolation unsigned xi = int (x); unsigned yi = int (y); if (xi >= This->width || yi >= This->height) return 0; unsigned dx = unsigned ((x - trunc (x)) * 256); unsigned dy = unsigned ((y - trunc (y)) * 256); RGBpixel *p0 = This->image + yi * This->width + xi; RGBpixel *p1 = p0 + This->width; unsigned k1, k2; k1 = 256 * p0 [0].green + dx * (int (p0 [1].green) - int (p0 [0].green)); k2 = 256 * p1 [0].green + dx * (int (p1 [1].green) - int (p1 [0].green)); return (256 * k1 + dy * (k2 - k1)) >> 16; } unsigned char Image::GetB_b (Image *This, float x, float y) { // linear interpolation unsigned xi = int (x); unsigned yi = int (y); if (xi >= This->width || yi >= This->height) return 0; unsigned dx = unsigned ((x - trunc (x)) * 256); unsigned dy = unsigned ((y - trunc (y)) * 256); RGBpixel *p0 = This->image + yi * This->width + xi; RGBpixel *p1 = p0 + This->width; unsigned k1, k2; k1 = 256 * p0 [0].blue + dx * (int (p0 [1].blue ) - int (p0 [0].blue )); k2 = 256 * p1 [0].blue + dx * (int (p1 [1].blue ) - int (p1 [0].blue )); return (256 * k1 + dy * (k2 - k1)) >> 16; } void Image::Get_b (Image *This, RGBpixel &out, float x, float y) { // linear interpolation unsigned xi = unsigned (x); unsigned yi = unsigned (y); if (xi >= This->width || yi >= This->height) { out.red = out.green = out.blue = 0; return; } unsigned dx = unsigned ((x - trunc (x)) * 256); unsigned dy = unsigned ((y - trunc (y)) * 256); RGBpixel *p0 = This->image + yi * This->width + xi; RGBpixel *p1 = p0 + This->width; unsigned k1, k2; k1 = 256 * p0 [0].red + dx * (int (p0 [1].red ) - int (p0 [0].red )); k2 = 256 * p1 [0].red + dx * (int (p1 [1].red ) - int (p1 [0].red )); out.red = (256 * k1 + dy * (k2 - k1)) >> 16; k1 = 256 * p0 [0].green + dx * (int (p0 [1].green) - int (p0 [0].green)); k2 = 256 * p1 [0].green + dx * (int (p1 [1].green) - int (p1 [0].green)); out.green = (256 * k1 + dy * (k2 - k1)) >> 16; k1 = 256 * p0 [0].blue + dx * (int (p0 [1].blue ) - int (p0 [0].blue )); k2 = 256 * p1 [0].blue + dx * (int (p1 [1].blue ) - int (p1 [0].blue )); out.blue = (256 * k1 + dy * (k2 - k1)) >> 16; } // --- // Lanczos 2 interpolation // --- // unsigned char Image::GetR_l (Image *This, float x, float y) { float xs = rint (x) - LANCZOS_SUPPORT; float ys = rint (y) - LANCZOS_SUPPORT; float xe = xs + LANCZOS_SUPPORT * 2; float ye = ys + LANCZOS_SUPPORT * 2; float norm = 0.0; float sum = 0.0; RGBpixel *img = This->image + (long (ys) * This->width + long (xs)); if (xs >= 0 && ys >= 0 && xe < This->width && ye < This->height) for (; ys <= ye; ys += 1.0) { for (float xc = xs; xc <= xe; xc += 1.0, img++) { float d = square (x - xc) + square (y - ys); if (d >= LANCZOS_SUPPORT * LANCZOS_SUPPORT) continue; d = lanczos_func [int (d * LANCZOS_TABLE_RES)]; norm += d; sum += d * img->red; } img += This->width - LANCZOS_SUPPORT * 2 - 1; } else { for (; ys <= ye; ys += 1.0) { if (ys < 0 || ys >= This->height) { img += This->width; continue; } for (float xc = xs; xc <= xe; xc += 1.0, img++) { if (xc < 0 || xc >= This->width) continue; float d = square (x - xc) + square (y - ys); if (d >= LANCZOS_SUPPORT * LANCZOS_SUPPORT) continue; d = lanczos_func [int (d * LANCZOS_TABLE_RES)]; norm += d; sum += d * img->red; } img += This->width - LANCZOS_SUPPORT * 2 - 1; } if (norm == 0.0) return 0; } int r = int (sum / norm); return r > 255 ? 255 : r < 0 ? 0 : r; } unsigned char Image::GetG_l (Image *This, float x, float y) { float xs = rint (x) - LANCZOS_SUPPORT; float ys = rint (y) - LANCZOS_SUPPORT; float xe = xs + LANCZOS_SUPPORT * 2; float ye = ys + LANCZOS_SUPPORT * 2; float norm = 0.0; float sum = 0.0; RGBpixel *img = This->image + (long (ys) * This->width + long (xs)); if (xs >= 0 && ys >= 0 && xe < This->width && ye < This->height) for (; ys <= ye; ys += 1.0) { for (float xc = xs; xc <= xe; xc += 1.0, img++) { float d = square (x - xc) + square (y - ys); if (d >= LANCZOS_SUPPORT * LANCZOS_SUPPORT) continue; d = lanczos_func [int (d * LANCZOS_TABLE_RES)]; norm += d; sum += d * img->green; } img += This->width - LANCZOS_SUPPORT * 2 - 1; } else { for (; ys <= ye; ys += 1.0) { if (ys < 0 || ys >= This->height) { img += This->width; continue; } for (float xc = xs; xc <= xe; xc += 1.0, img++) { if (xc < 0 || xc >= This->width) continue; float d = square (x - xc) + square (y - ys); if (d >= LANCZOS_SUPPORT * LANCZOS_SUPPORT) continue; d = lanczos_func [int (d * LANCZOS_TABLE_RES)]; norm += d; sum += d * img->green; } img += This->width - LANCZOS_SUPPORT * 2 - 1; } if (norm == 0.0) return 0; } int r = int (sum / norm); return r > 255 ? 255 : r < 0 ? 0 : r; } unsigned char Image::GetB_l (Image *This, float x, float y) { float xs = rint (x) - LANCZOS_SUPPORT; float ys = rint (y) - LANCZOS_SUPPORT; float xe = xs + LANCZOS_SUPPORT * 2; float ye = ys + LANCZOS_SUPPORT * 2; float norm = 0.0; float sum = 0.0; RGBpixel *img = This->image + (long (ys) * This->width + long (xs)); if (xs >= 0 && ys >= 0 && xe < This->width && ye < This->height) for (; ys <= ye; ys += 1.0) { for (float xc = xs; xc <= xe; xc += 1.0, img++) { float d = square (x - xc) + square (y - ys); if (d >= LANCZOS_SUPPORT * LANCZOS_SUPPORT) continue; d = lanczos_func [int (d * LANCZOS_TABLE_RES)]; norm += d; sum += d * img->blue; } img += This->width - LANCZOS_SUPPORT * 2 - 1; } else { for (; ys <= ye; ys += 1.0) { if (ys < 0 || ys >= This->height) { img += This->width; continue; } for (float xc = xs; xc <= xe; xc += 1.0, img++) { if (xc < 0 || xc >= This->width) continue; float d = square (x - xc) + square (y - ys); if (d >= LANCZOS_SUPPORT * LANCZOS_SUPPORT) continue; d = lanczos_func [int (d * LANCZOS_TABLE_RES)]; norm += d; sum += d * img->blue; } img += This->width - LANCZOS_SUPPORT * 2 - 1; } if (norm == 0.0) return 0; } int r = int (sum / norm); return r > 255 ? 255 : r < 0 ? 0 : r; } void Image::Get_l (Image *This, RGBpixel &out, float x, float y) { float xs = rint (x) - LANCZOS_SUPPORT; float ys = rint (y) - LANCZOS_SUPPORT; float xe = xs + LANCZOS_SUPPORT * 2; float ye = ys + LANCZOS_SUPPORT * 2; float norm = 0.0; float sumR = 0.0; float sumG = 0.0; float sumB = 0.0; RGBpixel *img = This->image + (long (ys) * This->width + long (xs)); if (xs >= 0 && ys >= 0 && xe < This->width && ye < This->height) for (; ys <= ye; ys += 1.0) { for (float xc = xs; xc <= xe; xc += 1.0, img++) { float d = square (x - xc) + square (y - ys); if (d >= LANCZOS_SUPPORT * LANCZOS_SUPPORT) continue; d = lanczos_func [int (d * LANCZOS_TABLE_RES)]; norm += d; sumR += d * img->red; sumG += d * img->green; sumB += d * img->blue; } img += This->width - LANCZOS_SUPPORT * 2 - 1; } else { for (; ys <= ye; ys += 1.0) { if (ys < 0 || ys >= This->height) { img += This->width; continue; } for (float xc = xs; xc <= xe; xc += 1.0, img++) { if (xc < 0 || xc >= This->width) continue; float d = square (x - xc) + square (y - ys); if (d >= LANCZOS_SUPPORT * LANCZOS_SUPPORT) continue; d = lanczos_func [int (d * LANCZOS_TABLE_RES)]; norm += d; sumR += d * img->red; sumG += d * img->green; sumB += d * img->blue; } img += This->width - LANCZOS_SUPPORT * 2 - 1; } if (norm == 0.0) { out.Set (0, 0, 0); return; } } int rR = int (sumR / norm); int rG = int (sumG / norm); int rB = int (sumB / norm); out.Set (rR > 255 ? 255 : rR < 0 ? 0 : rR, rG > 255 ? 255 : rG < 0 ? 0 : rG, rB > 255 ? 255 : rB < 0 ? 0 : rB); } lensfun-0.3.4/apps/lenstool/image.h000066400000000000000000000115071445356770400172500ustar00rootroot00000000000000/* Copyright (C) 2001 by Andrew Zabolotny This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __IMAGE_H__ #define __IMAGE_H__ #include "rgbpixel.h" #include #if defined (_MSC_VER) && !defined(CONF_LENSFUN_STATIC) #if defined auxfun_EXPORTS #define AF_EXPORT __declspec(dllexport) #else #define AF_EXPORT __declspec(dllimport) #endif #else #define AF_EXPORT #endif /** * This class represents an image object. * It provides loading/saving from a PNG file functionality (through libPNG), * the rest was cut off ;-) */ class AF_EXPORT Image { FILE *file; int filesize; bool lanczos_func_in_use; static float *lanczos_func; static int lanczos_func_use; unsigned char (*fGetR) (Image *This, float x, float y); unsigned char (*fGetG) (Image *This, float x, float y); unsigned char (*fGetB) (Image *This, float x, float y); void (*fGet) (Image *This, RGBpixel &out, float x, float y); // --- Nearest interpolation --- // /// Get interpolated red value at given position static unsigned char GetR_n (Image *This, float x, float y); /// Get interpolated green value at given position static unsigned char GetG_n (Image *This, float x, float y); /// Get interpolated blue value at given position static unsigned char GetB_n (Image *This, float x, float y); /// Get interpolated pixel value at given position static void Get_n (Image *This, RGBpixel &out, float x, float y); // --- Linear interpolation --- // /// Get interpolated red value at given position static unsigned char GetR_b (Image *This, float x, float y); /// Get interpolated green value at given position static unsigned char GetG_b (Image *This, float x, float y); /// Get interpolated blue value at given position static unsigned char GetB_b (Image *This, float x, float y); /// Get interpolated pixel value at given position static void Get_b (Image *This, RGBpixel &out, float x, float y); // --- Lanczos interpolation --- // /// Get interpolated red value at given position static unsigned char GetR_l (Image *This, float x, float y); /// Get interpolated green value at given position static unsigned char GetG_l (Image *This, float x, float y); /// Get interpolated blue value at given position static unsigned char GetB_l (Image *This, float x, float y); /// Get interpolated pixel value at given position static void Get_l (Image *This, RGBpixel &out, float x, float y); public: /// The actual image data RGBpixel *image; /// Image size unsigned width, height; /// The transparent color RGBpixel transp; enum InterpolationMethod { /// Nearest interpolation (very fast, very low quality) I_NEAREST, /// Bi-linear interpolation (fast, low quality) I_BILINEAR, /// Lanczos interpolation (slow, high quality) I_LANCZOS }; /// Initialize the image object Image (); /// Destroy the image object ~Image (); /// Open the file and prepare to read from it bool Open (const char *fName); /// Close the file void Close (); /// Free the image void Free (); /// Load next image from file: this completely discards previously loaded one bool LoadPNG (); /// Save the image into a PNG file in given format bool SavePNG (const char *fName); /// Check if file is at EOF bool AtEOF () { return ftell (file) >= filesize; } /// Allocate a new image of given size void Resize (unsigned newwidth, unsigned newheight); /// Initialize interpolation method void InitInterpolation (InterpolationMethod method); /// Get interpolated red value at given position unsigned char GetR (float x, float y) { return fGetR (this, x, y); } /// Get interpolated green value at given position unsigned char GetG (float x, float y) { return fGetG (this, x, y); } /// Get interpolated blue value at given position unsigned char GetB (float x, float y) { return fGetB (this, x, y); } /// Get interpolated pixel value at given position void Get (RGBpixel &out, float x, float y) { fGet (this, out, x, y); } }; #endif // __IMAGE_H__ lensfun-0.3.4/apps/lenstool/lenstool.cpp000066400000000000000000000403431445356770400203600ustar00rootroot00000000000000/* Test for library image modificator object. */ #include #include #include #include #include #include #include #include #include "lensfun.h" #include "image.h" #include "auxfun.h" /* Define this to apply stage 1 & 3 corrections in one step, see main comment to the lfModifier class */ #define COMBINE_13 #if defined(_MSC_VER) #define strcasecmp _stricmp #define snprintf _snprintf #define strtof (float)strtod #endif static struct { const char *Program; const char *Input; const char *Output; int ModifyFlags; bool Inverse; const char *Lens; const char *Camera; float Scale; float Crop; float Focal; float Aperture; float Distance; Image::InterpolationMethod Interpolation; lfLensType TargetGeom; bool Verbose; } opts = { NULL, NULL, "output.png", 0, false, NULL, NULL, 1.0f, 0, 0, 0, 1.0f, Image::I_LANCZOS, LF_RECTILINEAR, false }; static void DisplayVersion () { g_print ("Lenstool reference implementation for Lensfun version %d.%d.%d\n", LF_VERSION_MAJOR, LF_VERSION_MINOR, LF_VERSION_MICRO); g_print ("Copyright (C) 2007 Andrew Zabolotny\n\n"); g_print ("For distribution rules and conditions of use see the file\n"); g_print ("COPYING which is part of the distribution.\n"); } static void DisplayUsage () { DisplayVersion (); g_print ("\nCommand-line options:\n\n"); g_print (" -d --distortion Apply lens distortion\n"); g_print (" -g# --geometry=# Convert image geometry to given (one of:\n"); g_print (" rectilinear,fisheye,panoramic,equirectangular,\n"); g_print (" orthographic, stereographic, equisolid, thoby)\n"); g_print (" -t --tca Apply lens chromatic aberrations\n"); g_print (" -v --vignetting Apply lens vignetting\n"); g_print (" -a --all Apply all possible corrections (tca, vign, dist)\n"); g_print (" -i --inverse Inverse correction of the image (e.g. simulate\n"); g_print (" lens distortions instead of correcting them)\n"); g_print ("\n"); g_print (" -C# --camera=# Camera name\n"); g_print (" -c# --crop=# Set camera crop factor in case the camera is not given\n"); g_print ("\n"); g_print (" -L# --lens=# Lens name to search for in the database\n"); g_print (" -F# --focal=# Set focal length at which image has been taken\n"); g_print (" -A# --aperture=# Set aperture at which image has been taken\n"); g_print (" -D# --distance=# Set subject distance at which image has been taken\n"); g_print ("\n"); g_print (" -s# --scale=# Apply additional scale on the image\n"); g_print (" -I# --interpol=# Choose interpolation algorithm (n[earest], b[ilinear], l[anczos])\n"); g_print ("\n"); g_print (" -o# --output=# Set file name for output image\n"); g_print (" --verbose Verbose output\n"); g_print (" --version Display program version and exit\n"); g_print (" -h --help Display this help text\n"); } static bool ParseParameters(int argc, char **argv) { static struct option long_options[] = { {"output", required_argument, NULL, 'o'}, {"distortion", no_argument, NULL, 'd'}, {"geometry", optional_argument, NULL, 'g'}, {"tca", no_argument, NULL, 't'}, {"vignetting", no_argument, NULL, 'v'}, {"all", no_argument, NULL, 'a'}, {"inverse", no_argument, NULL, 'i'}, {"scale", required_argument, NULL, 'S'}, {"lens", required_argument, NULL, 'L'}, {"camera", required_argument, NULL, 'C'}, {"crop", required_argument, NULL, 'c'}, {"focal", required_argument, NULL, 'F'}, {"aperture", required_argument, NULL, 'A'}, {"distance", required_argument, NULL, 'D'}, {"interpol", required_argument, NULL, 'I'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 4}, {"verbose", no_argument, NULL, 5}, {0, 0, 0, 0} }; opts.Program = argv [0]; int c; while ((c = getopt_long (argc, argv, "o:dg::tvaiS:L:C:c:F:A:D:I:h", long_options, NULL)) != EOF) { switch (c) { case 'o': opts.Output = optarg; break; case 'd': opts.ModifyFlags |= LF_MODIFY_DISTORTION; break; case 'g': opts.ModifyFlags |= LF_MODIFY_GEOMETRY; if (optarg) { if (!strcasecmp (optarg, "rectilinear")) opts.TargetGeom = LF_RECTILINEAR; else if (!strcasecmp (optarg, "fisheye")) opts.TargetGeom = LF_FISHEYE; else if (!strcasecmp (optarg, "panoramic")) opts.TargetGeom = LF_PANORAMIC; else if (!strcasecmp (optarg, "equirectangular")) opts.TargetGeom = LF_EQUIRECTANGULAR; else if (!strcasecmp (optarg, "orthographic")) opts.TargetGeom = LF_FISHEYE_ORTHOGRAPHIC; else if (!strcasecmp (optarg, "stereographic")) opts.TargetGeom = LF_FISHEYE_STEREOGRAPHIC; else if (!strcasecmp (optarg, "equisolid")) opts.TargetGeom = LF_FISHEYE_EQUISOLID; else if (!strcasecmp (optarg, "thoby")) opts.TargetGeom = LF_FISHEYE_THOBY; else { DisplayUsage(); g_print ("\nTarget lens geometry must be one of 'rectilinear', 'fisheye', 'panoramic', 'equirectangular'\n'orthographic', 'stereographic', 'equisolid', 'thoby'\n"); return false; } } break; case 't': opts.ModifyFlags |= LF_MODIFY_TCA; break; case 'v': opts.ModifyFlags |= LF_MODIFY_VIGNETTING; break; case 'a': opts.ModifyFlags |= LF_MODIFY_VIGNETTING; opts.ModifyFlags |= LF_MODIFY_TCA; opts.ModifyFlags |= LF_MODIFY_DISTORTION; break; case 'i': opts.Inverse = true; break; case 'S': opts.ModifyFlags |= LF_MODIFY_SCALE; opts.Scale = _atof (optarg); break; case'L': opts.Lens = optarg; break; case'C': opts.Camera = optarg; break; case 'c': opts.Crop = _atof (optarg); break; case 'F': opts.Focal = _atof (optarg); break; case 'A': opts.Aperture = _atof (optarg); break; case 'D': opts.Distance = _atof (optarg); break; case 'I': if (smartstreq (optarg, "nearest")) opts.Interpolation = Image::I_NEAREST; else if (smartstreq (optarg, "bilinear")) opts.Interpolation = Image::I_BILINEAR; else if (smartstreq (optarg, "lanczos")) opts.Interpolation = Image::I_LANCZOS; else { DisplayUsage(); g_print ("\nUnknown interpolation method `%s'\n", optarg); return false; } break; case 'h': DisplayUsage (); return false; case 4: DisplayVersion (); return false; case 5: opts.Verbose = true; break; default: return false; } } if (optind <= argc) opts.Input = argv [optind]; if (!opts.Lens && !opts.Camera) { DisplayUsage(); g_print ("\nAt least a lens or camera name is required to perform a database lookup!\n"); return false; } if (!opts.Lens && opts.Input) { DisplayUsage(); g_print ("\nNo lens information (-L) supplied to process specified input image!\n"); return false; } return true; } static Image *ApplyModifier (int modflags, bool reverse, Image *img, const lfModifier *mod) { // Create a new image where we will copy the modified image Image *newimg = new Image (); // Output image always equals input image size, although // this is not a requirement of the library, it's just a // limitation of the testbed. newimg->Resize (img->width, img->height); #ifdef COMBINE_13 int lwidth = img->width * 2 * 3; #else int lwidth = img->width * 2; if (modflags & LF_MODIFY_TCA) lwidth *= 3; #endif float *pos = new float [lwidth]; int step_start = reverse ? 2 : 0; int step_delta = reverse ? -1 : +1; int step_finish = reverse ? -1 : 3; for (int step = step_start; step != step_finish; step += step_delta) { RGBpixel *dst = newimg->image; char *imgdata = (char *)img->image; bool ok = true; img->InitInterpolation (opts.Interpolation); for (unsigned y = 0; ok && y < img->height; y++) switch (step) { #ifdef COMBINE_13 case 0: ok = false; break; case 2: /* TCA and geometry correction */ ok = mod->ApplySubpixelGeometryDistortion (0.0, y, img->width, 1, pos); #else case 0: /* TCA correction */ ok = mod->ApplySubpixelDistortion (0.0, y, img->width, 1, pos); #endif if (ok) { float *src = pos; for (unsigned x = 0; x < img->width; x++) { dst->red = img->GetR (src [0], src [1]); dst->green = img->GetG (src [2], src [3]); dst->blue = img->GetB (src [4], src [5]); src += 2 * 3; dst++; } } break; case 1: /* Colour correction: vignetting */ ok = mod->ApplyColorModification (imgdata, 0.0, y, img->width, 1, LF_CR_4 (RED, GREEN, BLUE, UNKNOWN), 0); imgdata += img->width * 4; break; #ifndef COMBINE_13 case 2: /* Distortion and geometry correction, scaling */ ok = mod->ApplyGeometryDistortion (0.0, y, newimg->width, 1, pos); if (ok) { float *src = pos; for (unsigned x = 0; x < img->width; x++) { img->Get (*dst, src [0], src [1]); src += 2; dst++; } } break; #endif } // After TCA and distortion steps switch img and newimg. // This is crucial since newimg is now the input image // to the next stage. if (ok && (step == 0 || step == 2)) { Image *tmp = newimg; newimg = img; img = tmp; } } delete [] pos; delete newimg; return img; } int main (int argc, char **argv) { setlocale (LC_ALL, ""); if (!ParseParameters(argc, argv)) return -1; // load database lfDatabase *ldb = new lfDatabase (); if (ldb->Load () != LF_NO_ERROR) { delete ldb; g_print ("\rERROR: Database could not be loaded\n"); return -1; } // try to find camera in the database const lfCamera *cam = NULL; if (opts.Camera) { const lfCamera ** cameras = ldb->FindCamerasExt(NULL, opts.Camera); if (cameras) cam = cameras[0]; else g_print ("Cannot find a camera matching `%s' in database\n", opts.Camera); lf_free (cameras); } // try to find a matching lens in the database const lfLens *lens = NULL; if (opts.Lens) { const lfLens **lenses = ldb->FindLenses (cam, NULL, opts.Lens); if (lenses) lens = lenses [0]; else g_print ("Cannot find a lens matching `%s' in database\n", opts.Lens); lf_free (lenses); } // print camera and lens information if in verbose mode or if no input file is specified if (opts.Verbose || !opts.Input) { if (cam && lens) { g_print("Matching lens and camera combination found in the database:\n"); PrintCamera(cam, ldb); PrintLens(lens, ldb); } else if (!cam && lens) { g_print("Matching lens found in the database:\n"); PrintLens(lens, ldb); } else if (!lens && cam) { g_print("Matching camera found in the database:\n"); PrintCamera(cam, ldb); } } else { if (cam && lens) { g_print("= Selecting %s / %s\n", cam->Model, lens->Model); } else if (!cam && lens) { g_print("= Selecting %s\n", lens->Model); } } // nothing to process, so lets quit here if (!opts.Input) { delete ldb; return 0; } // assume standard values if parameters are not specified if (cam) opts.Crop = cam->CropFactor; else if (!opts.Crop) opts.Crop = lens->CropFactor; if (!opts.Focal) opts.Focal = lens->MinFocal; if (!opts.Aperture) opts.Aperture = lens->MinAperture; if (opts.Verbose) { g_print("\nProcessing parameters:\n" " |- Image crop factor: %g\n" " |- Focal length: %gmm\n" " |- Aperture: f/%g\n" " |- Distance: %gm\n\n", opts.Crop, opts.Focal, opts.Aperture, opts.Distance); } else { g_print("= Processing parameters: Crop %g, Focal %gmm, Aperture f/%g, Distance: %gm\n", opts.Crop, opts.Focal, opts.Aperture, opts.Distance); } Image *img = new Image (); g_print ("~ Loading `%s' ... ", opts.Input); if (!img->Open (opts.Input)) { g_print ("\rERROR: failed to open file `%s'\n", opts.Input); delete img; delete ldb; return -1; } if (!img->LoadPNG ()) { g_print ("\rERROR: failed to parse PNG data from file `%s'\n", opts.Input); delete img; delete ldb; return -1; } g_print ("done.\n~ Image size [%ux%u].\n", img->width, img->height); lfModifier *mod = new lfModifier (lens, opts.Crop, img->width, img->height); if (!mod) { g_print ("\rWarning: failed to create modifier\n"); delete img; delete ldb; return -1; } int modflags = mod->Initialize ( lens, LF_PF_U8, opts.Focal, opts.Aperture, opts.Distance, opts.Scale, opts.TargetGeom, opts.ModifyFlags, opts.Inverse); g_print("~ Selected modifications: "); if (modflags & LF_MODIFY_TCA) g_print ("[tca]"); if (modflags & LF_MODIFY_VIGNETTING) g_print ("[vign]"); if (modflags & LF_MODIFY_DISTORTION) g_print ("[dist]"); if (modflags & LF_MODIFY_GEOMETRY) g_print ("[geom]"); if (opts.Scale != 1.0) g_print ("[scale]"); if (modflags==0) g_print ("[NOTHING]"); g_print ("\n"); g_print("~ Run processing chain... "); clock_t st; clock_t xt = clock (); while (xt == (st = clock ())) ; img = ApplyModifier (modflags, opts.Inverse, img, mod); clock_t et = clock (); g_print ("done (%.3g secs)\n", double (et - st) / CLOCKS_PER_SEC); delete mod; g_print ("~ Save output as `%s'...", opts.Output); bool ok = img->SavePNG (opts.Output); delete img; delete ldb; if (ok) { g_print (" done\n"); return 0; } else { g_print (" FAILED\n"); return -1; } } lensfun-0.3.4/apps/lenstool/rgbpixel.h000066400000000000000000000076621445356770400200110ustar00rootroot00000000000000/* Copyright (C) 2001 by Andrew Zabolotny This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __RGBPIXEL_H__ #define __RGBPIXEL_H__ #ifdef HAVE_ENDIAN_H # include #endif #ifndef __LITTLE_ENDIAN # define __LITTLE_ENDIAN 1234 #endif #ifndef __BIG_ENDIAN # define __BIG_ENDIAN 4321 #endif #if !defined __BYTE_ORDER # if defined _HOST_BIG_ENDIAN || defined __BIG_ENDIAN__ || defined WORDS_BIGENDIAN || defined __sgi__ || defined __sgi || defined __powerpc__ || defined sparc || defined __ppc__ || defined __s390__ || defined __s390x__ # define __BYTE_ORDER __BIG_ENDIAN # else # define __BYTE_ORDER __LITTLE_ENDIAN # endif #else # define __BYTE_ORDER __LITTLE_ENDIAN #endif // For optimized performance, we sometimes handle all R/G/B values simultaneously #if __BYTE_ORDER == __BIG_ENDIAN # define RGB_MASK 0xffffff00 #else # define RGB_MASK 0x00ffffff #endif /** * An RGB pixel. Besides R,G,B color components this structure also * contains the Alpha channel component, which is used in images * (that potentially have an alpha channel). */ struct RGBpixel { /// The red, green, blue and alpha components unsigned char red, green, blue, alpha; /// Constructor (initialize to zero, alpha to 255) RGBpixel () /* : red(0), green(0), blue(0), alpha(255) {} */ { *(unsigned *)this = (unsigned)~RGB_MASK; } /// Copy constructor RGBpixel (const RGBpixel& p) /* : red (p.red), green (p.green), blue (p.blue), alpha (p.alpha) {} */ { *(unsigned *)this = *(unsigned *)&p; } /// Initialize the pixel with some R/G/B value RGBpixel (int r, int g, int b) : red (r), green (g), blue (b), alpha (255) {} /// Compare with an RGBpixel (including alpha value) bool operator == (const RGBpixel& p) const /* { return (p.red == red) && (p.green == green) && (p.blue == blue); } */ { return *(unsigned *)this == *(unsigned *)&p; } /// Check if the RGBpixel is not equal to another RGBpixel (including alpha) bool operator != (const RGBpixel& p) const { return !operator == (p); } /// Compare with another RGBpixel, but don't take alpha into account bool eq (const RGBpixel& p) const { return ((*(unsigned *)this) & RGB_MASK) == ((*(unsigned *)&p) & RGB_MASK); } /// Get the pixel intensity int Intensity () { return (red + green + blue) / 3; } /// Assign given red/green/blue values to this pixel void Set (const int r, const int g, const int b) { red = r; green = g; blue = b; alpha = 255; } /// Assign given red/green/blue/alpha values to this pixel void Set (const int r, const int g, const int b, const int a) { red = r; green = g; blue = b; alpha = a; } void Set (const RGBpixel& p) /* : red (p.red), green (p.green), blue (p.blue), alpha (p.alpha) {} */ { *(unsigned *)this = *(unsigned *)&p; } }; // We don't need RGB_MASK anymore #undef RGB_MASK /** * Eye sensivity to different color components, from NTSC grayscale equation. * The coefficients are multiplied by 100 and rounded towards nearest integer, * to facilitate integer math. The squared coefficients are also multiplied * by 100 and rounded to nearest integer (thus 173 == 1.73, 242 == 2.42 etc). */ /// Red component sensivity #define R_COEF 173 /// Green component sensivity #define G_COEF 242 /// Blue component sensivity #define B_COEF 107 #endif // RGBPIXEL_H__ lensfun-0.3.4/apps/setup.py.in000066400000000000000000000004711445356770400162730ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- """This setup script installs the “lensfun” package.""" from setuptools import setup setup(name="lensfun", version="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO}", package_dir={"": "${CMAKE_CURRENT_BINARY_DIR}"}, packages=["lensfun"]) lensfun-0.3.4/cmake/000077500000000000000000000000001445356770400142675ustar00rootroot00000000000000lensfun-0.3.4/cmake/modules/000077500000000000000000000000001445356770400157375ustar00rootroot00000000000000lensfun-0.3.4/cmake/modules/FindGLIB2.cmake000066400000000000000000000040261445356770400203430ustar00rootroot00000000000000IF (NOT MSVC) FIND_PACKAGE(PkgConfig) PKG_SEARCH_MODULE(GLIB2 glib-2.0) IF(WIN32 AND NOT BUILD_STATIC) FIND_FILE(GLIB2_DLL NAMES glib-2.dll glib-2-vs9.dll libglib-2.0-0.dll PATHS "${GLIB2_LIBRARY_DIRS}/../bin" NO_SYSTEM_ENVIRONMENT_PATH) ENDIF() ENDIF() IF (NOT GLIB2_FOUND OR NOT PKG_CONFIG_FOUND) FIND_PATH(GLIB2_GLIB2CONFIG_INCLUDE_PATH NAMES glibconfig.h PATHS /usr/local/lib /usr/lib /usr/lib64 /opt/local/lib ${GLIB2_BASE_DIR}/lib ${GLIB2_BASE_DIR}/include ${CMAKE_LIBRARY_PATH} PATH_SUFFIXES glib-2.0/include ) FIND_PATH(GLIB2_INCLUDE_DIRS NAMES glib.h PATHS /usr/local/include /usr/include /opt/local/include ${GLIB2_BASE_DIR}/include PATH_SUFFIXES gtk-2.0 glib-2.0 glib20 ) FIND_LIBRARY(GLIB2_LIBRARIES NAMES glib-2.0 glib20 glib PATHS /usr/local/lib /usr/lib /usr/lib64 /opt/local/lib ${GLIB2_BASE_DIR}/lib ) IF(GLIB2_GLIB2CONFIG_INCLUDE_PATH AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES) SET( GLIB2_INCLUDE_DIRS ${GLIB2_GLIB2CONFIG_INCLUDE_PATH} ${GLIB2_INCLUDE_DIRS} ) SET( GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ) SET( GLIB2_FOUND 1 ) ELSE() SET( GLIB2_INCLUDE_DIRS ) SET( GLIB2_LIBRARIES ) SET( GLIB2_FOUND 0) ENDIF() IF(WIN32 AND NOT BUILD_STATIC) FIND_FILE(GLIB2_DLL NAMES glib-2.dll glib-2-vs9.dll libglib-2.0-0.dll PATHS "${GLIB2_BASE_DIR}/bin" NO_SYSTEM_ENVIRONMENT_PATH) ENDIF() ENDIF () #INCLUDE( FindPackageHandleStandardArgs ) #FIND_PACKAGE_HANDLE_STANDARD_ARGS( GLIB2 DEFAULT_MSG GLIB2_LIBRARIES GLIB2_GLIB2CONFIG_INCLUDE_PATH GLIB2_GLIB2_INCLUDE_PATH ) IF (NOT GLIB2_FOUND AND GLIB2_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find glib2") ENDIF() lensfun-0.3.4/cmake/modules/toolchain_win32.cmake000066400000000000000000000012521445356770400217430ustar00rootroot00000000000000#me of the target operating system SET(CMAKE_SYSTEM_NAME Windows) # which compilers to use for C and C++ SET(CMAKE_C_COMPILER i686-w64-mingw32-gcc) SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres) # here is the target environment located SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32/) SET(LENSFUN_INSTALL_PREFIX /usr/i686-w64-mingw32/) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) lensfun-0.3.4/data/000077500000000000000000000000001445356770400141205ustar00rootroot00000000000000lensfun-0.3.4/data/db/000077500000000000000000000000001445356770400145055ustar00rootroot00000000000000lensfun-0.3.4/data/db/6x6.xml000066400000000000000000000060071445356770400156550ustar00rootroot00000000000000 Rollei 6x6 Generic Mamiya 645 Generic Mamiya Mamiya 645 Mamiya 645 0.577 Mamiya Mamiya ZD Mamiya 645 0.721 Phase One P 25 Mamiya 645 0.577 Rolleiflex 2.8E Rollei 6x6 0.510 Schneider Schneider 28mm Digitar f/2.8 Mamiya 645 0.577 4:3 Mamiya Mamiya 35mm f/3.5 Mamiya 645 0.577 4:3 Mamiya Mamiya 80mm f/2.8 Mamiya 645 0.577 4:3 Mamiya Mamiya 55-110mm f/4.5 Mamiya 645 0.577 4:3 Schneider Schneider 80mm Xenotar f/2.8 Rollei 6x6 0.510 1:1 lensfun-0.3.4/data/db/actioncams.xml000066400000000000000000000252441445356770400173570ustar00rootroot00000000000000 GoPro HD2 goProHero 6.4 GoPro Hero3+ black goProHero3+ 5.42 GoPro HERO4 Silver goProHero4 7.66 GoPro HERO4 Black goProHero4black 5 GoPro HERO5 Black goProHero4black 5 DJI Phantom Vision FC200 dijPhantomVisionFC200 6 DJI Phantom 3 Pro FC300X dijPhantom3ProFC300X 5.5 AEE DV AEE AEE DV AEE MagiCam SD19 & compatibles aeeDV 6 GitUp Git2 git2 5.57 DJI Mavic Pro FC220 djiMavicProFC220 5.64 DJI FC6310 djiFC6310 2.73 DJI FC3411 Air 2S djiFC3411 2.73 Hasselblad L1D-20c DJI Mavic 2 Pro l1d20c 2.8 Hasselblad L2D-20c DJI Mavic 3 l2d20c 1.953 DJI Mavic Air FC2103 djiMavicAirFC2103 5.6 GoPro HD2 & compatibles fixed lens festes Objektiv goProHero fisheye 6.4 4:3 GoPro GoPro Hero3+ black & compatibles fixed lens festes Objektiv goProHero3+ 5.42 4:3 GoPro HERO4 fixed lens festes Objektiv goProHero4 equisolid 7.66 4:3 DJI Phantom Vision FC200 & compatibles fixed lens festes Objektiv dijPhantomVisionFC200 equisolid 6 4:3 AEE AEE SD19 & compatibles fixed lens festes Objektiv aeeDV equisolid 6 4:3 DJI Phantom 3 Pro fixed lens festes Objektiv dijPhantom3ProFC300X 5.5 4:3 GitUp Git2 & compatibles fixed lens festes Objektiv git2 equisolid 5.57 4:3 GoPro HERO4 black fixed lens festes Objektiv goProHero4black stereographic 5 4:3 DJI Mavic Pro FC220 & compatibles fixed lens festes Objektiv djiMavicProFC220 5.64 4:3 DJI FC6310 & compatibles fixed lens festes Objektiv djiFC6310 2.73 16:9 Hasselblad L1D-20c & compatibles fixed lens festes Objektiv l1d20c 2.8 Hasselblad L2D-20c & compatibles fixed lens festes Objektiv l2d20c 1.953 4:3 DJI FC2103 & compatibles fixed lens festes Objektiv djiMavicAirFC2103 5.6 DJI FC3411 & compatibles FC3411 fixed lens FC3411 festes Objektiv djiFC3411 2.63 3:2 lensfun-0.3.4/data/db/compact-canon.xml000066400000000000000000007215601445356770400177640ustar00rootroot00000000000000 Canon Canon PowerShot Pro1 PowerShot Pro1 canonPro1 3.933 Canon Canon PowerShot Pro70 PowerShot Pro70 canonPro70 5.47 Canon Canon PowerShot G6 PowerShot G6 canonG3 4.843 Canon Canon PowerShot G5 PowerShot G5 canonG3 4.843 Canon Canon PowerShot G3 PowerShot G3 canonG3 4.843 Canon Canon PowerShot G2 PowerShot G2 canonG2 4.843 Canon Canon PowerShot G1 PowerShot G1 canonG1 4.843 Canon Canon PowerShot G7 PowerShot G7 canonG7 4.843 Canon Canon PowerShot G3 X PowerShot G3 X (3:2) canonG3X 2.727 Canon Canon PowerShot G5 X PowerShot G5 X (3:2) canonG7X 2.72 Canon Canon PowerShot G5 X 4:3 PowerShot G5 X (4:3) canonG7X 2.94 Canon Canon PowerShot G5 X 16:9 PowerShot G5 X (16:9) canonG7X 2.85 Canon Canon PowerShot G7 X PowerShot G7 X (3:2) canonG7X 2.72 Canon Canon PowerShot G7 X 4:3 PowerShot G7 X (4:3) canonG7X 2.94 Canon Canon PowerShot G7 X 16:9 PowerShot G7 X (16:9) canonG7X 2.85 Canon Canon PowerShot G7 X Mark II PowerShot G7 X Mark II (3:2) canonG7X 2.72 Canon Canon PowerShot G7 X Mark II 4:3 PowerShot G7 X Mark II (4:3) canonG7X 2.94 Canon Canon PowerShot G7 X Mark II 16:9 PowerShot G7 X Mark II (16:9) canonG7X 2.85 Canon Canon PowerShot G7 X Mark III PowerShot G7 X Mark III (3:2) canonG7X 2.72 Canon Canon PowerShot G9 PowerShot G9 canonG9 4.605 Canon Canon Powershot G9 X PowerShot G9 X canonG9X 2.72 Canon Canon PowerShot G9 X Mark II Canon PowerShot G9 X Mark II canonG9X 2.72 Canon Canon PowerShot G10 PowerShot G10 canonG10 4.605 Canon Canon PowerShot G11 PowerShot G11 canonG11 4.554 Canon Canon PowerShot G12 PowerShot G12 canonG12 4.63 Canon Canon PowerShot G1 X PowerShot G1 X canonG1X 1.85 Canon Canon PowerShot G1 X Mark II PowerShot G1 X Mark II canonG1X2 1.93 Canon Canon PowerShot G1 X Mark III PowerShot G1 X Mark III canonG1X3 1.613 Canon Canon PowerShot G5 X Mark II PowerShot G5 X Mark II canonG5X2 2.73 Canon Canon PowerShot G15 PowerShot G15 canonG15 4.65 Canon Canon PowerShot G16 PowerShot G16 canonG16 4.67 Canon Canon PowerShot SD550 PowerShot SD550 canonSD500 4.8 Canon Canon PowerShot SD950 IS PowerShot SD950 IS canonSD950 4.7 Canon Canon DIGITAL IXUS 750 IXUS 750 canonSD500 4.8 Canon IXY Digital 700 canonSD500 4.8 Canon Canon PowerShot SD500 PowerShot SD500 canonSD500 4.8 Canon Canon DIGITAL IXUS 700 IXUS 700 canonSD500 4.8 Canon IXY Digital 600 canonSD500 4.8 Canon Canon PowerShot SD450 PowerShot SD450 canonSD200 6.05 Canon Canon DIGITAL IXUS 55 IXUS 55 canonSD200 6.05 Canon Canon PowerShot SD400 PowerShot SD400 canonSD200 6.05 Canon Canon IXY DIGITAL 55 IXY 55 canonSD200 6.05 Canon Canon DIGITAL IXUS 50 IXUS 50 canonSD200 6.05 Canon Canon DIGITAL IXUS 70 IXUS 70 canonSD200 6.05 Canon Canon PowerShot SD300 PowerShot SD300 canonSD200 6.05 Canon Canon IXY DIGITAL 50 IXY 50 canonSD200 6.05 Canon Canon DIGITAL IXUS 40 IXUS 40 canonSD200 6.05 Canon Canon PowerShot SD200 PowerShot SD200 canonSD200 6.05 Canon Canon IXY DIGITAL 40 IXY 40 canonSD200 6.05 Canon Canon DIGITAL IXUS 30 IXUS 30 canonSD200 6.05 Canon Canon PowerShot S200 PowerShot S200 canonIxusII 6.5 Canon Canon DIGITAL IXUS v2 IXUS v2 canonIxusII 6.5 Canon Canon IXY DIGITAL 200a IXY 200a canonIxusII 6.5 Canon Canon PowerShot SD110 PowerShot SD110 canonIxusII 6.5 Canon Canon DIGITAL IXUS II IXUS II canonIxusII 6.5 Canon Canon IXY DIGITAL 30 IXY 30 canonIxusII 6.5 Canon Canon PowerShot SD100 PowerShot SD100 canonIxusII 6.5 Canon Canon DIGITAL IXUS i IXUS i canonIxusI 6.144 Canon Canon PowerShot SD10 PowerShot SD10 canonIxusI 6.144 Canon Canon PowerShot S500 PowerShot S500 canonIxus400 4.843 Canon Canon DIGITAL IXUS 500 IXUS 500 canonIxus400 4.843 Canon Canon IXY DIGITAL 500 IXY 500 canonIxus400 4.843 Canon Canon PowerShot S410 PowerShot S410 canonIxus400 4.843 Canon Canon DIGITAL IXUS 430 IXUS 430 canonIxus400 4.843 Canon Canon IXY DIGITAL 450 IXY 450 canonIxus400 4.843 Canon Canon PowerShot S400 PowerShot S400 canonIxus400 4.843 Canon Canon DIGITAL IXUS 400 IXUS 400 canonIxus400 4.843 Canon Canon IXY DIGITAL 400 IXY 400 canonIxus400 4.843 Canon Canon PowerShot S80 PowerShot S80 canonS70 4.843 Canon Canon PowerShot S70 PowerShot S70 canonS70 4.843 Canon Canon PowerShot S60 PowerShot S60 canonS70 4.843 Canon Canon PowerShot S50 PowerShot S50 canonS30 4.843 Canon Canon PowerShot S45 PowerShot S45 canonS30 4.843 Canon Canon PowerShot S40 PowerShot S40 canonS30 4.843 Canon Canon PowerShot S30 PowerShot S30 canonS30 4.843 Canon Canon PowerShot A1200 Powershot A1200 canonA1200 5.61 Canon Canon PowerShot A610 PowerShot A610 canonA610 4.8 Canon Canon PowerShot A620 PowerShot A620 canonA610 4.8 Canon Canon PowerShot A520 PowerShot A520 canonA510 6.05 Canon Canon PowerShot A510 PowerShot A510 canonA510 6.05 Canon Canon PowerShot A95 PowerShot A95 canonA80 4.85 Canon Canon PowerShot A80 PowerShot A80 canonA80 4.85 Canon Canon PowerShot A85 PowerShot A85 canonA70 6.500 Canon Canon PowerShot A75 PowerShot A75 canonA70 6.500 Canon Canon PowerShot A70 PowerShot A70 canonA70 6.500 Canon Canon PowerShot A60 PowerShot A60 canonA70 6.500 Canon Canon PowerShot A40 PowerShot A40 canonA70 6.500 Canon Canon PowerShot A30 PowerShot A30 canonA70 6.500 Canon Canon PowerShot A20 PowerShot A20 canonA70 6.500 Canon Canon PowerShot A10 PowerShot A10 canonA70 6.500 Canon Canon PowerShot S2 IS PowerShot S2 IS canonS2 6.0 Canon Canon PowerShot S1 IS PowerShot S1 IS canonS1 6.56 Canon Canon PowerShot S5 IS PowerShot S5 IS canonS5 6.0 Canon Canon PowerShot Pro90 IS PowerShot Pro90 IS canonPro90 5.28 Canon Canon DIGITAL IXUS 80 IS IXUS 80 IS canonIxus80IS 6.02 Canon Canon DIGITAL IXUS 95 IS IXUS 95 IS canonIxus80IS 5.6 Canon Canon PowerShot SX1 IS PowerShot SX1 IS canonSX1 5.5 Canon Canon PowerShot S90 PowerShot S90 canonS90 4.67 Canon Canon PowerShot A650 IS PowerShot A650 IS canonA650IS 4.67712 Canon Canon PowerShot SX150 IS PowerShot SX150 IS canonSX150IS 5.62 Canon Canon PowerShot SX10 IS PowerShot SX10 IS canonSX10IS 5.6 Canon Canon PowerShot SX130 IS PowerShot SX130 IS canonSX150IS 5.62 Canon Canon PowerShot SX220 HS PowerShot SX220 HS canonSX220HS 5.6 Canon Canon PowerShot SX230 HS PowerShot SX230 HS canonSX230HS 5.6 Canon Canon PowerShot A720 IS PowerShot A720 IS canonA720IS 6.03 Canon Canon PowerShot S120 PowerShot S120 canonS120 4.62 Canon Canon PowerShot A640 PowerShot A640 canonA640 4.79 Canon Canon PowerShot SX240 HS PowerShot SX240 HS canonSX260HS 5.56 Canon Canon PowerShot SX260 HS PowerShot SX260 HS canonSX260HS 5.56 Canon Canon IXUS 220 HS IXUS 220 HS canonIxus220HS 5.58 Canon Canon PowerShot S95 PowerShot S95 canonS95 4.67 Canon Canon PowerShot S100 PowerShot S100 canonS100 4.62 Canon Canon PowerShot A4000 IS PowerShot A4000 IS canonA4000IS 5.6 Canon Canon PowerShot ELPH 110 HS Powershot ELPH 110 HS canonIxus125HS 5.58 Canon Canon IXUS 125 HS IXUS 125 HS canonIxus125HS 5.58 Canon Canon PowerShot SX510 HS PowerShot SX510 HS canonSX510HS 5.58 Canon Canon PowerShot S110 PowerShot S110 canonS110 4.62 Canon Canon PowerShot SD1100 IS PowerShot SD1100 IS canonIxus80IS 6.02 Canon Canon PowerShot SX160 IS PowerShot SX160 IS canonSX160IS 5.6 Canon Canon PowerShot A495 PowerShot A495 canonA495 5.39 Canon Canon PowerShot A490 PowerShot A490 canonA495 5.39 Canon Canon PowerShot SX30 IS PowerShot SX30 IS canonSX30IS 5.581 Canon Canon PowerShot SX50 HS Powershot SX50 HS canonSX50HS 5.61 Canon Canon PowerShot SX60 HS Powershot SX60 HS canonSX60HS 5.61 Canon Canon PowerShot SX700 HS PowerShot SX700 HS canonSX710HS 5.6 Canon Canon PowerShot SX710 HS PowerShot SX710 HS canonSX710HS 5.6 Canon Canon PowerShot Pro1 & compatibles (Standard) fixed lens festes Objektiv canonPro1 3.933 4:3 Canon Canon PowerShot G3 & compatibles (Standard) fixed lens festes Objektiv canonG3 4.843 4:3 Canon Canon PowerShot G3 & compatibles, with WC-DC58N fixed lens, with WC-DC58N festes Objektiv, mit WC-DC58N canonG3 4.843 4:3 Canon Canon PowerShot G2 & compatibles (Standard) fixed lens festes Objektiv canonG2 4.843 4:3 Canon Canon PowerShot G2 & compatibles, with Geobartic 0.5x converter fixed lens, with Geobartic 0.5x converter festes Objektiv, mit Geobartic 0.5x-Konverter canonG2 4.843 4:3 Canon Canon PowerShot G1 & compatibles (Standard) fixed lens festes Objektiv canonG1 4.843 4:3 Canon Canon PowerShot G12 & compatibles (Standard) fixed lens festes Objektiv canonG12 4.63 4:3 Canon Canon PowerShot G1X & compatibles (Standard) fixed lens festes Objektiv canonG1X 1.85 4:3 Canon Canon PowerShot G15 & compatibles (Standard) fixed lens festes Objektiv canonG15 4.65 4:3 Canon Canon PowerShot SD500 & compatibles (Standard) fixed lens festes Objektiv canonSD500 4.8 4:3 Canon Canon PowerShot SD950 IS & compatibles (Standard) fixed lens festes Objektiv canonSD950 4.7 4:3 Canon Canon PowerShot SD200 & compatibles (Standard) fixed lens festes Objektiv canonSD200 6.05 4:3 Canon Canon DIGITAL IXUS II & compatibles (Standard) fixed lens festes Objektiv canonIxusII 6.5 4:3 Canon Canon DIGITAL IXUS i & compatibles (Standard) fixed lens festes Objektiv canonIxusI 4.843 4:3 Canon Canon DIGITAL IXUS 400 & compatibles (Standard) fixed lens festes Objektiv canonIxus400 4.843 4:3 Canon Canon DIGITAL IXUS 400 & compatibles, with Tiffen MegaPlus 0.56 converter fixed lens, with Tiffen MegaPlus 0.56 converter festes Objektiv, mit Tiffen MegaPlus 0.56-Konverter canonIxus400 4.843 4:3 Canon Canon PowerShot S70 & compatibles (Standard) fixed lens festes Objektiv canonS70 4.843 4:3 Canon Canon PowerShot S70 & compatibles, with TC-DC10 2x converter fixed lens, with TC-DC10 2× converter festes Objektiv, mit TC-DC10 2×-Konverter canonS70 4.843 4:3 Canon Canon PowerShot S30 & compatibles (Standard) fixed lens festes Objektiv canonS30 4.843 4:3 Canon Canon PowerShot A610 & compatibles (Standard) fixed lens festes Objektiv canonA610 4.8 4:3 Canon Canon PowerShot A610 & compatibles, with CHDK's DNG fixed lens, with CHDK's DNG festes Objektiv, mit CHDK-DNG canonA610 4.8 4:3 Canon Canon PowerShot A510 & compatibles (Standard) fixed lens festes Objektiv canonA510 6.05 4:3 Canon Canon PowerShot A80 & compatibles (Standard) fixed lens festes Objektiv canonA80 4.85 4:3 Canon Canon PowerShot A80 & compatibles, with Tiffen 0.56x converter fixed lens, with Tiffen 0.56× converter festes Objektiv, mit Tiffen 0.56×-Konverter canonA80 4.85 4:3 Canon Canon PowerShot A80 & compatibles, with Tiffen 2x converter fixed lens, with Tiffen 2× converter festes Objektiv, mit Tiffen 2×-Konverter canonA80 4.85 4:3 Canon Canon PowerShot A70 & compatibles (Standard) fixed lens festes Objektiv canonA70 6.500 4:3 Canon Canon PowerShot S2 IS & compatibles (Standard) fixed lens festes Objektiv canonS2 6.0 4:3 Canon Canon PowerShot S2 IS & compatibles, with TC-DC58B fixed lens, with TC-DC58B festes Objektiv, mit TC-DC58B canonS2 6.0 4:3 Canon Canon PowerShot S1 IS & compatibles (Standard) fixed lens festes Objektiv canonS1 6.56 4:3 Canon Canon PowerShot Pro90 IS & compatibles (Standard) fixed lens festes Objektiv canonPro90 5.28 4:3 Canon Canon PowerShot S5 IS & compatibles (Standard) fixed lens festes Objektiv canonS5 6.0 4:3 Canon Canon PowerShot S5 IS & compatibles, with TC-DC58B fixed lens, with TC-DC58B festes Objektiv, mit TC-DC58B canonS5 6.0 4:3 Canon Canon DIGITAL IXUS 80 IS & compatibles (Standard) fixed lens festes Objektiv canonIxus80IS 6.02 4:3 Canon Canon PowerShot S90 & compatibles (Standard) fixed lens festes Objektiv canonS90 4.67 Canon Canon PowerShot A650 IS & compatibles (Standard) fixed lens festes Objektiv canonA650IS 4.67712 4:3 Canon Canon PowerShot G11 & compatibles (Standard) fixed lens festes Objektiv canonG11 4.554 4:3 Canon Canon PowerShot SX150 IS & compatibles (Standard) fixed lens festes Objektiv canonSX150IS 5.62 4:3 Canon Canon PowerShot SX150 IS & compatibles, with CHDK's DNG fixed lens, with CHDK's DNG festes Objektiv, mit CHDK-DNG canonSX150IS 5.62 4:3 Canon Canon PowerShot SX220 HS & compatibles, with CHDK's DNG fixed lens, with CHDK's DNG festes Objektiv, mit CHDK-DNG canonSX220HS canonSX230HS 5.6 4:3 Canon Canon PowerShot SX220 HS & compatibles (Standard) fixed lens festes Objektiv canonSX220HS 5.6 4:3 Canon Canon PowerShot A1200 & compatibles (Standard) fixed lens festes Objektiv canonA1200 5.61 4:3 Canon Canon PowerShot A720 IS & compatibles (Standard) fixed lens festes Objektiv canonA720IS 6.03 4:3 Canon Canon PowerShot A640 & compatibles fixed lens festes Objektiv canonA640 4.79 4:3 Canon Canon PowerShot A640 & compatibles, with WC-DC58N fixed lens, with WC-DC58N festes Objektiv, mit WC-DC58N canonA640 4.79 4:3 Canon Canon PowerShot S120 & compatibles fixed lens festes Objektiv canonS120 4.62 4:3 Canon Canon PowerShot SX260 HS & compatibles, with CHDK's DNG fixed lens, with CHDK's DNG festes Objektiv, mit CHDK-DNG canonSX260HS 5.56 4:3 Canon Canon PowerShot S95 & compatibles fixed lens festes Objektiv canonS95 4.67 4:3 Canon Canon IXUS 220 HS & compatibles, with CHDK's DNG fixed lens, with CHDK's DNG festes Objektiv, mit CHDK-DNG canonIxus220HS 5.58 4:3 Canon Canon PowerShot G1X Mark II & compatibles fixed lens festes Objektiv canonG1X2 1.93 4:3 Canon Canon PowerShot G1 X Mark III & compatibles (Standard) fixed lens festes Objektiv canonG1X3 1.613 3:2 Canon G5 X Mark II & compatibles fixed lens canonG5X2 2.73 3:2 Canon Canon PowerShot A4000 IS & compatibles, with CHDK's DNG fixed lens, with CHDK's DNG festes Objektiv, mit CHDK-DNG canonA4000IS 5.6 4:3 Canon Canon PowerShot G7 & compatibles (Standard) fixed lens canonG7 4.843 Canon Canon G7 X & compatibles fixed lens festes Objektiv canonG7X 2.72 3:2 Canon Canon Powershot G9 X & compatibles fixed lens festes Objektiv canonG9X 2.72 Canon Canon PowerShot S100 & compatibles fixed lens festes Objektiv canonS100 4.62 4:3 Canon Canon IXUS 125 HS & compatibles fixed lens festes Objektiv canonIxus125HS 5.58 4:3 Canon Canon PowerShot SX510 HS & compatibles fixed lens festes Objektiv canonSX510HS 5.58 4:3 Canon Canon PowerShot SX510 HS & compatibles, with CHDK's DNG fixed lens, with CHDK's DNG festes Objektiv, mit CHDK-DNG canonSX510HS 5.58 4:3 Canon Canon PowerShot S110 & compatibles fixed lens festes Objektiv canonS110 4.62 4:3 Canon Canon PowerShot SX160 IS & compatibles, with CHDK's DNG fixed lens, with CHDK's DNG festes Objektiv, mit CHDK-DNG canonSX160IS 5.6 4:3 Canon Canon Powershot A495 & compatibles, with CHDK's DNG fixed lens, with CHDK's DNG festes Objektiv, mit CHDK-DNG canonA495 5.39 4:3 Canon Canon PowerShot G16 & compatibles fixed lens festes Objektiv canonG16 4.67 4:3 Canon Canon PowerShot SX10 IS fixed lens festes Objektiv canonSX10IS 5.6 4:3 Canon Canon PowerShot SX30 IS & compatibles, with CHDK's DNG fixed lens, with CHDK's DNG festes Objektiv, mit CHDK-DNG canonSX30IS 5.58 4:3 Canon Canon PowerShot SX50 HS & compatibles fixed lens festes Objektiv canonSX50HS 5.61 4:3 Canon Canon PowerShot SX60 HS & compatibles canonSX60HS 5.61 4:3 Canon Canon PowerShot SX710 HS & compatibles, with CHDK's DNG fixed lens, with CHDK's DNG festes Objektiv, mit CHDK-DNG canonSX710HS 5.6 4:3 Canon Canon PowerShot G3 X & compatibles fixed lens festes Objektiv canonG3X 2.727 3:2 lensfun-0.3.4/data/db/compact-casio.xml000066400000000000000000000152401445356770400177530ustar00rootroot00000000000000 Casio Computer Co.,Ltd Casio EX-Z750 casioZ750 4.8 Casio Computer Co.,Ltd Casio EX-P700 casioP600 4.65 Casio Computer Co.,Ltd Casio EX-P600 casioP600 4.65 Casio Computer Co.,Ltd Casio EX-Z4 casioZ4 6.05 Casio Computer Co.,Ltd Casio EX-Z3 casioZ4 6.05 Casio Computer Co.,Ltd Casio EX-Z55 casioZ4 6.05 Casio Computer Co.,Ltd Casio EX-Z40 casioZ4 6.05 Casio Computer Co.,Ltd Casio EX-Z30 casioZ4 6.05 Casio Casio QV-4000 canonG2 4.843 Casio Casio QV-3500EX casioQV3500 4.8 Casio Casio QV-3000EX casioQV3500 4.8 Casio Computer Co.,Ltd. Casio EX-FH20 casioEX-FH20 5.68 Casio EX-Z750 & compatibles (Standard) fixed lens festes Objektiv casioZ750 4.8 4:3 Casio EX-P600 & compatibles (Standard) fixed lens festes Objektiv casioP600 4.65 4:3 Casio EX-P600 & compatibles, with WC-DC58A fixed lens, with WC-DC58A festes Objektiv, mit WC-DC58A casioP600 4.65 4:3 Casio EX-Z4 & compatibles (Standard) fixed lens festes Objektiv casioZ4 6.05 4:3 Casio QV-3500EX & compatibles (Standard) fixed lens festes Objektiv casioQV3500 4.8 4:3 Casio QV-3500EX & compatibles, with Raynox 0.66x fixed lens, with Raynox 0.66× festes Objektiv, mit Raynox 0.66× casioQV3500 4.8 4:3 lensfun-0.3.4/data/db/compact-fujifilm.xml000066400000000000000000002023331445356770400204630ustar00rootroot00000000000000 Fujifilm FinePix F11 fujiF11 4.5 Fujifilm FinePix F10 fujiF11 4.5 Fujifilm FinePix S9000 fujiS9000 4.48 Fujifilm FinePix S9500 fujiS9000 4.48 Fujifilm FinePix S9600 fujiS9000 4.48 Fujifilm FinePix S5500 fujiS5500 6.491 Fujifilm FinePix S5100 fujiS5500 6.491 Fujifilm FinePix S7000 fuji602 4.487 Fujifilm FinePix S20Pro fuji602 4.487 Fujifilm FinePix S602 ZOOM fuji602 4.487 Fujifilm FinePix F601 ZOOM fuji601 4.487 Fujifilm FinePix F810 fuji810 4.5 Fujifilm FinePix F810 widescreen mode fuji810 4.9 Fujifilm FinePix F710 fuji810 4.5 Fujifilm FinePix E550 fuji810 4.5 Fujifilm FinePix 3800 fuji2800 6.3333333 Fujifilm FinePix S304 fuji2800 6.3333333 Fujifilm FinePix S3000 fuji2800 6.3333333 Fujifilm FinePix2800ZOOM fuji2800 6.3333333 Fujifilm FinePix F200EXR fujiF200exr 4.341 Fujifilm FinePix X100 fujix100 1.523 Fujifilm X100S fujix100 1.523 Fujifilm X100T fujix100 1.523 Fujifilm X100F fujix100 1.528 Fujifilm X100V fujix100v2 1.53 Fujifilm X10 fujix10 3.93 Fujifilm XF10 fujixf10 1.53 Fujifilm X70 fujix70 1.5375 Fujifilm X20 fujix10 3.93 Fujifilm X30 fujix10 3.93 Fujifilm FinePix HS20EXR fujihs20exr 5.71 Fujifilm FinePix F770EXR fujif770exr 5.43 Fujifilm FinePix S5600 fujiS5600 6.03 Fujifilm XQ1 fujiXQ1 3.91 Fujifilm FinePix A370 fujiA370 6.03 Fujifilm X-S1 fujiXS1 3.93 Fujifilm FinePix F11 & compatibles (Standard) fixed lens festes Objektiv fujiF11 4.5 4:3 Fujifilm FinePix S9000 & compatibles (Standard) fixed lens festes Objektiv fujiS9000 4.48 4:3 Fujifilm FinePix S5500 & compatibles (Standard) fixed lens festes Objektiv fujiS5500 6.491 4:3 Fujifilm FinePix S602 ZOOM & compatibles (Standard) fixed lens festes Objektiv fuji602 4.487 4:3 Fujifilm FinePix F601 ZOOM & compatibles (Standard) fixed lens festes Objektiv fuji601 4.487 4:3 Fujifilm FinePix F810 & compatibles (Standard) fixed lens festes Objektiv fuji810 4.5 4:3 Fujifilm FinePix F810 & compatibles, with WL-FXE01 (full wide) fixed lens, with WL-FXE01 (full wide) festes Objektiv, mit WL-FXE01 (kürzeste Brennw.) fuji810 4.5 4:3 Fujifilm FinePix 2800 ZOOM & compatibles (Standard) fixed lens festes Objektiv fuji2800 6.3333333 4:3 Fujifilm FinePix F200EXR & compatibles (Standard) fixed lens festes Objektiv fujiF200exr 4.341 4:3 Fujifilm X100 & compatibles (Standard) fixed lens festes Objektiv fujix100 1.523 3:2 Fujifilm X100 & compatibles (Standard) + TCL-X100 TCL-X100 fujix100 1.523 Fujifilm X100V & compatibles (Standard) X100V-lens X100V-Objektiv fujix100v2 1.53 Fujifilm X100V & compatibles, with WCL-X100 X100V-Lens, with WCL-X100 X100V-Objektiv, mit WCL-X100 fujix100v2 1.53 Fujifilm X100V & compatibles, with TCL-X100 X100V-Lens, with TCL-X100 X100V-Objektiv, mit TCL-X100 fujix100v2 1.53 Fujifilm X10 & compatibles (Standard) fixed lens festes Objektiv fujix10 3.93 4:3 Fujifilm FinePix HS20EXR & compatibles (Standard) fixed lens festes Objektiv fujihs20exr 5.71 4:3 Fujifilm FinePix F770EXR & compatibles (Standard) fixed lens festes Objektiv fujif770exr 5.43 4:3 Fujifilm FinePix S5600 fixed lens festes Objektiv fujiS5600 6.03 4:3 Fujifilm Fujifilm XQ1 fixed lens festes Objektiv fujiXQ1 3.91 4:3 Fujifilm Fujifilm FinePix A370 fixed lens festes Objektiv fujiA370 6.03 4:3 Fujifilm Fujifilm X-S1 fixed lens festes Objektiv fujiXS1 3.93 4:3 Fujifilm X70 & compatibles (Standard) fujix70 1.5375 Fujifilm XF10 & compatibles (Standard) fujixf10 1.53 lensfun-0.3.4/data/db/compact-kodak.xml000066400000000000000000000037571445356770400177600ustar00rootroot00000000000000 Eastman Kodak Company Kodak Kodak DC120 ZOOM Digital Camera Kodak DC120 kodakDC120 1 Eastman Kodak Company Kodak Kodak Digital Science DC50 Zoom Camera Kodak DC50 kodakDC50 1 Eastman Kodak Company Kodak Kodak CX6330 Zoom Digital Camera Kodak CX6330 kodakCX6330 6.593 Eastman Kodak Company Kodak Kodak CX7525 Zoom Digital Camera Kodak CX7525 kodakCX6330 6.07 Kodak Kodak CX6330 & compatibles fixed lens festes Objektiv kodakCX6330 6.593 4:3 lensfun-0.3.4/data/db/compact-konica-minolta.xml000066400000000000000000000317211445356770400215640ustar00rootroot00000000000000 Konica Minolta DiMAGE Z6 kmZ3 6.05 Konica Minolta DiMAGE Z5 kmZ3 6.05 Konica Minolta DiMAGE Z3 kmZ3 6.05 Konica Minolta Camera, Inc. Konica Minolta DiMAGE Z2 kmZ2 6.03 Minolta Co., Ltd. Minolta DiMAGE Z1 kmZ1 6.545 Konica Minolta DiMAGE Z20 kmZ10 6.05 Konica Minolta DiMAGE Z10 kmZ10 6.05 Konica Minolta DiMAGE A200 kmD7 3.933 Konica Minolta Camera, Inc. Konica Minolta DiMAGE A2 kmD7 3.933 Minolta Co., Ltd. Minolta DiMAGE A1 kmD7 3.933 Minolta Co., Ltd. Minolta DiMAGE 7Hi kmD7 3.933 Minolta Co., Ltd. Minolta DiMAGE 7i kmD7 3.933 Minolta Co., Ltd. Minolta DiMAGE 7 kmD7 3.933 Minolta Co., Ltd. Minolta DiMAGE Xt kmXt 6.5 Minolta Co., Ltd. Minolta DiMAGE Xi kmXt 6.5 Minolta Co., Ltd. Minolta DiMAGE X kmXt 6.5 Konica Minolta Camera, Inc. Konica Minolta DiMAGE G400 kmG400 6.144 Konica Minolta Camera, Inc. Konica Minolta Revio KD-420Z kmG400 6.144 Konica Minolta DiMAGE Z3 & compatibles (Standard) fixed lens festes Objektiv kmZ3 6.05 4:3 Konica Minolta DiMAGE Z2 & compatibles (Standard) fixed lens festes Objektiv kmZ2 6.03 4:3 Konica Minolta DiMAGE Z2 & compatibles, with ZCW-100 fixed lens, with ZCW-100 festes Objektiv, mit ZCW-100 kmZ2 6.03 4:3 Konica Minolta DiMAGE Z1 & compatibles (Standard) fixed lens festes Objektiv kmZ1 6.545 4:3 Konica Minolta DiMAGE Z1 & compatibles, with ZCW-100 fixed lens, with ZCW-100 festes Objektiv, mit ZCW-100 kmZ1 6.545 4:3 Konica Minolta DiMAGE Z10 & compatibles (Standard) fixed lens festes Objektiv kmZ10 6.05 4:3 Konica Minolta DiMAGE Z10 & compatibles, with ZCW-200 fixed lens, with ZCW-200 festes Objektiv, mit ZCW-200 kmZ10 6.05 4:3 Konica Minolta DiMAGE 7 & compatibles (Standard) fixed lens festes Objektiv kmD7 3.933 4:3 Konica Minolta DiMAGE 7 & compatibles, with ACW-100 converter fixed lens, with ACW-100 converter festes Objektiv, mit ACW-100-Konverter kmD7 3.933 4:3 Konica Minolta DiMAGE X & compatibles (Standard) fixed lens festes Objektiv kmXt 6.5 4:3 Konica Minolta DiMAGE G400 & compatibles (Standard) fixed lens festes Objektiv kmG400 6.144 4:3 lensfun-0.3.4/data/db/compact-leica.xml000066400000000000000000000124371445356770400177370ustar00rootroot00000000000000 Leica Digilux 2 leicaDigilux2 3.933 Leica D-LUX2 panasonicLX1 4.45 Leica Camera AG C-Lux Leica C-Lux (Typ 1546) panasonicZS200 2.73 Leica D-LUX 4 panasonicLX4 4.33 Leica D-LUX 3 panasonicLX3 4.33 Leica Camera AG Leica Q (Typ 116) leicaQTyp116 1 Leica Camera AG Leica Q2 leicaQ2 1 Leica Camera AG Leica Q2 Mono leicaQ2 1 Leica Camera AG Leica Q3 leicaQ2 1 Leica Leica X Vario (Typ 107) leicaXVario107 1.53 Leica Digilux 2 & compatibles (Standard) fixed lens festes Objektiv leicaDigilux2 3.933 4:3 LEICA CAMERA AG LEICA Q (Typ 116) & compatibles fixed lens festes Objektiv leicaQTyp116 1 LEICA CAMERA AG LEICA Q2 & compatibles fixed lens festes Objektiv leicaQ2 1 Leica Leica X Vario 18.0-46.0 mm f/3.5-6.4 fixed lens festes Objektiv leicaXVario107 1.53 lensfun-0.3.4/data/db/compact-nikon.xml000066400000000000000000001152141445356770400177750ustar00rootroot00000000000000 Nikon Coolpix P60 nikonP60 5.62 Nikon E8800 Coolpix 8800 nikon8800 3.933 Nikon E8700 Coolpix 8700 nikon5700 3.933 Nikon E5700 Coolpix 5700 nikon5700 3.933 Nikon E7900 Coolpix 7900 nikon7900 4.86 Nikon E7600 Coolpix 7600 nikon7900 4.86 Nikon E5900 Coolpix 5900 nikon7900 4.86 Nikon E5200 Coolpix 5200 nikon7900 4.86 Nikon E4200 Coolpix 4200 nikon7900 4.86 Nikon E5400 Coolpix 5400 nikon5400 4.843 Nikon E5000 Coolpix 5000 nikon5000 3.933 Nikon E4800 Coolpix 4800 nikon4800 6 Nikon E4500 Coolpix 4500 nikon4500 4.843 Nikon E995 Coolpix 995 nikon995 4.843 Nikon E990 Coolpix 990 nikon990 4.843 Nikon E950 Coolpix 950 nikon950 5.408 Nikon Coolpix P330 nikonP330 4.706 Nikon Coolpix P340 nikonP330 4.706 Nikon Coolpix S3300 nikonS3300 5.65 Nikon Corporation Nikon Coolpix P1000 nikonP1000 5.56 Nikon Coolpix P6000 nikonP6000 4.6 Nikon E8400 Coolpix 8400 nikon8400 3.933 Nikon Coolpix P7000 nikonP7000 4.69 Nikon Coolpix P7800 nikonP7800 4.67 Nikon Corporation Nikon Coolpix A nikonA 1.523 Nikon E8800 & compatibles (Standard) fixed lens festes Objektiv nikon8800 3.933 4:3 Nikon E8800 & compatibles, with WM-E80 fixed lens, with WM-E80 festes Objektiv, mit WM-E80 nikon8800 3.933 4:3 Nikon E8400 & compatibles (Standard) fixed lens festes Objektiv nikon8400 3.933 4:3 Nikon E8400 & compatibles, with WC-E75 fixed lens, with WC-E75 festes Objektiv, mit WC-E75 nikon8400 3.933 4:3 Nikon E5700 & compatibles (Standard) fixed lens festes Objektiv nikon5700 3.933 4:3 Nikon E5700 & compatibles, with TC-E15ED (full tele) fixed lens, with TC-E15ED (full tele) festes Objektiv, mit TC-E15ED (längste Brennw.) nikon5700 3.933 4:3 Nikon E5700 & compatibles, with WC-E80 (full wide) fixed lens, with WC-E80 (full wide) festes Objektiv, mit WC-E80 (kürzeste Brennw.) nikon5700 3.933 4:3 Nikon E7900 & compatibles (Standard) fixed lens festes Objektiv nikon7900 4.86 4:3 Nikon E5400 & compatibles (Standard) fixed lens festes Objektiv nikon5400 4.843 4:3 Nikon E5400 & compatibles, with WC-E80 fixed lens, with WC-E80 festes Objektiv, mit WC-E80 nikon5400 4.843 4:3 Nikon E5000 & compatibles (Standard) fixed lens festes Objektiv nikon5000 3.933 4:3 Nikon E5000 & compatibles, with WC-E68 (full wide) fixed lens, with WC-E68 (full wide) festes Objektiv, mit WC-E68 (kürzeste Brennw.) nikon5000 3.933 4:3 Nikon E4800 & compatibles (Standard) fixed lens festes Objektiv nikon4800 6 4:3 Nikon E995 & compatibles (Standard) fixed lens festes Objektiv nikon995 4.843 4:3 Nikon E995 & compatibles, with WC-E63 fixed lens, with WC-E63 festes Objektiv, mit WC-E63 nikon995 4.843 4:3 Nikon E995 & compatibles, with WC-E24 fixed lens, with WC-E24 festes Objektiv, mit WC-E24 nikon995 4.843 4:3 Nikon E995 & compatibles, with TC-E2 fixed lens, with TC-E2 festes Objektiv, mit TC-E2 nikon995 4.843 4:3 Nikon E990 & compatibles (Standard) fixed lens festes Objektiv nikon990 4.843 4:3 Nikon E990 & compatibles, with WC-E63 fixed lens, with WC-E63 festes Objektiv, mit WC-E63 nikon990 4.843 4:3 Nikon E950 & compatibles (Standard) fixed lens festes Objektiv nikon950 5.408 4:3 Nikon Coolpix P60 & compatibles (Standard) fixed lens festes Objektiv nikonP60 5.62 4:3 Nikon Coolpix P330 & compatibles (Standard) fixed lens festes Objektiv nikonP330 4.706 4:3 Nikon Coolpix S3300 & compatibles fixed lens festes Objektiv nikonS3300 5.65 4:3 Nikon Coolpix P7000 & compatibles fixed lens festes Objektiv nikonP7000 4.69 4:3 Nikon Coolpix A & compatibles fixed lens festes Objektiv nikonA 1.523 3:2 NIKON CORPORATION Nikon Coolpix P1000 nikonP1000 5.56 4:3 Nikon Coolpix P7800 & compatibles fixed lens festes Objektiv nikonP7800 4.67 4:3 lensfun-0.3.4/data/db/compact-olympus.xml000066400000000000000000001030551445356770400203670ustar00rootroot00000000000000 Olympus Corporation Olympus C8080WZ C-8080 Wide Zoom olympus8080 3.933 Olympus Imaging Corp. Olympus u-miniD,Stylus V µ-mini Digital olympusStylusV 6.0 Olympus Imaging Corp. Olympus u-miniD,Stylus V Stylus Verve Digital variant of the µ-mini Digital olympusStylusV 6.0 Olympus Imaging Corp. Olympus C70Z,C7000Z C-70 Zoom, C-7000 Zoom olympus7000 4.8 Olympus Optical Co.,Ltd Olympus C4100Z,C4000Z C-4000 Zoom, C-4100 Zoom olympus4000 4.92 Olympus Optical Co.,Ltd Olympus X-2,C-50Z X-2 olympusC50 4.9 Olympus Optical Co.,Ltd Olympus X-2,C-50Z C-50 Zoom variant of the X-2 olympusC50 4.9 Olympus Optical Co.,Ltd Olympus C750UZ C-750 Ultra Zoom olympus750 6.03 Olympus Optical Co.,Ltd Olympus C730UZ C-730 Ultra Zoom olympus700 6.52 Olympus Optical Co.,Ltd Olympus C700UZ C-700 Ultra Zoom olympus700 6.52 Olympus Imaging Corp. Olympus C7070WZ C-7070 Wide Zoom olympus5060 4.930 Olympus Corporation Olympus C5060WZ C-5060 Wide Zoom olympus5060 4.930 Olympus Optical Co.,Ltd Olympus C5050Z C-5050 Zoom olympus2040 4.930 Olympus Optical Co.,Ltd Olympus C4040Z C-4040 Zoom olympus2040 4.930 Olympus Optical Co.,Ltd Olympus C3040Z C-3040 Zoom olympus2040 4.930 Olympus Optical Co.,Ltd Olympus C2040Z C-2040 Zoom olympus2040 4.930 Olympus Optical Co.,Ltd Olympus C860L,D360L C-860L olympusC860 6.563 Olympus Optical Co.,Ltd Olympus C860L,D360L D-360L variant of the C-860L olympusC860 6.563 Olympus mju-II µ-II olympusEpic 1 Olympus Stylus Epic olympusEpic 1 Olympus Imaging Corp. Olympus SP350 SP-350 olympusSP350 4.8 Olympus Imaging Corp. Olympus SP500UZ SP-500 Ultra Zoom olympusSP500 6.0 Olympus Imaging Corp. Olympus SP560UZ SP-560 Ultra Zoom olympusSP560 5.8 Olympus Imaging Corp. Olympus XZ-1 olympusxz1 4.68 Olympus Imaging Corp. Olympus XZ-2 olympusxz1 4.68 Olympus Imaging Corp. Olympus Stylus1 Stylus 1 olympusStylus1 4.67 Olympus Imaging Corp. Olympus Stylus1,1s Stylus 1, 1s olympusStylus1 4.67 Olympus Corporation Olympus TG-1 Tough TG-1 olympusToughTG4 5.56 Olympus Corporation Olympus TG-2 Tough TG-2 olympusToughTG4 5.56 Olympus Corporation Olympus TG-3 Tough TG-3 olympusToughTG4 5.56 Olympus Corporation Olympus TG-4 Tough TG-4 olympusToughTG4 5.56 Olympus Corporation Olympus TG-5 Tough TG-5 olympusToughTG5 5.62 Olympus Corporation Olympus TG-6 Tough TG-6 olympusToughTG4 5.56 Olympus C8080WZ & compatibles (Standard) fixed lens festes Objektiv olympus8080 3.933 4:3 Olympus Stylus V & compatibles (Standard) fixed lens festes Objektiv olympusStylusV 6.0 4:3 Olympus C7000Z & compatibles (Standard) fixed lens festes Objektiv olympus7000 4.8 4:3 Olympus C4000Z & compatibles (Standard) fixed lens festes Objektiv olympus4000 4.92 4:3 Olympus C4000Z & compatibles, with A-28 iS/L converter fixed lens, with A-28 iS/L converter festes Objektiv, mit A-28 iS/L-Konverter olympus4000 4.92 4:3 Olympus C-50Z & compatibles (Standard) fixed lens festes Objektiv olympusC50 4.9 4:3 Olympus C750UZ & compatibles (Standard) fixed lens festes Objektiv olympus750 6.03 4:3 Olympus C700UZ & compatibles (Standard) fixed lens festes Objektiv olympus700 6.52 4:3 Olympus C2040Z & compatibles (Standard) fixed lens festes Objektiv olympus2040 4.930 4:3 Olympus C2040Z & compatibles, with WCON-08B fixed lens, with WCON-08B festes Objektiv, mit WCON-08B olympus2040 4.930 4:3 Olympus C5060WZ & compatibles (Standard) fixed lens festes Objektiv olympus5060 4.843 4:3 Olympus C860L & compatibles (Standard) fixed lens festes Objektiv olympusC860 6.563 4:3 Olympus Stylus Epic & compatibles (Standard) fixed lens festes Objektiv olympusEpic 1 3:2 Olympus XZ-1 & compatibles (Standard) fixed lens festes Objektiv olympusxz1 4.68 4:3 Olympus Stylus 1 & compatibles fixed lens festes Objektiv olympusStylus1 4.67 4:3 Olympus Olympus Tough TG-4 & compatibles fixed lens festes Objektiv olympusToughTG4 5.56 4:3 Olympus Olympus Tough TG-5 fixed lens festes Objektiv olympusToughTG5 5.62 4:3 lensfun-0.3.4/data/db/compact-panasonic.xml000066400000000000000000001657531445356770400206470ustar00rootroot00000000000000 Panasonic DMC-LX1 16:9 panasonicLX1 4.45 Panasonic DMC-LX1 3:2 panasonicLX1 5.08 Panasonic DMC-LX1 4:3 panasonicLX1 5.40 Panasonic DMC-LX3 4:3 panasonicLX3 4.7 Panasonic DMC-LX3 16:9 panasonicLX3 5.7528 Panasonic DMC-LX3 3:2 panasonicLX3 5.1 Panasonic DMC-LX3 1:1 panasonicLX3 5.32 Panasonic DMC-LX5 4:3 panasonicLX5 4.71 Panasonic DMC-LX7 4:3 panasonicLX7 5.1 Panasonic DMC-LX10 panasonicLX10 2.73 Panasonic DMC-LX15 panasonicLX10 2.73 Panasonic DMC-LC1 leicaDigilux2 3.933 Panasonic DMC-LZ2 panasonicLZ2 6.06 Panasonic DMC-LZ1 panasonicLZ2 6.06 Panasonic DMC-FX9 panasonicFX7 6.05 Panasonic DMC-FX8 panasonicFX7 6.05 Panasonic DMC-FX7 panasonicFX7 6.05 Panasonic DMC-FX2 panasonicFX7 6.05 Panasonic DMC-FZ30 panasonicFZ30 4.73 Panasonic DMC-FZ20 panasonicFZ10 6.0 Panasonic DMC-FZ10 panasonicFZ10 5.84 Panasonic DMC-FZ5 panasonicFZ5 6.0 Panasonic DMC-FZ3 panasonicFZ3 7.6 Panasonic DMC-FZ28 panasonicFZ28 5.6 Panasonic DMC-FX150 panasonicFX150 4.7 Panasonic DMC-LX2 panasonicDMCLX2 4.44 Panasonic DMC-FZ18 panasonicDMCFZ18 6.1 Panasonic DMC-FZ35 panasonicDMCFZ35 5.6 Panasonic DMC-FZ40 panasonicDMCFZ45 5.60 Panasonic DMC-FZ40 (3:2) panasonicDMCFZ45 5.81 Panasonic DMC-FZ45 panasonicDMCFZ45 5.60 Panasonic DMC-FZ45 (3:2) panasonicDMCFZ45 5.81 Panasonic DMC-FZ50 panasonicDMCFZ50 4.84 Panasonic DMC-FZ8 panasonicDMCFZ8 6.02 Panasonic DMC-FZ100 panasonicDMCFZ45 5.60 Panasonic DMC-FZ100 (3:2) panasonicDMCFZ45 5.81 Panasonic DMC-FZ200 panasonicDMCFZ200 5.56 Panasonic DMC-FZ300 panasonicDMCFZ200 5.56 Panasonic DMC-FZ330 panasonicDMCFZ200 5.56 Panasonic DMC-LX100 panasonicDMCLX100 2.21 Panasonic DC-LX100M2 panasonicDMCLX100 2.21 Panasonic DMC-FZ1000 panasonicFZ1000 2.73 Panasonic DMC-FZ2000 panasonicFZ2000 2.73 Panasonic DMC-FZ2500 panasonicFZ2000 2.73 Panasonic DC-FZ10002 panasonicFZ1000 2.73 Panasonic DMC-FZ150 panasonicFZ150 5.56 Panasonic DMC-LF1 panasonicLF1 4.67 Panasonic DMC-TZ60 panasonicTZ70 5.58 Panasonic DMC-TZ61 panasonicTZ70 5.58 Panasonic DMC-ZS40 panasonicTZ70 5.58 Panasonic DMC-TZ70 panasonicTZ70 5.58 Panasonic DMC-TZ71 panasonicTZ70 5.58 Panasonic DMC-ZS50 panasonicTZ70 5.58 Panasonic DMC-TZ80 panasonicTZ70 5.58 Panasonic DMC-TZ81 panasonicTZ70 5.58 Panasonic DMC-ZS60 panasonicTZ70 5.58 Panasonic DMC-TZ90 panasonicTZ70 5.58 Panasonic DMC-TZ91 panasonicTZ70 5.58 Panasonic DC-TZ90 panasonicTZ70 5.58 Panasonic DMC-TZ96 panasonicTZ70 5.58 Panasonic DMC-ZS70 panasonicTZ70 5.58 Panasonic DMC-TZ100 panasonicTZ100 2.75 Panasonic DMC-TZ101 panasonicTZ100 2.75 Panasonic DMC-TZ110 panasonicTZ100 2.75 Panasonic DMC-ZS100 panasonicTZ100 2.75 Panasonic DMC-ZS110 panasonicTZ100 2.75 Panasonic DC-ZS200 panasonicZS200 2.73 Panasonic DC-ZS220 panasonicZS200 2.73 Panasonic DC-TZ200 panasonicZS200 2.73 Panasonic DC-TZ220 panasonicZS200 2.73 Panasonic DC-TZ202 panasonicZS200 2.73 Leica DMC-LX1 & compatibles (Standard) fixed lens festes Objektiv panasonicLX1 4.45 16:9 Leica DMC-LX3 & compatibles (Standard) fixed lens festes Objektiv panasonicLX3 4.7 4:3 Leica DMC-LX5 & compatibles (Standard) fixed lens festes Objektiv panasonicLX5 4.71 4:3 Leica DMC-LX7 & compatibles (Standard) fixed lens festes Objektiv panasonicLX7 5.1 4:3 Leica DMC-LX10 & compatibles (Standard) fixed lens festes Objektiv objectif intégré panasonicLX10 2.73 Leica DMC-LZ2 & compatibles (Standard) fixed lens festes Objektiv panasonicLZ2 6.06 4:3 Leica DMC-FX7 & compatibles (Standard) fixed lens festes Objektiv panasonicFX7 6.05 4:3 Leica DMC-FZ28 & compatibles (Standard) fixed lens festes Objektiv panasonicFZ28 5.6 4:3 Leica DMC-FZ30 & compatibles (Standard) fixed lens festes Objektiv panasonicFZ30 4.73 4:3 Panasonic DMC-FZ45 & compatibles (Standard) fixed lens festes Objektiv panasonicDMCFZ45 5.81 3:2 Leica DMC-FZ10 & compatibles (Standard) fixed lens festes Objektiv panasonicFZ10 5.84 4:3 Leica DMC-FZ5 & compatibles (Standard) fixed lens festes Objektiv panasonicFZ5 6.0 4:3 Leica DMC-FZ3 & compatibles (Standard) fixed lens festes Objektiv panasonicFZ3 7.6 4:3 Leica DMC-FZ200 & compatibles (Standard) fixed lens festes Objektiv panasonicDMCFZ200 5.56 4:3 Leica DMC-LX100 & compatibles fixed lens festes Objektiv panasonicDMCLX100 2.21 4:3 Leica FZ1000 & compatibles fixed lens festes Objektiv panasonicFZ1000 2.73 3:2 Leica FZ2000 & compatibles fixed lens festes Objektiv panasonicFZ2000 2.73 3:2 Leica FZ150 & compatibles fixed lens festes Objektiv panasonicFZ150 5.56 4:3 Panasonic DMC-LF1 & compatibles fixed lens festes Objektiv panasonicLF1 4.67 4:3 Leica DMC-TZ70 & compatibles fixed lens festes Objektiv panasonicTZ70 5.58 4:3 Leica DMC-TZ100 & compatibles fixed lens festes Objektiv panasonicTZ100 2.75 3:2 Panasonic DC-ZS200 & compatibles fixed lens festes Objektiv panasonicZS200 2.73 lensfun-0.3.4/data/db/compact-pentax.xml000066400000000000000000000147341445356770400201630ustar00rootroot00000000000000 Pentax Corporation Pentax Pentax Optio 43WR Optio 43WR pentax43WR 6.5 Pentax Corporation Pentax Pentax Optio 750Z Optio 750Z pentax750 4.843 Pentax Corporation Pentax Pentax Optio 555 Optio 555 pentax750 4.843 Pentax Corporation Pentax Pentax Optio 550 Optio 550 pentax750 4.843 Pentax Corporation Pentax Pentax Optio 450 Optio 450 pentax750 4.843 Pentax Corporation Pentax Pentax Optio 33LF Optio 33LF pentax230 6.563 Pentax Corporation Pentax Pentax Optio 33L Optio 33L pentax230 6.563 Pentax Corporation Pentax Pentax Optio 230GS Optio 230GS pentax230 6.563 Pentax Corporation Pentax Pentax Optio 330GS Optio 330GS pentax230 6.563 Asahi Optical Co.,Ltd Pentax Pentax Optio 430 Optio 430 pentax430 4.85 Pentax Pentax Optio 43WR & compatibles (Standard) fixed lens festes Objektiv pentax43WR 6.5 4:3 Pentax Pentax Optio 750Z & compatibles (Standard) fixed lens festes Objektiv pentax750 4.843 4:3 Pentax Pentax Optio 230GS & compatibles (Standard) fixed lens festes Objektiv pentax230 6.563 4:3 Pentax Pentax Optio 430 & compatibles (Standard) fixed lens festes Objektiv pentax430 4.85 4:3 lensfun-0.3.4/data/db/compact-ricoh.xml000066400000000000000000000272741445356770400177730ustar00rootroot00000000000000 Ricoh GR Digital ricohGRdigital 4.8 Ricoh Caplio GX8 ricohGX 4.9 Ricoh Caplio GX ricohGX 4.9 Ricoh Caplio RR30 ricohRR30 6.4 Ricoh Imaging Company, Ltd. Ricoh GR ricohGR 1.523 Ricoh Imaging Company, Ltd. Ricoh GR III ricohGRIII 1.53 Ricoh Imaging Company, Ltd. Ricoh GR IIIx ricohGRIIIx 1.53 Ricoh GR Digital & compatibles (Standard) fixed lens festes Objektiv ricohGRdigital 4.8 4:3 Ricoh Caplio GX & compatibles (Standard) fixed lens festes Objektiv ricohGX 4.9 4:3 Ricoh Caplio GX & compatibles, with DW-4 fixed lens, with DW-4 festes Objektiv, mit DW-4 ricohGX 4.9 4:3 Ricoh Caplio RR30 & compatibles (Standard) fixed lens festes Objektiv ricohRR30 6.4 4:3 Ricoh Ricoh GR & compatibles fixed lens festes Objektiv ricohGR 1.523 3:2 Ricoh imaging company, ltd. Ricoh GR III & compatibles fixed lens festes Objektiv ricohGRIII 1.53 Ricoh imaging company, ltd. Ricoh GR III & compatibles, with GW-4 fixed lens, with GW-4 festes Objektiv, mit GW-4 ricohGRIII 1.53 Ricoh imaging company, ltd. Ricoh GR IIIx & compatibles fixed lens festes Objektiv ricohGRIIIx 1.53 lensfun-0.3.4/data/db/compact-samsung.xml000066400000000000000000000305061445356770400203340ustar00rootroot00000000000000 Samsung WB2000 samsungWB2000 5.69 Samsung SM-G935F Galaxy S7 samsungS7 6.19 Samsung SM-G950F Galaxy S8 samsungS8 6.19 Samsung SM-G9500 Galaxy S8 samsungS8 6.19 Samsung SM-N950U Galaxy Note 8 samsungS8wide 6.047 Samsung SM-G991B Galaxy S21 samsungS21uw 6.0 Samsung WB2000 & compatibles (Standard) fixed lens festes Objektiv samsungWB2000 5.69 4:3 Samsung Samsung S7 wide angle lens cover samsungS7 6.19 4:3 Samsung Samsung S8 wide angle lens samsungS8wide 6.047 4:3 Samsung SM-G950F samsungS8 6.19 4:3 Samsung Samsung Galaxy S21 ultrawide samsungS21uw 6.0 4:3 lensfun-0.3.4/data/db/compact-sigma.xml000066400000000000000000000044321445356770400177560ustar00rootroot00000000000000 Sigma Sigma DP1 DP1 sigmaDP1 1.739 Sigma Sigma DP1 Merrill DP1 Merrill sigmaDP1M 1.531 Sigma Sigma DP1S DP1S sigmaDP1 1.739 Sigma Sigma DP1X DP1X sigmaDP1 1.739 Sigma Sigma DP2 DP2 sigmaDP2 1.739 Sigma Sigma DP2 Merrill DP2 Merrill sigmaDP2M 1.531 Sigma Sigma DP2S DP2S sigmaDP2 1.739 Sigma Sigma DP2X DP2X sigmaDP2 1.739 Sigma Sigma DP3 Merrill DP3 Merrill sigmaDP3M 1.531 Sigma Sigma DP2 & compatibles (Standard) fixed lens festes Objektiv sigmaDP2 1.739 3:2 lensfun-0.3.4/data/db/compact-sony.xml000066400000000000000000003175071445356770400176600ustar00rootroot00000000000000 Sony DSC-R1 sonyR1 1.68 Sony DSC-H1 sonyH1 6.0 Sony DSC-F828 sony828 3.933 Sony Cybershot Cyber-shot DSC-F717 sony707 3.933 Sony Cybershot Cyber-shot DSC-F707 sony707 3.933 Sony DSC-P200 sonyW1 4.8 Sony DSC-P150 sonyW1 4.8 Sony DSC-P100 sonyW1 4.8 Sony DSC-P93 sonyW1 4.8 Sony DSC-W12 sonyW1 4.8 Sony DSC-W7 sonyW1 4.8 Sony DSC-W15 sonyW1 4.8 Sony DSC-W5 sonyW1 4.8 Sony DSC-W1 sonyW1 4.8 Sony DSC-V3 sonyV1 4.843 Sony DSC-V1 sonyV1 4.843 Sony DSC-T1 sonyT1 5.650 Sony Cybershot Cyber-shot DSC-S85 sonyS85 4.843 Sony Cybershot Cyber-shot DSC-S75 sonyS85 4.843 Sony DSC-S90 sonyS60 6.5 Sony DSC-ST80 sonyS60 6.5 Sony DSC-S80 sonyS60 6.5 Sony DSC-S60 sonyS60 6.5 Sony DSC-P73 sonyS60 6.5 Sony DSC-RX100 RX100 sonyRX100 2.73 Sony DSC-RX100M2 RX100 II sonyRX100II 2.73 Sony DSC-RX100M3 RX100 III sonyRX100III 2.73 Sony DSC-RX100M4 RX100 IV sonyRX100III 2.73 Sony DSC-RX100M5 RX100 V sonyRX100III 2.73 Sony DSC-RX100M6 RX100 VI sonyRX100VI 2.66 Sony DSC-RX100M7 RX100 VII sonyRX100VI 2.66 Sony DSC-RX100M5A RX100 VA sonyRX100III 2.73 Sony DSC-HX300 sonyHX300 5.58 Sony DSC-HX20V sonyHX20V 5.62 Sony Xperia Z3 sonyXperiaZ3 7.87 Sony DSC-RX10 RX10 sonyRX10 2.73 Sony DSC-RX10M2 RX10 II sonyRX10II 2.73 Sony DSC-RX10M3 RX10 III sonyRX10III 2.73 Sony DSC-RX10M4 RX10 IV sonyRX10III 2.73 Sony DSC-RX1RM2 RX1 R II sonyRX1 1 Sony DSC-RX0 RX0 sonyRX0M2 2.70 Sony DSC-RX0M2 RX0 II sonyRX0M2 2.70 Carl Zeiss DSC-R1 & compatibles (Standard) fixed lens festes Objektiv sonyR1 1.68 3:2 Carl Zeiss DSC-H1 & compatibles (Standard) fixed lens festes Objektiv sonyH1 6.0 4:3 Carl Zeiss DSC-H1 & compatibles, with VCL-DH0758 0.7x converter fixed lens, with VCL-DH0758 0.7× converter festes Objektiv, mit VCL-DH0758 0.7×-Konverter sonyH1 6.0 4:3 Carl Zeiss DSC-H1 & compatibles, with VCL-DH1758 1.7x converter fixed lens, with VCL-DH1758 1.7× converter festes Objektiv, mit VCL-DH1758 1.7×-Konverter sonyH1 6.0 4:3 Carl Zeiss DSC-F828 & compatibles (Standard) fixed lens festes Objektiv sony828 3.933 4:3 Carl Zeiss DSC-F828 & compatibles, at 2 feet lens-to-subject fixed lens, at 2 feet lens-to-subject festes Objektiv, bei 60 cm Fokusabstand sony828 3.933 4:3 Carl Zeiss DSC-F707 & compatibles (Standard) fixed lens festes Objektiv sony707 3.933 4:3 Carl Zeiss DSC-F707 & compatibles, macro at 1 inch lens-to-subject fixed lens, macro at 1 inch lens-to-subject festes Objektiv, Makro bei 1 Zoll Fokusabstand sony707 3.933 4:3 Carl Zeiss DSC-F707 & compatibles, macro at 2 inches lens-to-subject fixed lens, macro at 2 inches lens-to-subject festes Objektiv, Makro bei 2 Zoll Fokusabstand sony707 3.933 4:3 Carl Zeiss DSC-F707 & compatibles, macro at 4 inches lens-to-subject fixed lens, macro at 4 inches lens-to-subject festes Objektiv, Makro bei 4 Zoll Fokusabstand sony707 3.933 4:3 Carl Zeiss DSC-F707 & compatibles, macro at 6 inches lens-to-subject fixed lens, macro at 6 inches lens-to-subject festes Objektiv, Makro bei 6 Zoll Fokusabstand sony707 3.933 4:3 Carl Zeiss DSC-F707 & compatibles, macro at 8 inches lens-to-subject fixed lens, macro at 8 inches lens-to-subject festes Objektiv, Makro bei 8 Zoll Fokusabstand sony707 3.933 4:3 Carl Zeiss DSC-F707 & compatibles, macro at 12 inches lens-to-subject fixed lens, macro at 12 inches lens-to-subject festes Objektiv, Makro bei 12 Zoll Fokusabstand sony707 3.933 4:3 Carl Zeiss DSC-F707 & compatibles, macro at 16 inches lens-to-subject fixed lens, macro at 16 inches lens-to-subject festes Objektiv, Makro bei 16 Zoll Fokusabstand sony707 3.933 4:3 Carl Zeiss DSC-F707 & compatibles, macro at 20 inches lens-to-subject fixed lens, macro at 20 inches lens-to-subject festes Objektiv, Makro bei 20 Zoll Fokusabstand sony707 3.933 4:3 Carl Zeiss DSC-F707 & compatibles, macro at 24 inches lens-to-subject fixed lens, macro at 24 inches lens-to-subject festes Objektiv, Makro bei 24 Zoll Fokusabstand sony707 3.933 4:3 Carl Zeiss DSC-F707 & compatibles, macro at 32 inches lens-to-subject fixed lens, macro at 32 inches lens-to-subject festes Objektiv, Makro bei 32 Zoll Fokusabstand sony707 3.933 4:3 Carl Zeiss DSC-F707 & compatibles, with VCL-HGD0758 wide angle fixed lens, with VCL-HGD0758 wide angle festes Objektiv, mit VCL-HGD0758 Weitwinkel sony707 3.933 4:3 Carl Zeiss DSC-F707 & compatibles, with Sakar 1858W fixed lens, with Sakar 1858W festes Objektiv, mit Sakar 1858W sony707 3.933 4:3 Carl Zeiss DSC-W1 & compatibles (Standard) fixed lens festes Objektiv sonyW1 4.8 4:3 Carl Zeiss DSC-V1 & compatibles (Standard) fixed lens festes Objektiv sonyV1 4.843 4:3 Carl Zeiss DSC-V1 & compatibles, with VCL-DEH07V converter fixed lens, with VCL-DEH07V converter festes Objektiv, mit VCL-DEH07V-Konverter sonyV1 4.843 4:3 Carl Zeiss DSC-V1 & compatibles, with VCL-DEH17V converter fixed lens, with VCL-DEH17V converter festes Objektiv, mit VCL-DEH17V-Konverter sonyV1 4.843 4:3 Carl Zeiss DSC-T1 & compatibles (Standard) fixed lens festes Objektiv sonyT1 5.650 4:3 Carl Zeiss DSC-S85 & compatibles (Standard) fixed lens festes Objektiv sonyS85 4.843 4:3 Carl Zeiss DSC-S85 & compatibles, with VCL-MHG07a converter fixed lens, with VCL-MHG07a converter festes Objektiv, mit VCL-MHG07a-Konverter sonyS85 4.843 4:3 Carl Zeiss DSC-S60 & compatibles (Standard) fixed lens festes Objektiv sonyS60 6.5 4:3 Sony DSC-RX100 & compatibles (Standard) fixed lens festes Objektiv sonyRX100 2.73 3:2 Sony DSC-RX100 II & compatibles fixed lens festes Objektiv sonyRX100II 2.73 3:2 Sony DSC-RX100 III & compatibles fixed lens festes Objektiv sonyRX100III 2.73 3:2 Sony DSC-RX100 VI & compatibles fixed lens festes Objektiv sonyRX100VI 2.66 Sony DSC-HX300 & compatibles (Standard) fixed lens festes Objektiv sonyHX300 5.58 4:3 Sony Sony Xperia Z3 & compatibles fixed lens festes Objektiv sonyXperiaZ3 7.87 4:3 Sony Sony RX10 & compatibles fixed lens festes Objektiv sonyRX10 2.73 3:2 Sony Sony RX10II & compatibles fixed lens festes Objektiv sonyRX10II 2.73 3:2 Sony Sony RX10III & compatibles fixed lens festes Objektiv sonyRX10III 2.73 Carl Zeiss DSC-RX1RM2 & compatibles fixed lens festes Objektiv sonyRX1 1 3:2 Sony DSC-RX0M2 fixed lens festes Objektiv sonyRX0M2 2.70 lensfun-0.3.4/data/db/contax.xml000066400000000000000000000031431445356770400165240ustar00rootroot00000000000000 Contax/Yashica M42 M39/1 DKL T2 Generic Contax G M42 M39/1 DKL T2 Generic Contax 35mm film: full frame Contax/Yashica 1 Contax Zeiss 21mm f/2.8 Distagon Contax/Yashica 1 Contax Zeiss 28mm f/2.8 Distagon Contax/Yashica 1 Contax Contax G Planar T* 2/35 Contax G 1.534 lensfun-0.3.4/data/db/generic.xml000066400000000000000000000110631445356770400166440ustar00rootroot00000000000000 Generic 4/3 System Canon EF Canon EF-M Canon EF-S Canon FD Canon FL Contax/Yashica Contax G Fujifilm X Hasselblad 500 Hasselblad H Leica M Leica R Leica S M42 M39/1 DKL Mamiya 645 Micro 4/3 System Minolta AF Minolta MC Minolta MD Nikon CX Nikon F Nikon F AF Nikon F AI Nikon F AI-S Nikon Z Olympus OM Pentax Q Pentax K Pentax KA Pentax KAF Pentax KAF2 Pentax KAF3 Pentax KAF4 Rollei 6x6 Samsung NX Samsung NX mini Sigma SA Sony Alpha Sony E Tamron Adaptall T2 C Kiev 88 Generic Generisch Crop-factor 1.0 (Full Frame) Crop-Faktor 1.0 (Kleinbildformat) Generic 1 Generic Generisch Crop-factor 1.1 Crop-Faktor 1.1 Generic 1.1 Generic Generisch Crop-factor 1.3 (APS-H) Crop-Faktor 1.3 (APS-H) Generic 1.267 Generic Generisch Crop-factor 1.5 (APS-C) Crop-Faktor 1.5 (APS-C) Generic 1.53 Generic Generisch Crop-factor 1.6 (APS-C) Crop-Faktor 1.6 (Canon APS-C) Generic 1.611 Generic Generisch Crop-factor 1.7 Crop-Faktor 1.7 (Sigma) Generic 1.739 Generic Generisch Crop-factor 2.0 (Four-Thirds) Crop-Faktor 2.0 (Four-Thirds) Generic 2 Generic Generisch Rectilinear 10-1000mm f/1.0 Rektilinear 10-1000mm f/1.0 Generic rectilinear 1 Generic Generisch Fisheye 8-20mm f/1.0 Fischauge 8-20mm f/1.0 Generic fisheye 1 Generic Generisch Panoramic 10-100mm f/1.0 Panoramaobjektiv 10-100mm f/1.0 Generic panoramic 1 lensfun-0.3.4/data/db/mil-canon.xml000066400000000000000000003216331445356770400171140ustar00rootroot00000000000000 Canon EF-M Canon EF-S Canon EF M42 M39/1 DKL T2 Generic Canon RF Canon EF-S Canon EF M42 M39/1 DKL T2 Generic Canon Canon EOS M EOS M Canon EF-M 1.613 Canon Canon EOS M2 EOS M2 Canon EF-M 1.613 Canon Canon EOS M3 EOS M3 Canon EF-M 1.613 Canon Canon EOS M5 EOS M5 Canon EF-M 1.613 Canon Canon EOS M6 EOS M6 Canon EF-M 1.613 Canon Canon EOS M6 Mark II EOS M6 Mark II Canon EF-M 1.613 Canon Canon EOS M10 EOS M10 Canon EF-M 1.613 Canon Canon EOS M50 EOS M50 Canon EF-M 1.613 Canon Canon EOS M50m2 EOS M50 Mark II Canon EF-M 1.613 Canon Canon EOS KISS M EOS KISS M Canon EF-M 1.613 Canon Canon EOS M100 EOS M100 Canon EF-M 1.613 Canon Canon EOS M200 EOS M200 Canon EF-M 1.613 Canon Canon EOS R7 EOS R7 Canon RF 1.613 Canon Canon EOS R10 EOS R10 Canon RF 1.613 Canon Canon EOS R EOS R Canon RF 1 Canon Canon EOS RP EOS RP Canon RF 1 Canon Canon EOS R3 EOS R3 Canon RF 1 Canon Canon EOS R5 EOS R5 Canon RF 1 Canon Canon EOS R6 EOS R6 Canon RF 1 Canon Canon EOS R6m2 EOS R6 Mark II Canon RF 1 Canon Canon EOS R8 EOS R8 Canon RF 1 Canon Canon EF-M 18-55mm f/3.5-5.6 IS STM Canon EF-M 1.613 Canon Canon EF-M 55-200mm f/4.5-6.3 IS STM Canon EF-M 1.613 Canon Canon EF-M 22mm f/2 STM Canon EF-M 1.613 Canon Canon EF-M 28mm f/3.5 Macro IS STM Canon EF-M 1.613 Canon Canon EF-M 15-45mm f/3.5-6.3 IS STM Canon EF-M 1.613 Canon Canon EF-M 11-22mm f/4-5.6 IS STM Canon EF-M 1.613 Canon Canon EF-M 32mm f/1.4 STM Canon EF-M 1.613 Canon Canon RF 24-105mm F4L IS USM Canon RF 1.0 Canon Canon RF 24-105mm F4-7.1 IS STM Canon RF 1.0 Canon Canon RF 24-240mm F4-6.3 IS USM Canon RF 1.0 Canon Canon RF 50mm F1.8 STM Canon RF 1.0 Canon Canon RF 70-200mm F2.8L IS USM Canon RF 1.0 Canon Canon RF 85mm F1.2L USM Canon RF 1.0 Canon Canon RF 100-500mm F4.5-7.1L IS USM Canon RF 1.0 Canon Canon RF 85mm F2 MACRO IS STM Canon RF 1.0 Canon Canon RF 100-400mm F5.6-8 IS USM Canon RF 1.0 Canon Canon RF 100mm F2.8L Macro IS USM Canon RF 1.0 Canon Canon RF 15-35mm F2.8L IS USM Canon RF 1.0 Canon Canon RF 800mm F11 IS STM Canon RF 1.0 Canon Canon RF 16mm F2.8 STM Canon RF 1.0 Canon Canon RF 14-35mm F4 L IS USM Canon RF 1.0 Canon Canon RF 35mm F1.8 MACRO IS STM Canon RF 1.0 Canon Canon RF-S 18-150mm F3.5-6.3 IS STM Canon RF 1.613 Canon Canon RF 24-70mm F2.8L IS USM Canon RF 1.0 lensfun-0.3.4/data/db/mil-fujifilm.xml000066400000000000000000005053751445356770400176320ustar00rootroot00000000000000 Fujifilm X M42 M39/1 DKL T2 Generic Fujifilm X-Pro1 Fujifilm X 1.529 Fujifilm X-Pro2 Fujifilm X 1.528 Fujifilm X-E1 Fujifilm X 1.529 Fujifilm X-E2 Fujifilm X 1.529 Fujifilm X-E2S Fujifilm X 1.529 Fujifilm X-E3 Fujifilm X 1.529 Fujifilm X-E4 Fujifilm X 1.534 Fujifilm X-T1 Fujifilm X 1.529 Fujifilm X-T2 Fujifilm X 1.528 Fujifilm X-T3 Fujifilm X 1.534 Fujifilm X-T4 Fujifilm X 1.534 Fujifilm X-T5 Fujifilm X 1.534 Fujifilm X-Pro3 Fujifilm X 1.534 Fujifilm X-H1 Fujifilm X 1.528 Fujifilm X-H2 Fujifilm X 1.528 Fujifilm X-H2S Fujifilm X 1.528 Fujifilm X-M1 Fujifilm X 1.529 Fujifilm X-A1 Fujifilm X 1.529 Fujifilm X-A2 Fujifilm X 1.529 Fujifilm X-T10 Fujifilm X 1.529 Fujifilm X-T20 Fujifilm X 1.529 Fujifilm X-T30 Fujifilm X 1.534 Fujifilm X-T30 II Fujifilm X 1.534 Fujifilm X-S10 Fujifilm X 1.534 Fujifilm X-S20 Fujifilm X 1.534 Fujifilm X-T100 Fujifilm X 1.529 Fujifilm X-A3 Fujifilm X 1.529 Fujifilm X-A5 Fujifilm X 1.529 Fujifilm X-A7 Fujifilm X 1.529 Fujifilm GFX 50R Fujifilm G 0.79 Fujifilm GFX 50S Fujifilm G 0.79 Fujifilm GFX100S Fujifilm G 0.79 Fujifilm XF18-55mmF2.8-4 R LM OIS XF 18-55mm f/2.8-4 R LM OIS Fujifilm X 1.529 Fujifilm XC16-50mmF3.5-5.6 OIS XC 16-50mm f/3.5-5.6 OIS Fujifilm X 1.529 Fujifilm XC50-230mmF4.5-6.7 OIS XC 50-230mm f/4.5-6.7 OIS Fujifilm X 1.529 Fujifilm XC50-230mmF4.5-6.7 OIS II XC 50-230mm f/4.5-6.7 OIS II Fujifilm X 1.529 Fujifilm XF55-200mmF3.5-4.8 R LM OIS XF 55-200mm f/3.5-4.8 R LM OIS Fujifilm X 1.529 Fujifilm XF27mmF2.8 XF 27mm f/2.8 Fujifilm X 1.529 Fujifilm XF18mmF2 R XF 18mm f/2 R Fujifilm X 1.529 Fujifilm XF35mmF1.4 R XF 35mm f/1.4 R Fujifilm X 1.529 Fujifilm XF60mmF2.4 R Macro XF 60mm f/2.4 R Macro Fujifilm X 1.529 Fujifilm XF23mmF1.4 R XF 23mm f/1.4 R Fujifilm X 1.529 Fujifilm XC16-50mmF3.5-5.6 OIS II XC 16-50mm f/3.5-5.6 OIS II Fujifilm X 1.529 Fujifilm XF14mmF2.8 R XF 14mm f/2.8 R Fujifilm X 1.529 Fujifilm XF16mmF1.4 R WR XF 16mm f/1.4 R WR Fujifilm X 1.529 Fujifilm XF23mmF2 R WR XF 23mm f/2 R WR Fujifilm X 1.529 Fujifilm XF50mmF2 R WR XF 50mm f/2 R WR Fujifilm X 1.528 Fujifilm XF56mmF1.2 R APD XF 56mm f/1.2 R APD Fujifilm X 1.529 Fujifilm XF16-55mmF2.8 R LM WR XF 16-55mm f/2.8 R LM WR Fujifilm X 1.529 Fujifilm XF56mmF1.2 R XF 56mm f/1.2 R Fujifilm X 1.529 Fujifilm XF10-24mmF4 R OIS XF 10-24mm f/4 R OIS Fujifilm X 1.529 Fujifilm XF10-24mmF4 R OIS WR XF 10-24mm f/4 R OIS WR Fujifilm X 1.529 Fujifilm XF18-135mmF3.5-5.6R LM OIS WR XF 18-135mm f/3.5-5.6R LM OIS WR Fujifilm X 1.529 Fujifilm XF100-400mmF4.5-5.6 R LM OIS WR XF 100-400mm f/4.5-5.6 R LM OIS WR Fujifilm X 1.529 Fujifilm XF100-400mmF4.5-5.6 R LM OIS WR + 1.4x converter XF 100-400mm f/4.5-5.6 R LM OIS WR + 1.4× conv. XF 100-400mm f/4.5-5.6 R LM OIS WR + 1.4×-Konv. Fujifilm X 1.529 Fujifilm XF16mmF2.8 R WR XF 16mm f/2.8 R WR Fujifilm X 1.529 Fujifilm XF50-140mmF2.8 R LM OIS WR XF 50-140mm f/2.8 R LM OIS WR Fujifilm X 1.529 Fujifilm XC15-45mmF3.5-5.6 OIS PZ XC 15-45mm f/3.5-5.6 OIS PZ Fujifilm X 1.529 Fujifilm XF35mmF2 R WR XF 35mm f/2 R WR Fujifilm X 1.528 Fujifilm XC35mmF2 XC 35mm f/2 Fujifilm X 1.528 Fujifilm XF70-300mmF4-5.6 R LM OIS WR XF 70-300mm f/4-5.6 R LM OIS WR Fujifilm X 1.534 Fujifilm XF16-80mmF4 R OIS WR XF 16-80mm f/4 R OIS WR Fujifilm X 1.534 Fujifilm GF23mmF4 R LM WR Fujifilm G 0.79 Fujifilm GF45mmF2.8 R WR Fujifilm G 0.79 Fujifilm GF110mmF2 R LM WR Fujifilm G 0.79 Fujifilm XF33mmF1.4 R LM WR XF 33mm f/1.4 R LM WR Fujifilm X 1.534 Fujifilm XF90mmF2 R LM WR XF 90mm f/2 R LM WR Fujifilm X 1.534 Fujifilm XF23mmF1.4 R LM WR XF 23mm f/1.4 R LM WR Fujifilm X 1.53 lensfun-0.3.4/data/db/mil-leica.xml000066400000000000000000000121221445356770400170610ustar00rootroot00000000000000 Leica L Leica M M42 M39/1 DKL T2 Generic Leica Camera AG Leica SL (Typ 601) Leica L 1 Leica Camera AG Leica SL2 Leica L 1 Leica Camera AG Leica SL2-S Leica L 1 Leica Camera AG Leica T (Typ 701) Leica L 1.53 Leica Camera AG Leica TL Leica L 1.53 Leica Camera AG Leica TL2 Leica L 1.53 Leica Camera AG Leica CL (Typ 7323) Leica L 1.53 Leica Camera AG Digilux 3 Micro 4/3 System 2 Leica Camera AG Summicron TL 1:2 23 ASPH. Leica L 1.53 Leica Camera AG Summilux-TL 1:1.4/35 ASPH. Leica L 1.53 Leica Camera AG Elmarit-TL 1:2.8/18 ASPH. Leica L 1.53 Leica Camera AG VARIO-ELMARIT-SL 1:2.8/24-70 ASPH. Leica L 1 Leica Camera AG APO-SUMMICRON-SL 1:2/50 ASPH. Leica L 1 lensfun-0.3.4/data/db/mil-nikon.xml000066400000000000000000003072261445356770400171360ustar00rootroot00000000000000 Nikon CX Nikon F Nikon F AI Nikon F AI-S Nikon F AF M42 M39/1 DKL T2 Generic Nikon Z Nikon F Nikon F AI Nikon F AI-S Nikon F AF M42 M39/1 DKL T2 Generic Nikon Corporation Nikon Nikon 1 S1 1 S1 Nikon CX 2.727 Nikon Corporation Nikon Nikon 1 V1 1 V1 Nikon CX 2.727 Nikon Corporation Nikon Nikon 1 J1 1 J1 Nikon CX 2.727 Nikon Corporation Nikon Nikon 1 AW1 1 AW1 Nikon CX 2.727 Nikon Corporation Nikon Nikon 1 S2 1 S2 Nikon CX 2.727 Nikon Corporation Nikon Nikon 1 V2 1 V2 Nikon CX 2.727 Nikon Corporation Nikon Nikon 1 J2 1 J2 Nikon CX 2.727 Nikon Corporation Nikon Nikon 1 V3 1 V3 Nikon CX 2.727 Nikon Corporation Nikon Nikon 1 J3 1 J3 Nikon CX 2.727 Nikon Corporation Nikon Nikon 1 J4 1 J4 Nikon CX 2.727 Nikon Corporation Nikon Nikon 1 J5 1 J5 Nikon CX 2.727 Nikon Corporation Nikon Nikon Z 5 Z 5 Nikon Z 1 Nikon Corporation Nikon Nikon Z 6 Z 6 Nikon Z 1 Nikon Corporation Nikon Nikon Z 6_2 Z 6II Nikon Z 1 Nikon Corporation Nikon Nikon Z 7 Z 7 Nikon Z 1 Nikon Corporation Nikon Nikon Z 7_2 Z 7II Nikon Z 1 Nikon Corporation Nikon Nikon Z 8 Z 8 Nikon Z 1 Nikon Corporation Nikon Nikon Z 9 Z 9 Nikon Z 1 Nikon Corporation Nikon Nikon Z 30 Z 30 Nikon Z 1.531 Nikon Corporation Nikon Nikon Z 50 Z 50 Nikon Z 1.531 Nikon Corporation Nikon Nikon Z fc Z fc Nikon Z 1.531 Nikon 1 Nikkor VR 10-30mm f/3.5-5.6 Nikon CX 2.727 Nikon 1 Nikkor VR 30-110mm f/3.8-5.6 Nikon CX 2.727 Nikon 1 Nikkor AW 11-27.5mm f/3.5-5.6 Nikon CX 2.727 Nikon 1 Nikkor 18.5mm f/1.8 Nikon CX 2.727 Nikon 1 Nikkor 32mm f/1.2 Nikon CX 2.727 Nikon 1 Nikkor 10mm f/2.8 Nikon CX 2.727 Nikon 1 Nikkor AW 10mm f/2.8 Nikon CX 2.727 Nikon Nikkor Z MC 50mm f/2.8 Nikon Z 1.0 Nikon NIKKOR Z 14-24mm f/2.8 S Nikon Z 1.0 Nikon NIKKOR Z 14-30mm f/4 S Nikon Z 1.0 Nikon NIKKOR Z 24-70mm f/2.8 S Nikon Z 1 Nikon NIKKOR Z 24-70mm f/4 S Nikon Z 1 Nikon NIKKOR Z 20mm f/1.8 S Nikon Z 1 Nikon NIKKOR Z 50mm f/1.8 S Nikon Z 1.0 Nikon NIKKOR Z 70-200mm f/2.8 VR S Nikon Z 1.0 Nikon NIKKOR Z 85mm f/1.8 S Nikon Z 1.0 Nikon NIKKOR Z 24-200mm f/4-6.3 VR Nikon Z 1 Nikon NIKKOR Z DX 16-50mm f/3.5-6.3 VR Nikon Z 1.531 Nikon NIKKOR Z 35mm f/1.8 S Nikon Z 1.0 Nikon NIKKOR Z 40mm f/2 Nikon Z 1 Nikon NIKKOR Z MC 105mm f/2.8 VR S Nikon Z 1.0 Nikon NIKKOR Z 28-75mm f/2.8 Nikon Z 1.0 Nikon NIKKOR Z 24-120mm f/4 S Nikon Z 1.0 Nikon NIKKOR Z 100-400mm f/4.5-5.6 VR S Nikon Z 1 Nikon NIKKOR Z 50mm f/1.2 S Nikon Z 1 lensfun-0.3.4/data/db/mil-olympus.xml000066400000000000000000004362111445356770400175250ustar00rootroot00000000000000 Micro 4/3 System M42 M39/1 DKL T2 Generic Olympus Imaging Corp. Olympus E-P1 Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-P2 Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-P3 Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-P5 Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-PL1 Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-PL1s Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-PL2 Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-PL3 Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-PL5 Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-PL6 Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-PL7 Micro 4/3 System 2 Olympus Corporation Olympus E-PL8 Micro 4/3 System 2 Olympus Corporation Olympus E-PL9 Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-PM1 Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-PM2 Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-M1 Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-M1MarkII Micro 4/3 System 2 Olympus Corporation Olympus E-M1MarkIII Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-M5 Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-M5MarkII Micro 4/3 System 2 Olympus Corporation Olympus E-M5MarkIII Micro 4/3 System 2 Olympus Imaging Corp. Olympus E-M10 Micro 4/3 System 2 Olympus Corporation Olympus E-M10MarkII E-M10 II Micro 4/3 System 2 Olympus Corporation Olympus E-M10 Mark III E-M10 III Micro 4/3 System 2 Olympus Corporation Olympus E-M10MarkIIIS E-M10 III S Micro 4/3 System 2 Olympus Corporation Olympus E-M10MarkIV E-M10 IV Micro 4/3 System 2 Olympus Imaging Corp. Olympus PEN-F Micro 4/3 System 2 Olympus Olympus M.Zuiko Digital ED 12mm f/2.0 Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 12-50mm f/3.5-6.3 EZ Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.6 Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.6 L Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital 14-42mm f/3.5-5.6 II Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.6 II R Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 14-150mm f/4.0-5.6 Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 14-150mm f/4.0-5.6 II Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital 17mm f/2.8 Pancake Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 45mm f/1.2 Pro Micro 4/3 System 2 Olympus Olympus M.Zuiko Digital 45mm f/1.8 Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 17mm f/1.2 Pro Micro 4/3 System 2 Olympus Olympus M.Zuiko Digital 17mm f/1.8 Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 40-150mm f/4.0-5.6 R Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 9-18mm f/4.0-5.6 Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 12-40mm f/2.8 Pro Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 12-100mm f/4.0 IS Pro Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 25mm f/1.2 Pro Micro 4/3 System 2 Olympus Olympus M.Zuiko Digital 25mm f/1.8 Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 75mm f/1.8 Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 75-300mm f/4.8-6.7 II Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.6 EZ Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 60mm f/2.8 Macro Micro 4/3 System 2 4:3 Olympus Olympus M.Zuiko Digital ED 7-14mm f/2.8 Pro Micro 4/3 System 2 4:3 Olympus OLYMPUS M.40-150mm F2.8 Olympus M.Zuiko Digital ED 40-150mm F2.8 Pro Micro 4/3 System 2.0 4:3 Olympus M.40-150mm F2.8 + MC-14 Olympus M.Zuiko Digital ED 40-150mm f/2.8 PRO + 1.4× conv. Micro 4/3 System 2.0 4:3 Olympus Olympus 9mm Body Cap Lens Fisheye Micro 4/3 System stereographic 2 4:3 Olympus Olympus M.Zuiko Digital ED 8mm f/1.8 Fisheye Pro Micro 4/3 System equisolid 2 4:3 Olympus OLYMPUS M.12-200mm F3.5-6.3 Olympus M.Zuiko Digital ED 12-200mm f/3.5-6.3 Micro 4/3 System 2 4:3 Olympus OLYMPUS M.30mm F3.5 Macro Olympus M.Zuiko Digital ED 30mm f/3.5 Macro Micro 4/3 System 2 4:3 Olympus OLYMPUS M.12-45mm F4.0 Olympus M.Zuiko Digital ED 12-45mm f/4.0 Pro Micro 4/3 System 2 4:3 Olympus OLYMPUS M.8-25mm F4.0 Olympus M.Zuiko Digital ED 8-25mm f/4.0 PRO Micro 4/3 System 2.0 4:3 lensfun-0.3.4/data/db/mil-panasonic.xml000066400000000000000000010021411445356770400177600ustar00rootroot00000000000000 Panasonic DMC-G1 Micro 4/3 System 2 Panasonic DMC-GF1 Micro 4/3 System 2 Panasonic DMC-GH1 Micro 4/3 System 2 Panasonic DMC-GM1 Micro 4/3 System 2 Panasonic DMC-GX1 Micro 4/3 System 2 Panasonic DMC-G2 Micro 4/3 System 2 Panasonic DMC-GF2 Micro 4/3 System 2 Panasonic DMC-GH2 Micro 4/3 System 2 Panasonic DMC-G3 Micro 4/3 System 2 Panasonic DMC-GF3 Micro 4/3 System 2 Panasonic DMC-GH3 Micro 4/3 System 2 Panasonic DMC-GH4 Micro 4/3 System 2 Panasonic DC-GH5 Micro 4/3 System 2 Panasonic DC-GH5M2 Micro 4/3 System 2 Panasonic DC-GH5S Micro 4/3 System 2 Panasonic DC-GH6 Micro 4/3 System 2 Panasonic DMC-G5 Micro 4/3 System 2 Panasonic DC-G9 Micro 4/3 System 2 Panasonic DC-GX9 Micro 4/3 System 2 Panasonic DC-GX7MK3 Micro 4/3 System 2 Panasonic DC-G100 Micro 4/3 System 2 Panasonic DC-G110 Micro 4/3 System 2 Panasonic DMC-GF5 Micro 4/3 System 2 Panasonic DMC-G6 Micro 4/3 System 2 Panasonic DMC-GF6 Micro 4/3 System 2 Panasonic DMC-G7 Micro 4/3 System 2 Panasonic DMC-GF7 Micro 4/3 System 2 Panasonic DMC-GX7 Micro 4/3 System 2 Panasonic DMC-G70 Micro 4/3 System 2 Panasonic DMC-G10 Micro 4/3 System 2 Panasonic DMC-GM5 Micro 4/3 System 2 Panasonic DMC-GF8 Micro 4/3 System 2 Panasonic DMC-GX8 Micro 4/3 System 2 Panasonic DMC-G80 Micro 4/3 System 2 Panasonic DMC-G81 Micro 4/3 System 2 Panasonic DMC-G85 Micro 4/3 System 2 Panasonic DMC-GX80 Micro 4/3 System 2 Panasonic DMC-GX85 Micro 4/3 System 2 Panasonic DC-GX800 Micro 4/3 System 2 Panasonic DC-GX880 Micro 4/3 System 2 Panasonic DC-G90 Micro 4/3 System 2 Panasonic DC-G91 Micro 4/3 System 2 Panasonic DC-G95 Micro 4/3 System 2 Panasonic DC-G99 Micro 4/3 System 2 Panasonic DC-S1 Leica L 1 Panasonic DC-S1H Leica L 1 Panasonic DC-S1R Leica L 1 Panasonic DC-S5 Leica L 1 Panasonic DC-S5M2 Leica L 1 Panasonic Lumix G 14mm f/2.5 Asph. Micro 4/3 System 2 4:3 Panasonic Lumix G 14mm f/2.5 Asph. + GWC1 0.79x Micro 4/3 System 2 4:3 Panasonic Lumix G 20mm f/1.7 Asph. Micro 4/3 System 2 4:3 Panasonic Lumix G X Vario PZ 14-42mm f/3.5-5.6 Asph. Power OIS Lumix G X Vario PZ 14-42mm f/3.5-5.6 Micro 4/3 System 2 4:3 Panasonic Lumix G Vario 12-60mm f/3.5-5.6 Asph. Power OIS Micro 4/3 System 2 4:3 Panasonic Lumix G Vario 14-42mm f/3.5-5.6 II Asph. Mega OIS Lumix G Vario 14-42mm f/3.5-5.6 II Micro 4/3 System 2 4:3 Panasonic Lumix G X Vario PZ 14-42mm f/3.5-5.6 Asph. Power OIS + GWC1 0.79x Lumix G X Vario PZ 14-42mm f/3.5-5.6 + GWC1 0.79× Micro 4/3 System 2 4:3 Panasonic Lumix G Vario 14-45mm f/3.5-5.6 Asph. Mega OIS Micro 4/3 System 2 4:3 Panasonic Lumix G Vario HD 14-140mm f/4.0-5.8 Asph. Mega OIS Lumix G Vario HD 14-140mm f/4.0-5.8 Micro 4/3 System 2 4:3 Panasonic LEICA DG NOCTICRON 42.5/F1.2 Leica DG Nocticron 42.5mm f/1.2 Asph. Power OIS Micro 4/3 System 2 4:3 Panasonic Lumix G Vario 45-200mm f/4.0-5.6 Mega OIS Lumix G Vario 45-200mm f/4.0-5.6 Mega OIS Micro 4/3 System 2 4:3 Panasonic Lumix G Vario 45-200mm f/4.0-5.6 II Lumix G Vario 45-200mm f/4.0-5.6 II power OIS Micro 4/3 System 2 4:3 Panasonic Lumix G Vario 100-300mm f/4.0-5.6 Mega OIS Lumix G Vario 100-300mm f/4.0-5.6 Micro 4/3 System 2 4:3 Panasonic LUMIX G VARIO 100-300/F4.0-5.6II Lumix G Vario 100-300mm F4-5.6 II Power O.I.S. Micro 4/3 System 2 4:3 Panasonic Leica DG Summilux 25mm f/1.4 Asph. Micro 4/3 System 2 4:3 Panasonic Leica DG Summilux 25mm f/1.4 II Micro 4/3 System 2 4:3 Panasonic LUMIX G VARIO 35-100/F2.8 Lumix G X Vario 35-100mm f/2.8 Power OIS Micro 4/3 System 2 4:3 Panasonic LUMIX G VARIO 35-100/F2.8II LUMIX G X VARIO 35-100 mm f/2.8 II Power OIS Micro 4/3 System 2 4:3 Panasonic Lumix G X Vario 12-35mm f/2.8 Asph. Power OIS Lumix G X Vario 12-35mm f/2.8 Micro 4/3 System 2 4:3 Panasonic Lumix G X Vario 12-35mm f/2.8 II Asph. Power OIS Lumix G X Vario 12-35mm f/2.8 II Micro 4/3 System 2 4:3 Panasonic Lumix G 20mm f/1.7 II Asph. Micro 4/3 System 2 4:3 Panasonic Lumix G Vario 35-100mm f/4.0-5.6 Asph. Mega OIS Micro 4/3 System 2 4:3 Panasonic Lumix G Vario 45-150mm f/4.0-5.6 Asph. Mega OIS Lumix G Vario 45-150mm f/4.0-5.6 Micro 4/3 System 2 Panasonic Lumix G Vario 7-14mm f/4.0 Asph. Micro 4/3 System 2 4:3 Panasonic Leica DG Macro-Elmarit 45mm f/2.8 Micro 4/3 System 2 4:3 Panasonic Lumix G X Vario PZ 45-175mm f/4.0-5.6 Asph. Power OIS Lumix G X Vario PZ 45-175mm f/4.0-5.6 Micro 4/3 System 2 4:3 Panasonic Leica DG Summilux 15mm f/1.7 Asph. Micro 4/3 System 2 4:3 Panasonic Lumix G Vario 12-32mm f/3.5-5.6 Asph. Mega OIS Micro 4/3 System 2 4:3 Panasonic Lumix G 14mm f/2.5 II Micro 4/3 System 2 4:3 Panasonic Lumix G 42.5mm f/1.7 Micro 4/3 System 2 4:3 Panasonic Lumix G Vario 14-140mm f/3.5-5.6 Lumix G Vario 14-140mm f/3.5-5.6 Asph. Power OIS Micro 4/3 System 2 4:3 Panasonic Lumix G Vario 14-140mm f/3.5-5.6 II Lumix G Vario 14-140mm f/3.5-5.6 Asph. II Power OIS Micro 4/3 System 2 4:3 Panasonic Lumix G 25mm f/1.7 Asph. Micro 4/3 System 2 4:3 Panasonic Leica DG 12-60mm f/2.8-4.0 Leica DG Vario-Elmarit 12-60mm f/2.8-4.0 Asph. Power OIS Micro 4/3 System 2 4:3 Panasonic LEICA DG 8-18/F2.8-4.0 Leica DG Vario-Elmarit 8-18mm f/2.8-4 Asph. Micro 4/3 System 2 4:3 Panasonic LEICA DG 10-25/F1.7 Leica DG Vario-Summilux 10-25mm f/1.7 Asph. Micro 4/3 System 2.0 Panasonic LEICA DG 100-400/F4.0-6.3 Leica DG Vario-Elmar 100-400mm f/4.0-6.3 Asph. Power OIS Micro 4/3 System 2 4:3 Panasonic Lumix G Macro 30mm f/2.8 Micro 4/3 System 2 4:3 Panasonic Lumix S 20-60/F3.5-5.6 Leica L 1 Panasonic LUMIX S 70-300/F4.5-5.6 Leica L 1.0 Panasonic Lumix S 24/F1.8 Leica L 1.0 Panasonic Lumix S 50/F1.8 Leica L 1.0 Panasonic Lumix S 85/F1.8 Leica L 1.0 Panasonic Leica D Summilux 25mm F1.4 Asph. Micro 4/3 System 2.0 Panasonic LEICA DG 50-200/F2.8-4.0 Leica DG Vario-Elmarit 50-200 mm F2.8-4 Asph OIS Micro 4/3 System 2.0 4:3 Panasonic Leica D Vario-Elmar 14-150mm f/3.5-5.6 Asph. OIS 4/3 System 2 4:3 Panasonic LEICA DG SUMMILUX 9/F1.7 Leica DG Summilux 9mm f/1.7 Micro 4/3 System 2 4:3 Panasonic LUMIX S 16-35/F4 Leica L 1 lensfun-0.3.4/data/db/mil-pentax.xml000066400000000000000000000017651445356770400173160ustar00rootroot00000000000000 Pentax Q Generic Pentax Pentax Q Pentax Q 5.53 Pentax Pentax Q7 Pentax Q 4.6 Pentax Pentax Q10 Pentax Q 5.53 Pentax 01 Standard Prime 8.5mm f/1.9 AL [IF] Pentax Q 5.53 4:3 lensfun-0.3.4/data/db/mil-samsung.xml000066400000000000000000000311751445356770400174720ustar00rootroot00000000000000 Samsung NX M42 M39/1 DKL T2 Generic Samsung NX mini M42 M39/1 DKL T2 Generic Samsung EK-GN120 Galaxy NX Samsung NX 1.531 Samsung NX10 Samsung NX 1.525 Samsung NX11 Samsung NX 1.525 Samsung NX100 Samsung NX 1.525 Samsung NX1000 Samsung NX 1.525 Samsung NX20 Samsung NX 1.525 Samsung NX200 Samsung NX 1.525 Samsung NX210 Samsung NX 1.525 Samsung NX300 Samsung NX 1.531 Samsung NX300M Samsung NX 1.531 Samsung NX500 Samsung NX 1.531 Samsung NX1100 Samsung NX 1.531 Samsung NX2000 Samsung NX 1.531 Samsung NX3000 Samsung NX 1.531 Samsung NX1 Samsung NX 1.531 Samsung NX5 Samsung NX 1.525 Samsung NX30 Samsung NX 1.531 Samsung NX mini Samsung NX mini 2.727 Samsung Samsung NX 20-50mm f/3.5-5.6 ED Samsung NX 1.528 Samsung Samsung NX 30mm f/2 Pancake Samsung NX 1.528 Samsung Samsung NX 16mm f/2.4 Pancake Samsung NX 1.525 Samsung Samsung NX 18-55mm f/3.5-5.6 OIS Samsung NX 1.531 Samsung Samsung NX 45mm f/1.8 2D/3D Samsung NX 1.525 Samsung Samsung NX 20mm f/2.8 Pancake Samsung NX 1.525 Samsung Samsung NX 16-50mm f/3.5-5.6 PZ ED OIS Samsung NX 1.525 Samsung Samsung NX 10mm f/3.5 Fisheye Samsung NX 10mm f/3.5 Fischauge Samsung NX equisolid 1.531 Samsung Samsung NX 50-200mm f/4-5.6 Samsung NX 1.531 Samsung Samsung NX 16-50mm f/2-2.8 S Samsung NX 1.531 Samsung Samsung NX 50-150mm F2.8 S Samsung NX 1.531 Samsung NX-M 9mm F3.53.5-5.6 Samsung NX-M 9mm f/3.5 ED Samsung NX mini 2.727 Samsung NX-M 9-27mm F3.5-5.6 Samsung NX-M 9-27mm f/3.5-5.6 ED OIS Samsung NX mini 2.727 lensfun-0.3.4/data/db/mil-samyang.xml000066400000000000000000000556151445356770400174610ustar00rootroot00000000000000 Samyang Samyang 7.5mm f/3.5 UMC Fish-eye MFT Samyang 7.5mm f/3.5 UMC Fischauge MFT Micro 4/3 System fisheye 2 4:3 Samyang Samyang 8mm f/2.8 UMC Fish-eye Samyang 8mm f/2.8 UMC Fischauge Sony E Fujifilm X Samsung NX stereographic 1.534 Samyang Samyang 50mm f/1.4 AS UMC Sony E 1.534 Samyang Samyang 12mm f/2.0 NCS CS Sony E Fujifilm X Micro 4/3 System Samsung NX Canon EF-M 1.534 Samyang Samyang AF 35mm f/2.8 Sony E 1.0 Samyang Samyang AF 14mm f/2.8 Samyang AF 14mm f/2.8 Sony E 1 Samyang Samyang AF 24mm f/2.8 Samyang AF 24mm f/2.8 Sony E 1 Samyang Samyang AF 45mm f/1.8 Sony E 1 Samyang Samyang AF 85mm f/1.4 Sony E 1 Samyang Samyang AF 24mm f/1.8 Sony E 1 Samyang Samyang AF 12mm f/2.0 Sony E Fujifilm X 1.534 Samyang Samyang AF 18mm f/2.8 Sony E 1 Samyang Samyang AF 75mm f/1.8 Sony E 1 Samyang Samyang AF 35mm f/1.8 Sony E 1 Samyang Samyang XP 10mm f/3.5 Canon EF 1.005 lensfun-0.3.4/data/db/mil-sigma.xml000066400000000000000000002234111445356770400171110ustar00rootroot00000000000000 Sigma Sigma fp fp Leica L 1 Sigma Sigma fp L fp L Leica L 1 Sigma sd Quattro Sigma SA 1.523 Sigma E 30mm f/2.8 Sigma 30mm f/2.8 EX DN Sony E Micro 4/3 System 1.534 Sigma Sigma 30mm f/2.8 EX DN Sony E Micro 4/3 System 2 4:3 Sigma Sigma 19mm f/2.8 EX DN Sony E Micro 4/3 System 2 4:3 Sigma Sigma 19mm f/2.8 EX DN Sony E Micro 4/3 System 1.534 Sigma Sigma 56mm F1.4 DC DN | C 018 Micro 4/3 System 2.0 Sigma Sigma 56mm F1.4 DC DN | Contemporary 018 Sigma 56 mm F1.4 DC DN | C 018 Sony E Fujifilm X Leica L Canon EF-M 1.534 Sigma Sigma 60mm f/2.8 DN Sony E Micro 4/3 System 2 4:3 Sigma Sigma 60mm f/2.8 DN Sony E Micro 4/3 System 1.534 Sigma Sigma 19mm f/2.8 DN Sony E Micro 4/3 System 1.534 Sigma Sigma 19mm f/2.8 DN Micro 4/3 System Sony E 2 4:3 Sigma SIGMA 30mm f/1.4 DC DN | Contemporary C 016 30mm f/1.4 DC DN Sony E Micro 4/3 System 1.534 Sigma Sigma 16mm f/1.4 DC DN | Contemporary C 017 Sigma 16mm f/1.4 DC DN C Micro 4/3 System Sony E 2 4:3 Sigma Sigma 16mm f/1.4 DC DN | Contemporary 017 Sigma 16mm f/1.4 DC DN Contemporary Micro 4/3 System Sony E Fujifilm X Leica L Canon EF-M 1.534 Sigma 105mm F1.4 DG HSM | Art 018 Sigma 105 mm F1.4 DG HSM Art Sony E Canon EF Leica L Nikon F AF Sigma SA 1 Sigma 35mm F1.2 DG DN | Art 019 Sony E 1 Sigma 14-24mm F2.8 DG DN | Art 019 Sony E Leica L 1 Sigma 85mm F1.4 DG DN | Art 020 Sony E Leica L 1 Sigma 105mm F2.8 DG DN MACRO | Art 020 Sony E Leica L 1.0 Sigma 18-50mm F2.8 DC DN | Contemporary 021 Sony E Leica L 1.534 Sigma 45mm F2.8 DG DN | Contemporary 019 Sony E Leica L 1.0 Sigma 40mm F1.4 DG HSM | Art 018 Sigma 40mm F1.4 DG HSM | Art Canon EF Leica L Sony E Nikon F AF Sigma SA 1.0 Sigma 20mm F2 DG DN | Contemporary 022 Sony E Leica L 1.0 Sigma 24mm F2 DG DN | Contemporary 021 Sony E Leica L 1.0 Sigma 24-70mm F2.8 DG DN | Art 019 Sony E Leica L 1.0 Sigma 35mm F2 DG DN | Contemporary 020 Sony E Leica L 1.0 Sigma 65mm F2 DG DN | Contemporary 020 Sony E Leica L 1.0 Sigma 90mm F2.8 DG DN | Contemporary 021 Sony E Leica L 1.0 Sigma 28-70mm F2.8 DG DN | Contemporary 021 Sony E Leica L 1.0 Sigma 16-28mm F2.8 DG DN | Contemporary 022 Sony E Leica L 1.0 lensfun-0.3.4/data/db/mil-sony.xml000066400000000000000000010206141445356770400170020ustar00rootroot00000000000000 Sony E M42 M39/1 DKL T2 Generic Sony NEX-3 Sony E 1.534 Sony NEX-C3 Sony E 1.534 Sony NEX-F3 Sony E 1.534 Sony NEX-3N Sony E 1.534 Sony NEX-5 Sony E 1.534 Sony NEX-5N Sony E 1.534 Sony NEX-5R Sony E 1.534 Sony NEX-5T Sony E 1.534 Sony NEX-6 Sony E 1.534 Sony NEX-7 Sony E 1.534 Sony ILCE-6000 Alpha 6000 Sony E 1.534 Sony ILCE-3000 Alpha 3000 Sony E 1.534 Sony ILCE-5000 Alpha 5000 Sony E 1.534 Sony ILCE-5100 Alpha 5100 Sony E 1.534 Sony ILCE-7 Alpha 7 Sony E 1 Sony ILCE-7R Alpha 7R Sony E 1 Sony ILCE-7RM2 Alpha 7R II Sony E 1 Sony ILCE-7M3 Alpha 7 III Sony E 1 Sony ILCE-7RM3 Alpha 7R III Sony E 1 Sony ILCE-7RM3A Alpha 7R IIIA Sony E 1 Sony ILCE-7M4 Alpha 7 IV Sony E 1 Sony ILCE-7RM4 Alpha 7R IV Sony E 1 Sony ILCE-7RM4A Alpha 7R IV A Sony E 1 Sony ILCE-7RM5 Alpha 7R V Sony E 1 Sony ILCE-7S Alpha 7S Sony E 1 Sony ILCE-7M2 Alpha 7 II Sony E 1 Sony ILCE-7C Alpha 7C Sony E 1 Sony ILCE-7SM2 Alpha 7S II Sony E 1 Sony ILCE-7SM3 Alpha 7S III Sony E 1 Sony ILCE-6100 Alpha 6100 Sony E 1.534 Sony ILCE-6300 Alpha 6300 Sony E 1.534 Sony ILCE-6400 Alpha 6400 Sony E 1.534 Sony ILCE-6500 Alpha 6500 Sony E 1.534 Sony ILCE-6600 Alpha 6600 Sony E 1.534 Sony ILCE-6700 Alpha 6700 Sony E 1.534 Sony ILCE-9 Alpha 9 Sony E 1 Sony ILCE-1 Alpha 1 Sony E 1 Sony ILME-FX3 FX3 Sony E 1 Sony ILME-FX30 FX30 Sony E 1.546 Sony ZV-E1 Sony E 1 Sony ZV-E10 Sony E 1.534 Sony E 16mm f/2.8 Sony E 1.534 Sony E 18-55mm f/3.5-5.6 OSS Sony E 1.534 Sony E 50mm f/1.8 OSS Sony E 1.534 Sony E 55-210mm f/4.5-6.3 OSS Sony E 1.534 Sony VCL-ECF1 fisheye converter VCL-ECF1 Fischauge-Vorsatz Sony E fisheye 1.534 Sony VCL-ECU1 ultra wide converter VCL-ECU1 Ultraweitwinkel-Vorsatz Sony E 1.534 Sony E 10-18mm f/4 OSS Sony E 1.534 Sony E 10-18mm f/4 OSS Sony E 1 Sony E 18-200mm f/3.5-6.3 OSS Sony E 1.534 Sony E 24mm f/1.8 ZA Sony E 1.534 Sony E 30mm f/3.5 Macro Sony E 1.534 Sony E PZ 16-50mm f/3.5-5.6 OSS E 16-50mm f/3.5-5.6 OSS PZ Sony E 1.534 Sony E 18-200mm f/3.5-6.3 OSS LE Sony E 1.534 Sony E 35mm f/1.8 OSS Sony E 1.534 Sony E 20mm f/2.8 Sony E 1.534 Sony E 16-70mm f/4 ZA OSS Sony E 1.534 Sony E PZ 18-105mm f/4 G OSS Sony E 1.534 Sony E 18-135mm f/3.5-5.6 OSS Sony E 1.534 Sony FE 28-70mm f/3.5-5.6 OSS Sony E 1 Sony FE 70-300mm f/4.5-5.6 G OSS Sony E 1 Sony FE 35mm f/1.4 ZA Sony E 1 Sony FE 35mm f/1.8 Sony E 1 Sony FE 55mm f/1.8 ZA Sony E 1 Sony FE 24-70mm f/4 ZA OSS Sony E 1.534 Sony FE 24-70mm f/4 ZA OSS Sony E 1 Sony FE 28mm f/2 Sony E 1 Sony FE 21mm f/2.8 FE 28mm f/2 + Sony SEL075 UWC Sony E 1 Sony FE 90mm f/2.8 Macro G OSS Sony E 1 Sony FE 24-240mm f/3.5-6.3 OSS Sony E 1 Sony FE 70-200mm f/4 G OSS Sony E 1 Sony FE 70-200mm f/2.8 GM OSS Sony E 1 Sony FE 16-35mm f/2.8 GM Sony E 1.0 Sony FE 16-35mm f/4 ZA OSS Sony E 1 Sony FE 85mm f/1.4 GM Sony E 1.0 Sony FE 85mm f/1.8 Sony E 1 Sony FE 24-70mm f/2.8 GM Sony E 1 Sony FE 24-105mm f/4 G OSS Sony E 1 Sony FE 35mm f/2.8 ZA Sony E 1 Sony FE 50mm f/1.8 Sony E 1 Sony FE 12-24mm f/4 G Sony E 1 Sony FE 100-400mm f/4.5-5.6 GM OSS Sony E 1 Sony E 16-55mm f/2.8 G Sony E 1.534 Sony E 70-350mm f/4.5-6.3 G OSS Sony E 1.534 Sony FE 200-600mm f/5.6-6.3 G OSS Sony E 1 Sony FE 20mm f/1.8 G Sony E 1 Sony FE 50mm f/2.5 G Sony E 1 Sony FE 24mm f/2.8 G Sony E 1 Sony FE 35mm f/1.4 GM (SEL35F14GM) Sony E 1 Sony FE 24mm f/1.4 GM Sony E 1 Sony FE 50mm f/2.8 Macro Sony E 1.0 Sony FE 50mm f/2.8 Macro Sony E 1.534 Sony E 11mm f/1.8 Sony E 1.534 Sony FE 14mm f/1.8 GM Sony E 1.0 Sony FE 40mm f/2.5 G Sony E 1.0 Sony FE 50mm f/1.2 GM Sony E 1.0 Sony FE 28-60mm f/4-5.6 Sony E 1.0 Sony FE 20-70mm f/4 G Sony E 1 Sony FE 24-70mm f/2.8 GM II Sony E 1.0 lensfun-0.3.4/data/db/mil-tamron.xml000066400000000000000000001452641445356770400173220ustar00rootroot00000000000000 Tamron E 17-70mm F2.8 B070 Sony E 1.534 4:3 Tamron Tamron 18-200mm f/3.5-6.3 Di III VC Sony E Canon EF-M 1.534 Tamron 14-150mm F/3.5-5.8 DiIII C001: Tamron 14-150mm f/3.5-5.8 Di III Micro 4/3 System 2 4:3 Tamron E 28-75mm F2.8-2.8 Sony E rectilinear 1 Tamron E 20mm F2.8 F050 Tamron 20mm F2.8 Di III OSD M1:2 Sony E rectilinear 1 Tamron E 17-28mm F2.8-2.8 Sony E 1 Tamron E 28-200mm F2.8-5.6 A071 Sony E 1 Tamron E 18-300mm F3.5-6.3 B061 Sony E 1.534 Tamron 18-300mm F3.5-6.3 DiIII-A VC VXD B061X Fujifilm X 1.534 Tamron E 70-180mm F2.8 A056 Tamron 70-180mm f/2.8 Di III VXD A056 Sony E 1.0 Tamron E 35mm F2.8 F053 Sony E 1.0 Tamron E 24mm F2.8 Sony E 1.5 Tamron E 150-500mm F5-6.7 A057 Tamron 150-500mm F5-6.7 Di III VC VXD Sony E 1.0 Tamron E 11-20mm F2.8 B060 Tamron 11-20 mm F2.8 Di III-A RXD (B060) Sony E 1.534 lensfun-0.3.4/data/db/mil-tokina.xml000066400000000000000000000016751445356770400173040ustar00rootroot00000000000000 Tokina E 20mm f/2 Sony E 1 Tokina Tokina AT-X M35 PRO DX (AF 35mm f/2.8 Macro) Nikon F AF Canon EF 1.534 lensfun-0.3.4/data/db/mil-zeiss.xml000066400000000000000000000452731445356770400171560ustar00rootroot00000000000000 Zeiss Touit 1.8/32 Touit 32mm f/1.8 Fujifilm X Sony E 1.534 Zeiss E 25mm f/2 Batis 25mm f/2 Sony E 1 Zeiss ZEISS Batis 2/25 Batis 25mm f/2 Sony E 1 Zeiss E 85mm F1.8 Batis 85mm f/1.8 Sony E 1 Zeiss E 50mm F2 Loxia 50mm f/2 Planar T* Sony E 1 Zeiss E 21mm F2.8 Loxia 21mm f/2.8 Sony E 1 Zeiss Zeiss Batis 2.8/18 Batis 18mm f/2.8 Sony E 1 Zeiss Touit 2.8/12 Fujifilm X Sony E 1.53 Zeiss Distagon 18mm f/4 Sony E 1 Zeiss Distagon 28mm f/2.8 MMJ Sony E 1 Zeiss Planar 50mm f/1.7 AEJ Sony E 1 Zeiss Sonnar 85mm f/2.8 AEJ Sony E 1 lensfun-0.3.4/data/db/misc.xml000066400000000000000000002356601445356770400161760ustar00rootroot00000000000000 M42 Tamron Adaptall Generic M39/1 Generic DKL Generic T2 Generic C Tamron Adaptall Generic Kiev 88 Generic Nokia Lumia 1020 lumia1020 3.93 Microsoft Lumia 950 lumia950 6.02 Microsoft Lumia 950 XL lumia950 6.02 SEIKO EPSON CORP. Epson R-D1 Leica M 1.525 LG Mobile LG LG-H815 LG G4 lgH815 6.34 Huawei VOG-L29 P30 Pro vogl29 4.86 Huawei CLT-L29 P20 Pro cltl29 4.55 Huawei WAS-LX1A P10 Lite waslx1a 6.88 Nokia Lumia 1520 lumia1520 6.26 Honor DLI-L22 6A dlil22 8.235 Apple iPhone XS iPhoneXS 6.118 Apple iPhone XS (tele) iPhoneXStele 8.667 Apple iPhone XS back camera 4.25mm f/1.8 & compatibles fixed lens festes Objektiv iPhoneXS 6.118 4:3 Apple iPhone XS back camera 6mm f/2.4 & compatibles fixed lens festes Objektiv iPhoneXStele 8.667 4:3 Fujian 35mm f/1.7 C 2 4:3 Zeiss Lumia 1020 fixed lens festes Objektiv lumia1020 3.93 16:9 Zeiss Lumia 950 fixed lens festes Objektiv lumia950 6.02 4:3 Pentacon Pentacon 50mm f/1.8 auto multi coating M42 1.526 Cosina Cosina Cosinon-S 50mm 1:2 Pentax K 1.538 Cosina 24mm 2.0 Macro Pentax K 1.526 Mitakon Mitakon wide MC f=24mm 1:2.8 Pentax K 1.538 Mitakon Mitakon Speedmaster 50mm f/0.95 III Sony E 1 Zenit Zenitar MC 16mm f/2.8 M42 Nikon F Canon EF Pentax K fisheye 1.529 Fotasy Fotasy M3517 35mm f/1.7 M42 1.529 Voigtländer Voigtländer Skoparex 1:3,4/35 DKL 1.529 Voigtländer Voigtländer Color-Skopar X 1:2,8/50 DKL 1.529 Cosina Cosina 19-35mm f/3.5-4.5 MC Canon EF Nikon F Sony Alpha Pentak K 1 Voigtländer Voigtlander Ultron 40mm f/2 SLII Aspherical Voigtländer Ultron 40mm f/2 SL-II Aspherical Nikon F AI-S 1 Voigtländer Nokton 25mm f/0.95 II Voigtländer Nokton 25mm f/0.95 Type II Micro 4/3 System 2.0 LG LG G4 & compatibles fixed lens festes Objektiv lgH815 6.34 16:9 Huawei P30 Pro fixed lens festes Objektiv vogl29 4.86 4:3 Huawei Huawei P20 Pro & compatibles fixed lens festes Objektiv cltl29 4.55 4:3 Huawei Huawei P10 Lite & compatibles fixed lens festes Objektiv waslx1a 6.88 4:3 Beroflex Beroflex 1:8 500mm T2 1.531 Yongnuo Yongnuo YN 35mm f/2 Canon EF 1.62 Yongnuo Yongnuo YN 50mm f/1.8 Canon EF 1 Yongnuo Yongnuo YN 50mm f/1.8 II Canon EF 1 Irix Irix 15mm f/2.4 Canon EF Nikon F Pentax KA 1 Arsenal MC Volna-3 80mm f/2.8 Kiev 88 1.523 Meike Meike 25mm f/1.8 Canon EF-M Fujifilm X Micro 4/3 System Nikon CX Sony E 1.534 Meike Meike 35mm f/1.7 Fujifilm X Sony E 1.528 Meike Meike 50mm F1.2 Nikon Z 1.0 Meike Meike 50mm f/2.0 Fujifilm X Micro 4/3 System Sony E Nikon CX Canon EF-M 1.528 Meike Meike 28mm f/2.8 Fujifilm X Micro 4/3 System Sony E Nikon CX Canon EF-M 1.529 Zeiss Standard lumia1520 6.26 16:9 Miranda Miranda 28mm f/2.8 MC Contax/Yashica Canon FD M42 Nikon F Pentax K Minolta MD 1 Petri Auto Petri 1:2.8 f=28mm M42 1.529 Venus Laowa 12mm f/2.8 Zero-D Canon EF Nikon F Pentax KAF3 Sony Alpha Sony E 1 Venus Laowa 9mm f/2.8 Zero-D Fujifilm X Sony E Canon EF-M Micro 4/3 System Nikon Z Leica L 1.529 Venus Laowa 7.5mm f/2.0 Micro 4/3 System 2 Venus Laowa 17mm f/1.8 C-Dreamer Micro 4/3 System 2.0 Venus Laowa 60mm f/2.8 2X Ultra-Macro Canon EF Nikon F Pentax K Sony Alpha Sony E 1 TTArtisan TTArtisan APS-C 23mm F1.4 Sony E Fujifilm X Canon EF-M Canon RF Nikon Z Micro 4/3 System Leica L 1.534 Chinon Auto Chinon 35mm f/2.8 M42 Sony E 1 Chinon Chinon 75-205mm f/3.8 M42 1 Voigtländer Voigtlander Super Wide-Heliar 15mm f/4.5 III 15mm F4,5 Super Wide Heliar aspherical III Sony E 1 SLR Magic SLR Magic 8mm f/4 Micro 4/3 System 2 4:3 Opteka Opteka 15mm f/4 Wide Macro 1:1 Nikon F Canon EF 1 Honor Honor 6A & compatibles fixed lens festes Objektiv dlil22 8.235 4:3 Voigtländer Voigtlander HELIAR-HYPER WIDE 10mm F5.6 Voigtländer HELIAR-HYPER WIDE 10mm F5.6 Sony E 1 Viltrox Viltrox AF 85mm f/1.8 Z Nikon Z 1 Viltrox 23mmF1.4XM Fujifilm X 1.53 Viltrox Viltrox 23mm F1.4 E Sony E 1.53 Pentacon Pentacon electric 2.8/29mm Sony E 1 Meyer Optik Görlitz Meyer Optik Görlitz 3.5/30mm Sony E 1 Voigtländer Voigtlander APO-LANTHAR 50mm F2 Aspherical Sony E Nikon Z 1.0 Voigtländer Voigtlander Color Skopar 20mm F3.5 SLII Aspherical Pentax KAF4 Canon EF Nikon F AF 1 Rollei Rollei Rolleinar MC f/4 21mm Sony E 1 Rollei Rollei Rolleinar MC f/2.8 28mm Sony E 1 Kipon Elegant 35mm F/2.4 Nikon Z 1 lensfun-0.3.4/data/db/om-system.xml000066400000000000000000000037061445356770400171720ustar00rootroot00000000000000 OM Digital Solutions OM System OM-1 Micro 4/3 System 2 OM Digital Solutions OM System OM-5 Micro 4/3 System 2 OM Digital Solutions OM System OM 20mm F1.4 Micro 4/3 System 2 lensfun-0.3.4/data/db/rf-leica.xml000066400000000000000000000067551445356770400167260ustar00rootroot00000000000000 Leica M M42 M39/1 DKL T2 Generic Leica Camera AG Leica M (Typ 240) Leica M 1 Leica Camera AG Leica M Monochrom (Typ 246) Leica M 1 Leica Camera AG M9 Digital Camera Leica M 1 Leica Camera AG Leica M10 Leica M 1 Leica Camera AG Leica M10 Monochrom Leica M 1 Leica Camera AG Leica M10-P Leica M 1 Leica Camera AG Leica M10-R Leica M 1 Leica Camera AG Leica M11 Leica M 1 Leica Camera AG Leica M11 Monochrom Leica M 1 Leica Camera AG Elmarit-M 1:2.8/28 ASPH. Elmarit-M 28mm f/2.8 ASPH Leica M 1 Leica Camera AG Elmarit-M 1:2.8/90 Elmarit-M 90mm f/2.8 Leica M 1 Leica Camera AG Summicron-M 1:2/50 Summicron-M 50mm f/2 Leica M 1 Leica Camera AG Summicron-M 1:2/28 ASPH. Leica M 1 lensfun-0.3.4/data/db/slr-canon.xml000066400000000000000000025350731445356770400171420ustar00rootroot00000000000000 Canon EF-S Canon EF M42 M39/1 DKL T2 Tamron Adaptall Generic Canon EF M42 M39/1 DKL T2 Tamron Adaptall Generic Canon FD Canon FL M42 M39/1 DKL T2 Tamron Adaptall Generic Canon FL M42 M39/1 DKL T2 Generic Canon Canon EOS 5DS EOS 5DS Canon EF 1 Canon Canon EOS 5DS R EOS 5DS R Canon EF 1 Canon Canon EOS 6D EOS 6D Canon EF 1.005 Canon Canon EOS 6D Mark II EOS 6D Mark II Canon EF 1.005 Canon Canon EOS 5D Mark IV EOS 5D Mark IV Canon EF 1 Canon Canon EOS 5D Mark III EOS 5D Mark III Canon EF 1 Canon Canon EOS 5D Mark II EOS 5D Mark II Canon EF 1 Canon Canon EOS 5D EOS 5D Canon EF 1 Canon Canon EOS-1Ds EOS-1Ds Canon EF 1 Canon Canon EOS-1Ds Mark II EOS-1Ds Mark II Canon EF 1 Canon Canon EOS-1D Mark II EOS-1D Mark II Canon EF 1.255 Canon Canon EOS-1D Mark II N EOS-1D Mark II N Canon EF 1.255 Canon Canon EOS-1Ds Mark III EOS-1Ds Mark III Canon EF 1 Canon Canon EOS-1D Mark III EOS-1D Mark III Canon EF 1.282 Canon Canon EOS-1D Mark IV EOS-1D Mark IV Canon EF 1.290 Canon Canon EOS-1D EOS-1D Canon EF 1.255 Canon Canon EOS-1D X EOS-1D X Canon EF 1 Canon Canon EOS-1D X Mark II EOS-1D X Mark II Canon EF 1 Canon Canon EOS 1000D EOS 1000D Canon EF-S 1.622 Canon Canon EOS DIGITAL REBEL XS EOS Digital Rebel XS Canon EF-S 1.622 Canon Canon EOS Kiss Digital F EOS Kiss Digital F Canon EF-S 1.622 Canon Canon EOS 1100D EOS 1100D Canon EF-S 1.620 Canon Canon EOS REBEL T3 EOS Rebel T3 Canon EF-S 1.620 Canon Canon EOS Kiss X50 EOS Kiss X50 Canon EF-S 1.620 Canon Canon EOS 300D DIGITAL EOS 300D Canon EF-S 1.587 Canon Canon EOS DIGITAL REBEL EOS Digital REBEL Canon EF-S 1.587 Canon Canon EOS Kiss Digital EOS Kiss Digital Canon EF-S 1.587 Canon Canon EOS 350D DIGITAL EOS 350D Canon EF-S 1.622 Canon Canon EOS DIGITAL REBEL XT EOS Digital Rebel XT Canon EF-S 1.622 Canon Canon EOS Kiss Digital N EOS Kiss Digital N Canon EF-S 1.622 Canon Canon EOS 400D DIGITAL EOS 400D Canon EF-S 1.622 Canon Canon EOS DIGITAL REBEL XTi EOS Digital Rebel XTi Canon EF-S 1.622 Canon Canon EOS Kiss Digital X EOS Kiss Digital X Canon EF-S 1.622 Canon Canon EOS 450D EOS 450D Canon EF-S 1.622 Canon Canon EOS DIGITAL REBEL XSi EOS Digital Rebel XSi Canon EF-S 1.622 Canon Canon EOS Kiss Digital X2 EOS Kiss Digital X2 Canon EF-S 1.622 Canon Canon EOS 500D EOS 500D Canon EF-S 1.613 Canon Canon EOS REBEL T1i EOS Rebel T1i Canon EF-S 1.613 Canon Canon EOS Kiss X3 EOS Kiss X3 Canon EF-S 1.613 Canon Canon EOS 550D EOS 550D Canon EF-S 1.613 Canon Canon EOS REBEL T2i EOS Rebel T2i Canon EF-S 1.613 Canon Canon EOS Kiss X4 EOS Kiss X4 Canon EF-S 1.613 Canon Canon EOS 600D EOS 600D Canon EF-S 1.613 Canon Canon EOS REBEL T3i EOS Rebel T3i Canon EF-S 1.613 Canon Canon EOS Kiss X5 EOS Kiss X5 Canon EF-S 1.613 Canon Canon EOS 650D EOS 650D Canon EF-S 1.613 Canon Canon EOS REBEL T4i EOS Rebel T4i Canon EF-S 1.613 Canon Canon EOS Kiss X6i EOS Kiss X6i Canon EF-S 1.613 Canon Canon EOS 700D EOS 700D Canon EF-S 1.613 Canon Canon EOS REBEL T5i EOS Rebel T5i Canon EF-S 1.613 Canon Canon EOS 800D EOS 800D Canon EF-S 1.613 Canon Canon EOS REBEL T7i EOS Rebel T7i Canon EF-S 1.613 Canon Canon EOS Kiss X7i EOS Kiss X7i Canon EF-S 1.613 Canon Canon EOS 750D EOS 750D Canon EF-S 1.613 Canon Canon EOS Rebel T6i EOS Rebel T6i Canon EF-S 1.613 Canon Canon EOS Kiss X8i EOS Kiss X8i Canon EF-S 1.613 Canon Canon EOS 760D EOS 760D Canon EF-S 1.613 Canon Canon EOS Rebel T6s EOS Rebel T6s Canon EF-S 1.613 Canon Canon EOS 8000D EOS 8000D Canon EF-S 1.613 Canon Canon EOS Kiss X9i EOS Kiss X9i Canon EF-S 1.613 Canon Canon EOS 850D EOS 850D Canon EF-S 1.613 Canon Canon EOS Rebel T8i EOS Rebel T8i Canon EF-S 1.613 Canon Canon EOS Kiss X10i EOS Kiss X10i Canon EF-S 1.613 Canon Canon EOS 9000D EOS 9000D Canon EF-S 1.613 Canon Canon EOS 1200D EOS 1200D Canon EF-S 1.620 Canon Canon EOS REBEL T5 EOS Rebel T5 Canon EF-S 1.620 Canon Canon EOS Kiss X70 EOS Kiss X70 Canon EF-S 1.620 Canon Canon EOS 1300D EOS 1300D Canon EF-S 1.620 Canon Canon EOS Rebel T6 EOS Rebel T6 Canon EF-S 1.620 Canon Canon EOS 2000D EOS 2000D Canon EF-S 1.613 Canon Canon EOS Kiss X90 EOS Kiss X90 Canon EF-S 1.613 Canon Canon EOS Rebel T7 EOS Rebel T7 Canon EF-S 1.613 Canon Canon EOS 4000D EOS 4000D Canon EF-S 1.613 Canon Canon EOS Rebel T100 EOS Rebel T100 Canon EF-S 1.613 Canon Canon EOS 100D EOS 100D Canon EF-S 1.613 Canon Canon EOS REBEL SL1 EOS Rebel SL1 Canon EF-S 1.613 Canon Canon EOS Kiss X7 EOS Kiss X7 Canon EF-S 1.613 Canon Canon EOS 200D EOS 200D Canon EF-S 1.613 Canon Canon EOS REBEL SL2 EOS Rebel SL2 Canon EF-S 1.613 Canon Canon EOS 250D EOS 250D Canon EF-S 1.613 Canon Canon EOS REBEL SL3 EOS Rebel SL3 Canon EF-S 1.613 Canon Canon EOS 200D II EOS 200D II Canon EF-S 1.613 Canon Canon EOS Kiss X9 EOS Kiss X9 Canon EF-S 1.613 Canon Canon EOS 7D EOS 7D Canon EF-S 1.620 Canon Canon EOS 7D Mark II EOS 7D Mark II Canon EF-S 1.605 Canon Canon EOS 90D EOS 90D Canon EF-S 1.613 Canon Canon EOS 80D EOS 80D Canon EF-S 1.613 Canon Canon EOS 77D EOS 77D Canon EF-S 1.613 Canon Canon EOS 70D EOS 70D Canon EF-S 1.600 Canon Canon EOS 60D EOS 60D Canon EF-S 1.620 Canon Canon EOS 50D EOS 50D Canon EF-S 1.622 Canon Canon EOS 40D EOS 40D Canon EF-S 1.622 Canon Canon EOS 30D EOS 30D Canon EF-S 1.600 Canon Canon EOS 20D EOS 20D Canon EF-S 1.600 Canon Canon EOS 10D EOS 10D Canon EF-S 1.587 Canon Canon EOS D60 EOS D60 Canon EF-S 1.587 Canon Canon EOS D30 EOS D30 Canon EF-S 1.587 Canon 35mm film: full frame Canon EF 1 Kodak DCS Pro SLR/c Canon EF 1 Kodak DCS520 DCS 520 Canon EF 1.593 Canon EOS D2000 Canon EF 1.593 Canon Canon EF-S 10-22mm f/3.5-4.5 USM Canon EF-S 1.613 Canon Canon EF 16-35mm f/2.8L USM Canon EF 1 Canon Canon EF 16-35mm f/2.8L II USM Canon EF 1 Canon Canon EF 16-35mm f/2.8L III USM Canon EF 1 Canon Canon EF 17-35mm f/2.8L USM Canon EF 1 Canon Canon EF 17-40mm f/4L USM Canon EF 1 Canon Canon EF-S 17-55mm f/2.8 IS USM Canon EF-S 1.622 Canon Canon EF-S 17-85mm f/4-5.6 IS USM Canon EF-S 1.611 Canon Canon EF-S 18-55mm f/3.5-5.6 Canon EF-S 1.611 Canon Canon EF-S 18-55mm f/3.5-5.6 IS II Canon EF-S 1.611 Canon Canon EF-S 18-55mm f/3.5-5.6 III Canon EF-S 1.611 Canon Canon EF-S 18-55mm f/3.5-5.6 IS STM Canon EF-S 1.613 Canon Canon EF 20mm f/2.8 USM Canon EF 1 Canon Canon EF 24-70mm f/2.8L USM Canon EF 1 Canon Canon EF 24-85mm f/3.5-4.5 USM Canon EF 1 Canon Canon EF 24-85mm f/3.5-4.5 USM Canon EF 1.611 Canon Canon EF 28-70mm f/2.8L USM Canon EF 1.611 Canon Canon EF 24-105mm f/4L IS USM Canon EF 1 Canon Canon EF 24-105mm f/4L IS USM Canon EF 1.611 Canon Canon EF 28-105mm f/3.5-4.5 II USM Canon EF 1 Canon Canon EF 28-300mm f/3.5-5.6L IS USM Canon EF 1 Canon Canon EF 28-135mm f/3.5-5.6 IS USM Canon EF 1 Canon Canon EF 35mm f/1.4L USM Canon EF 1 Canon EF35mm f/1.4L II USM (750) Canon EF 35mm f/1.4L II USM Canon EF 1.605 Canon Canon EF 35mm f/2 IS USM Canon EF 1.005 Canon Canon EF 35mm f/2 IS USM Canon EF 1.613 Canon Canon EF 35-70mm f/3.5-4.5 Canon EF 1.611 Canon Canon EF 35-80mm f/4-5.6 III Canon EF 1.611 Canon Canon EF 35-105mm f/3.5-4.5 Canon EF 1.005 Canon Canon EF 35-105mm f/3.5-4.5 Canon EF 1.611 Canon Canon EF 35-105mm f/4.5-5.6 Canon EF 1.611 Canon Canon EF 35-135mm f/4-5.6 USM Canon EF 1.611 Canon Canon EF 50mm f/1.4 USM Canon EF 1 Canon Canon EF 55-200mm f/4.5-5.6 Canon EF 1.611 Canon Canon EF-S 55-250mm f/4-5.6 IS Canon EF-S 1.611 Canon Canon EF-S 55-250mm f/4-5.6 IS II Canon EF-S 1.611 Canon Canon EF-S 55-250mm f/4-5.6 IS STM Canon EF-S 1.611 Canon Canon EF 70-200mm f/2.8L USM Canon EF 1 Canon Canon EF 70-200mm f/2.8L IS USM Canon EF 1 Canon Canon EF 70-200mm f/2.8L IS USM Canon EF 1.62 Canon Canon EF 70-200mm f/2.8L IS USM + EF 1.4x extender Canon EF 70-200mm f/2.8L IS USM + EF 1.4× ext. Canon EF 70-200mm f/2.8L IS USM + EF 1,4×-Konv. Canon EF 1 Canon Canon EF 70-200mm f/2.8L IS II USM Canon EF 1 Canon Canon EF 70-200mm f/2.8L IS II USM + EF 2x extender III Canon EF 70-200mm f/2.8L IS II USM + EF 2× III ext. Canon EF 70-200mm f/2.8L IS II USM + EF-2×-III-Konv. Canon EF 1 Canon Canon EF 70-200mm f/2.8L IS USM + EF 2x II extender Canon EF 70-200mm f/2.8L IS USM + EF 2× II ext. Canon EF 70-200mm f/2.8L IS USM + EF-2×-II-Konv. Canon EF 1.62 Canon Canon EF 70-200mm f/4L USM Canon EF 1 Canon Canon EF 70-200mm f/4L USM + EF 1.4x extender Canon EF 70-200mm f/4L USM + EF 1.4× ext. Canon EF 70-200mm f/4L USM + EF 1,4×-Konv. Canon EF 1 Canon Canon EF 70-200mm f/4L IS USM Canon EF 1 Canon Canon EF 70-200mm f/4L IS USM Canon EF 1.613 Canon Canon EF 70-300mm f/4.5-5.6 DO IS USM Canon EF 1 Canon Canon EF 70-300mm f/4-5.6 IS USM Canon EF 1.611 Canon Canon EF 75-300mm f/4-5.6 IS USM Canon EF 1.611 Canon Canon EF 80-200mm f/2.8L Canon EF 1 Canon Canon EF 85mm f/1.2L II USM Canon EF 1 Canon Canon EF 100mm f/2.8 Macro USM Canon EF 1 Canon Canon EF 100-200mm f/4.5A Canon EF 1.005 Canon Canon EF 100-300mm f/5.6L Canon EF 1 Canon Canon EF 100-400mm f/4.5-5.6L IS USM Canon EF 1.611 Canon Canon EF 100-400mm f/4.5-5.6L IS USM Canon EF 1 Canon Canon EF 100-400mm f/4.5-5.6L IS II USM Canon EF 1 Canon Canon EF 100-400mm f/4.5-5.6L IS II USM Canon EF 1.613 Canon Canon EF 24mm f/1.4L USM Canon EF 1 Canon Canon EF 24mm f/2.8 Canon EF 1 Canon Canon EF 28mm f/1.8 Canon EF 1.611 Canon Canon EF 28mm f/1.8 USM Canon EF 1 Canon Canon EF 28mm f/2.8 Canon EF 1.611 Canon Canon EF 35mm f/2 Canon EF 1 Canon Canon EF 50mm f/1.2L USM Canon EF 1 Canon Canon EF 50mm f/1.4 USM Canon EF 1.611 Canon Canon EF 50mm f/1.8 Canon EF 1.267 Canon Canon EF 50mm f/1.8 Canon EF 1.613 Canon Canon EF 50mm f/1.8 MkII Canon EF 50mm f/1.8 II Canon EF 1 Canon Canon EF 50mm f/1.8 MkII Canon EF 50mm f/1.8 II Canon EF 1.267 Canon Canon EF 50mm f/1.8 MkII Canon EF 50mm f/1.8 II Canon EF 1.622 Canon Canon FDn 50mm 1:1.4 Canon FD 2 Canon Canon FDn 50mm 1:1.4 Canon FD 1.534 Canon Canon EF-S 60mm f/2.8 Macro USM Canon EF-S 1.611 Canon Canon EF 85mm f/1.2L USM Canon EF 1 Canon Canon EF 85mm f/1.8 USM Canon EF 1 Canon Canon EF 100mm f/2.8L Macro IS USM Canon EF 1 Canon Canon EF 100mm f/2.8L Macro IS USM Canon EF 1.605 Canon Canon EF 100mm f/2.8 Macro Canon EF 1.611 Canon Canon FDn 100mm 1:2.8 Canon FD 2 Canon Canon EF 135mm f/2L Canon EF 135mm f/2 L USM Canon EF 1 Canon Canon EF 135mm f/2.8 Soft Focus Canon EF 1.267 Canon Canon EF 200mm f/2.8L USM Canon EF 1 Canon Canon EF 200mm f/2.8L II USM Canon EF 1.611 Canon Canon TS-E 24mm f/3.5L Canon EF 1 Canon Canon TS-E 24mm f/3.5L Canon EF 1.622 Canon Canon TS-E 45mm f/2.8 Canon EF 1 Canon Canon TS-E 90mm f/2.8 Canon EF 1 Canon Canon EF-S 18-135mm f/3.5-5.6 IS Canon EF-S 1.613 Canon Canon EF-S 18-135mm f/3.5-5.6 IS USM Canon EF-S 18-135mm f/3.5-5.6 IS USM Canon EF-S 1.605 Canon Canon EF-S 18-135mm f/3.5-5.6 IS STM Canon EF-S 1.613 Canon Canon EF-S 18-55mm f/3.5-5.6 IS Canon EF-S 1.622 Canon Canon EF 24-70mm f/2.8L II USM Canon EF 1 Canon Canon EF-S 15-85mm f/3.5-5.6 IS USM Canon EF-S 1.613 Canon Canon EF 50-200mm f/3.5-4.5L Canon EF 1.622 Canon Canon EF 50-200mm f/3.5-4.5L Canon EF 1 Canon Canon EF 70-300mm f/4-5.6L IS USM Canon EF 1.605 Canon Canon EF 70-300mm f/4-5.6L IS USM Canon EF 1 Canon Canon EF 90-300mm f/4.5-5.6 Canon EF 1.005 Canon Canon EF-S 18-200mm f/3.5-5.6 IS Canon EF-S 1.620 Canon Canon EF 28-80mm f/3.5-5.6 USM IV Canon EF 1.613 Canon Canon EF 400mm f/5.6L USM Canon EF 1.005 Canon Canon EF 400mm f/5.6L USM + 1.4x extender Canon EF 400mm f/5.6L USM + EF 1.4× ext. Canon EF 400mm f/5.6L USM + EF 1,4×-Konv. Canon EF 1.005 Canon Canon EF 300mm f/2.8L IS II USM Canon EF 1 Canon Canon EF 300mm f/2.8L IS II USM Canon EF 1.6 Canon Canon EF 300mm f/2.8L IS II USM + EF 1.4x extender III Canon EF 300mm f/2.8L IS II USM + EF 1.4× ext. III Canon EF 300mm f/2.8L IS II USM + EF 1,4×-Konv. III Canon EF 1 Canon Canon EF 300mm f/2.8L IS II USM + EF 1.4x extender III Canon EF 300mm f/2.8L IS II USM + EF 1.4× ext. III Canon EF 300mm f/2.8L IS II USM + EF 1,4×-Konv. III Canon EF 1.6 Canon Canon EF 300mm f/2.8L IS II USM + EF 2.0x extender III Canon EF 300mm f/2.8L IS II USM + EF 2.0× ext. III Canon EF 300mm f/2.8L IS II USM + EF 2,0×-Konv. III Canon EF 1 Canon Canon EF 300mm f/2.8L IS II USM + EF 2.0x extender III Canon EF 300mm f/2.8L IS II USM + EF 2.0× ext. III Canon EF 300mm f/2.8L IS II USM + EF 2,0×-Konv. III Canon EF 1.6 Canon Canon EF 300mm f/4L IS USM Canon EF 1.605 Canon Canon EF 300mm f/4L IS USM + 1.4x extender Canon EF 300mm f/4L IS USM + 1.4× ext. Canon EF 300mm f/4L IS USM + 1.4×-Konv. Canon EF 1.605 Canon Canon EF 500mm f/4L IS II USM Canon EF 1 Canon Canon EF 500mm f/4L IS II USM Canon EF 1.6 Canon Canon EF 500mm f/4L IS II USM + EF 1.4x extender III Canon EF 500mm f/4L IS II USM + EF 1.4× ext. III Canon EF 500mm f/4L IS II USM + EF 1.4×-Konv. III Canon EF 1 Canon Canon EF 500mm f/4L IS II USM + EF 1.4x extender III Canon EF 500mm f/4L IS II USM + EF 1.4× ext. III Canon EF 500mm f/4L IS II USM + EF 1.4×-Konv. III Canon EF 1.6 Canon Canon EF 500mm f/4L IS II USM + EF 2.0x extender III Canon EF 500mm f/4L IS II USM + EF 2.0× ext. III Canon EF 500mm f/4L IS II USM + EF 2.0×-Konv. III Canon EF 1 Canon Canon EF 500mm f/4L IS II USM + EF 2.0x extender III Canon EF 500mm f/4L IS II USM + EF 2.0× ext. III Canon EF 500mm f/4L IS II USM + EF 2.0×-Konv. III Canon EF 1.6 Canon Canon Lens FL 50mm F1.4 Canon FL 1.529 Canon Canon Lens FL 135mm F3.5 Canon FL 1.529 Canon Canon FDn 135mm 1:2.8 Canon FD 1.534 Canon Canon EF 16-35mm f/4L IS USM Canon EF 1.0 Canon Canon EF 70-210mm f/3.5-4.5 USM Canon EF 1 Canon Canon EF 24-70mm f/4L IS USM Canon EF 1 Canon Canon EF 24-70mm f/4L IS USM Canon EF 1.600 Canon Canon EF-S 10-18mm f/4.5-5.6 IS STM Canon EF-S 1.62 Canon Canon EF-S 24mm f/2.8 STM Canon EF-S 1.622 Canon Canon FDn 24mm 1:2.8 Canon FD 1.529 Canon Canon FDn 50mm 1:1.8 Canon FD 1.529 Canon Canon EF 40mm f/2.8 STM Canon EF 1 Canon Canon EF 14mm f/2.8L II USM Canon EF 1 Canon Canon EF 8-15mm f/4L Fisheye USM Canon EF 8-15mm f/4L Fischauge USM Canon EF equisolid 1 Canon Canon EF 50mm f/1.8 STM Canon EF 1.005 Canon Canon EF 50mm f/1.8 STM Canon EF 1.613 Canon Canon EF 50mm f/2.5 Compact Macro Canon EF 1 Canon Canon FDn 200mm 1:4 Canon FD 1.534 Canon Canon FD 200mm f/2.8 S.S.C. Canon FD 1.534 Canon Canon EF 24mm f/2.8 IS USM Canon EF 1.613 Canon EF-S18-55mm f/4-5.6 IS STM Canon EF-S 18-55mm f/4-5.6 IS STM Canon EF-S 1.613 Canon Canon EF 24-105mm f/4L IS II USM Canon EF 1.0 Canon Canon EF 24-105mm f/4L IS II USM Canon EF 1.605 Canon Canon EF 24mm f/1.4L II USM Canon EF 1.005 Canon Canon EF 22-55mm f/4-5.6 USM Canon EF 1.613 Canon Canon FD 50mm f/1.4 S.C.C. Canon FD 1 Canon Canon EF 15mm f/2.8 Fisheye Canon EF 1.0 Canon Canon EF 24-105mm f/3.5-5.6 IS STM Canon EF 1.0 Canon Canon EF 85mm f/1.4L IS USM Canon EF 1 Canon Canon EF 80-200mm f/4.5-5.6 Canon EF 1 Canon Canon EF 28mm f/2.8 Canon EF 1.0 Canon Canon EF 75-300mm F4-5.6 III Canon EF-S 1.613 Canon Canon EF 70-210mm f/4 Canon EF 1.005 Canon Canon EF 28-80mm f/3.5-5.6 USM Canon EF 1.0 lensfun-0.3.4/data/db/slr-hasselblad.xml000066400000000000000000000011071445356770400201260ustar00rootroot00000000000000 Hasselblad 500 Generic Hasselblad H Generic Hasselblad Hasselblad 500 mech. Hasselblad 500 0.66 Hasselblad Hasselblad H3D Hasselblad H 0.72 lensfun-0.3.4/data/db/slr-konica-minolta.xml000066400000000000000000001232671445356770400207450ustar00rootroot00000000000000 Minolta AF Sony Alpha M42 M39/1 DKL T2 Generic Minolta MC Minolta MD M42 M39/1 DKL T2 Tamron Adaptall Generic Minolta MD Minolta MC M42 M39/1 DKL T2 Tamron Adaptall Generic Konica Minolta Maxxum 5D Minolta AF 1.531 Konica Minolta Dynax 5D Minolta AF 1.531 Konica Minolta Maxxum 7D Minolta AF 1.522 Konica Minolta Dynax 7D Minolta AF 1.522 Konica Minolta KM 24-105mm f/3.5-4.5 AF D Minolta AF 1.526 Konica Minolta KM 28-100mm f/3.5-5.6 AF D Minolta AF 1.526 Konica Minolta KM 80-200mm f/2.8 Minolta AF 1.526 Konica Minolta KM 20mm f/2.8 Minolta AF 1.526 Minolta Minolta MC Rokkor-PG 50mm 1:1.4 Minolta MC 2 Minolta Minolta AF 35-105mm f/3.5-4.5 Minolta AF 1.523 Minolta Minolta MD 35mm 1/2.8 Minolta MD 1.529 Minolta Minolta MD Rokkor 50mm 1:1.4 Minolta MD 1.534 Minolta Minolta AF 135mm f/2.8 Minolta AF 1 Minolta Minolta AF 100-300mm f/4.5-5.6 APO (D) Minolta AF 1 Minolta Minolta AF 85mm f/1.4G (D) Minolta AF 1 Minolta Minolta AF 28-75mm F2.8 (D) Minolta AF 1 Minolta Minolta AF 50mm f/2.8 Macro Minolta AF 1 Minolta Minolta AF 50mm f/1.4 Minolta AF 1 Minolta Minolta AF 50mm f/1.7 Minolta AF 1.523 Minolta Minolta AF 17-35mm f/2.8-4 (D) Minolta AF 1 Minolta Minolta/Sony AF 24-105mm f/3.5-4.5 (D) Minolta AF 1 Minolta Minolta AF 70-210mm f/4 Macro Minolta AF 1 lensfun-0.3.4/data/db/slr-leica.xml000066400000000000000000000005671445356770400171120ustar00rootroot00000000000000 Leica R M42 M39/1 DKL T2 Tamron Adaptall Generic Leica S Generic lensfun-0.3.4/data/db/slr-nikon.xml000066400000000000000000017423521445356770400171610ustar00rootroot00000000000000 Nikon F Nikon F AI Nikon F AI-S Nikon F AF M42 M39/1 DKL T2 Tamron Adaptall Generic Nikon F AI Nikon F Nikon F AI-S Nikon F AF M42 M39/1 DKL T2 Tamron Adaptall Generic Nikon F AI-S Nikon F Nikon F AI Nikon F AF M42 M39/1 DKL T2 Tamron Adaptall Generic Nikon F AF Nikon F Nikon F AI Nikon F AI-S M42 M39/1 DKL T2 Generic Nikon Corporation Nikon Nikon D40 D40 Nikon F AF 1.525 Nikon Corporation Nikon Nikon D40X D40X Nikon F AF 1.523 Nikon Corporation Nikon Nikon D50 D50 Nikon F AF 1.525 Nikon Corporation Nikon Nikon D60 D60 Nikon F AF 1.523 Nikon Corporation Nikon Nikon D70 D70 Nikon F AF 1.525 Nikon Corporation Nikon Nikon D70s D70s Nikon F AF 1.525 Nikon Corporation Nikon Nikon D80 D80 Nikon F AF 1.523 Nikon Corporation Nikon Nikon D90 D90 Nikon F AF 1.523 Nikon Corporation Nikon Nikon D100 D100 Nikon F AF 1.525 Nikon Corporation Nikon Nikon D200 D200 Nikon F AF 1.523 Nikon Corporation Nikon Nikon D300 D300 Nikon F AF 1.523 Nikon Corporation Nikon Nikon D300S D300S Nikon F AF 1.523 Nikon Corporation Nikon Nikon D500 D500 Nikon F AF 1.531 Nikon Corporation Nikon Nikon D600 D600 Nikon F AF 1 Nikon Corporation Nikon Nikon D610 D610 Nikon F AF 1 Nikon Corporation Nikon Nikon D700 D700 Nikon F AF 1 Nikon Corporation Nikon Nikon D750 D750 Nikon F AF 1 Nikon Corporation Nikon Nikon D780 D780 Nikon F AF 1 Nikon Corporation Nikon Nikon D800 D800 Nikon F AF 1 Nikon Corporation Nikon Nikon D800E D800E Nikon F AF 1 Nikon Corporation Nikon Nikon D810 D810 Nikon F AF 1 Nikon Corporation Nikon Nikon D850 D850 Nikon F AF 1 Nikon Corporation Nikon Nikon D3000 D3000 Nikon F AF 1.523 Nikon Corporation Nikon Nikon D3100 D3100 Nikon F AF 1.558 Nikon Corporation Nikon Nikon D3200 D3200 Nikon F AF 1.554 Nikon Corporation Nikon Nikon D3300 D3300 Nikon F AF 1.523 Nikon Corporation Nikon Nikon D3400 D3400 Nikon F AF 1.523 Nikon Corporation Nikon Nikon D3500 D3500 Nikon F AF 1.523 Nikon Corporation Nikon Nikon D5000 D5000 Nikon F AF 1.523 Nikon Corporation Nikon Nikon D5100 D5100 Nikon F AF 1.523 Nikon Corporation Nikon Nikon D5200 D5200 Nikon F AF 1.534 Nikon Corporation Nikon Nikon D5300 D5300 Nikon F AF 1.534 Nikon Corporation Nikon Nikon D5500 D5500 Nikon F AF 1.534 Nikon Corporation Nikon Nikon D5600 D5600 Nikon F AF 1.534 Nikon Corporation Nikon Nikon D7000 D7000 Nikon F AF 1.523 Nikon Corporation Nikon Nikon D7100 D7100 Nikon F AF 1.534 Nikon Corporation Nikon Nikon D7200 D7200 Nikon F AF 1.534 Nikon Corporation Nikon Nikon D7500 D7500 Nikon F AF 1.534 Nikon Corporation Nikon Nikon D1 D1 Nikon F AF 1.525 Nikon Corporation Nikon Nikon D1H D1H Nikon F AF 1.525 Nikon Corporation Nikon Nikon D1X D1X Nikon F AF 1.525 Nikon Corporation Nikon Nikon D2H D2H Nikon F AF 1.546 Nikon Corporation Nikon Nikon D2Hs D2Hs Nikon F AF 1.546 Nikon Corporation Nikon Nikon D2X D2X Nikon F AF 1.522 Nikon Corporation Nikon Nikon D2Xs D2Xs Nikon F AF 1.522 Nikon Corporation Nikon Nikon D3 D3 Nikon F AF 1 Nikon Corporation Nikon Nikon D3X D3X Nikon F AF 1 Nikon Corporation Nikon Nikon D3S D3S Nikon F AF 1 Nikon Corporation Nikon Nikon D4 D4 Nikon F AF 1 Nikon Corporation Nikon Nikon D4s D4s Nikon F AF 1 Nikon Corporation Nikon Nikon D5 D5 Nikon F AF 1.003 Nikon Corporation Nikon Nikon D6 D6 Nikon F AF 1 Nikon Corporation Nikon Nikon Df Df Nikon F AF 1.001 Fujifilm FinePixS1Pro FinePix S1 Pro Nikon F AF 1.543 Fujifilm FinePixS2Pro FinePix S2 Pro Nikon F AF 1.543 Fujifilm FinePix S3Pro FinePix S3 Pro Nikon F AF 1.534 Fujifilm FinePix S5Pro FinePix S5 Pro Nikon F AF 1.560 Fujifilm IS Pro FinePix IS Pro Nikon F AF 1.560 Kodak DCS Pro SLR/n Nikon F AF 1 Kodak DCS Pro 14nx Nikon F AF 1 Kodak DCS Pro 14N DCS-14n Nikon F AF 1 Nikon 35mm film: full frame Nikon F AF 1 Nikon Nikon AF-S DX Zoom-Nikkor 12-24mm f/4G IF-ED Nikkor AF-S 12-24mm f/4G DX IF-ED Nikon F AF 1.528 Nikon Nikon AF-S Nikkor 16-35mm f/4G ED VR Nikkor AF-S 16-35mm f/4G ED VR Nikon F AF 1 Nikon Nikon AF-S DX Nikkor 16-80mm f/2.8-4E ED VR NIKKOR AF-S 16-80mm f/2.8-4E DX ED VR Nikon F AF 1.534 Nikon Nikon AF-S DX Zoom-Nikkor 16-85mm f/3.5-5.6G ED VR NIKKOR AF-S 16-85mm f/3.5-5.6G DX ED VR Nikon F AF 1.528 Nikon Nikon AF-S Zoom-Nikkor 17-35mm f/2.8D IF-ED Nikkor AF-S 17-35mm f/2.8D IF-ED Nikon F AF 1.528 Nikon Nikon AF-S DX Zoom-Nikkor 17-55mm f/2.8G IF-ED Nikkor AF-S 17-55mm f/2.8G DX IF-ED Nikon F AF 1.528 Nikon Nikon AF Zoom-Nikkor 18-35mm f/3.5-4.5D IF-ED Nikkor AF 18-35mm f/3.5-4.5D IF-ED Nikon F AF 1 Nikon Nikon AF Zoom-Nikkor 18-35mm f/3.5-4.5D IF-ED Nikkor AF 18-35mm f/3.5-4.5D IF-ED Nikon F AF 1.528 Nikon Nikon AF-S DX Zoom-Nikkor 18-55mm f/3.5-5.6G ED Nikkor AF-S 18-55mm f/3.5-5.6G DX ED Nikon F AF 1.528 Nikon Nikon AF-S DX Zoom-Nikkor 18-55mm f/3.5-5.6G VR Nikkor AF-S 18-55mm f/3.5-5.6G DX VR Nikon F AF 1.528 Nikon Nikon AF-S DX VR Nikkor 18-55mm f/3.5-5.6G II NIKKOR AF-S 18-55mm f/3.5-5.6G DX VR II Nikon F AF 1.523 Nikon Nikon AF-S DX Zoom-Nikkor 18-70mm f/3.5-4.5G IF-ED Nikkor AF-S 18-70mm f/3.5-4.5G DX IF-ED Nikon F AF 1.528 Nikon Nikon AF-S DX Zoom-Nikkor 18-105mm f/3.5-5.6G ED VR Nikkor AF-S 18-105mm f/3.5-5.6G DX ED VR Nikon F AF rectilinear 1.534 Nikon Nikon AF-S DX Zoom-Nikkor 18-135mm f/3.5-5.6G IF-ED Nikkor AF-S 18-135mm f/3.5-5.6G DX IF-ED Nikon F AF 1.528 Nikon Nikon AF-S DX VR Zoom-Nikkor 18-200mm f/3.5-5.6G IF-ED Nikkor AF-S 18-200mm f/3.5-5.6G DX VR IF-ED Nikon F AF 1.5 Nikon Nikon AF-S DX VR Zoom-Nikkor 18-200mm f/3.5-5.6G IF-ED II Nikkor AF-S 18-200mm f/3.5-5.6G DX VR IF-ED II Nikon F AF 1.5 Nikon Nikon AF Zoom-Nikkor 24-50mm f/3.3-4.5D Nikkor AF 24-50mm f/3.3-4.5D Nikon F AF 1.528 Nikon Nikon AF Zoom-Nikkor 24-50mm f/3.3-4.5 Nikkor AF 24-50mm f/3.3-4.5 Nikon F AF 1 Nikon Nikon AF Zoom-Nikkor 24-85mm f/2.8-4D IF Nikkor AF 24-85mm f/2.8-4D IF Nikon F AF 1 Nikon Nikon AF Zoom-Nikkor 24-85mm f/2.8-4D IF Nikkor AF 24-85mm f/2.8-4D IF Nikon F AF 1.528 Nikon Nikon AF-S Zoom-Nikkor 24-85mm f/3.5-4.5G IF-ED Nikkor AF-S 24-85mm f/3.5-4.5G IF-ED Nikon F AF 1 Nikon Nikon AF-S VR Zoom-Nikkor 24-120mm f/3.5-5.6G IF-ED Nikkor AF-S 24-120mm f/3.5-5.6G VR IF-ED Nikon F AF 1.528 Nikon Nikon AF-S Nikkor 24-120mm f/4G ED VR 170 NIKKOR AF-S 24-120mm f/4G ED VR Nikon F AF 1 Nikon Nikon AF Zoom-Nikkor 28-85mm f/3.5-4.5 Nikon F AF 1.0 Nikon Nikon AF Zoom-Nikkor 28-200mm f/3.5-5.6G IF-ED Nikkor AF 28-200mm f/3.5-5.6G IF-ED Nikon F AF 1.528 Nikon Nikon AF-S Zoom-Nikkor 28-300mm f/3.5-5.6G ED VR Nikkor AF-S 28-300mm f/3.5-5.6G ED VR Nikon F AF 1 Nikon Nikon AF Zoom-Nikkor 35-70mm f/2.8D Nikkor AF 35-70mm f/2.8D Nikon F AF 1.528 Nikon Nikon AI-S Zoom-Nikkor 50-135mm f/3.5 Nikkor AI-S 50-135mm f/3.5 Nikon F AI-S 1.528 Nikon Nikon AF-S DX Zoom-Nikkor 55-200mm f/4-5.6G ED Nikkor AF-S 55-200mm f/4-5.6G DX ED Nikon F AF 1.528 Nikon Nikon AF Zoom-Nikkor 70-180mm f/4.5-5.6D ED Micro Nikkor AF 70-180mm f/4.5-5.6D ED Micro Nikon F AF 1.528 Nikon Nikon AF-S VR Zoom-Nikkor 70-200mm f/2.8G IF-ED Nikkor AF-S 70-200mm f/2.8G VR IF-ED Nikon F AF 1.528 Nikon Nikon AI-S Zoom-Nikkor 70-210mm f/4.5-5.6 Nikkor AI-S 70-210mm f/4.5-5.6 Nikon F AI-S 1 Nikon Nikon AF Zoom-Nikkor 70-210mm f/4 Nikon F 1 Nikon Nikon AF Zoom-Nikkor 70-210mm f/4 Nikkor AF 70-210mm f/4 Nikon F AF 1.528 Nikon Nikon AF Nikkor 70-210mm f/4-5.6 Nikkor AF 70-210mm f/4-5.6 Nikon F AF 1.523 Nikon Nikon AF Zoom-Nikkor 70-300mm f/4-5.6D ED Nikkor AF 70-300mm f/4-5.6D ED Nikon F AF 1.528 Nikon Nikon AF Zoom-Nikkor 70-300mm f/4-5.6G Nikkor AF 70-300mm f/4-5.6G Nikon F AF 1.528 Nikon Nikon AF Zoom-Nikkor 80-200mm f/2.8D ED Nikkor AF 80-200mm f/2.8D ED Nikon F AF 1 Nikon Nikon AF Zoom-Nikkor 80-200mm f/2.8 ED Nikkor AF 80-200mm f/2.8 ED Nikon F AF 1.523 Nikon Nikon AF-S Nikkor 80-400mm f/4.5-5.6G ED VR Nikon F AF 1.0 Nikon Nikon AF Zoom-Nikkor 80-400mm f/4.5-5.6D ED VR 183 Nikkor AF 80-400mm f/4.5-5.6D ED VR Nikon F AF 1.528 Nikon Nikon AF Nikkor 14mm f/2.8D ED Nikkor AF 14mm f/2.8D ED Nikon F AF 1.528 Nikon Nikon AI Nikkor 15mm f/3.5 Nikkor AI 15mm f/3.5 Nikon F AI 1.528 Nikon Nikon AF-S Nikkor 20mm f/1.8G ED NIKKOR AF-S 20mm f/1.8G ED Nikon F AF 1 Nikon Nikon AF Nikkor 20mm f/2.8D Nikkor AF 20mm f/2.8D Nikon F AF 1.528 Nikon Nikon AI-S Nikkor 24mm f/2.8 Nikkor AI-S 24mm f/2.8 Nikon F AI-S 1 Nikon Nikon AF Nikkor 24mm f/2.8D 54 Nikkor AF 24mm f/2.8D Nikon F AF 1.528 Nikon Nikon AF Nikkor 24mm f/2.8D Nikkor AF 24mm f/2.8D Nikon F AF 1 Nikon Nikon AI-S Nikkor 24mm f/2 Nikkor AI-S 24mm f/2 Nikon F AI-S 1.528 Nikon Nikon AI-S Nikkor 28mm f/2.8 Nikkor AI-S 28mm f/2.8 Nikon F AI-S 1 Nikon Nikon AF Nikkor 28mm f/2.8D 62 Nikkor AF 28mm f/2.8D Nikon F AF 1 Nikon Nikon AI-S Nikkor 28mm f/2 Nikkor AI-S 28mm f/2 Nikon F AI-S 1.528 Nikon Nikon AI-S Nikkor 28mm f/3.5 PC (unshifted) Nikkor AI-S 28mm f/3.5 PC (unshifted) Nikkor AI-S 28mm f/3.5 PC (ungeshiftet) Nikon F AI-S 1 Nikon Nikon AF-S Nikkor 28mm f/1.8G NIKKOR AF-S 28mm f/1.8G Nikon F AF 1 Nikon Nikon AF Nikkor 28mm f/1.4D Nikkor AF 28mm f/1.4D Nikon F AF 1 Nikon Nikon AI-S Nikkor 35mm f/2 Nikkor AI-S 35mm f/2 Nikon F AI-S 1 Nikon Nikon AI-S Nikkor 35mm f/1.4 Nikkor AI-S 35mm f/1.4 Nikon F AI-S 1.528 Nikon Nikon AF-S DX Nikkor 35mm f/1.8G NIKKOR AF-S 35mm f/1.8G DX Nikon F AF 1.528 Nikon Nikon AF Nikkor 35mm f/2D 66 Nikkor AF 35mm f/2.0D Nikon F AF 1 Nikon Nikon AF Nikkor 35mm f/2.8 PC "black knob" Nikkor AF 35mm f/2.8 PC “black knob” Nikkor AF 35mm f/2.8 PC „schwarzer Knauf“ Nikon F 1 Nikon Nikon Zoom-NIKKOR Auto 43-86mm F3.5 Nikon F 1 Nikon Nikon AI Nikkor 45mm f/2.8 GN Nikkor AI 45mm f/2.8 GN Nikon F AI 1.528 Nikon Nikon AF Nikkor 50mm f/1.4D Nikkor AF 50mm f/1.4D Nikon F AF 1 Nikon Nikon AI-S Nikkor 50mm f/1.4 Nikkor AI-S 50mm f/1.4 Nikon F AI-S 1.528 Nikon Nikon AF Nikkor 50mm f/1.8D Nikkor AF 50mm f/1.8D Nikon F AF rectilinear 1.528 Nikon Nikon AF Nikkor 50mm f/1.8D Nikkor AF 50mm f/1.8D Nikon F AF 1 Nikon Nikon AI-S Nikkor 50mm f/1.8 Nikkor AI-S 50mm f/1.8 Nikon F AI-S 1.528 Nikon Nikon Nikkor 50mm f/2 Nikkor 50mm f/2 Nikon F 1.528 Nikon Nikon AI Nikkor 55mm f/1.2 Nikkor AI 55mm f/1.2 Nikon F AI 1.528 Nikon Nikon AI-S Nikkor 55mm f/2.8 Micro Nikkor AI-S 55mm f/2.8 Micro Nikon F AI-S 1.528 Nikon Nikon AI-S Nikkor 55mm f/2.8 Micro Nikkor AI-S 55mm f/2.8 Micro Nikon F AI-S 1 Nikon Nikon AI-S Nikkor 58mm f/1.2 Noct Nikkor AI-S 58mm f/1.2 Noct Nikon F AI Nikon F AI-S 1.528 Nikon Nikon AF-S Nikkor 58mm f/1.4G Nikon F AF 1.0 Nikon Nikon AF Nikkor 85mm f/1.8D Nikkor AF 85mm f/1.8D Nikon F AF 1 Nikon Nikon AF Nikkor 105mm f/2.8D Nikkor AF 105mm Micro f/2.8D Nikon F AF 1.528 Nikon Nikon AF-S VR Micro-Nikkor 105mm f/2.8G IF-ED 138 Nikkor AF-S VR 105mm f/2.8G Micro IF-ED Nikon F AF 1 Nikon Nikon AI-S Nikkor 135mm f/2 Nikkor AI-S 135mm f/2 Nikon F AI-S 1.528 Nikon Nikon AI-S Nikkor 180mm f/2.8 ED Nikkor AI-S 180mm f/2.8 ED Nikon F AI-S 1.528 Nikon Nikon AI-S Nikkor 500mm f/8 Reflex Nikkor AI-S 500mm f/8 Reflex Nikon F AI-S 1 Nikon Nikon AI-S Nikkor 500mm f/8 Reflex Nikkor AI-S 500mm f/8 Reflex Nikon F AI-S 1.528 Nikon Nikon AF-S Nikkor 85mm f/1.8G 179 NIKKOR AF-S 85mm f/1.8G Nikon F AF 1 Nikon Nikon AF Nikkor 85mm f/1.8 21 Nikkor AF 85mm f/1.8 Nikon F AF 1.523 Nikon Nikon AF-S Zoom-Nikkor 24-70mm f/2.8G ED Nikkor AF-S 24-70mm f/2.8G ED Nikon F AF 1 Nikon Nikon AF-S Zoom-Nikkor 14-24mm f/2.8G ED 146 Nikkor AF-S 14-24mm f/2.8G ED Nikon F AF 1 Nikon Nikon AF-S VR Zoom-Nikkor 70-300mm f/4.5-5.6G IF-ED Nikkor AF-S 70-300mm f/4.5-5.6G VR IF-ED Nikon F AF 1 Nikon Nikon AF-S VR Zoom-Nikkor 70-300mm f/4.5-5.6G IF-ED Nikkor AF-S 70-300mm f/4.5-5.6G VR IF-ED Nikon F AF 1.523 Nikon Nikon AF-S VR Zoom-Nikkor 70-200mm f/4G IF-ED NIKKOR AF-S 70-200mm f/4G IF-ED VR Nikon F AF 1 Nikon Nikon AI-S Nikkor 50mm f/1.2 Nikkor AI-S 50mm f/1.2 Nikon F AI Nikon F AI-S 1 Nikon Nikon AF-S Nikkor 50mm f/1.8G 176 NIKKOR AF-S 50mm f/1.8G Nikon F AF 1.523 Nikon Nikon AF-S Nikkor 50mm f/1.8G NIKKOR AF-S 50mm f/1.8G Nikon F AF 1 Nikon Nikon AF-S DX Nikkor 10-24mm f/3.5-4.5G ED Nikkor AF-S 10-24mm f/3.5-4.5G DX ED Nikon F AF 1.558 Nikon Nikon AF-S DX Nikkor 55-300mm f/4.5-5.6G ED VR Nikkor AF-S 55-300mm f/4.5-5.6G DX ED VR Nikon F AF 1.523 Nikon Nikon AF-S Nikkor 50mm f/1.4G 160 NIKKOR AF-S 50mm f/1.4G Nikon F AF 1.534 Nikon Nikon AF-S Nikkor 50mm f/1.4G NIKKOR AF-S 50mm f/1.4G Nikon F AF 1 Nikon Nikon AF Nikkor 20mm f/2.8D Nikkor AF 20mm f/2.8D Nikon F AF 1 Nikon Nikon AI-S Nikkor 20mm f/2.8 Nikkor AI-S 20mm f/2.8 Nikon F AI-S 1 Nikon Nikon AF-S Nikkor 24-85 mm f/3.5-4.5G ED VR Nikkor AF-S 24-85mm f/3.5-4.5G ED VR Nikon F AF 1 Nikon Nikon AF-S Nikkor 800mm f/5.6E FL ED VR Nikkor AF-S 800mm f/5.6E FL ED VR Nikon F AF 1 Nikon Nikon AF-S Nikkor 600mm f/4G ED VR NIKKOR AF-S 600mm f/4G ED VR Nikon F AF 1 Nikon Nikon AF-S DX Nikkor 18-140mm f/3.5-5.6G ED VR Nikkor AF-S 18-140mm f/3.5-5.6G DX ED VR Nikon F AF 1.523 Nikon Nikon AI-S Fisheye-Nikkor 6mm f/2.8 Nikkor AI-S 6mm f/2.8 Fisheye Nikon F AI-S fisheye 1 Nikon Nikon AF Zoom-Nikkor 28-80mm f/3.3-5.6G Nikkor AF 28-80mm f/3.3-5.6G Nikon F AF 1 Nikon Nikon AF Zoom-Nikkor 28-200mm f/3.5-5.6G IF-ED Nikkor AF 28-200mm f/3.5-5.6G IF-ED Nikon F AF 1 Nikon Nikon AF Zoom-Nikkor 20-35mm f/2.8D IF Nikkor AF 20-35mm f/2.8D IF Nikon F AF 1 Nikon Nikon Nikkor AI 20mm f/3.5 Nikkor AI 20mm f/3.5 Nikon F AI 1 Nikon Nikon AF Micro-Nikkor 60mm f/2.8D Nikkor AF 60mm f/2.8D Micro Nikon F AF 1 Nikon Nikon AF DX Fisheye-Nikkor 10.5mm f/2.8G ED Nikkor AF 10.5mm f/2.8G DX ED Fisheye Nikon F AF equisolid 1.523 Nikon Nikon AF DX Fisheye-Nikkor 10.5mm f/2.8G ED Nikkor AF 10.5mm f/2.8G DX ED Fisheye Nikon F AF fisheye 1 Nikon Nikon AF-S DX Nikkor 18-300mm f/3.5-6.3G ED VR Nikkor AF-S 18-300mm f/3.5-6.3G DX ED VR Nikon F AF 1.523 Nikon Nikon AF-S Micro Nikkor 60mm f/2.8G ED Nikkor AF-S 60mm f/2.8G ED Micro Nikon F AF 1.523 Nikon Nikon AF-S Nikkor 85mm f/1.4G NIKKOR AF-S 85mm f/1.4G Nikon F AF 1 Nikon Nikon Lens Series E 28mm f/2.8 Nikon F AI-S 1 Nikon Nikon Lens Series E 50mm f/1.8 Nikon F AI-S 1 Nikon Nikon Lens Series E 100mm f/2.8 Nikon F AI-S 1 Nikon Nikon AF Micro-Nikkor 105mm f/2.8D Nikkor AF 105mm f/2.8D Micro Nikon F AF 1 Nikon Nikkor 55mm f/3.5 Micro Nikon F 1.529 Nikon Nikon AF-S Nikkor 300mm f/4E PF ED VR NIKKOR AF-S 300mm f/4E PF ED VR Nikon F AF 1 Nikon Nikon AF-S DX Nikkor 18-300mm f/3.5-5.6G ED VR NIKKOR AF-S 18-300mm f/3.5-5.6G DX ED VR Nikon F AF 1.534 Nikon Nikon AF-S Nikkor 35mm f/1.8G ED NIKKOR AF-S 35mm f/1.8G ED Nikon F AF 1 Nikon Nikon AF DC-Nikkor 135mm f/2D Nikkor AF 135mm f/2D DC Nikon F AF 1 Nikon Nikon AF DC-Nikkor 105mm f/2D Nikkor AF 105mm f/2D DC Nikon F AF 1 Nikon Nikon AF-P DX Nikkor 18-55mm f/3.5-5.6G VR NIKKOR AF-P 18-55mm f/3.5-5.6G DX VR Nikon F AF 1.523 Nikon Nikon AF-S Nikkor 70-200mm f/2.8G ED VR II 162 NIKKOR AF-S 70-200mm f/2.8G ED VR II Nikon F AF 1 Nikon Nikon AF Zoom-Nikkor 28-70mm f/3.5-4.5D Nikkor AF 28-70mm f/3.5-4.5D Nikon F AF 1 Nikon Nikon AF Zoom-Nikkor 28-105mm f/3.5-4.5D IF Nikon F AF 1 Nikon Nikon AF-S DX Micro Nikkor 40mm f/2.8G Nikkor AF-S 40mm f/2.8G DX Micro Nikon F AF 1.534 Nikon Nikon AF-P DX Nikkor 70-300mm f/4.5-6.3G ED VR NIKKOR AF-P 70-300mm f/4.5-6.3G DX ED VR Nikon F AF 1.534 Nikon Nikon AF-P Nikkor 70-300mm f/4.5-5.6E ED VR NIKKOR AF-P 70-300mm f/4.5-5.6E ED VR Nikon F AF 1 Nikon Nikon AF-S DX Nikkor 35mm f/1.8G Nikkor AF-S 35mm f/1.8G DX Nikon F AF 1 Nikon Nikon AF Nikkor 35-70mm f/2.8 Nikkor AF 35-70mm f/2.8 Nikon F AF 1 Nikon Nikon AI-S Nikkor 50mm f/1.4 Nikkor AI-S 50mm f/1.4 Nikon F AI-S 1 Nikon Nikon AI-S Nikkor 50mm f/1.8 Nikkor AI-S 50mm f/1.8 Nikon F AI-S 1 Nikon Nikon AI-S Nikkor 105mm f/2.5 Nikkor AI-S 105mm f/2.5 Nikon F AI Nikon F AI-S 1 Nikon Nikon AI-S Nikkor 135mm f/2.8 Nikkor AI-S 135mm f/2.8 Nikon F AI-S 1 Nikon Nikon AI-S Nikkor 135mm f/3.5 Nikkor AI-S 135mm f/3.5 Nikon F AI-S 1 Nikon Nikon AF Nikkor 180mm f/2.8D IF-ED Nikkor AF 180mm f/2.8D IF-ED Nikon F AF 1 Nikon Nikkor AI-S 85mm f/2.0 Nikon F AI-S 1 Nikon Nikon AI-S Nikkor 200mm f/4 Nikkor AI-S 200mm f/4 Nikon F AI-S 1 Nikon Nikon AI-S Nikkor 300mm f/4.5 Nikkor AI-S 300mm f/4.5 Nikon F AI-S 1 Nikon Nikon AF-S VR Nikkor 400mm f/2.8G ED Nikon F AF 1.0 Nikon Nikon AF-S VR Nikkor 400mm f/2.8G ED + converter TC-14EIII Nikkor AF-S 400mm f/2.8G ED + converter TC-14EIII Nikon F AF rectilinear 1.0 Nikon Nikon AF-S VR Nikkor 400mm f/2.8G ED + converter TC-20EIII Nikkor AF-S 400mm f/2.8G ED + converter TC-20EIII Nikon F AF rectilinear 1 Nikon Nikon AI-S Nikkor 400mm f/3.5 Nikkor AI-S 400mm f/3.5 Nikon F AI-S 1 Nikon Nikon AI-S Nikkor 400mm f/3.5 + TC14B teleconverter Nikkor AI-S 400mm f/3.5 + TC14B teleconverter Nikon F AI-S 1 Nikon Nikon AF-S Nikkor 70-200mm f/2.8E FL ED VR 164 NIKKOR AF-S 70-200mm f/2.8E FL ED VR Nikon F AF 1 Nikon Nikon AF-S Nikkor 300mm f/4D IF-ED NIKKOR AF-S 300mm f/4D IF-ED Nikon F AF 1 Nikon Nikon AF Nikkor 300mm f/4 IF-ED NIKKOR AF 300mm f/4 IF-ED Nikon F AF 1 Nikon Nikon AF-S Nikkor 24-70mm f/2.8E ED VR 170 NIKKOR AF-S 24-70mm f/2.8E ED VR Nikon F AF 1 Nikon Nikon AF-P DX Nikkor 10-20mm f/4.5-5.6G VR 168 Nikon AF-P DX Nikkor 10-20mm f/4.5-5.6G VR Nikkor AF-P 10-20mm f/4.5-5.6G DX VR Nikon F AF 1.534 Nikon 200-500mm F5.6 174 NIKKOR AF-S 200-500mm f/5.6E ED VR Nikon F AF 1.534 Nikon Nikon AF-S Nikkor 200-500mm f/5.6E ED VR NIKKOR AF-S 200-500mm f/5.6E ED VR Nikon F AF 1 Nikon Nikon AI 80-200mm f/4.5 Zoom New Nikkor AI 80-200mm f/4.5 Zoom New Nikon F AF 1 Nikon Nikon AF-S Zoom-Nikkor 17-35mm f/2.8D IF-ED Nikkor AF-S 17-35mm f/2.8D IF-ED Nikon F AF 1 Nikon Nikon AF-S Nikkor 18-35mm f/3.5-4.5G ED Nikkor AF-S 18-35mm f/3.5-4.5G ED Nikon F AF 1 Nikon Nikon AF-S Nikkor 24mm f/1.8G ED NIKKOR AF-S 24mm f/1.8G ED Nikon F AF 1.001 Nikon Nikon AF-S VR Zoom-Nikkor 70-200mm f/2.8G IF-ED Nikon F AF 1.0 Nikon Nikon AF-S Nikkor 500mm f/5.6E PF ED VR Nikon F AF 1.0 Nikon Nikon AF-S Nikkor 600mm f/4E FL ED VR Nikon F AF 1.0 Nikon Nikon AF-S Nikkor 600mm f/4E FL ED VR + converter TC-14EIII Nikkor AF-S 600mm f/4E FL ED VR + converter TC-14EIII Nikon F AF rectilinear 1.0 Nikon Nikon AF-S VR Zoom-Nikkor 200-400mm f/4G IF-ED Nikon F AF 1 lensfun-0.3.4/data/db/slr-olympus.xml000066400000000000000000001673351445356770400175540ustar00rootroot00000000000000 4/3 System M42 M39/1 DKL T2 Generic Olympus OM M42 M39/1 DKL T2 Tamron Adaptall Generic Olympus Imaging Corp. Olympus E-300 4/3 System 2 Olympus Imaging Corp. Olympus E-330 4/3 System 2 Olympus Imaging Corp. Olympus E-400 4/3 System 2 Olympus Imaging Corp. Olympus E-410 4/3 System 2 Olympus Imaging Corp. Olympus E-420 4/3 System 2 Olympus Imaging Corp. Olympus E-450 4/3 System 2 Olympus Imaging Corp. Olympus E-500 4/3 System 2 Olympus Imaging Corp. Olympus E-510 4/3 System 2 Olympus Imaging Corp. Olympus E-520 4/3 System 2 Olympus Imaging Corp. Olympus E-600 4/3 System 2 Olympus Imaging Corp. Olympus E-620 4/3 System 2 Olympus Optical Co.,Ltd Olympus E-10 olympusE10 3.933 Olympus Optical Co.,Ltd Olympus E-20,E-20N,E-20P E-20, E-20N, E-20P olympusE10 3.933 Olympus Imaging Corp. Olympus E-30 4/3 System 2 Olympus Corporation Olympus E-1 4/3 System 2 Olympus Imaging Corp. Olympus E-3 4/3 System 2 Olympus Imaging Corp. Olympus E-5 4/3 System 2 Olympus Olympus Zuiko Digital ED 7-14mm f/4.0 4/3 System 2 4:3 Olympus Olympus Zuiko Digital ED 9-18mm f/4.0-5.6 4/3 System 2 4:3 Olympus Olympus Zuiko Digital 11-22mm f/2.8-3.5 4/3 System 2 4:3 Olympus Olympus Zuiko Digital ED 14-42mm f/3.5-5.6 4/3 System 2 4:3 Olympus Olympus Zuiko Digital 14-45mm f/3.5-5.6 4/3 System 2 4:3 Olympus Olympus Zuiko Digital 14-54mm f/2.8-3.5 4/3 System 2 4:3 Olympus Olympus Zuiko Digital 25mm f/2.8 4/3 System 2 4:3 Olympus Olympus Zuiko Digital 35mm f/3.5 Macro 4/3 System 2 4:3 Olympus Olympus Zuiko Digital 40-150mm f/3.5-4.5 4/3 System 2 4:3 Olympus Olympus Zuiko Digital ED 40-150mm f/4.0-5.6 4/3 System 2 4:3 Olympus Olympus Zuiko Digital ED 50-200mm f/2.8-3.5 4/3 System 2 4:3 Olympus Olympus Zuiko Digital ED 50-200mm f/2.8-3.5 SWD 4/3 System 2 4:3 Olympus Olympus Zuiko Digital ED 50mm f/2.0 Macro 4/3 System 2 4:3 Olympus Olympus E-10 & compatibles (Standard) fixed lens festes Objektiv olympusE10 3.933 Olympus Olympus E-10 & compatibles, with WCON-08B fixed lens, with WCON-08B festes Objektiv, mit WCON-08B olympusE10 3.933 Olympus Olympus E-10 & compatibles, with B-300 (full tele) fixed lens, with B-300 (full tele) festes Objektiv, mit B-300 (längste Brennw.) olympusE10 3.933 Olympus Olympus E-10 & compatibles, macro (full tele): 8 inches lens-to-subject fixed lens, macro (full tele): 8 inches lens-to-subject festes Objektiv, Makro (längste Brennw.): 8 Zoll Fokusabstand olympusE10 3.933 Olympus Olympus E-10 & compatibles, macro (full tele): 12 inches lens-to-subject fixed lens, macro (full tele): 12 inches lens-to-subject festes Objektiv, Makro (längste Brennw.): 12 Zoll Fokusabstand olympusE10 3.933 Olympus Olympus E-10 & compatibles, macro (full tele): 16 inches lens-to-subject fixed lens, macro (full tele): 16 inches lens-to-subject festes Objektiv, Makro (längste Brennw.): 16 Zoll Fokusabstand olympusE10 3.933 Olympus Olympus E-10 & compatibles, macro (full tele): 20 inches lens-to-subject fixed lens, macro (full tele): 20 inches lens-to-subject festes Objektiv, Makro (längste Brennw.): 20 Zoll Fokusabstand olympusE10 3.933 Olympus Olympus Zuiko Digital ED 12-60mm f/2.8-4.0 SWD 4/3 System 2 4:3 Olympus Olympus Zuiko Digital ED 14-35mm F2.0 SWD 4/3 System 2 4:3 Olympus Zuiko Auto-S 50mm f/1.8 Olympus OM 1.613 lensfun-0.3.4/data/db/slr-panasonic.xml000066400000000000000000000005521445356770400200020ustar00rootroot00000000000000 Panasonic DMC-L1 4/3 System 2 Panasonic DMC-L10 4/3 System 2 lensfun-0.3.4/data/db/slr-pentax.xml000066400000000000000000006017311445356770400173340ustar00rootroot00000000000000 Pentax K Байонет K Pentax KA Pentax KAF Pentax KAF2 Pentax KAF3 Pentax KAF4 M42 M39/1 DKL T2 Tamron Adaptall Generic Pentax KA Pentax K Pentax KAF Pentax KAF2 Pentax KAF3 Pentax KAF4 M42 M39/1 DKL T2 Tamron Adaptall Generic Pentax KAF Pentax K Pentax KA Pentax KAF2 Pentax KAF3 Pentax KAF4 M42 M39/1 DKL T2 Tamron Adaptall Generic Pentax KAF2 Pentax K Pentax KA Pentax KAF Pentax KAF3 Pentax KAF4 M42 M39/1 DKL T2 Tamron Adaptall Generic Pentax KAF3 Pentax K Pentax KA Pentax KAF Pentax KAF2 Pentax KAF4 M42 M39/1 DKL T2 Tamron Adaptall Generic Pentax KAF4 Pentax K Pentax KA Pentax KAF Pentax KAF2 Pentax KAF3 M42 M39/1 DKL T2 Tamron Adaptall Generic Pentax 35mm film: full frame Pentax KAF2 1 Pentax Corporation Pentax Pentax *ist DL2 *ist DL2 Pentax KAF2 1.531 Pentax Corporation Pentax Pentax *ist DL *ist DL Pentax KAF2 1.531 Pentax Corporation Pentax Pentax *ist DS2 *ist DS2 Pentax KAF2 1.531 Pentax Corporation Pentax Pentax *ist DS *ist DS Pentax KAF2 1.531 Pentax Corporation Pentax Pentax *ist D *ist D Pentax KAF2 1.531 Pentax Pentax K-m K-m Pentax KAF2 1.531 Pentax Corporation Pentax Pentax K100D K100D Pentax KAF2 1.531 Pentax Corporation Pentax Pentax K100D Super K100D Super Pentax KAF2 1.531 Pentax Corporation Pentax Pentax K110D K110D Pentax KAF2 1.531 Pentax Corporation Pentax Pentax K10D K10D Pentax KAF2 1.531 Pentax Corporation Pentax Pentax K20D K20D Pentax KAF2 1.538 Pentax Pentax K-30 K-30 Pentax KAF2 1.526 Pentax Pentax K-50 K-50 Pentax KAF2 1.526 Pentax Pentax K-500 K-500 Pentax KAF2 1.534 Pentax Pentax K-7 K-7 Pentax KAF2 1.538 Pentax Pentax K-5 K-5 Pentax KAF2 1.526 Pentax Pentax K-5 II K-5 II Pentax KAF2 1.526 Pentax Pentax K-5 II s K-5 II s Pentax KAF2 1.526 Ricoh Imaging Company, Ltd. Pentax Pentax K-3 K-3 Pentax KAF2 1.534 Ricoh Imaging Company, Ltd. Pentax Pentax K-3 II K-3 II Pentax KAF2 1.534 Ricoh Imaging Company, Ltd. Pentax Pentax K-3 Mark III K-3 III Pentax KAF2 1.546 Ricoh Imaging Company, Ltd. Pentax Pentax K-1 K-1 Pentax KAF4 1 Ricoh Imaging Company, Ltd. Pentax PENTAX K-1 Mark II K-1 Mark II Pentax KAF4 1.0 Pentax Pentax K2000 K2000 Pentax KAF2 1.531 Pentax Pentax K200D K200D Pentax KAF2 1.531 Pentax Pentax K-x K-x Pentax KAF2 1.531 Pentax Pentax K-r K-r Pentax KAF2 1.523 Ricoh Imaging Company, Ltd. Pentax Pentax K-S2 K-S2 Pentax KAF2 1.534 Ricoh Imaging Company, Ltd. Pentax Pentax K-S1 K-S1 Pentax KAF2 1.534 Ricoh Imaging Company, Ltd. Pentax Pentax K-70 K-70 Pentax KAF4 1.534 Pentax Pentax K-01 K-01 Pentax KAF2 1.522 Ricoh Imaging Company, Ltd. Pentax Pentax KP KP Pentax KAF2 1.534 Pentax smc Pentax-DA 12-24mm f/4 ED AL IF Pentax KAF2 1.53 Pentax smc Pentax-DA 16-45mm f/4 ED AL Pentax KAF2 1.522 Pentax HD Pentax-D FA 15-30mm f/2.8 ED SDM WR Pentax K 1 Pentax HD Pentax-DA 16-85mm f/3.5-5.6 ED DC WR Pentax KAF2 1.526 Pentax smc Pentax-DA 18-55mm f/3.5-5.6 AL Pentax KAF2 1.53 Pentax smc Pentax-DA 18-55mm f/3.5-5.6 AL II L WR smc Pentax-DA 18-55mm f/3.5-5.6 AL II/L/WR Pentax KAF2 1.53 Pentax smc Pentax-DA 18-135mm f/3.5-5.6 ED AL IF DC WR Pentax K 1.53 Pentax smc Pentax-DA 18-250mm f/3.5-6.3 ED AL [IF] Pentax KAF2 1.53 Pentax Pentax-F 28-80mm f/3.5-4.5 Pentax KAF2 1.526 Pentax HD Pentax-D FA 28-105mm f/3.5-5.6 ED DC WR Pentax KAF3 1 Pentax HD Pentax-D FA* 70-200mm f/2.8 ED DC AW Pentax KAF3 1 Pentax smc Pentax-DA 50-200mm f/4-5.6 DA ED Pentax KAF2 1.53 Pentax HD Pentax-DA 55-300mm f/4-5.8 ED WR Pentax KAF3 1 Pentax smc Pentax-DA 55-300mm f/4-5.8 ED Pentax KAF2 1.53 Pentax smc Pentax-DA L 55-300mm f/4-5.8 ED Pentax KAF2 1.53 Pentax smc Pentax-DA 55-300mm f/4-5.8 ED Pentax KAF 1.522 Pentax smc Pentax-DA 15mm f/4 ED AL Limited Pentax KAF2 1.53 Pentax smc Pentax K 30mm f/2.8 Pentax K 1.53 Pentax smc Pentax-DA 40mm f/2.8 Limited Pentax KAF2 1.53 Pentax smc Pentax-DA 40mm f/2.8 XS Pentax KAF2 1 Pentax smc Pentax-FA 43mm f/1.9 Limited Pentax KAF2 1.53 Pentax smc Pentax-FA 77mm f/1.8 Limited Pentax KAF3 1 Pentax Takumar 135mm f/2.5 Bayonet Pentax K 1.53 Pentax smc Pentax-M 50mm f/1.7 Pentax K 1.526 Pentax smc Pentax-M 50mm f/2 Pentax K 1.53 Pentax smc Pentax-D FA Macro 100mm f/2.8 WR Pentax KAF2 1.53 Pentax smc Pentax-D FA Macro 100mm f/2.8 WR Pentax KAF 1 Pentax smc Pentax-M 150mm f/3.5 Pentax K 1.53 Pentax smc Pentax-DA 35mm f/2.4 AL Pentax KAF2 1.526 Pentax smc Pentax-DA 35mm f/2.4 AL Pentax KAF 1 Pentax HD Pentax-DA 70mm f/2.4 Limited Pentax KAF2 1.534 Pentax smc Pentax-DA 70mm f/2.4 Limited Pentax KAF2 1.534 Pentax smc Pentax-DA* 50-135mm f/2.8 ED IF SDM Pentax KAF2 1.526 Pentax smc Pentax-FA 50mm f/1.4 Pentax KAF2 1.526 Pentax smc Pentax-FA 50mm f/1.4 Pentax KAF2 1 Pentax HD Pentax-DA 21mm f/3.2 ED AL Limited Pentax KAF2 1.526 Pentax smc Pentax-DA 21mm f/3.2 AL Limited Pentax KAF2 1.526 Pentax smc Pentax-FA 28mm f/2.8 AL Pentax KAF2 1.53 Pentax smc Pentax-FA 28mm f/2.8 AL Pentax KAF2 1 Pentax smc Pentax-DA* 16-50mm f/2.8 ED AL IF SDM Pentax KAF2 1.526 Pentax smc Pentax-DA Fish-Eye 10-17mm f/3.5-4.5 ED IF Pentax KAF2 equisolid 1.538 Pentax smc Pentax-A 50mm f/1.7 Pentax KA 1 Pentax smc Pentax-A 50mm f/1.7 Pentax KA 1.526 Pentax smc Pentax-A 28mm 1:2.8 Pentax KA 1.538 Pentax smc Pentax-M 28mm 1:3.5 Pentax K 1.538 Pentax smc Pentax-M 35mm 1:2 Pentax K 1.538 Pentax smc Pentax-FA 31mm f/1.8 AL Limited Pentax KAF2 1.526 Pentax smc Pentax-DA 50mm f/1.8 Pentax KAF2 1.526 Pentax smc Pentax-DA 50mm f/1.8 Pentax KAF2 1 Pentax HD Pentax-DA 20-40mm f/2.8-4 ED Limited DC WR Pentax KAF2 1.526 Pentax smc Pentax-M Macro 1:4 50mm Pentax K 1.529 Pentax smc Pentax-M Macro 1:4 100mm Pentax K 1.531 Pentax smc Pentax-DA L 18-50mm f/4-5.6 DC WR RE Pentax KAF3 1.534 Pentax smc Pentax-DA L 18-50mm f/4-5.6 DC WR RE Pentax KAF3 1 Pentax HD Pentax-DA 18-50mm f/4-5.6 DC WR RE Pentax KAF2 1.522 Pentax HD Pentax-D FA 150-450mm f/4.5-5.6 ED DC AW Pentax KAF3 1 Pentax smc Pentax-DA L 50-200mm f/4-5.6 ED WR Pentax KAF2 1.534 Pentax smc Pentax-DA L 50-200mm f/4-5.6 ED WR Pentax KAF 1 Pentax smc Pentax-DA 17-70mm f/4 AL [IF] SDM Pentax KAF2 1.53 Pentax Super-Takumar 55mm f/1.8 M42 1.523 Pentax Super-Takumar 50mm f/1.4 M42 1 Pentax HD Pentax-D FA 24-70mm f/2.8 ED SDM WR Pentax KAF3 1 Pentax smc Pentax-DA 35mm f/2.8 Macro Limited Pentax KAF3 1 Pentax Pentax SMC Takumar 50mm f/1.4 M42 Sony E 1 Pentax smc Pentax-FA 28-70mm f/4 AL Pentax KAF 1 Pentax smc Pentax-A 50mm f/1.4 Pentax KA 1.522 Pentax smc Pentax-F 28mm f/2.8 Pentax KAF 1.522 Pentax smc PENTAX DA* 60-250mm f/4 [IF] SDM smc PENTAX DA* 60-250mm f/4 IF SDM Pentax KAF2 1.534 Pentax HD Pentax-DA 55-300mm f/4.5-6.3 ED PLM WR RE Pentax KAF2 1.534 Pentax smc PENTAX-F 35-80mm f/4-5.6 Pentax KAF2 1.531 Pentax HD PENTAX-DA* 11-18mm f/2.8 ED DC AW Pentax KAF2 1.534 Pentax HD PENTAX DA* 16-50mm f/2.8 ED PLM AW Pentax KAF2 1.546 lensfun-0.3.4/data/db/slr-ricoh.xml000066400000000000000000000045221445356770400171340ustar00rootroot00000000000000 Ricoh Ricoh XR Rikenon 1:1.4 50mm Pentax K 1.523 Ricoh Ricoh 50mm 1:2.0 Pentax K 1 lensfun-0.3.4/data/db/slr-samsung.xml000066400000000000000000000014421445356770400175030ustar00rootroot00000000000000 Samsung Techwin Co. Samsung SAMSUNG GX10 GX10 Pentax KAF2 1.531 Samsung Techwin Co. Samsung GX20 GX20 Pentax KAF2 1.538 Samsung Techwin Samsung GX-1S GX-1S Pentax KAF2 1.531 lensfun-0.3.4/data/db/slr-samyang.xml000066400000000000000000000336411445356770400174730ustar00rootroot00000000000000 Samyang Samyang 8mm f/3.5 Fish-Eye CS Samyang 8mm f/3.5 Fischauge CS Pentax KAF Canon EF Nikon F AI Fujifilm X Sony Alpha Sony E 4/3 System Micro 4/3 System Samsung NX stereographic 1.534 Samyang Samyang 10mm f/2.8 ED AS NCS CS Canon EF Canon EF-M Fujifilm X Micro 4/3 System Nikon F AI Pentax KAF Samsung NX Sony Alpha Sony E 1.534 Samyang Samyang 12mm f/3.1 VDSLR ED AS NCS Fish-eye Nikon F AF 1.0 Samyang Samyang 14mm f/2.8 AE ED AS IF UMC Pentax KAF Canon EF Nikon F AI Fujifilm X Sony Alpha Sony E 4/3 System Micro 4/3 System Samsung NX Nikon CX Canon EF-M 1 Samyang Samyang 14mm f/2.8 AE ED AS IF UMC Pentax KAF Canon EF Nikon F AI Fujifilm X Sony Alpha Sony E 4/3 System Micro 4/3 System Samsung NX Nikon CX Canon EF-M 1.523 Samyang Samyang 16mm f/2.0 ED AS UMC CS Nikon F AF Canon EF Fujifilm X Sony Alpha Micro 4/3 System Samsung NX Canon EF-M Pentax KAF 1.534 Samyang Samyang 20mm f/1.8 ED AS UMC Pentax K Canon EF Nikon F AI Fujifilm X Sony Alpha Sony E Micro 4/3 System Samsung NX Canon EF-M 1 Samyang Samyang 500mm f/6.3 MC IF Mirror Lens Samyang 500mm f/6.3 MC IF Spiegelobjektiv T2 1.534 Samyang Samyang 35mm f/1.4 AS UMC Nikon F AI 1 Samyang Samyang T-S 24mm f/3.5 ED AS UMC Nikon F AI Canon EF Sony Alpha Sony E Pentax KAF 1 Samyang Samyang 12mm f/2.8 Fish-Eye ED AS NCS Samyang 12mm f/2.8 Fischauge ED AS NCS Nikon F AI Canon EF Sony E stereographic 1 Samyang Samyang 35mm T1.5 Cine Lens Canon EF 1.620 Samyang Samyang 135mm f/2 ED UMC Nikon F Canon EF Pentax KAF Micro 4/3 System Sony Alpha Sony E Fujifilm X Samsung NX 1 Samyang Samyang 35mm f/1.4 AS UMC Canon EF-S 1.605 Samyang Samyang 85mm f/1.4 IF UMC Aspherical Canon EF Canon EF-M Fujifilm X Micro 4/3 System Nikon F AI 4/3 System Pentax KAF Samsung NX Sony Alpha Sony E 1 lensfun-0.3.4/data/db/slr-schneider.xml000066400000000000000000000044171445356770400177770ustar00rootroot00000000000000 Schneider Schneider 28mm f/2.8 PC Canon EF Nikon F AI-S 1 Schneider D-Xenon 1:3.5-5.6 18-55mm AL Pentax KAF2 1.53 Schneider D-Xenon 1:4-5.6 50-200mm AL Pentax KAF2 1.53 Schneider Schneider Retina-Curtagon 1:4/28mm DKL 1.529 lensfun-0.3.4/data/db/slr-sigma.xml000066400000000000000000014241131445356770400171330ustar00rootroot00000000000000 Sigma SA M42 M39/1 DKL T2 Generic Sigma Sigma SD1 SD1 Sigma SA 1.500 Sigma Sigma SD1 Merrill SD1 Merrill Sigma SA 1.500 Sigma Sigma SD9 SD9 Sigma SA 1.739 Sigma Sigma SD10 SD10 Sigma SA 1.739 Sigma Sigma SD14 SD14 Sigma SA 1.739 Sigma Sigma SD15 SD15 Sigma SA 1.739 Sigma Sigma 10-20mm f/4-5.6 EX DC HSM Sigma 10-20mm f/4-5.6 EX DC Nikon F AF Sigma SA Canon EF Pentax KAF2 Sony Alpha 4/3 System 1.53 Sigma Sigma 10-20mm f/4-5.6 EX DC HSM Sigma 10-20mm f/4-5.6 EX DC Nikon F AF Sigma SA Canon EF Pentax KAF2 Sony Alpha 4/3 System 1.620 Sigma Sigma 12-24mm F4 DG HSM Art Nikon F AF 1.0 Sigma Sigma 12-24mm f/4.5-5.6 EX DG HSM Sigma SA Canon EF Nikon F AF Pentax KAF 1 Sigma Sigma 15-30mm f/3.5-4.5 EX DG Aspherical Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 1 Sigma Sigma 15-30mm f/3.5-4.5 EX DG Aspherical Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 1.611 Sigma Sigma 17-35mm f/2.8-4 EX DG Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 1.53 Sigma Sigma 17-70mm f/2.8-4.5 DC Macro Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 1.611 Sigma Sigma 17-70mm f/2.8-4.5 DC Macro Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 1.523 Sigma Sigma 18-50mm f/2.8 EX DC Sigma SA Nikon F AF Pentax KAF 1.53 Sigma Sigma 18-50mm f/2.8 EX DC Canon EF 1.611 Sigma Sigma 18-50mm f/3.5-5.6 DC Sigma SA Canon EF Nikon F AF Pentax KAF 4/3 System 1.611 Sigma Sigma 18-125mm f/3.5-5.6 DC Sigma SA Canon EF Nikon F AF Pentax KAF 4/3 System 1.53 Sigma Sigma 18-125mm f/3.5-5.6 DC Sigma SA Canon EF Nikon F AF Pentax KAF 4/3 System 1.611 Sigma Sigma 18-200mm f/3.5-6.3 DC Sigma SA Nikon F AF Canon EF Pentax KAF2 Sony Alpha 1.53 Sigma Sigma 18-200mm f/3.5-6.3 II DC OS HSM Sigma Canon EF Nikon F AF Pentax KAF 1.53 Sigma Sigma 18-200mm f/3.5-6.3 DC Macro OS HSM Sigma SA Nikon F AF Canon EF-S Pentax KAF Minolta AF Sony Alpha 1.523 Sigma Sigma 24-60mm f/2.8 EX DG Nikon F AF Canon EF Pentax KAF2 Sony Alpha 1.53 Sigma Sigma 24-70mm f/2.8 EX DG Macro Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 1.611 Sigma Sigma 24-70mm f/2.8 IF EX DG HSM Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 1.526 Sigma Sigma 24-70mm f/2.8 IF EX DG HSM Sigma SA Canon EF Sony Alpha Nikon F AF Pentax KAF 1.005 Sigma Sigma 28-70mm f/2.8 EX DG Sigma SA Canon EF Nikon F AF Pentax KAF 1 Sigma Sigma 28-70mm f/2.8 AF Minolta AF 1 Sigma Sigma 28-300mm f/3.5-6.3 Macro ASP IF Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 1.53 Sigma Sigma 50-500mm f/4-6.3 EX DG HSM Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 4/3 System 1.53 Sigma Sigma 50-500mm f/4.5-6.3 APO DG OS HSM Sigma SA Canon EF Nikon F AF Pentax KAF Sony Alpha 1 Sigma Sigma 55-200mm f/4-5.6 DC Canon EF Nikon F AF Pentax KAF2 4/3 System 1.531 Sigma Sigma 70-300mm f/4-5.6 APO Macro Super II Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 1.611 Sigma Sigma 70-300mm f/4-5.6 DG OS Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 1.53 Sigma Sigma 70-300mm f/4-5.6 DL Macro Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 1.53 Sigma Sigma 150-500mm f/5-6.3 APO DG OS HSM Nikon F AF Sigma SA Canon EF Sony Alpha Pentax KAF 1 Sigma Sigma 14mm f/1.8 DG HSM | A Sigma SA Canon EF Nikon F Sony E 1 Sigma Sigma 14mm f/2.8 EX Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 1 Sigma Sigma 14mm f/3.5 EX Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 1.53 Sigma Sigma 20mm f/1.8 EX DG Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 1 Sigma Sigma 28mm f/1.8 EX DG Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 1.53 Sigma Sigma 30mm f/1.4 EX DC HSM Sigma SA Canon EF Minolta AF Nikon F AF Pentax KAF 4/3 System 1.53 Sigma Sigma 30mm f/1.4 EX DC HSM Canon EF Sigma SA Nikon F AF Sony Alpha Pentax KAF 1.620 Sigma Sigma 50mm f/1.4 EX DG HSM Sigma SA Canon EF Nikon F AF Sony Alpha Pentax KAF 4/3 System 1 Sigma Sigma 50mm f/1.4 EX DG HSM Sigma SA Canon EF Nikon F AF Sony Alpha Pentax KAF 4/3 System 1.53 Sigma Sigma 70mm f/2.8 EX DG Macro Sigma SA Canon EF Nikon F AF Sony Alpha Pentax KAF 1.534 Sigma Sigma 85mm f/1.4 EX DG HSM Sigma SA Canon EF Nikon F AF Sony Alpha Pentax KAF 1.534 Sigma Sigma 150mm f/2.8 EX DG APO HSM Macro 4/3 System 2 4:3 Sigma Sigma 150mm f/2.8 EX DG APO HSM Macro Canon EF Nikon F AF 1 Sigma Sigma 17-50mm f/2.8 EX DC OS HSM Sigma SA Nikon F AF Canon EF Pentax KAF2 Sony Alpha 1.523 Sigma Sigma 17-50mm f/2.8 EX DC HSM Pentax KAF3 1 Sigma Sigma 24mm f/1.4 DG HSM | [A] Art 015 Sigma 24mm f/1.4 DG HSM | A Nikon F AF Sigma SA Canon EF Sony Alpha Pentax KAF 1 Sigma Sigma 35mm f/1.4 DG HSM Nikon F AF Sigma SA Canon EF Sony Alpha Pentax KAF 1 Sigma Sigma 8mm f/3.5 EX DG Circular Sigma 8mm f/3.5 EX DG circular fisheye Sigma 8mm f/3.5 EX DG zirkulares Fischauge Nikon F AF Sigma SA Canon EF equisolid 1.523 Sigma Sigma 8mm f/3.5 EX DG Circular Sigma 8mm f/3.5 EX DG circular fisheye Sigma 8mm f/3.5 EX DG zirkulares Fischauge Nikon F AF Sigma SA Canon EF equisolid 1.620 Sigma Sigma 8mm f/3.5 EX DG Circular Sigma 8mm f/3.5 EX DG circular fisheye Sigma 8mm f/3.5 EX DG zirkulares Fischauge Nikon F AF Sigma SA Canon EF equisolid 1 Sigma Sigma 8-16mm f/4.5-5.6 DC HSM Sigma SA Canon EF Nikon F AF Pentax KAF Sony Alpha 1.613 Sigma Sigma 8-16mm f/4.5-5.6 DC HSM Sigma SA Canon EF Nikon F AF Pentax KAF Sony Alpha 1.534 Sigma Sigma 10-20mm f/3.5 EX DC HSM Nikon F AF Sigma SA Canon EF-S Sony Alpha Pentax KAF 1.613 Sigma Sigma 10-20mm f/3.5 EX DC HSM Nikon F AF Sigma SA Canon EF-S Sony Alpha Pentax KAF 1.534 Sigma Sigma 17-70mm f/2.8-4 DC Macro OS HSM Nikon F AF Sigma SA Canon EF Sony Alpha Pentax KAF 1.523 Sigma Sigma 70-200mm f/2.8 EX DG Macro HSM II 4/3 System Sigma SA Nikon F AF Sony Alpha Pentax KAF2 Canon EF 1.526 Sigma Sigma 70-200mm f/2.8 EX DG APO OS HSM Sigma 70-200mm f/2.8 EX DG OS HSM Sigma SA Nikon F AF Sony Alpha Canon EF 1.005 Sigma Sigma 70-200mm f/2.8 EX DG APO OS HSM Sigma 70-200mm f/2.8 EX DG OS HSM Sigma SA Nikon F AF Sony Alpha Canon EF Pentax KAF2 4/3 System 1.534 Sigma Sigma 10mm f/2.8 EX DC Fisheye HSM Sigma 10mm f/2.8 EX DC Fischauge HSM Sigma SA Nikon F AF Sony Alpha Pentax KAF2 Canon EF equisolid 1.622 Sigma Sigma 10mm f/2.8 EX DC Fisheye HSM Sigma 10mm f/2.8 EX DC Fischauge HSM Nikon F AF Sony Alpha Pentax KAF2 Canon EF fisheye 1.523 Sigma Sigma 100-300mm f/4 APO EX DG HSM Sigma SA Nikon F AF Sony Alpha Pentax KAF2 Canon EF 1.523 Sigma Sigma 100-300mm f/4 APO EX DG HSM Sigma SA Nikon F AF Sony Alpha Pentax KAF2 Canon EF 1 Sigma Sigma 100-300mm f/4 APO EX DG HSM + Kenko Teleplus PRO 300 AF 1.4x DGX extender Sigma 100-300mm f/4 APO EX DG HSM + Kenko Teleplus PRO 300 AF 1.4× DGX ext. Sigma 100-300mm f/4 APO EX DG HSM + Kenko Teleplus PRO 300 AF 1.4× DGX Konv. Sigma SA Nikon F AF Sony Alpha Pentax KAF2 Canon EF 1 Sigma Sigma 50-150mm f/2.8 APO EX DC HSM II Sigma SA Nikon F AF Sony Alpha Pentax KAF2 Canon EF 1.523 Sigma Sigma 50-150mm f/2.8 APO EX DC HSM II Sigma SA Nikon F AF Sony Alpha Pentax KAF2 Canon EF 1.620 Sigma Sigma 50-150mm f/2.8 APO EX DC OS HSM Sigma SA Nikon F AF Sony Alpha Pentax KAF2 Canon EF 1.534 Sigma Sigma 105mm f/2.8 EX DG OS HSM Macro Nikon F AF Sigma SA Canon EF Sony Alpha 1.523 Sigma Sigma 105mm f/2.8 EX DG OS HSM Macro Nikon F AF Canon EF 1 Sigma Sigma 80-400mm f/4.5-5.6 EX DG OS Canon EF Nikon F AF 1 Sigma Sigma 24-105mm f/4.0 DG OS HSM [A] Canon EF Sigma SA Nikon F AF Sony Alpha 1.005 Sigma Sigma 18-250mm f/3.5-6.3 DC OS Macro HSM Canon EF Sigma SA Nikon F AF Sony Alpha Pentax KAF2 1.523 Sigma Sigma 18-35mm f/1.8 DC HSM [A] Canon EF Sigma SA Nikon F AF Sony Alpha Pentax KAF2 1.523 Sigma Sigma 180mm f/2.8 EX DG OS HSM APO Macro Canon EF Sigma SA Nikon F AF Sony Alpha 1 Sigma Sigma 50mm f/1.4 DG HSM [A] Canon EF Sigma SA Nikon F AF Sony Alpha 1.005 Sigma Sigma 180mm f/5.6 APO Macro Sony Alpha Olympus OM Canon FD Pentax K Nikon F 1.523 Sigma Sigma 70-300mm f/4-5.6 DG Macro Sony Alpha Sigma SA Pentax KAF2 Canon EF Nikon F AF 1 Sigma Sigma 4.5mm f/2.8 EX DC HSM circular fisheye Sigma 4.5mm f/2.8 EX DC HSM Zirkular-Fischauge Canon EF Nikon F AF Sony Alpha Pentax KAF2 Sigma SA fisheye 1.534 Sigma Sigma 50-100mm f/1.8 DC HSM Art Canon EF Nikon F Sigma SA 1.534 Sigma Sigma 17-70mm f/2.8-4 DC MACRO OS HSM Contemporary Sigma 17-70mm f/2.8-4 DC Macro OS HSM | C Nikon F AF Sigma SA Canon EF 1.53 Sigma Sigma 24mm f/2.8 Super Wide II Minolta AF Pentax KAF 1.523 Sigma Sigma 20mm f/1.4 DG HSM | Art 015 Sigma 20mm f/1.4 DG HSM | A Canon EF Nikon F AF Sigma SA 1 Sigma Sigma 150-600mm f/5-6.3 DG OS HSM | C Canon EF Sigma SA Nikon F AF 1.613 Sigma Sigma 85mm f/1.4 EX DG HSM Pentax KAF3 Nikon F AF Sigma SA Canon EF Sony Alpha 1 Sigma Sigma 150-600mm f/5-6.3 DG OS HSM | C Canon EF Sigma SA Nikon F AF 1.534 Sigma Sigma 150-600mm f/5-6.3 DG OS HSM | C Canon EF Sigma SA Nikon F AF 1 Sigma 100-400mm F5-6.3 DG OS HSM | Contemporary 017 100-400mm F5-6.3 DG OS HSM | C Sony E 1 Sigma 70-200mm F2.8 DG OS HSM | Sports 018 70-200mm F2.8 DG OS HSM | S Canon EF Sigma SA Nikon F Sony E 1 Sigma Sigma 18-300mm f/3.5-6.3 DC Macro OS HSM Sigma 18-300mm f/3.5-6.3 DC Macro HSM Sigma SA Canon EF Nikon F AF Sony Alpha Pentax KAF 1.613 Sigma Sigma 60-600mm f/4.5-6.3 DG OS HSM | S Sigma 60-600mm F4.5-6.3 DG OS HSM | Sports 018 Canon EF-S Nikon F AF Sigma SA 1.605 Sigma 60-600mm f/4.5-6.3 DG OS HSM | Sports 018 +1.4x extender Sigma 60-600mm F4.5-6.3 DG OS HSM | Sports 018 + 1.4x ext. Canon EF-S 1.605 lensfun-0.3.4/data/db/slr-soligor.xml000066400000000000000000000010051445356770400174770ustar00rootroot00000000000000 Soligor MC Soligor C/D Wide-Auto 1:2.8 f=24mm Pentax KAF2 1.531 lensfun-0.3.4/data/db/slr-sony.xml000066400000000000000000002542321445356770400170250ustar00rootroot00000000000000 Sony Alpha Minolta AF M42 M39/1 DKL T2 Tamron Adaptall Generic Sony SLT-A33 Alpha 33 Sony Alpha 1.523 Sony SLT-A35 Alpha 35 Sony Alpha 1.523 Sony SLT-A37 Alpha 37 Sony Alpha 1.523 Sony SLT-A55V Alpha 55 Sony Alpha 1.523 Sony SLT-A57 Alpha 57 Sony Alpha 1.523 Sony SLT-A58 Alpha 58 Sony Alpha 1.523 Sony SLT-A65V Alpha 65 Sony Alpha 1.523 Sony ILCA-68 Alpha 68 Sony Alpha 1.534 Sony SLT-A77V Alpha 77 Sony Alpha 1.534 Sony ILCA-77M2 Alpha 77 II Sony Alpha 1.534 Sony SLT-A99 Alpha 99 Sony Alpha 1.005 Sony SLT-A99V Alpha 99V Sony Alpha 1.005 Sony DSLR-A100 Alpha 100 Sony Alpha 1.523 Sony DSLR-A200 Alpha 200 Sony Alpha 1.523 Sony DSLR-A230 Alpha 230 Sony Alpha 1.523 Sony DSLR-A290 Alpha 290 Sony Alpha 1.523 Sony DSLR-A300 Alpha 300 Sony Alpha 1.534 Sony DSLR-A330 Alpha 330 Sony Alpha 1.534 Sony DSLR-A350 Alpha 350 Sony Alpha 1.534 Sony DSLR-A380 Alpha 380 Sony Alpha 1.528 Sony DSLR-A390 Alpha 390 Sony Alpha 1.523 Sony DSLR-A450 Alpha 450 Sony Alpha 1.534 Sony DSLR-A500 Alpha 500 Sony Alpha 1.534 Sony DSLR-A550 Alpha 550 Sony Alpha 1.534 Sony DSLR-A560 Alpha 560 Sony Alpha 1.523 Sony DSLR-A580 Alpha 580 Sony Alpha 1.523 Sony DSLR-A700 Alpha 700 Sony Alpha 1.534 Sony DSLR-A850 Alpha 850 Sony Alpha 1 Sony DSLR-A900 Alpha 900 Sony Alpha 1 Sony ILCA-99M2 Alpha 99 II Sony Alpha 1 Sony Sony AF DT 16-105mm f/3.5-5.6 Sony Alpha 1.527 Sony Sony DT 16-50mm f/2.8 SSM (SAL1650) Sony DT 16-50mm f/2.8 SSM Sony Alpha 1.527 Sony Sony DT 18-55mm f/3.5-5.6 SAM (SAL1855) Sony DT 18-55mm f/3.5-5.6 SAM Sony Alpha 1.527 Sony Minolta/Sony AF DT 18-70mm f/3.5-5.6 (D) Sony Alpha 1.527 Sony Sony AF DT 55-200mm f/4-5.6 SAM (SAL55200-2) Sony AF DT 55-200mm f/4-5.6 SAM Sony Alpha rectilinear 1.527 Sony Sony 50mm f/1.4 (SAL50F14) Sony 50mm f/1.4 Sony Alpha 1.534 Sony Sony DT 35mm f/1.8 SAM (SAL35F18) Sony DT 35mm f/1.8 SAM Sony Alpha 1.523 Sony Sony DT 50mm f/1.8 SAM Sony Alpha 1.523 Sony Sony DT 55-300mm f/4.5-5.6 SAM (SAL55300) Sony DT 55-300mm f/4.5-5.6 SAM Sony Alpha 1.523 Sony Sony DT 18-135mm f/3.5-5.6 SAM Sony Alpha 1.523 Sony Sony AF DT 30mm f/2.8 SAM Macro (SAL30M28) Sony AF DT 30mm f/2.8 SAM Macro Sony Alpha 1.523 Sony Sony AF DT 18-250mm f/3.5-6.3 (SAL18250) Sony AF DT 18-250mm f/3.5-6.3 Sony Alpha 1.523 Sony Minolta/Sony AF 500mm F8 Reflex Sony AF 500mm F8 Reflex Sony Alpha 1 Sony Minolta/Sony AF 100mm F2.8 Macro (D) Sony AF 100mm F2.8 Macro Sony Alpha 1 Sony Carl Zeiss Vario-Sonnar T* 16-35mm f/2.8 ZA SSM II (SAL1635Z2) Zeiss Vario-Sonnar T* 16-35mm f/2.8 ZA SSM II Sony Alpha 1 Sony Carl Zeiss Vario-Sonnar T* 24-70mm f/2.8 ZA SSM II (SAL2470Z2) Zeiss Vario-Sonnar T* 24-70mm f/2.8 ZA SSM II Sony Alpha 1 Sony Sony 70-300mm f/4.5-5.6 G SSM II (SAL70300G2) Sony 70-300mm f/4.5-5.6 G SSM II Sony Alpha 1 Sony Sony 35mm F1.4 G (SAL35F14G) Sony 35mm f/1.4 G Sony Alpha 1 Sony Sony Carl Zeiss Planar T* 50mm F1.4 ZA SSM (SALF0F14Z) Zeiss Planar T* 50mm f/1.4 ZA SSM Sony Alpha 1 Sony Carl Zeiss Distagon T* 24mm F2 ZA SSM (SAL24F20Z) Sony Alpha 1.0 Sony Sony 28-75mm F2.8 SAM (SAL2875) Sony 28-75mm F2.8 SAM Sony Alpha 1 Sony Sony 85mm F2.8 SAM (SAL85F28) Sony Alpha 1.5 lensfun-0.3.4/data/db/slr-tamron.xml000066400000000000000000005116761445356770400173450ustar00rootroot00000000000000 Tamron Adaptall Generic Tamron Tamron SP AF 10-24mm f/3.5-4.5 Di II LD Aspherical (IF) Canon EF Nikon F AF Pentax KAF Sony Alpha 1.53 Tamron Tamron 10-24mm f/3.5-4.5 Di II VC HLD B023 Tamron 10-24mm f/3.5-4.5 Di II VC HLD Canon EF Nikon F AF 1.6 Tamron Tamron SP AF 17-35mm f/2.8-4 Di LD Aspherical (IF) Canon EF Nikon F AF Pentax KAF 1 Tamron Tamron 17-35mm f/2.8-4 Di OSD (A037) Canon EF Nikon F AF 1 Tamron Tamron AF 17-50mm f/2.8 XR Di-II LD (Model A16) Canon EF Nikon F AF Pentax KAF Sony Alpha 1.53 Tamron Tamron SP AF 17-50mm f/2.8 XR Di II LD Aspherical (IF) Canon EF Nikon F AF Pentax KAF Sony Alpha 1.53 Tamron Tamron SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical (IF) Canon EF Nikon F AF 1.613 Tamron Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro A14 Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro Canon EF Nikon F AF Pentax KAF Sony Alpha 1.53 Tamron AF 18-200mm f/3.5-6.3 Di II VC Canon EF Nikon F AF Sony Alpha 1.558 Tamron Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro Canon EF Nikon F AF Pentax KAF Sony Alpha 1.611 Tamron Tamron AF 18-250mm f/3.5-6.3 Di II LD Aspherical (IF) Macro Canon EF Nikon F AF Pentax KAF Sony Alpha 1.53 Tamron Tamron AF 19-35mm f/3.5-4.5 Canon EF Nikon F AF Pentax KAF 1.611 Tamron Tamron SP 24-70mm f/2.8 Di VC USD Canon EF Nikon F AF 1 Tamron Tamron SP 24-70mm F/2.8 Di VC USD G2 (A032) Canon EF Nikon F AF 1 Tamron Tamron SP AF 24-135mm f/3.5-5.6 AD Aspherical (IF) Macro Canon EF Nikon F AF Pentax KAF 1.611 Tamron Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical (IF) Tamron SP AF 28-75mm f/2.8 XR Di (IF) Macro Canon EF Nikon F AF Pentax KAF Sony Alpha 1 Tamron Tamron SP AF 28-105mm f/2.8 LD Aspherical IF Canon EF Nikon F AF Pentax KAF 1 Tamron Tamron AF 28-300mm f/3.5-6.3 XR Di LD Aspherical (IF) Canon EF Nikon F AF Pentax KAF Sony Alpha 1.53 Tamron Tamron 28-300mm f/3.5-6.3 Di VC PZD A010 Tamron 28-300mm f/3.5-6.3 Di VC PZD Canon EF Nikon F AF Sony Alpha 1.005 Tamron Tamron 35-70mm f/3.5 CF Macro Nikon F Pentax K 1.53 Tamron Tamron SP 35mm f/1.8 Di VC USD F012 Canon EF Nikon F AF Sony Alpha 1.0 Tamron Tamron AF 70-300mm f/4-5.6 LD Macro 1:2 Canon EF Nikon F AF Pentax KAF2 Sony Alpha 1.53 Tamron Tamron SP 70-300mm f/4-5.6 Di VC USD (A005) Canon EF Nikon F AF Sony Alpha 1 Tamron Tamron SP 70-300mm f/4-5.6 Di USD Sony Alpha 1.534 Tamron Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD Canon EF Nikon F AF Sony Alpha 1.613 Tamron Tamron AF 18-270mm F/3.5-6.3 Di II VC PZD Nikon F AF Canon EF Sony Alpha 1.534 Tamron Tamron SP AF 90mm f/2.8 Di Macro 1:1 Nikon F AF Canon EF Pentax KAF2 Sony Alpha 1.53 Tamron Tamron SP AF 11-18mm f/4.5-5.6 Di-II LD Aspherical (IF) Canon EF Nikon F AF Sony Alpha Pentax KAF2 1.620 Tamron Tamron 16-300mm f/3.5-6.3 Di II VC PZD B016 Macro Tamron 16-300mm f/3.5-6.3 Di II VC PZD Macro B016 Canon EF 1.613 Tamron Tamron AF 16-300mm f/3.5-6.3 Di II VC PZD B016 Macro Tamron 16-300mm f/3.5-6.3 Di II VC PZD Macro B016 Nikon F AF Sony Alpha 1.534 Tamron Tamron SP AF 150-600mm f/5-6.3 Di VC USD (A011) Tamron SP 150-600mm f/5-6.3 Di VC USD Canon EF Nikon F AF Sony Alpha 1.534 Tamron Tamron SP AF 150-600mm F/5-6.3 Di VC USD G2 (A022) Canon EF Nikon F AF Sony Alpha 1.0 Tamron Tamron SP AF 60mm f/2 Di II LD (IF) Macro 1:1 Tamron SP AF 60mm f/2 Di II LD (IF) Macro Canon EF Nikon F AF Sony Alpha 1.523 Tamron Tamron SP AF 70-200mm f/2.8 Di LD (IF) Macro (A001) Tamron SP AF 70-200mm f/2.8 Di LD (IF) Macro Canon EF Nikon F AF Sony Alpha Pentax KAF2 1 Tamron Tamron AF 80-210mm f/4.5-5.6 280D Nikon F AF Canon EF Sony Alpha Pentax KAF2 1 Tamron Tamron SP 70-200mm f/2.8 Di VC USD A009 Tamron SP 70-200mm f/2.8 Di VC USD Nikon F AF Canon EF Sony Alpha 1.005 Tamron Tamron SP 70-200mm F/2.8 Di VC USD G2 Canon EF Nikon F AF 1.0 Tamron Tamron SP 90mm f/2.8 Di VC USD Macro 1:1 Tamron SP 90mm f/2.8 Di VC USD Macro 1:1 Nikon F AF 1.0 Tamron TAMRON SP 90mm F/2.8 Di VC USD MACRO1:1 F004 Tamron SP 90mm F/2.8 Di VC USD Macro 1:1 Canon EF 1.0 Tamron Tamron SP 90mm f/2.8 Di VC USD Macro 1:1 F004 Tamron SP 90mm f/2.8 Di VC USD Macro 1:1 Nikon F AF Canon EF Sony Alpha 1.613 Tamron Tamron AF 18-270mm F/3.5-6.3 Di II VC LD Aspherical (IF) Macro Canon EF Nikon F AF 1.534 Tamron Tamron 200mm f/3.5 CT-200 BBAR Tamron Adaptall 2 4:3 Tamron Tamron SP 15-30mm f/2.8 Di VC USD (A012) Tamron SP 15-30mm f/2.8 Di VC USD Nikon F AF Canon EF Sony Alpha 1 Tamron Tamron SP 15-30mm f/2.8 Di VC USD G2 (A041) Canon EF Nikon F AF 1 Tamron Tamron 18-400mm f/3.5-6.3 Di II VC HLD (B028) Canon EF Nikon F AF 1.53 Tamron Tamron SP 35mm f/1.4 Di USD Nikon F AF Canon EF 1 Tamron TAMRON 100-400mm F/4.5-6.3 Di VC USD A035 Nikon F AF Canon EF 1.0 Tamron Tamron 35-150mm f/2.8-4.0 Di VC OSD A043 Tamron 35-150mm f/2.8-4 Di VC OSD (A043) Nikon F AF Canon EF 1.0 Tamron Tamron SP 45mm F/1.8 Di VC USD Nikon F AF Canon EF Sony Alpha 1.0 lensfun-0.3.4/data/db/slr-tokina.xml000066400000000000000000001610521445356770400173170ustar00rootroot00000000000000 Tokina Tokina 11-16mm f/2.8 AT-X 116 AF Pro DX Tokina AF 11-16mm f/2.8 AT-X Pro DX Canon EF Nikon F AF Sony Alpha 1 Tokina Tokina 11-16mm f/2.8 AT-X 116 AF Pro DX Tokina AF 11-16mm f/2.8 AT-X Pro DX Canon EF Nikon F AF Sony Alpha 1.53 Tokina Tokina ATX-i 11-20mm F2.8 CF Nikon F AF 1.523 Tokina Tokina 12-24mm f/4 AT-X 124 AF Pro DX Tokina AF 12-24mm f/4 AT-X Pro DX Canon EF Nikon F AF 1.53 Tokina Tokina AT-X 14-20 F2 PRO DX Nikon F AF Canon EF 1.523 Tokina Tokina 19-35mm f/3.5-4.5 AF 193 Tokina AF 19-35mm f/3.5-4.5 Canon EF Nikon F AF 1.611 Tokina Tokina 28-70mm f/2.8 AT-X 287 Pro SV Tokina 28-70mm f/2.8 AT-X Pro SV Canon EF Nikon F AF Pentax KAF 1.611 Tokina Tokina AT-X 24-70mm f/2.8 PRO FX Canon EF Nikon F AF 1 Tokina Tokina 80-200mm f/4.5-5.6 SZ-X Canon EF Nikon F AF Pentax KAF 1.53 Tokina Tokina 17mm f/3.5 AT-X 17 AF Pro Tokina AF 17mm f/3.5 AT-X Pro Canon EF Nikon F AF 1.53 Tokina Tokina 17mm f/3.5 AT-X 17 AF Pro Tokina AF 17mm f/3.5 AT-X Pro Canon EF Nikon F AF 1.611 Tokina Tokina 17mm f/3.5 AT-X 17 AF Pro Canon EF 1 Tokina Tokina 500mm f/8 RMC Mirror Lens Tokina 500mm f/8 RMC Spiegelobjektiv Pentax K Canon FD Minolta M Olympus OM Nikon F AI 1.53 Tokina Tokina AF 16-28mm f/2.8 AT-X Pro SD FX Canon EF Nikon F AF 1 Tokina Tokina AF 12-28mm f/4 AT-X Pro DX Canon EF Nikon F AF 1.534 Tokina Tokina AT-X M100 100mm f/2.8 Pro D Macro AF Tokina AF 100mm f/2.8 AT-X Pro D Macro Nikon F AF 1.534 Tokina Tokina AF 80-200mm f/2.8 AT-X 828 Pro Pentax KAF Canon EF Sony Alpha Nikon F AF 1 Tokina Tokina AF 28-80mm f/2.8 AT-X 280 Pro Pentax KAF Canon EF Sony Alpha Nikon F AF 1 Tokina Tokina AF 11-20mm f/2.8 AT-X Pro DX Nikon F AF Canon EF 1.534 Tokina Tokina AF 100mm f/2.8 AT-X Pro D M100 Macro Canon EF Nikon F AF 1 Tokina Tokina 17mm f/3.5 RMC II Nikon F AI 1.0 Tokina Tokina atx-i 11-16mm F2.8 CF Nikon F AF Canon EF-S 1.523 lensfun-0.3.4/data/db/slr-ussr.xml000066400000000000000000000507211445356770400170260ustar00rootroot00000000000000 KMZ КМЗ Zenit 122 Зенит 122 M42 1 KMZ КМЗ Zenit 122K Зенит 122K Pentax K 1 KMZ КМЗ Zenit 212K Зенит 212K Pentax K 1 KMZ КМЗ Zenit 312K Зенит 312K Pentax K 1 KMZ КМЗ Zenit 412LS Зенит 412LS M42 1 KMZ КМЗ Zenit KM Зенит KM Pentax K 1 KMZ КМЗ MC Mir-20M 3.5/20 МС Мир-20М 3.5/20 M42 1 KMZ КМЗ MC Zenitar 2.8/16 МС Зенитар 2.8/16 M42 Pentax K Nikon F fisheye 1 KMZ КМЗ MC Zenitar 2/50 МС Зенитар 2/50 M42 Pentax K 1 KMZ КМЗ MC APO Telezenitar 2.8/135 МС АПО Телезенитар 2.8/135 M42 1 KMZ КМЗ MC APO Telezenitar 4.5/300 МС АПО Телезенитар 4.5/300 M42 1 KMZ КМЗ MC Variozenitar-K 2.8-3.5/25-45 МС Вариозенитар-К 2.8-3.5/25-45 M42 1 BelOMO БелОМО MC Peleng 3.5/8 МС Пеленг 3.5/8 M42 Pentax K Nikon F Canon EF fisheye 1 KMZ КМЗ MC MTO 11CA 10/1000 МС МТО 11СА M42 1.531 KMZ КМЗ MC Helios-44M-4 58mm 1:2 МС Гелиос-44М-4 58мм 1:2 M42 1.538 KMZ КМЗ MC Helios-44M-4 58mm 1:2 МС Гелиос-44М-4 58мм 1:2 M42 1 KMZ КМЗ Helios-44 58mm 1:2 Гелиос-44 58мм 1:2 M42 1 MTO МТО MTO-500 500mm f/8 mirror lens МТО-500 500мм f/8 M39/1 1.529 KMZ КМЗ MIR-1B 37mm f/2.8 МИР-1В 37мм f/2.8 M42 1.523 KMZ КМЗ MIR-1B 37mm f/2.8 МИР-1B 2.8/37 M42 1 KMZ КМЗ Helios-40 85mm f/1.5 Гелиос-40 85мм f/1.5 M39 Sony E 1 KMZ КМЗ Industar-50-2 3.5/50 ИНДУСТАР-50-2 3.5/50 M42 1 KMZ КМЗ Jupiter-37AM MC 3.5/135 ЮПИТЕР-37AM MC 3.5/135 M42 1 lensfun-0.3.4/data/db/slr-vivitar.xml000066400000000000000000000040641445356770400175150ustar00rootroot00000000000000 Vivitar Vivitar 100mm f/3.5 AF Macro Canon EF Sony Alpha Nikon F AF 1.523 Vivitar Vivitar Series One 70-210mm 1:3.5 SN 22... Vivitar Series 1 70-210mm 1:3.5 SN 22… Nikon F Pentax K Canon FD Canon FL Olympus OM M42 1.534 lensfun-0.3.4/data/db/slr-zeiss.xml000066400000000000000000000302731445356770400171670ustar00rootroot00000000000000 Zeiss Carl Zeiss Distagon T* 2/35 ZF.2 Nikon F AI-S 1 Zeiss Carl Zeiss Distagon T* 2,8/21 ZF.2 Nikon F AI-S 1 Zeiss Carl Zeiss Distagon T* 2,8/21 ZE Canon EF 1 Zeiss Carl Zeiss Jena 1Q Biotar 1:2 f=58mm T M42 1.538 Zeiss Zeiss Distagon T* 25mm f/2.8 ZF.2 Nikon F AI-S 1 Zeiss Zeiss Milvus 1.4/50 Canon EF Nikon F AI-S 1 Zeiss Zeiss Otus 85mm f/1.4 Nikon F AF Canon EF 1 Zeiss Carl Zeiss Planar T* 1,4/50 ZF.2 Nikon F AF 1.523 Zeiss Carl Zeiss Distagon T* 3,5/18 ZF.2 Nikon F AF 1.0 Zeiss Carl Zeiss Planar T* 1,4/50 ZF.2 Nikon F AF 1.0 Zeiss Carl Zeiss Distagon T* 3,5/18 ZF.2 Nikon F AF 1.523 Zeiss Touit 2.8/50M Fujifilm X 1.529 Zeiss Zeiss Makro-Planar T* 2/100 ZF.2 Makro-Planar T* 2/100 Nikon F AF Canon EF Pentax KAF4 1.0 Zeiss Carl Zeiss Jena 135mm f/3.5 Sony E 1 Zeiss Carl Zeiss Sonnar T* 135mm F1.8 ZA (SAL135F18Z) Sony Alpha 1 Zeiss Carl Zeiss Jena Flektogon 4/20mm Sony E 1 lensfun-0.3.4/data/db/timestamp.txt000066400000000000000000000000131445356770400172430ustar00rootroot000000000000001645386247 lensfun-0.3.4/docs/000077500000000000000000000000001445356770400141375ustar00rootroot00000000000000lensfun-0.3.4/docs/CMakeLists.txt000066400000000000000000000030701445356770400166770ustar00rootroot00000000000000# find doxygen FIND_PACKAGE(Doxygen REQUIRED) # set some files/path for later user # we don't use path doc because path doc is used by cmake itself because # of target doc SET(CMAKE_DOC_OUT ${CMAKE_BINARY_DIR}/doc_doxygen) set(DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/doxyfile") # create doxyfile CONFIGURE_FILE(doxyfile.in.cmake ${DOXYFILE} @ONLY) # now build documentation ADD_CUSTOM_TARGET(doc ALL COMMAND "${DOXYGEN_EXECUTABLE}" DEPENDS "${DOXYFILE}" manual-main.txt ../include/lensfun/lensfun.h.in WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMENT "Building documentation with doxygen" ) # install documentation INSTALL(DIRECTORY ${CMAKE_DOC_OUT}/ DESTINATION ${CMAKE_INSTALL_DOCDIR}) # create and install man pages FIND_PROGRAM(RST2MAN_EXECUTABLE NAMES rst2man rst2man.py rst2man2 rst2man2.py) ADD_CUSTOM_TARGET(man ALL) ADD_CUSTOM_COMMAND( TARGET man COMMAND ${RST2MAN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/man/g-lensfun-update-data.1.rst > ${CMAKE_CURRENT_BINARY_DIR}/g-lensfun-update-data.1 COMMAND ${RST2MAN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/man/lensfun-update-data.1.rst > ${CMAKE_CURRENT_BINARY_DIR}/lensfun-update-data.1 COMMAND ${RST2MAN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/man/lensfun-add-adapter.1.rst > ${CMAKE_CURRENT_BINARY_DIR}/lensfun-add-adapter.1 WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" ) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/g-lensfun-update-data.1 ${CMAKE_CURRENT_BINARY_DIR}/lensfun-update-data.1 ${CMAKE_CURRENT_BINARY_DIR}/lensfun-add-adapter.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 ) lensfun-0.3.4/docs/cc-by-sa-3.0.txt000066400000000000000000000511151445356770400165770ustar00rootroot00000000000000License THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. 1. Definitions 1. "Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License. 2. "Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined below) for the purposes of this License. 3. "Creative Commons Compatible License" means a license that is listed at http://creativecommons.org/compatiblelicenses that has been approved by Creative Commons as being essentially equivalent to this License, including, at a minimum, because that license: (i) contains terms that have the same purpose, meaning and effect as the License Elements of this License; and, (ii) explicitly permits the relicensing of adaptations of works made available under that license under this License or a Creative Commons jurisdiction license with the same License Elements as this License. 4. "Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership. 5. "License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, ShareAlike. 6. "Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License. 7. "Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast. 8. "Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work. 9. "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation. 10. "Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images. 11. "Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium. 2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws. 3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: 1. to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections; 2. to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified."; 3. to Distribute and Publicly Perform the Work including as incorporated in Collections; and, 4. to Distribute and Publicly Perform Adaptations. 5. For the avoidance of doubt: 1. Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; 2. Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor waives the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; and, 3. Voluntary License Schemes. The Licensor waives the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License. The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved. 4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: 1. You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(c), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(c), as requested. 2. You may Distribute or Publicly Perform an Adaptation only under the terms of: (i) this License; (ii) a later version of this License with the same License Elements as this License; (iii) a Creative Commons jurisdiction license (either this or a later license version) that contains the same License Elements as this License (e.g., Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible License. If you license the Adaptation under one of the licenses mentioned in (iv), you must comply with the terms of that license. If you license the Adaptation under the terms of any of the licenses mentioned in (i), (ii) or (iii) (the "Applicable License"), you must comply with the terms of the Applicable License generally and the following provisions: (I) You must include a copy of, or the URI for, the Applicable License with every copy of each Adaptation You Distribute or Publicly Perform; (II) You may not offer or impose any terms on the Adaptation that restrict the terms of the Applicable License or the ability of the recipient of the Adaptation to exercise the rights granted to that recipient under the terms of the Applicable License; (III) You must keep intact all notices that refer to the Applicable License and to the disclaimer of warranties with every copy of the Work as included in the Adaptation You Distribute or Publicly Perform; (IV) when You Distribute or Publicly Perform the Adaptation, You may not impose any effective technological measures on the Adaptation that restrict the ability of a recipient of the Adaptation from You to exercise the rights granted to that recipient under the terms of the Applicable License. This Section 4(b) applies to the Adaptation as incorporated in a Collection, but this does not require the Collection apart from the Adaptation itself to be made subject to the terms of the Applicable License. 3. If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and (iv) , consistent with Ssection 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties. 4. Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise. 5. Representations, Warranties and Disclaimer UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. Termination 1. This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License. 2. Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. 8. Miscellaneous 1. Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License. 2. Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License. 3. If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. 4. No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. 5. This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You. 6. The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law. lensfun-0.3.4/docs/doxyfile.in.cmake000066400000000000000000002352021445356770400173750ustar00rootroot00000000000000# Doxyfile 1.8.4 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed # in front of the TAG it is preceding . # All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = lensfun # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_MICRO@.@VERSION_BUGFIX@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = @CMAKE_DOC_OUT@ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian, # Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, # Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. Note that you specify absolute paths here, but also # relative paths, which will be relative from the directory where doxygen is # started. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding # "class=itcl::class" will allow you to use the command class in the # itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, # and language is one of the parsers supported by doxygen: IDL, Java, # Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, # C++. For instance to make doxygen treat .inc files as Fortran files (default # is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note # that for custom extensions you also need to set FILE_PATTERNS otherwise the # files are not read by doxygen. EXTENSION_MAPPING = # If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all # comments according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you # can mix doxygen, HTML, and XML commands with Markdown formatting. # Disable only in case of backward compatibilities issues. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by by putting a % sign in front of the word # or globally by setting AUTOLINK_SUPPORT to NO. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES (the # default) will make doxygen replace the get and set methods by a property in # the documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields or simple typedef fields will be shown # inline in the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO (the default), structs, classes, and unions are shown on a separate # page (for HTML and Man pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can # be an expensive process and often the same symbol appear multiple times in # the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too # small doxygen will become slower. If the cache is too large, memory is wasted. # The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid # range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536 # symbols. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if section-label ... \endif # and \cond section-label ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this # feature you need bibtex and perl available in the search path. Do not use # file names with spaces, bibtex cannot handle them. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = @CMAKE_SOURCE_DIR@/docs/manual-main.txt \ @CMAKE_BINARY_DIR@/lensfun.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = @CMAKE_SOURCE_DIR@ # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = YES # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be ignored. # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = # If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C, C++ and Fortran comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = . # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If left blank doxygen will # generate a default style sheet. Note that it is recommended to use # HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this # tag will in the future become obsolete. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional # user-defined cascading style sheet that is included after the standard # style sheets created by doxygen. Using this option one can overrule # certain style aspects. This is preferred over using HTML_STYLESHEET # since it does not replace the standard style sheet and is therefor more # robust against future updates. Doxygen will copy the style sheet file to # the output directory. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of # entries shown in the various tree structured indices initially; the user # can expand and collapse entries dynamically later on. Doxygen will expand # the tree to such a level that at most the specified number of entries are # visible (unless a fully collapsed tree already exceeds this amount). # So setting the number of entries 1 will produce a full collapsed tree by # default. 0 is a special value representing an infinite number of entries # and will result in a full expanded tree by default. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely # identify the documentation publisher. This should be a reverse domain-name # style string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) # at top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. Since the tabs have the same information as the # navigation tree you can set this option to NO if you already set # GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. # Since the tree basically has the same information as the tab index you # could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you may also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = YES # When MathJax is enabled you can set the default output format to be used for # the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and # SVG. The default value is HTML-CSS, which is slower, but has the best # compatibility. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to # the MathJax Content Delivery Network so you can quickly see the result without # installing MathJax. # However, it is strongly recommended to install a local # copy of MathJax from http://www.mathjax.org before deployment. MATHJAX_RELPATH = http://lensfun.sourceforge.net/mathjax # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript # pieces of code that will be used on startup of the MathJax code. MATHJAX_CODEFILE = @CMAKE_SOURCE_DIR@/docs/mathjaxConfiguration.js # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using Javascript. # There are two flavours of web server based search depending on the # EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for # searching and an index file used by the script. When EXTERNAL_SEARCH is # enabled the indexing and searching needs to be provided by external tools. # See the manual for details. SERVER_BASED_SEARCH = NO # When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP # script for searching. Instead the search results are written to an XML file # which needs to be processed by an external indexer. Doxygen will invoke an # external search engine pointed to by the SEARCHENGINE_URL option to obtain # the search results. Doxygen ships with an example indexer (doxyindexer) and # search engine (doxysearch.cgi) which are based on the open source search # engine library Xapian. See the manual for configuration details. EXTERNAL_SEARCH = NO # The SEARCHENGINE_URL should point to a search engine hosted by a web server # which will returned the search results when EXTERNAL_SEARCH is enabled. # Doxygen ships with an example search engine (doxysearch) which is based on # the open source search engine library Xapian. See the manual for configuration # details. SEARCHENGINE_URL = # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed # search data is written to a file for indexing by an external tool. With the # SEARCHDATA_FILE tag the name of this file can be specified. SEARCHDATA_FILE = searchdata.xml # When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the # EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is # useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple # projects and redirect the results back to the right project. EXTERNAL_SEARCH_ID = # The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen # projects other than the one defined by this configuration file, but that are # all added to the same external search index. Each project needs to have a # unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id # of to a relative location where the documentation can be found. # The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ... EXTRA_SEARCH_MAPPINGS = #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4 will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images # or other source files which should be copied to the LaTeX output directory. # Note that the files will be copied as-is; there are no commands or markers # available. LATEX_EXTRA_FILES = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- # If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files # that can be used to generate PDF. GENERATE_DOCBOOK = NO # The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be put in # front of it. If left blank docbook will be used as the default path. DOCBOOK_OUTPUT = docbook #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = __cplusplus \ LF_EXPORT= \ CONF_LENSFUN_STATIC # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. For each # tag file the location of the external documentation should be added. The # format of a tag file without this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths # or URLs. Note that each tag file must have a unique name (where the name does # NOT include the path). If a tag file is not located in the directory in which # doxygen is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # If the EXTERNAL_PAGES tag is set to YES all external pages will be listed # in the related pages index. If set to NO, only the current project's # pages will be listed. EXTERNAL_PAGES = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If the UML_LOOK tag is enabled, the fields and methods are shown inside # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more # manageable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES lensfun-0.3.4/docs/example/000077500000000000000000000000001445356770400155725ustar00rootroot00000000000000lensfun-0.3.4/docs/example/example.c000066400000000000000000000052421445356770400173740ustar00rootroot00000000000000/* A simple example of library usage from plain C */ #include "lensfun.h" #include #include #include int main () { int i, j; const struct lfMount *const *mounts; const struct lfCamera *const *cameras; const struct lfLens *const *lenses; struct lfDatabase *ldb; lfError e; /* Initialize locale in order to get translated names */ setlocale (LC_ALL, ""); ldb = lf_db_new (); if (!ldb) { fprintf (stderr, "Failed to create database\n"); return -1; } g_print ("HomeDataDir: %s\n", ldb->HomeDataDir); lf_db_load (ldb); g_print ("< --------------- < Mounts > --------------- >\n"); mounts = lf_db_get_mounts (ldb); for (i = 0; mounts [i]; i++) { g_print ("Mount: %s\n", lf_mlstr_get (mounts [i]->Name)); if (mounts [i]->Compat) for (j = 0; mounts [i]->Compat [j]; j++) g_print ("\tCompat: %s\n", mounts [i]->Compat [j]); } g_print ("< --------------- < Cameras > --------------- >\n"); cameras = lf_db_get_cameras (ldb); for (i = 0; cameras [i]; i++) { g_print ("Camera: %s / %s %s%s%s\n", lf_mlstr_get (cameras [i]->Maker), lf_mlstr_get (cameras [i]->Model), cameras [i]->Variant ? "(" : "", cameras [i]->Variant ? lf_mlstr_get (cameras [i]->Variant) : "", cameras [i]->Variant ? ")" : ""); g_print ("\tMount: %s\n", lf_db_mount_name (ldb, cameras [i]->Mount)); g_print ("\tCrop factor: %g\n", cameras [i]->CropFactor); } g_print ("< --------------- < Lenses > --------------- >\n"); lenses = lf_db_get_lenses (ldb); for (i = 0; lenses [i]; i++) { g_print ("Lens: %s / %s\n", lf_mlstr_get (lenses [i]->Maker), lf_mlstr_get (lenses [i]->Model)); g_print ("\tCrop factor: %g\n", lenses [i]->CropFactor); g_print ("\tAspect ratio: %g\n", lenses [i]->AspectRatio); g_print ("\tFocal: %g-%g\n", lenses [i]->MinFocal, lenses [i]->MaxFocal); g_print ("\tAperture: %g-%g\n", lenses [i]->MinAperture, lenses [i]->MaxAperture); g_print ("\tCenter: %g,%g\n", lenses [i]->CenterX, lenses [i]->CenterY); if (lenses [i]->Mounts) for (j = 0; lenses [i]->Mounts [j]; j++) g_print ("\tMount: %s\n", lf_db_mount_name (ldb, lenses [i]->Mounts [j])); } g_print ("< ---< Saving database into one big file >--- >\n"); e = lf_db_save_file (ldb, "example-big.xml", mounts, cameras, lenses); if (e != LF_NO_ERROR) fprintf (stderr, "Failed writing to file, error code %d\n", e); lf_db_destroy (ldb); return 0; } lensfun-0.3.4/docs/example/tfun.cpp000066400000000000000000000114511445356770400172540ustar00rootroot00000000000000/* Test for database search functions. */ #include "lensfun.h" #include #include #include #include #include static void DisplayVersion () { g_print ("Lensfun version %d.%d.%d: test database search routines\n", LF_VERSION_MAJOR, LF_VERSION_MINOR, LF_VERSION_MICRO); g_print ("Copyright (C) 2007 Andrew Zabolotny\n\n"); g_print ("For distribution rules and conditions of use see the file\n"); g_print ("COPYING which is part of the distribution.\n"); } static void DisplayUsage () { DisplayVersion (); g_print ("\nIf no options are given, some standard tests will be run.\n"); g_print ("Command-line options:\n\n"); g_print (" -L# --lens=# Use calibration data for this lens\n"); g_print (" -m# --max=# Limit the amount results\n"); g_print (" -f --fuzzy More fuzzy search algorithm\n"); g_print (" -V --version Display program version and exit\n"); g_print (" -h --help Display this help text\n"); } static void PrintMount (const lfMount *mount) { g_print ("Mount: %s\n", lf_mlstr_get (mount->Name)); if (mount->Compat) for (int j = 0; mount->Compat [j]; j++) g_print ("\tCompat: %s\n", mount->Compat [j]); } static void PrintCamera (const lfCamera *camera, const lfDatabase *ldb) { g_print ("Camera: %s / %s %s%s%s\n", lf_mlstr_get (camera->Maker), lf_mlstr_get (camera->Model), camera->Variant ? "(" : "", camera->Variant ? lf_mlstr_get (camera->Variant) : "", camera->Variant ? ")" : ""); g_print ("\tMount: %s\n", lf_db_mount_name (ldb, camera->Mount)); g_print ("\tCrop factor: %g\n", camera->CropFactor); } static void PrintLens (const lfLens *lens, const lfDatabase *ldb) { g_print ("Lens: %s / %s\n", lf_mlstr_get (lens->Maker), lf_mlstr_get (lens->Model)); g_print ("\tCrop factor: %g\n", lens->CropFactor); g_print ("\tAspect ratio: %g\n", lens->AspectRatio); g_print ("\tFocal: %g-%g\n", lens->MinFocal, lens->MaxFocal); g_print ("\tAperture: %g-%g\n", lens->MinAperture, lens->MaxAperture); g_print ("\tCenter: %g,%g\n", lens->CenterX, lens->CenterY); if (lens->Mounts) for (int j = 0; lens->Mounts [j]; j++) g_print ("\tMount: %s\n", lf_db_mount_name (ldb, lens->Mounts [j])); } static void PrintCameras (const lfCamera **cameras, const lfDatabase *ldb, int maxEntries=-1) { if (cameras) for (int i = 0; cameras [i]; i++) { g_print ("--- camera %d: ---\n", i + 1); PrintCamera (cameras [i], ldb); if ((maxEntries > 0) && (i>=maxEntries-1)) break; } else g_print ("\t- failed\n"); } static void PrintLenses (const lfLens **lenses, const lfDatabase *ldb, int maxEntries=-1) { if (lenses) for (int i = 0; lenses [i]; i++) { g_print ("--- lens %d, score %d: ---\n", i + 1, lenses [i]->Score); PrintLens (lenses [i], ldb); if ((maxEntries > 0) && (i>=maxEntries-1)) break; } else g_print ("\t- failed\n"); } int main (int argc, char **argv) { static struct option long_options[] = { {"lens", required_argument, NULL, 'L'}, {"max", required_argument, NULL, 'm'}, {"fuzzy", no_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {0, 0, 0, 0} }; static struct { int maxResults; bool fuzzySearch; const char *Lens; } opts = { -1, 0, NULL, }; setlocale (LC_ALL, ""); int c; while ((c = getopt_long (argc, argv, "L:m:fhV", long_options, NULL)) != EOF) { switch (c) { case'L': opts.Lens = optarg; break; case 'm': opts.maxResults = atoi(optarg); break; case 'f': opts.fuzzySearch = LF_SEARCH_LOOSE; break; case 'h': DisplayUsage(); return 0; case 'V': DisplayVersion (); return 0; default: return -1; } } lfDatabase *ldb = lf_db_new (); ldb->Load (); if (opts.Lens == NULL) { g_print ("No lens name is given\n"); DisplayUsage(); ldb->Destroy (); return -1; } g_print (">>> Looking for lens '%s' %d\n", opts.Lens, opts.fuzzySearch); const lfLens **lenses = ldb->FindLenses (NULL, NULL, opts.Lens, opts.fuzzySearch); PrintLenses (lenses, ldb, opts.maxResults); lf_free (lenses); ldb->Destroy (); return 0; } lensfun-0.3.4/docs/gpl-3.0.txt000066400000000000000000001045131445356770400157640ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . lensfun-0.3.4/docs/lensfun-logo.svg000066400000000000000000000760531445356770400173030ustar00rootroot00000000000000 image/svg+xml lensfun-0.3.4/docs/lgpl-3.0.txt000066400000000000000000000167271445356770400161510ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. lensfun-0.3.4/docs/make-release-0.3.x.txt000066400000000000000000000066561445356770400200140ustar00rootroot00000000000000This file describes how to make a 0.3.x maintenance release. WHY ============ The code in lensfun master has switched to database version 2, but there hasn't been a new stable release yet and everybody out there is still using the 0.3.x branch. There hasn't been a new release in the lensfund 0.3.x branch since 0.3.2 in 2015. The database keeps evolving, but many users don't know they have to run `lensfun-update-data` to update their local database checkout. Also many distributions ship the 0.3.2 version without any recent database updates. Many third-party software packages that rely on the lensfun database also aren't ready to switch to 0.3.95/0.4.0 and database version 2 yet. darktable for example has some code to support lensfun 0.3.95, but doesn't reliably build against it. It is therefore a good a idea to keep shipping 0.3.x maintenance releases that just contain more recent database snapshots and a few minor fixes. This will also make people aware that database development continues. HOW TO MAKE A RELEASE ===================== 1. Clone the lensfun repository. If you already have a local checkout, switch to the master branch instead. ``` git clone git@github.com:lensfun/lensfun.git ``` 2. Use the `tools/lensfun_convert_db_v2_to_v1.py` tool to convert the database in `master` to version 1: ``` python3 tools/lensfun_convert_db_v2_to_v1.py /tmp/converted/ data/db/ ``` This will create a couple of tarballes in `/tmp/converted/db/`. These are the same tarballs that the `lensfun-update-data` downloads. The code in `lensfun_convert_db_v2_to_v1.py` was ripped out of the script that does the conversion for the webserver `lensfun-update-data` pulls them from. 3. Switch to the `release_0.3.x` branch. ``` git checkout release_0.3.x ``` 4. Delete all XML files in `data/db/`. ``` rm data/db/*.xml ``` 5. Extract the converted XML files to `data/db/`. ``` tar -xvf /tmp/converted/db/version_1.tar -C data/db/ ``` 6. Check the database. ``` python3 tools/check_database/check_database.py data/db/ ``` 7. Check that everything is fine. Build the library, install it locally, test it with an application, etc. 8. Make any other changes, e.g. bugfixes. 9. Add all changed database files to the git staging area and make a commit. ``` git add data/db/* ``` 10. Update the Changelog file. You can use the following command to generate a list of supported cameras: ``` xmlstarlet sel -t --var nl -n --break -m "/lensdatabase" -m "camera" --if 'model[@lang="en"]' -v 'concat(maker, " ", model[@lang="en"], $nl)' --else -v 'concat(maker, " ", model, $nl)' --break data/db/*.xml | sort ``` Likewise, the following command will generate a list of supported lenses: ``` xmlstarlet sel -t --var nl -n --break -m "/lensdatabase" -m "lens" --if 'model[@lang="en"]' -v 'concat(maker, " ", model[@lang="en"], $nl)' --else -v 'concat(maker, " ", model, $nl)' --break data/db/*.xml | sort ``` You can use this information to update the ChangeLog. 11. Update the version number in `CMakeLists.txt`. ``` # version SET(VERSION_MAJOR 0) SET(VERSION_MINOR 3) SET(VERSION_MICRO 3) SET(VERSION_BUGFIX 0) SET(VERSION_API 1) ``` 12. Add `ChangLog`, `CMakeLists` and any other changed files and make a commit. ``` git add Changelog CMakeLists.txt git commit -m "Release 0.3.3" ``` 12. Add a new release tag. ``` git tag v0.3.3 ``` 13. Push the `release_0.3.x` branch and the new tag to GitHub. ``` git push git push origin v0.3.3 ``` 14. Make a new release on GitHub. lensfun-0.3.4/docs/man/000077500000000000000000000000001445356770400147125ustar00rootroot00000000000000lensfun-0.3.4/docs/man/README000066400000000000000000000005641445356770400155770ustar00rootroot00000000000000The man pages are created from restructuredText files (extension .rst). So please do not edit the man pages (extension .1). Edit the rst files instead an call rst2man xxx.1.rst > xxx.1 rst2man is part of the package python3-docutils. The .1 file are included for convenience into the repository. They may be removed someday, possiby along with this README file. lensfun-0.3.4/docs/man/g-lensfun-update-data.1.rst000066400000000000000000000021101445356770400216620ustar00rootroot00000000000000======================== g-lensfun-update-data ======================== ---------------------------- update Lensfun's database ---------------------------- :Author: This manual page was written by Torsten Bronger :Date: 2013-12-23 :Manual section: 1 SYNOPSIS ============ ``g-lensfun-update-data`` DESCRIPTION =============== ``g-lensfun-update-data`` is a GUI version of ``lensfun-update-data``. Both programs do the same, however, ``g-lensfun-update-data`` will ask for a root password if needed in a popup window rather than on the command line. This way, it comes in handy if a GUI program wants to let the user update Lensfun's database. See the manpage of ``lensfun-update-data`` for further information, and pay special attention to the DIAGNOSTICS section. COPYRIGHT ============= Lensfun is Copyright © 2007 Andrew Zabolotny License of the code: GNU Lesser General Public License, version 3 License of the database: Creative Commons Attribution-Share Alike 3.0 license SEE ALSO =========== lensfun-update-data(1), lensfun-add-adapter(1) lensfun-0.3.4/docs/man/lensfun-add-adapter.1.rst000066400000000000000000000072001445356770400214200ustar00rootroot00000000000000====================== lensfun-add-adapter ====================== -------------------------------------------------------- add lens mount compatibilities to Lensfun's database -------------------------------------------------------- :Author: This manual page was written by Torsten Bronger :Date: 2013-12-23 :Manual section: 1 SYNOPSIS ============ | ``lensfun-add-adapter`` | ``lensfun-add-adapter`` [``--maker`` `MAKER`] [``--model`` `MODEL`] [``--mount`` `MOUNT`] | ``lensfun-add-adapter`` ``--remove-local-mount-config`` DESCRIPTION =============== Lensfun is a library that corrects flaws in photographic images introduced by the lens. It also contains a comprehensive database of cameras and lenses together with their characteristics to be able to apply automatic corrections of images taken with these devices. Lensfun is used by darktable, digiKam, rawstudio, GimpLensfun, UFRaw, and others. Lensfun contains information about lens mounts of cameras and available mounts for lens models. This way, the calling application can offer the user a list with lenses that fit on their camera in order to pick one. Otherwise, you would see *all* lenses every time. This can be pretty overwhelming. But if you bought an adapter for another mount system, you would want to see lenses of that mount system listed for your camera. So, you must tell Lensfun somehow that you own the adapter. You can do so by calling ``lensfun-add-adapter``. The easiest way to use it is to call it with no parameters. ``lensfun-add-adapter`` will then enter an interactive mode. First you have to enter your camera model. ``lensfun-add-adapter`` will use that to determine the destination mount. In particular, the extended lens lists will show up for every camera with that mount, not just the one you entered. Then, you have to select the mount of the lenses you can now put on your camera, using the adapter. That's it. With the options ``--maker``, ``--model``, and ``--mount``, you can avoid interactive mode by passing the nevcessary data explicitly. If you pass only maker/model or only mount, ``lensfun-add-adapter`` will enter interactive mode only for the missing data. You can also use ``lensfun-add-adapter`` to reset your adapter configuration. Call it with the ``--help`` paremeter to see all functions. OPTIONS ========= ``--maker`` `MAKER` ``--model`` `MODEL` The exact maker and model of the camera the mount of which should be made compatible. You must provide these options only in combination rather than only one of them. ``--mount`` `MOUNT` The exact name of the mount of the lenses that should be made compatible. ``--remove-local-mount-config`` Resets the local mount configuration, i.e. the additional mount compatibilities that were created by this program. Effectively, it removes the file ``_mount.xml`` from the local Lensfun database of the current user. FILES ===== ``~/.local/share/lensfun/_mounts.xml`` File with all mount compatibilities that were added by this program. DIAGNOSTICS =============== Exit status: =========== ===================================== 0 successful 1 invalid command line arguments 2 invalid input in interactive mode =========== ===================================== REPORTING BUGS ==================== Report bugs at . COPYRIGHT ============= Lensfun is Copyright © 2007 Andrew Zabolotny License of the code: GNU Lesser General Public License, version 3 License of the database: Creative Commons Attribution-Share Alike 3.0 license SEE ALSO ============ lensfun-update-data(1) lensfun-0.3.4/docs/man/lensfun-update-data.1.rst000066400000000000000000000042041445356770400214440ustar00rootroot00000000000000====================== lensfun-update-data ====================== ---------------------------- update Lensfun's database ---------------------------- :Author: This manual page was written by Torsten Bronger :Date: 2015-03-11 :Manual section: 1 SYNOPSIS ============ ``lensfun-update-data`` DESCRIPTION =============== Lensfun is a library that corrects flaws in photographic images introduced by the lens. It also contains a comprehensive database of cameras and lenses together with their characteristics to be able to apply automatic corrections of images taken with these devices. Lensfun is used by darktable, digiKam, rawstudio, GimpLensfun, UFRaw, and others. ``lensfun-update-data`` is a command-line program that updates Lensfun's database. It looks whether a new version is available online, and if this is the case, it fetches the latest version and installs it locally. If called as root, the database is installed system-wide, otherwise, it is installed in the user's directory. FILES ====== ``lensfun-update-data`` will place the fetched database in ``/var/lib/lensfun-updates/`` (if called as root) or in ``~/.local/share/lensfun/updates/`` (otherwise). If necessary, it will create this directory. If there is already a database, it is replaced fully. If Lensfun detects a database in one of these directories, it will use that instead of the default location below ``/usr/...``. DIAGNOSTICS =============== ``lensfun-update-data`` prints log messages to stdout. Exit status: =========== ===================================== 0 if OK (updates were installed), 1 if no newer version could be found, 3 if no DB location responded validly. =========== ===================================== REPORTING BUGS ==================== Report bugs at . COPYRIGHT ============= Lensfun is Copyright © 2007 Andrew Zabolotny License of the code: GNU Lesser General Public License, version 3 License of the database: Creative Commons Attribution-Share Alike 3.0 license SEE ALSO ============ g-lensfun-update-data(1), lensfun-add-adapter(1) lensfun-0.3.4/docs/manual-doc.conf000066400000000000000000002355401445356770400170370ustar00rootroot00000000000000# Doxyfile 1.8.4 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed # in front of the TAG it is preceding . # All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = lensfun # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @CONF_VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = @OUT@ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian, # Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, # Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. Note that you specify absolute paths here, but also # relative paths, which will be relative from the directory where doxygen is # started. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding # "class=itcl::class" will allow you to use the command class in the # itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, # and language is one of the parsers supported by doxygen: IDL, Java, # Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, # C++. For instance to make doxygen treat .inc files as Fortran files (default # is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note # that for custom extensions you also need to set FILE_PATTERNS otherwise the # files are not read by doxygen. EXTENSION_MAPPING = # If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all # comments according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you # can mix doxygen, HTML, and XML commands with Markdown formatting. # Disable only in case of backward compatibilities issues. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by by putting a % sign in front of the word # or globally by setting AUTOLINK_SUPPORT to NO. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES (the # default) will make doxygen replace the get and set methods by a property in # the documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields or simple typedef fields will be shown # inline in the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO (the default), structs, classes, and unions are shown on a separate # page (for HTML and Man pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can # be an expensive process and often the same symbol appear multiple times in # the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too # small doxygen will become slower. If the cache is too large, memory is wasted. # The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid # range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536 # symbols. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if section-label ... \endif # and \cond section-label ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this # feature you need bibtex and perl available in the search path. Do not use # file names with spaces, bibtex cannot handle them. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = docs/manual-main.txt \ include/lensfun/lensfun.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = . # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = YES # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be ignored. # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = # If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C, C++ and Fortran comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = . # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If left blank doxygen will # generate a default style sheet. Note that it is recommended to use # HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this # tag will in the future become obsolete. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional # user-defined cascading style sheet that is included after the standard # style sheets created by doxygen. Using this option one can overrule # certain style aspects. This is preferred over using HTML_STYLESHEET # since it does not replace the standard style sheet and is therefor more # robust against future updates. Doxygen will copy the style sheet file to # the output directory. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of # entries shown in the various tree structured indices initially; the user # can expand and collapse entries dynamically later on. Doxygen will expand # the tree to such a level that at most the specified number of entries are # visible (unless a fully collapsed tree already exceeds this amount). # So setting the number of entries 1 will produce a full collapsed tree by # default. 0 is a special value representing an infinite number of entries # and will result in a full expanded tree by default. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely # identify the documentation publisher. This should be a reverse domain-name # style string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) # at top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. Since the tabs have the same information as the # navigation tree you can set this option to NO if you already set # GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. # Since the tree basically has the same information as the tab index you # could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you may also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = YES # When MathJax is enabled you can set the default output format to be used for # the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and # SVG. The default value is HTML-CSS, which is slower, but has the best # compatibility. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to # the MathJax Content Delivery Network so you can quickly see the result without # installing MathJax. # However, it is strongly recommended to install a local # copy of MathJax from http://www.mathjax.org before deployment. MATHJAX_RELPATH = http://lensfun.sourceforge.net/mathjax # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript # pieces of code that will be used on startup of the MathJax code. MATHJAX_CODEFILE = docs/mathjaxConfiguration.js # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using Javascript. # There are two flavours of web server based search depending on the # EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for # searching and an index file used by the script. When EXTERNAL_SEARCH is # enabled the indexing and searching needs to be provided by external tools. # See the manual for details. SERVER_BASED_SEARCH = NO # When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP # script for searching. Instead the search results are written to an XML file # which needs to be processed by an external indexer. Doxygen will invoke an # external search engine pointed to by the SEARCHENGINE_URL option to obtain # the search results. Doxygen ships with an example indexer (doxyindexer) and # search engine (doxysearch.cgi) which are based on the open source search # engine library Xapian. See the manual for configuration details. EXTERNAL_SEARCH = NO # The SEARCHENGINE_URL should point to a search engine hosted by a web server # which will returned the search results when EXTERNAL_SEARCH is enabled. # Doxygen ships with an example search engine (doxysearch) which is based on # the open source search engine library Xapian. See the manual for configuration # details. SEARCHENGINE_URL = # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed # search data is written to a file for indexing by an external tool. With the # SEARCHDATA_FILE tag the name of this file can be specified. SEARCHDATA_FILE = searchdata.xml # When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the # EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is # useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple # projects and redirect the results back to the right project. EXTERNAL_SEARCH_ID = # The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen # projects other than the one defined by this configuration file, but that are # all added to the same external search index. Each project needs to have a # unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id # of to a relative location where the documentation can be found. # The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ... EXTRA_SEARCH_MAPPINGS = #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4 will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images # or other source files which should be copied to the LaTeX output directory. # Note that the files will be copied as-is; there are no commands or markers # available. LATEX_EXTRA_FILES = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- # If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files # that can be used to generate PDF. GENERATE_DOCBOOK = NO # The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be put in # front of it. If left blank docbook will be used as the default path. DOCBOOK_OUTPUT = docbook #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = __cplusplus \ LF_EXPORT= \ CONF_LENSFUN_STATIC # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. For each # tag file the location of the external documentation should be added. The # format of a tag file without this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths # or URLs. Note that each tag file must have a unique name (where the name does # NOT include the path). If a tag file is not located in the directory in which # doxygen is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # If the EXTERNAL_PAGES tag is set to YES all external pages will be listed # in the related pages index. If set to NO, only the current project's # pages will be listed. EXTERNAL_PAGES = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If the UML_LOOK tag is enabled, the fields and methods are shown inside # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more # manageable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES lensfun-0.3.4/docs/manual-main.txt000066400000000000000000001170351445356770400171060ustar00rootroot00000000000000/** @mainpage Lensfun: A library for rectifying and simulating photographic lens distortions @section intro Introduction The goal of the Lensfun library is to provide a open source database of photographic lenses and their characteristics. In the past there was a effort in this direction (see http://www.epaperpress.com/ptlens/), but then author decided to take the commercial route and the database froze at the last public stage. This database was used as the basement on which Lensfun database grew, thanks to PTLens author which gave his permission for this, while the code was totally rewritten from scratch (and the database was converted to a totally new, XML-based format). The Lensfun library not only provides a way to read the database and search for specific things in it, but also provides a set of algorithms for correcting images based on detailed knowledge of lens properties and calibration data. Right now Lensfun is designed to correct distortion, transversal (also known as lateral) chromatic aberrations, and vignetting. Furthermore, it can convert between different types of lenses, for example from fisheye into rectilinear. @section contents Contents
  • @ref license
  • @ref credits
  • Command line programs
    • @ref lensfun-update-data
    • @ref lensfun-add-adapter
  • @ref database
    • @ref dbformat
    • @ref dbsearch
    • @ref filldb
  • @ref corrections
  • @ref programming
    • @ref basearch
    • @ref samplecode
@page license Software license The libraries which are part of this package are licensed under the terms of the GNU Lesser General Public License, version 3. Libraries are located under the subdirectory libs/ of the source package. A copy of the license is available in the file lgpl-3.0.txt which can be found in the source archive. You can read it here: @ref lgpl or on the GNU site. Applications which are part of this package are licensed under the terms of the GNU General Public License, version 3. Applications are located under the apps/ subdirectory of the source package. A copy of the license can be found in the file gpl-3.0.txt which can be found in the source archive. You can read it here: @ref gpl or on the GNU site. Test programs and tools are put into public domain, unless explicitly specified otherwise in the header of the source files. Test programs are located under the tests/ subdirectory, and tools are located in tools/. The lens database is licensed under the Creative Commons Attribution-Share Alike 3.0 license. The database is located under the data/ subdirectory of the source package. You can read it here: @ref cc-by-ca or on the Creative Commons Web site. @page credits Credits This project was contrived by Andrew Zabolotny, who developed all features present in Lensfun. Later, when Andrew had no time anymore for regular releases, Sebastian Kraft took over maintenance. The following people contributed code:
  • Niels Kristian Bech Jensen
  • Pascal de Bruijn
  • Thomas Modes
  • Torsten Bronger
The following people directly or indirectly contributed to the birth and growth of this library:
  • Thomas Niemann for the original open-source PTLens software and database.
  • Pablo d'Angelo for the idea of a open-source lens database.
  • The whole PanoTools team: for all math and knowledge I have borrowed from PanoTools.
    • Helmut Dersch – The father of most (all?) open-source panorama creation tools.
    • Daniel M. German
    • Kevin Kratzke
    • Rik Littlefield
    • Fulvio Senore
    • Jim Watters
    • Thomas Rauscher
    • Pablo d'Angelo (thanks once more :)
    • Bret McKee
    • Robert Platt
Also I would like to thank all the people sending profiles for the database. @page lensfun-update-data Updating Lensfun's database: lensfun‑update-data New lenses and cameras arrive at Lensfun every week. So, it is desirable to update your copy of Lensfun's database to stay up-to-date. In particular, if you have sent calibration pictures to Torsten's calibration service, you must update your local Lensfun database after the calibration in order to be able to use the new calibrations. For this purpose, there exists a simple command-line tool called “update‑lensfun‑data”. If you call it (it doesn't need parameters), just wait for a second and the database is updated. It will report whether an update was necessary. If you want the updates to be installed system-wide, the program needs root privileges. So call the program with “sudo lensfun‑update‑data” and enter your root password. There exists a second version of the programm called “g‑lensfun‑update‑data”. It will let you enter the root password – if new data is available – in a neat window. This version is especially useful for GUI programs, which can call it in the background. If it is sufficient that the updates are available to only your user account, call “lensfun‑update‑data” without root priviledges. The updates are then written to ~/.local/share/lensfun/updates”. In case there is more than one version of Lensfun on your system (e.g. you installed a new version, but the original version of your Linux distribution is still there and used by some programs), “lensfun‑update‑data” tries to detect this and updates the other database versions, too. @page lensfun-add-adapter Adding mount adapters: lensfun‑add‑adapter Lensfun contains information about lens mounts of cameras and available mounts for lens models. This way, the calling application can offer the user a list with lenses that fit on their camera in order to pick one. Otherwise, you would see *all* lenses every time. This can be pretty overwhelming. But if you bought an adapter for another mount system, you would want to see lenses of that mount system listed for your camera. So, you must tell Lensfun somehow that you own the adapter. You can do so by calling lensfun‑add‑adapter. The easiest way to use it is to call it with no parameters. lensfun‑add‑adapter will then enter an interactive mode. First you have to enter your camera model. lensfun‑add‑adapter will use that to determine the destination mount. In particular, the extended lens lists will show up for every camera with that mount, not just the one you entered. Then, you have to select the mount of the lenses you can now put on your camera, using the adapter. That's it. You can also use lensfun‑add‑adapter to reset your adapter configuration. Call it with the ‑‑help paremeter to see all functions. @page database Lens database Lensfun uses an XML-based format for its database. A single XML file can contain entries for mounts, cameras and lenses. The whole file content is enclosed in a @ element. The database is made of multiple XML files, conventionally split by manufacturer and camera type. Compact, SLR, and mirrorless cameras/lenses are split apart for easier maintainance. The database contains three kinds of objects: @b mounts, @b cameras and @b lenses. Every @b camera has a mount type assigned (and only one). Similarily, @b lenses also have a list of mounts assigned, because lenses often come in several variants with different mounts. Finally, every @b mount has assigned a list of compatible mounts, so if your camera has mount B which is compatible with mount A, you can list all the lenses that come either with mounts A or B. However, there are various custom adapters that can be used to connect lenses to bodies with “incompatible” mounts, so the application in any case may provide a mean to choose from the whole list in addition to filtering lenses by mount. The cameras may be autodetected by using EXIF information from the source image. However, the Lensfun library is not tied in any way to EXIF tags, it is in the application's responsibility to read those tags in any way they like. In fact, you may detect the camera which was used to take the image in some other way (for example, if you want to use Lensfun for processing images taken from videocams, which usually do not use EXIF, or scanned images from film cameras), you may even ask the user directly to choose the camera from a list. Same about lenses: you may either autodetect them (which is tricky even if you have EXIF information, since unlike camera/model the lens model is highly manufacturer-dependent and is usually hidden in the Exif.MakerNote tag which is a big binary blob; luckily the exiv2 library can parse many vendor-specific MakerNote's), or you may provide some mean for the user to enter the lens model manually. The Lensfun library will help you a little here, since it provides a means to match a set of lenses from the database given a human-entered lens description (e.g. fuzzy lens search).
  • @ref dbformat
  • @ref dbsearch
@page dbformat Database file format Here goes a simple lens database file, I hope I don't have to explain much what is what, as the format is pretty much self-documenting. @verbatim Pentax K M42 Pentax SMC Pentax M 50mm f/1.4 Pentax K 1.0 rectilinear Pentax Pentax K10D Pentax KAF2 1.531 @endverbatim The “version” attribute at the @ element denotes the format version of this database file. It is an integer number and defaults to “0”. Because it was introduced in Lensfun 0.3, “0” is the format version of all Lensfun releases before that. Database format changes mostly are backwards-compatible, so that a certain Lensfun version supports database versions up to a certain number. The most recent lens database is offered for download in all versions, and the @ref lensfun-update-data "lensfun-update-data" program fetches the appropriate for you. See @ref db_versions for the version history. Since lenses and cameras may be known with different names in different languages/countries, the library provides a built-in mechanism for name translations. You can provide such multi-language strings for every language you want, and when the library client will ask for string value, it will get the one in the current locale. This mechanism is also useful sometimes when you want to use a name for camera which is different from the value put in EXIF data. For example: @verbatim Konica Minolta Camera, Inc. Konica Minolta Коника Минольта @endverbatim The value without a “lang” attribute is always used for identification, but GUI may use the translated string for display. If no language matches, and an "en" translation is present, it is used. And only if there's no native translation and there's no "en" translation, the no-language version is used. Here is a complete list of elements recognized by the library and the format of the data within elements.
  • @ref el_mount
  • @ref el_camera
  • @ref el_lens
@page db_versions Database format versions
database
version
Lensfun
release
changesincompatibilities with
previous versions
0≤ 0.2.8
10.3
  • new: @ tag
  • new: @ tag
  • removed: @ tag
  • APS-C crop factors are given with a higher accuracy
@page el_mount Describing camera mounts: \ Add \ element only for mounts for interchangeable lenses. If the lens is fixed (mostly a compact camera), a \ element for it may be declared locally by the user (see \ref lensfun-add-adapter), but it should not be in the core database. Possible embedded elements:
\string\
This gives the name of the mount. Mount names for fixed-lens cameras – and only they – must start with a lower case letter.
\string\
Declares that this mount is compatible with another one. Usually this means that either they are directly compatible (e.g. the Pentax KAF2 mount is compatible with Pentax K so you can insert K lenses into a KAF2 camera) or there exists mount adapters which permit to install lenses with such mounts into this mount. Note that the compatibility is unidirectional, e.g. in the above example it doesn't say that you can insert Pentax KAF2 lenses into a Pentax K camera; if you need a two-way compatibility, declare it both ways. Also the “compatibility” is restricted in the sense that if mount A is compatible with mount B (e.g. you can put B lenses on an A camera), and mount B is compatible with mount C, this does not neccessarily mean that mount A is compatible with mount C. Recursion doesn't work here, this is a design decision. If you need to make mount A compatible with mount C, declare it so explicitely. Things are slightly complicated with mirrorless systems because they are adaptable to virtually any non-mirrorless system. In order to avoid too many useless entries in the lens selection lists for mirrorless mounts, only important (e.g. because only few native lenses yet exist) compatibilities should be included into Lensfun's official database (e.g. Canon EF on Canon M). The user can override this easily in their local database files, adding compatibilities for all mounts they have adaptors for, see @ref lensfun-add-adapter.
@page el_camera Declaring cameras: \ Possible embedded elements:
\string\
Camera maker. This must be specified \b exactly as it is specified in camera EXIF data to allow for automatic recognition of the camera. Upper and lower case doesn't matter, though.
\string\
Camera model. This must be specified \b exactly as it is specified in camera EXIF data to allow for automatic recognition of the camera. Upper and lower case doesn't matter, though.
\string\
Camera variant. Sometimes makers create several cameras without changing EXIF information. Unfortunately, camera variant cannot be automatically detected so this is a manual choice item. This field can also be used to deal with cameras with more than one aspect ratio. For every available aspect ratio, make a copy of the \ entry, entering the aspect ratio into the \ field (e.g. \16:9\). Of course, the crop factor may have to be adapted as well.
\string\
Camera mount. There can be only one such element in camera declaration. If you want to specify that it is possible to use lenses with a different mount on this camera, use the \ element in mount declaration.
\number\
Camera crop factor. This is the ratio between the standard film frame diagonal (36x24mm) and camera sensor diagonal. Be accurate here. For example, no APS-C camera really has crop factor 1.5.
@page el_lens Declaring lenses: \ Possible embedded elements:
\string\
Lens maker.
\string\
Lens model. This must be specified exactly as it is returned by EXIF reading libraries to allow for automatic recognition of the lens. However, upper and lower case doesn't matter, neither does the ordering of the “words” in the lens model name. A “word” in Lensfun interpretation is a sequence of characters of the same type (Lensfun senses three character types: digits, punctuation characters and all others). Words made of single punctuation characters are ignored. Also, as a special exception, the word consisting of a single “f” is ignored too. So, “[IF]” is really split into three words – “[”, “IF”, “]”, and then first and last words are discarded. Accordingly, “smc PENTAX-DA 12-24mm F4 ED AL [IF]” is split into “smc”, “pentax”, “da”, “12”, “24”, “mm”, “4”, “ED”, “AL”, “IF”. Have a look at other lenses of the same manufacturer for the naming conventions. See below for further information about the parsing of the model name field.
\string\
Lens type. This is one of: “rectilinear", “fisheye”, “panoramic”, “equirectangular”, “orthographic”, “stereographic”, “equisolid”, “fisheye_thoby”. If this field is not given, Lensfun assumes rectilinear.
\
Lens focal length in mm. This can be either a single value for a fixed-focal length lens, or a minimum and maximum value in the case of a zoom lens.
\
Lens aperture as the f-number. This can be either a single value for a fixed-aperture lens (very rare), or the minimal and maximal possible f-stop number for this lens (over the whole zoom range for a zoom lens).
\string\
Lens mount. There can be multiple \ entries if the same lens is manufactured with several mounts, or it has a variable mount (e.g. Tamron Adaptall).
\number\
This is the crop factor of the camera with which all shots for computing distortion models were made. The library will compute correction factors if you used this lens on another camera with a different crop factor. Generally it is advised to use a camera with maximal crop factor for this lens, because the models may become imprecise for crop factors smaller than the one used for models.
\number\
This is the aspect ratio of the camera with which all shots for computing distortion models were made. It is the ratio of the longer edge to the shorter edge. Lensfun needs the aspect ratio internally for correct application of the distortion parameters. You may give it is as a real number or as a ratio with a colon like “4:3”. It defaults to 1.5 or 3:2.
\
The decentering of the lens, i.e. the offset of its optical axis from the center of the viewframe. “x” denotes the offset in horizontal direction, “y” in vertical direction. The scale is so that the smaller dimension (for very most cameras the height) has the value 2. Both offsets default to 0. It may be particularly helpful for shift lenses.
\calibration data\
@ref elem_calibration
Library recognizes several ways to specify lens parameters directly in lens model name. The first way to specify lens focal length and aperture range is “[min focal]-[max focal]mm f/[min aperture]-[max aperture]” where the “mm” and “f/” are totally optional. For primes the 'max' values may be omited. Examples:
  • 70-210mm f/4-5.6
  • 18-55 3.5-5.6
  • 50 f2
Another pattern for lens parameters is “[min aperture]-[max aperture]/[min focal]-[max focal]”. Examples:
  • 2.8-3.5/25-45
  • 4.5/300
(Note that “max aperture” refers here to the minimal f-stop number at the maximal focal length of a zoom lens. Its value is ignored by Lensfun. As explained above, Lensfun only stores the minimal and maximal possible f-stop number of the lens, not matter at which focal length, e.g. 3.5–32.) If the focal length in the lens model name is wrong because a converter is used, one of the words “converter” or “extender” must appear somewhere in the lens model name. Moreover, the library finds missing min/max values for focal length and aperture by looking at the range of these parameters in the @ section. @page elem_calibration Lens calibration data format Possible embedded elements:
\
Declares the image distortion model for this lens. Distortion is specific for every focal length (in mm), so you can declare multiple distortion entries with different focal values; the library will interpolate the parameters for intermediate focal lengths. The model name may be "none", "poly3", "poly5", or "ptlens". @see lfDistortionModel
\
Declares the Transversal Chromatic Aberrations model for this lens, depending on focal length. The library will interpolate the parameters for intermediate focal lengths. The model name may be "none", "linear", or "poly3". @see lfTCAModel
\
Declares the vignetting model for this lens at given focal length (in mm), given aperture (as f-number), and given distance to subject in focus (in meters). This kind of calibration requires relatively many sample points since it depends on three variables. The library will interpolate the parameters for between the sample points if necessary. The model name may be "none" or "pa". @see lfVignettingModel
\
Declares the image crop for this lens. Crop can be specific for every focal length (in mm), so you can declare multiple crop entries with different focal values; the library will interpolate the parameters for intermediate focal lengths. The mode name may be "no_crop", "crop_rectangle", or "crop_circle". @see lfCropMode
\
Declares the *real* focal length of the lens in the paraxial approximation, in contrast to the *nominal* focal length used in all "focal" attributes. Especially for fisheye lenses, both values can differ significantly. Lensfun itself needs the real focal length for lens type transformations. It uses the nominal focal length as a fallback. The real focal length can be determined reliably only with a 360° panorama, e.g. with Hugin. However, Hugin's results need to be rectified. The real focal length must correspond to the distortion coefficients. Typically, they are the result of the very same parameter optimisation.
@page dbsearch How database files are found and loaded In a typical application, all XML files are loaded automatically at startup. If the same object is defined in multiple files, later definitions override earlier definitions, e.g. user can override system-wide definitions by placing appropriately formatted XML files in its home directory. A typical application will initialize the lens database by calling the method lfDatabase::Load() with no parameters. This method searches for all available XML files and loads them, ignoring files with errors. The main place where Lensfun looks for database files usually is /usr/share/lensfun/version_x, where x is the database format version (@ref db_versions). However, this is configurable at compilation time, and for locally compiled Lensfun, it is mostly /usr/local/share/lensfun/version_x. A special directory is /var/lib/lensfun-updates/version_x: If it exists and contains a newer database, it is loaded instead of the main place. On Windows, this is something like C:\\Documents and Settings\\\%User\%\\something\\version_x but I'm not sure exactly :-). “Newer database” means that the file timestamp.txt, which is amongst the XML files, contains a larger value. This value is the database timestamp in UNIX time. After having read the global database, the user's home directory is searched. Usually, this is ~/.local/share/lensfun. The exact path can be found in the variable lfDatabase::HomeDataDir. The subdirectory updates/version_x may contain a user-specific DB update. This represents an alternative to /var/lib/lensfun-updates/version_x for which no root priviledges are needed. ~/.local/share/lensfun/version_x is also scanned with higher priority than the one without the version_x, so that the user can set entries specific for a database version. This is useful only if you need to maintain two or more different Lensfun versions on your system. So sum it up for Linux and other Unix-like platforms, the load order is:
  1. the directory Lensfun's database was installed into (usually /usr/share/{local/}lensfun/version_x), @em or /var/lib/lensfun-updates/version_x, @em or ~/.local/share/lensfun/updates/version_x, whatever is newest
  2. ~/.local/share/lensfun
  3. ~/.local/share/lensfun/version_x
Another way to load database file is to load them one by one. For this you call lfDatabase::Load(const char *) for every XML file that must be loaded. @page corrections How the corrections work For both the people working on Lensfun and the people working with Lensfun, it is very important to understand how corrections are applied to the images. @section ordering Order of the image operations The image operations are not commutative. Thus, it is important to apply them in the right order. This is:
  1. devignetting
  2. anti-TCA
  3. undistortion
  4. change of projection
  5. scaling
@subsection imagecorrections Image corrections The first three image operations that are applied are the image corrections. Their order relative to each other is closely connected with the way the lens errors are \a measured. Vignetting is measured on the pristine image, consequently, it must be corrected before any pixel-warping operations are applied. The same is true for TCA measurements. Distortion is also measured on the pristine image, however, undistortion is not affected by a previous devigneting or anti-TCA. This results in the above enumerated order: First devignetting, then anti-TCA, then undistortion. Well, the order of devignetting and anti-TCA is still not clearly defined by this actually. But imagine very very hefty TCA. It distorts the red and the blue channel relatively to the green one. This would affect the vignetting measurement considerably. However, the other way round would be much less invasive: A massive vignetting would not change the TCA measurements much. Therefore, vignetting must be eliminated before TCA is eliminated. Otherwise, devignetting would work on the wrong image. By the way, correcting TCA and distortion one directly after the other makes it possible to do this very efficiently: The pixel coordinates are transformed by both image operators, and after that, only \a one interpolation and \a one pixel value lookup are necessary. @subsection changeofprojection Change of projection Lensfun can also re-map a fisheye to a rectilinear image. Mathematically speaking, a perfect lens follows a well-defined projection (in other places also called “lens type” or “geometry”), like: @f[\begin{aligned} r &= 2f\sin(\theta/2) &\text{equisolid} \\ r &= f\theta &\text{equidistant} \\ r &= 2f\tan(\theta/2) &\text{stereographic} \\ r &= f\sin(\theta) &\text{orthographic} \\ r &= f\tan(\theta) &\text{rectilinear} \end{aligned} @f] Here, @f$\theta@f$ is the angle between the incoming ray of light and the optical axis, @f$f@f$ is the focal length, and @f$r@f$ is the distance of the resulting dot on the sensor from the sensor center. You see, the rectilinear projection is just one of many. And all of them have their advantages and disadvantages. The first four projections are considered fisheye. Lensfun can change the projection of the image. But converting e.g. from fisheye to rectilinear is not a correction. A fisheye image is as perfect as a rectilinear image if it follows the respective projection formula. And the image follows the projection formula after a successful distortion correction. Therefore, the change of projection is perfomed \a after the image corrections. @subsection scaling Scaling Often it is desirable to scale the resulting image, e.g. to eliminate black areas at the borders caused by one of the previous image operations. This scaling affect the resulting image, therefore, it comes last in the processing. @section actualorder How it is really done The actual order perfomed in the Lensfun-calling program will differ from the above list. Why is this? Understanding this is very important for hacking on Lensfun as well as for using it in your own programs. When it comes to pixel coordinate transformations, it is very sensful to start with the perfect, rectified image (still empty) and distort its pixel coordinates to the distorted image. This distorted image is the source image (the RAW file), and you can do a simple pixel lookup there, possibly with interpolation. This way, you find all pixel values for your rectified image efficiently and accurately. However, if you perform pixel lookup this way, things happen the other way round compared to the section before, because you follow the path through the image manipulations the reverse way:
  1. scaling
  2. change of projection
  3. undistortion
  4. anti-TCA
  5. devignetting
This reverse order is the reason why the formulae for distortion models in ::lfDistortionModel map the \a undistorted coordinate to the \a distorted coordinate. This seems to be wrong at first because we want to undistort after all. But given how undistortion is actually done, it makes sense. The same is true for ::lfTCAModel. Note that in the sequence \a scaling → change of projection → \a undistortion → anti-TCA, the resulting coordinates of the previous step are the input coordinates for the respective next step. In reality, devignetting is performed first nevertheless, because it can be separated from all other operations, by calling lfModifier::ApplyColorModification. Then, you do the coordinate-transforming operations from scaling to anti-TCA. Lensfun can do this in one function call with lfModifier::ApplySubpixelGeometryDistortion. Finally, you do a lookup on the vignetting-corrected RAW data, using the transformed coordinates. @page programming Using this library in your programs One of main goals while developing this library was easiness of use. Libraries with complex API are usually slow to be accepted by the community, and often libraries that can do less but have a cleaner API are preferred over more sophisticated libraries that have a user-unfriendly API. The library is accessible both from plain C and C++ programs. Since the library itself is written in C++ (without use of bloated and bloating libraries like libstdc++ or boost), the C interface is a (very) thin wrapper around the C++ classes. The overhead imposed by the wrappers is negligible.
  • @ref basearch
  • @ref samplecode
@page basearch Library architecture The library provides five basic types of objects to work with: @b mounts (lfMount), @b cameras (lfCamera), @b lenses (lfLens), @b databases (lfDatabase) and @b modificators (lfModifier). The lfMount structure provides the information about a mount. For now the only information about a mount is its name and the list of compatible mounts. The lfCamera structure provides information about a particular camera. Camera maker, model name, mount type and other things are included here. The lfLens structure provides information about a lens. This structure contains a lot of information, since it's the heart of the library. Besides other things, this contains a list of lens calibration data. This information tells the library how to correct images distorted by a certain lens. The lfDatabase class provides a interface to the XML database. It allows to load, save XML files and to search the database for lenses, cameras and mounts. Finally, the lfModifier class will allow you to modify images. Not only correct for distortion introduced by lenses but also apply special effects on a image such as emulating certain lens (e.g. apply a reverse transform), modify the geometry of a image (e.g. convert a fisheye image to a rectilinear etc). A typical application will first load the database by creating a lfDatabase object and invoking the respective lfDatabase::Load() method. After that it can look for a Lens object using the bits of information from the user or from the source file. For example, the EXIF data contains the camera maker and camera model. Using this you can search for the respective camera in the database. In camera record you look at the mount field, and then do a lens search based on at least mount name. Additionaly, you may provide the lens manufacturer and/or model name from the EXIF data (which is not always possible). You get a list of possible lenses. If it's just one lens, you can assume that it's exactly the lens that was used to take the shot (this is true for compact cameras which have a fixed mount). Now if you found more than one matching lens you must provide the user a choice. User chooses the exact lens that was used to make a shot. After that you can create a lfModifier object using lens data. Using this object the image may be modified according to user preferences. Lensfun transformations -- at least those involving TCA and vignetting correction -- must be applied to linear RGB data in the sensor's original colour space. Linear RGB can only be retrieved from RAW files, as JPEG files from most cameras already have colour transfromations applied. This is very important. If you do e.g. TCA correction on sRGB data, the colour fringes are still visible. And if you do vignetting correction after a gamma has been applied, the corners probably will look too bright. So make sure that Lensfun comes early enough in your processing chain. @page filldb Filling the database Earlier or later (usually earlier) you'll find out that your camera/lens is not in the database. Well, that's easy to fix, just add it to the database yourself! ;) As stated in the section @ref dbsearch, the library will look for xml database files in various subdirectories. The best place to put your own definitions into is ~/.local/share/lensfun/. This directory is guaranteed to not be overwriten by library or even OS upgrades, so it's safe to keep them there. So now you just create a new file under ~/.local/share/lensfun/ -- with any name, but with the '.xml' extension: @verbatim ... put your definitions here ... @endverbatim and it will be automatically found and loaded at library initialization time, Of course, if you create new camera/lens definitions, I will be grateful if you send them to me so that I can include them in future releases of the database.
  • @ref addcamera
  • @ref addlens
@page addcamera Adding new cameras to the database Adding new cameras is very easy. You just have to know its crop factor, and the EXIF identification strings for this camera; that's all. If you don't know the crop factor, you can search in google for e.g. “Nikon D300 sensor size”. Let's suppose you found out that your sensor size is 23.6 × 15.8mm. Now compute the length of the diagonal using Pythagora's theorem: @f[ d = \sqrt{23.6^2 + 15.8^2}\,\mathrm{mm} = 28.4\,\mathrm{mm} @f] Now you just divide the magic number 43.27 (the diagonal of a usual 35mm film frame) by the number you got: @f[ \mathrm{cropfactor} = \frac{43.27}{28.4} = 1.523 @f] Now you must find out the identification string for your camera from EXIF data. For this you can use the exiv2 script: @verbatim $ exiv2 blah.nef .... Camera make : NIKON CORPORATION Camera model : NIKON D300 .... @endverbatim Now you can create a XML entry for your camera: @verbatim Nikon Corporation Nikon Nikon D300 D300 Nikon F AF 1.523 @endverbatim Now add this definition to a XML database file along Lensfun database search path and your camera will be detected and Lensfun will work properly with images produced by it.
  • @ref el_camera
@page addlens Adding new lenses to the database There are several levels of detalization you can use when adding a new lens into the database. First, you could just add the basic identification information to the database, just to let the database know that such a lens exist. Then, you might try to find out the mathematical model for the distortion of the lens. Finally, you might try to find out the vignetting and transversal chromatic aberration parameters of the lens and get a complete lens description in database. A simple lens database entry would look something like: @verbatim Pentax smc Pentax-DA 12-24mm f/4 ED AL IF Pentax KAF2 @endverbatim The above code just tells Lensfun that there exist a lens called “smc Pentax-DA 12-24mm f/4 ED AL IF” manufactured by Pentax and it uses the Pentax KAF2 mount. This is not very useful except to make user happy that there's at least one other person in the world owning his lens. A better lens database entry would contain at least some data about how to correct lens distortion. This data can be calculated from test shots. Some special program should be used for this, or you could try to manually adjust the coefficients until you get decent results. Computing math model coefficients for distortion, tca, vignetting is a separate very complex matter. It is out of the scope of this manual to give even a short brief about this. There's a tutorial on Lensfun site that will teach you how to create a complete lens entry using just Hugin.
  • @ref el_lens
@page samplecode Sample code Here goes some coding examples, from simple to complex.
  • \ref example.c
This is a example written in pure C and it shows how to load the whole database, then prints it to stdout and finally saves the whole database to a new XML file.
  • \ref tfun.cpp
This is a more complex sample in C++ which shows how to do database lookups. The results found are saved to a new XML file.
  • \ref lenstool.cpp
This is a more or less complex command-line application which can access most library functionality. It has been used as the main library testbed. */ /** \example example.c Sample program demonstrating basic usage of C API. */ /** \example tfun.cpp This example shows how to do basic database lookups. */ /** \example lenstool.cpp Library testbed. This program can access most library functionality. */ /** \page gpl GNU General Public License, version 3 \verbinclude gpl-3.0.txt */ /** \page lgpl GNU Lesser General Public License, version 3 \verbinclude lgpl-3.0.txt */ /** \page cc-by-ca Creative Commons Attribution-Share Alike 3.0 Unported \verbinclude cc-by-sa-3.0.txt */ lensfun-0.3.4/docs/mathjaxConfiguration.js000066400000000000000000000000621445356770400206570ustar00rootroot00000000000000MathJax.Hub.Config({ messageStyle: "none" }); lensfun-0.3.4/docs/mounts.txt000066400000000000000000000047031445356770400162310ustar00rootroot00000000000000Canon: FL - Introduced in 1964 FD - Another mount (incompatible with FL) feat. automatic aperture EF - Another incompatible mount, EF stands for electro-focus EF-S - A newer variant of EF with shorter flange depth, allowing for manufacturing of less expensive wide-angle lenses. Not useable on cameras with crop 1.0 and on EF-only cameras. Contax: N - ? Contax/Yashica - ? G - Rangefinder mount with autofocus Generic: M42 - First used in Zeiss Contax S (1949) and then adopted by many other manufacturers due to patent-less nature. T2 - Introduced by Tamron in 1957, with adaptors for virtually all other mounts (due to large flange distance). Used in astronomical devices and some mirror lenses. C - Intended for cinematographic lenses on very different viewframe sizes (often smaller that µFT), it can be adapted to most mirrorless systems. It has a very short flange distance, but due to the small radius of most C mount lenses, the adapter can be realised as a ring around the lens. In photography, most C mount lenses must be considered fun lenses. Leica: M - Classical Leica rangefinder mount R - SLR mount, discontinued since 2009 S - Medium-format mount Hasselblad: H - Current medium format mount of this brand Minolta: MC - Older Minolta mount for manual lenses MD - Newer version of MC with aperture information to the camera AF - (1985) features autofocus, several generations. Nikon: F - Introduced in 1959 F AI - (1977) - Added electrical interface for automatic aperture control. F AI-S - (1979) - Added a mean to tell camera current focal length. F AF - (1986) - Added screwdriver AF coupling, compatible with older mounts Olympus: 4/3 System - (2002), the new "digital" mount together with Kodak Pentax: K - the original mount as introduced in 1975 KF - the world's first autofocus mount, 1981. Abandoned. KA - the K mount plus electrical contacts to detect the min/max lens aperture and also whether the 'A' aperture mode is enabled. KAF - the KA mount plus autofocus KAF2 - in addition to KAF features implements power zooming and adds MTF information to the lens data Samsung: NX - mirrorless APS-C mount introduced in 2010 NX mini - mirrorless 1" mount introduced in 2014 Voigtländer: DKL - the "Deckel" mount used in the Bessamatic lensfun-0.3.4/docs/website/000077500000000000000000000000001445356770400156015ustar00rootroot00000000000000lensfun-0.3.4/docs/website/README.md000066400000000000000000000012171445356770400170610ustar00rootroot00000000000000The Lensfun website is based on __Jekyll__ which is a static website generator. See http://jekyllrb.com/ for more information. Basic instructions: * Install Ruby and its development packages sudo apt-get install ruby ruby-dev nodejs * Install Jekyll sudo gem install jekyll rdiscount * Run Jekyll to build the html files and serve the whole web site with a local web server at http://localhost:4000/ jekyll serve * All web content can be found in the `_site/` subfolder and may be packaged into the documentation or uploaded to any web server. Use `jekyll build` to only build without starting a local web server. lensfun-0.3.4/docs/website/_config.yml000066400000000000000000000002641445356770400177320ustar00rootroot00000000000000name: "Lensfun" description: "Homepage of the Lensfun library and database" url: "http://localhost:4000" markdown: rdiscount permalink: pretty safe: false exclude: [README.md] lensfun-0.3.4/docs/website/_includes/000077500000000000000000000000001445356770400175465ustar00rootroot00000000000000lensfun-0.3.4/docs/website/_includes/footer.html000066400000000000000000000002311445356770400217260ustar00rootroot00000000000000
lensfun-0.3.4/docs/website/_includes/header.html000066400000000000000000000005731445356770400216710ustar00rootroot00000000000000 {{ site.name }} lensfun-0.3.4/docs/website/_includes/navigation.html000066400000000000000000000004671445356770400226020ustar00rootroot00000000000000 lensfun-0.3.4/docs/website/_includes/top-navigation.html000066400000000000000000000007431445356770400233770ustar00rootroot00000000000000 lensfun-0.3.4/docs/website/_layouts/000077500000000000000000000000001445356770400174405ustar00rootroot00000000000000lensfun-0.3.4/docs/website/_layouts/default.html000066400000000000000000000005321445356770400217520ustar00rootroot00000000000000{% include header.html %}
{% include top-navigation.html %} {% include navigation.html %}

{{page.title}}

{{ content }}

{% include footer.html %} lensfun-0.3.4/docs/website/_plugins/000077500000000000000000000000001445356770400174215ustar00rootroot00000000000000lensfun-0.3.4/docs/website/_plugins/sorted_for.rb000066400000000000000000000010471445356770400221160ustar00rootroot00000000000000module Jekyll class SortedForTag < Liquid::For def render(context) sorted_collection = context[@collection_name].dup sorted_collection = sorted_collection.sort_by { |i| i.to_liquid[@attributes['sort_by']] } sorted_collection_name = "#{@collection_name}_sorted".sub('.', '_') context[sorted_collection_name] = sorted_collection @collection_name = sorted_collection_name super end def end_tag 'endsorted_for' end end end Liquid::Template.register_tag('sorted_for', Jekyll::SortedForTag) lensfun-0.3.4/docs/website/_posts/000077500000000000000000000000001445356770400171105ustar00rootroot00000000000000lensfun-0.3.4/docs/website/_posts/changelogs/000077500000000000000000000000001445356770400212225ustar00rootroot00000000000000lensfun-0.3.4/docs/website/_posts/changelogs/2013-10-20-Release-0.2.8-Changelog.md000066400000000000000000000044041445356770400264760ustar00rootroot00000000000000--- title: Changelog for release 0.2.8 layout: default category: changelog --- Another minor maintenance release. Most fixes were related to the build system. But as always we have many(!) new lens profiles. Thanks to all submitters! Interchangeable lens: * Canon EF-S 60mm f/2.8 Macro * Canon EF-S 18-135mm f/3.5-5.6 IS * Canon EF 100mm f/2.8L Macro IS USM * Canon EF 200mm f/2.8L USM * Canon EF 85mm f/1.2L II USM * Canon EF 50mm f/1.2L USM * Canon EF 70-200mm f/2.8L USM * Canon EF 70-200mm f/2.8L IS II USM * Canon FDn 100mm 1:2.8 * Canon FDn 50mm 1:1.4 * Nikkor 24-70mm f/2.8G ED * Nikon AF-S DX VR Zoom-Nikkor 18-55mm f/3.5-5.6G * Nikon AF-S DX Zoom-Nikkor 18-70mm f/3.5-4.5G IF-ED * Nikon AF-S Zoom-Nikkor 14-24mm f/2.8G ED * Nikon AF-S Nikkor 85mm f/1.8G * Zuiko Digital 25mm F2.8 * Zuiko Digital 35mm f/3.5 Macro * Zuiko Digital ED 14-42mm F3.5-5.6 * Zuiko Digital ED 40-150mm F4.0-5.6 * Zuiko Digital ED 9-18mm F4.0-5.6 * smc PENTAX-D FA Macro 100mm F2.8 WR * smc PENTAX-DA 15mm F4 ED AL Limited * smc PENTAX-DA 18-55mm F3.5-5.6 AL WR * smc PENTAX-DA 21mm f/3.2 AL Limited * smc PENTAX-DA 35mm f/2.4 AL * smc PENTAX-FA 43mm F1.9 Limited * smc PENTAX-FA 50mm f/1.4 * smc PENTAX-DA* 50-135mm f/2.8 ED [IF] SDM * SIGMA 8mm f/3.5 EX DG Circular * SIGMA 8-16mm f/4.5-5.6mm DC HSM * SIGMA 10-20mm F4-5.6 EX DC HSM * SIGMA 17-50mm F2.8 EX DC OS HSM * SIGMA 24-60mm F2.8 EX DG * SIGMA E 30mm F2.8 * SIGMA 35mm f/1.4 DG HSM * SIGMA 150mm F2.8 MACRO HSM * SIGMA 150-500mm f/5-6.3 APO DG OS HSM * OLYMPUS M.14-150mm F4.0-5.6 * OLYMPUS M.17mm F1.8 * OLYMPUS M.45mm F1.8 * Leica DG Summilux 25/f1.4 * LUMIX G 14/F2.5 + GWC1 0.79x * LUMIX G VARIO PZ 14-42/F3.5-5.6 * Samsung 16mm f/2.4 * Samyang 7.5mm F/3.5 UMC Fish-eye MFT * Samyang 8mm f/2.8 UMC Fish-eye * Samyang 14mm f/2.8 ED AS IF UMC * Samyang 500mm f/6.3 MC IF Mirror Lens * Sony E 10-18mm F4 OSS * Sony E PZ 16-50mm F3.5-5.6 OS * Sony E 18-200mm F3.5-6.3 OSS * Sony E 18-200mm F3.5-6.3 OSS LE * Sony E 30mm F3.5 Macro * Sony E 35mm F1.8 OSS * Sony DT 16-50mm F2.8 SSM * Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD * Tamron SP AF 90mm f/2.8 (172E) Compact cameras: * Canon PowerShot G11 * Canon PowerShot G1X * Canon PowerShot SX150 IS * Fujifilm X10 * Fujifilm X100S * Panasonic DMC-FZ28 * Panasonic LX7 * SAMSUNG WB2000 compact camera * Sigma DP2 lensfun-0.3.4/docs/website/_posts/changelogs/2014-09-30-Release-0.3.0-Changelog.md000066400000000000000000000162441445356770400265060ustar00rootroot00000000000000--- title: Changelog for release 0.3.0 layout: default category: changelog --- * Streamlined the names of Nikkor, Tamron, Tokina, Panasonic, Leica, Olympus, Sony, and Sigma lenses so that auto-detection works better * Fixed names of Sony Coolpix cameras * Comprehensive update of Lensfun's documentation * Lens lists may now be sorted by focal length * The tag is now mandatory for and in the database files * Increased accuracy because APS-C is not anymore assumed to have the crop factor 1.5 (non-Canon) or 1.6 (Canon), but the accurate crop factor of the respective camera * Added command line tool "lensfun-update-data" for updating the database * Added command line tool "lensfun-add-adapter" for managing mount compatibilities * Removed compatibility of Four Third on Micro Four Third * Removed compatibility of Sony Alpha on Sony E * Many bugfixes, especially for the case if sensor sizes of calibration and image to-be-corrected are different * MaxAperture is now the maximal f-stop number one can set on the given lens * Removed non-working implementation of CCI * Made primary keys of the database tables explicit and documented * Replaced field-of-view data with real-focal-length data; marked the FOV API deprecated * Higher accuracy for fisheye <--> rectinilear transformation for lenses with real focal length data * The field-of-view distortion model (FOV1) was removed because it is inherently flawed * Simplified method for finding the database directories; see documentation * Removed old non-CMake build system * Added new cameras New interchangeable lenses: * Canon EF-S 15-85mm f/3.5-5.6 IS USM * Canon EF 16-35mm f/2.8L II USM * Canon EF-S 18-55mm f/3.5-5.6 IS * Canon EF-M 18-55mm f/3.5-5.6 IS STM * Canon EF-S 18-135mm f/3.5-5.6 IS STM * Canon EF-S 18-200mm f/3.5-5.6 IS * Canon EF-M 22mm f/2 STM * Canon EF 24-70mm f/2.8L II USM * Canon EF 28-80mm f/3.5-5.6 USM IV * Canon EF 50mm f/1.8 MkII * Canon EF 50-200mm f/3.5-4.5L * Canon EF-S 55-250mm f/4-5.6 IS * Canon EF 70-300mm f/4-5.6L IS USM * Cosina Cosinon-S 50mm 1:2 * KMZ MC MTO 11CA mirror tele * Leica DG Macro-Elmarit 45mm f/2.8 * Mitakon wide MC f=24mm 1:2.8 * 1 Nikkor AW 11-27.5mm f/3.5-5.6 * Nikkor AI-S 6mm f/2.8 Fisheye * Nikkor AF-S 18-140mm f/3.5-5.6G DX ED VR * Nikkor AF-S 18-200mm f/3.5-5.6G DX VR IF-ED * Nikkor AF-S 24-85 mm f/3.5-4.5G ED VR * Nikkor AI-S 50mm f/1.2 * Nikkor AF-S 50mm f/1.8G * Nikkor AF-S 55-300mm f/4.5-5.6G DX ED VR * Nikkor AF-S 70-200mm f/4G VR IF-ED * Nikkor AF-S 70-300mm f/4.5-5.6G VR IF-ED * Nikkor AF-S VR 105mm f/2.8G IF-ED * Nikkor AF-S 600mm f/4G ED VR * Nikkor AF-S 800mm f/5.6E FL ED VR * Fujian 35mm f/1.7 * Fujifilm XC 16-50mm f/3.5-5.6 OIS * Fujifilm XF 18mm f/2 R * Fujifilm XF 18-55mm f/2.8-4 R LM OIS * Fujifilm XF 27mm f/2.8 * Fujifilm XF 35mm f/1.4 R * Fujifilm XC 50-230mm f/4.5-6.7 OIS * Fujifilm XF 55-200mm f/3.5-4.8 R LM OIS * Olympus M.9-18mm f/4.0-5.6 * Olympus Zuiko Digital ED 12-60mm f/2.8-4.0 SWD * Olympus M.Zuiko Digital 25mm f/1.8 * Olympus M.40-150mm f/4.0-5.6 R * Olympus M.Zuiko Digital ED 75mm f/1.8 * Olympus M.Zuiko Digital 75-300mm f/4.8-6.7 II * Panasonic Lumix G Vario 7-14mm f/4.0 * Panasonic Lumix G Vario 12-35mm f/2.8 * Panasonic Lumix G Vario 14-42mm f/3.5-5.6 II * Panasonic Lumix G Vario 14-45mm f/3.5-5.6 Asph. Mega OIS * Panasonic Lumix G 20mm f/1.7 II * Panasonic Lumix G Vario 35-100mm f/2.8 * Panasonic Lumix G Vario 45-150mm f/4.0-5.6 * Panasonic Lumix G Vario PZ 45-175mm f/4.0-5.6 * Pentacon 50mm f/1.8 auto multi coating * Pentax-DA Fish-Eye 10-17mm f/3.5-4.5 ED IF * Pentax-FA 28mm f/2.8 AL * Pentax-M 28mm 1:3.5 * Pentax-FA 31mm F1.8 AL Limited * Pentax-M 35mm 1:2 * Pentax-A 50mm f/1.7 * Pentax-DA L 55-300mm f/4-5.8 ED * Ricoh XR Rikenon 1:1.4 50mm * Samyang 8mm f/3.5 Fish-Eye CS * Samyang T-S 24mm f/3.5 ED AS UMC * Samsung NX 16-50mm f/3.5-5.6 PZ ED OIS * Samsung Zoom 18-55mm f/3.5-5.6 OIS * Samsung NX 20mm f/2.8 Pancake * Samsung NX 45mm f/1.8 2D/3D * Samyang 12mm f/2.0 NCS CS * Samyang 35mm f/1.4 AS UMC * Samyang 50mm f/1.4 AS UMC (APS-C only) * Sigma 10mm f/2.8 EX DC Fisheye HSM * Sigma 18-35mm f/1.8 DC HSM * Sigma 18-250mm f/3.5-6.3 DC OS MACRO HSM * Sigma 24-70mm f/2.8 IF EX DG HSM * Sigma 24-105mm f/4.0 DG OS HSM [A] * Sigma 17-70mm f/2.8-4 DC Macro OS HSM * Sigma 19mm f/2.8 DN * Sigma 19mm f/2.8 EX DN * Sigma 30mm f/2.8 EX DN * Sigma 50mm f/1.4 DG HSM [A] * Sigma 50-150mm f/2.8 APO EX DC HSM II * Sigma 60mm f/2.8 DN * Sigma 70-200mm f/2.8 EX DG APO OS HSM * Sigma 70-200mm f/2.8 EX DG Macro HSM II * Sigma 80-400mm f/4.5-5.6 EX DG OS * Sigma 100-300mm f/4 APO EX DG HSM * Sigma 105mm f/2.8 EX DG OS HSM Macro * Sigma 180mm f/2.8 EX DG OS HSM APO Macro * Sigma 180mm f/5.6 APO Macro * Sony E 10-18mm f/4 OSS * Sony E 16-70mm f/4 ZA OSS * Sony E PZ 18-105mm f/4 G OSS * Sony DT 18-135mm f/3.5-5.6 SAM * Sony AF DT 35mm f/1.8 SAM * Sony AF DT 50mm f/1.8 SAM * Sony DT 55-300mm f/4.5-5.6 SAM * Tamron SP AF 11-18mm f/4.5-5.6 Di-II LD Aspherical (IF) * Tamron 16-300mm f/3.5-6.3 Di II VC PZD * Tamron 18-200mm f/3.5-6.3 XR Di II LD * Tokina AF 12-28mm f/4 AT-X Pro DX * Tokina AF 16-28mm f/2.8 AT-X Pro SD FX * Tokina 500mm f/8 RMC Mirror Lens * Vivitar 100mm f/3.5 AF Macro * Carl Zeiss Distagon T* 2,8/21 ZE * Carl Zeiss Distagon T* 2,8/21 ZF.2 * Zeiss E 32mm f/1.8 New compact cameras: * Canon PowerShot A640 * Canon PowerShot A720 * Canon PowerShot IXUS 70 * Canon PowerShot S90 * Canon PowerShot S120 * Canon PowerShot SX220 HS * Canon PowerShot SX230 HS * Canon PowerShot SX260 HS * Fujifilm FinePix F770EXR * Fujifilm FinePix HS20EXR * Fujifilm FineFix S5600 * Fujifilm X20 * GoPro Hero HD2 * Kodak CX6330 * Nikon Coolpix S3300 * Nokia Lumia 1020 * Olympus Stylus 1 * Panasonic Lumix DMC-LX7 * Panasonic Lumix DMC-FZ200 * Sony DSC-HX300 * Sony RX100 II * Sony RX100 III Additional/updated data for: * Canon EF-S 18-55mm f/3.5-5.6 IS II * Canon EF 24-70mm f/2.8L II USM * Canon EF 24-105mm f/4L IS USM * Canon EF 50mm f/1.8 MkII * Canon EF 50-200mm f/3.5-4.5L * Canon EF 70-200mm f/2.8L IS II USM * Canon EF 70-200mm f/4L IS USM * Canon EF 85mm f/1.8 USM * Canon EF 100mm f/2.8L Macro IS USM * Nikkor AF-S 10-24mm f/3.5-4.5G DX ED * Nikkor AF-S 16-85mm f/3.5-5.6G DX ED VR * Nikkor AF-S 18-55mm f/3.5-5.6G DX VR * Nikkor AF-S 18-105mm f/3.5-5.6G DX ED VR * Nikkor AF-S 18-200mm f/3.5-5.6G DX VR IF-ED II * Nikkor AF 20mm f/2.8D * Nikkor AF-S 35mm f/1.8G DX * Nikkor AF-S 50mm f/1.4G * Nikkor AF-S 55-300mm f/4.5-5.6G DX ED VR * Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.6 L * Olympus M.Zuiko Digital 17mm f/1.8 * Panasonic Lumix G Vario 45-200mm f/4.0-5.6 Mega OIS * Pentax 01 Standard Prime 8.5 mm f/1.9 AL [IF] * Pentax-DA* 16-50mm f/2.8 ED AL IF SDM * Pentax-DA* 50-135mm f/2.8 ED IF SDM * Pentax-D FA Macro 100mm f/2.8 WR * Samyang 8mm f/2.8 Fisheye * Sigma 8-16mm F4.5-5.6 DC HSM * Sigma 10-20mm f/3.5 EX DC HSM * Sigma 10-20mm f/4-5.6 EX DC HSM * Sigma 15-30mm f/3.5-4.5 EX DG Aspherical * Sigma 30mm f/1.4 EX DC HSM * Sigma 35mm f/1.4 DG HSM * Sigma 50mm f/1.4 EX DG HSM * Sigma 70-200mm f/2.8 EX DG Macro HSM II * Sigma 150mm f/2.8 EX DG APO HSM Macro * Sony RX100 * Sony DT 18-55mm f/3.5-5.6 SAM * Sony E 20mm f/2.8 * Sony AF DT 55-200mm f/4-5.6 SAM * Panasonic Lumix G Vario 14-42 f/3.5-5.6 II * Panasonic Lumix G X Vario PZ 14-42 f/3.5-5.6 * Tamron SP AF 17-50mm f/2.8 lensfun-0.3.4/docs/website/_posts/changelogs/2015-05-10-Release-0.3.1-Changelog.md000066400000000000000000000075711445356770400265050ustar00rootroot00000000000000--- title: Changelog for release 0.3.1 layout: default category: changelog --- * Improved performance when used with 32-bit float image buffers. * Introduced automated testing. * lensfun-update-data now also works without root privileges * Fixed autoscaling for panoramic and equirectangular projections New interchangeable lenses: * Canon EF 16-35mm f/4L IS USM * Canon EF-S 18-55mm f/3.5-5.6 IS STM * Canon Lens FL 50mm F1.4 * Canon FDn 50mm 1:1.4 (APS-C) * Nikkor AF-S 60mm f/2.8G ED Micro * Canon EF 70-210mm f/3.5-4.5 USM * Canon Lens FL 135mm F3.5 * Canon EF 300mm f/2.8L IS II USM (also with 1.4x and 2.0x converters) * Canon EF 400mm f/5.6L USM (also with 1.4x converter) * Canon EF 500mm f/4L IS II USM (also with 1.4x and 2.0x converters) * Cosina 19-35mm f/3.5-4.5 MC * Fotasy M3517 35mm f/1.7 * Fujifilm TCL-X100 teleconverter (for X100/X100s cameras) * Fujifilm XF 23mm f/1.4 R * Fujifilm XF 60mm f/2.4 R Macro * KMZ MC HELIOS-44M-4 58mm 1:2 * Leica DG Summilux 15mm f/1.7 * Lumix G Vario 12-32 f/3.5-5.6 * Lumix G 14mm f/2.5 II * Minolta MD 35mm 1/2.8 * Minolta AF 35-105mm f/3.5-4.5 * Nikkor AF 10.5mm f/2.8G DX ED Fisheye * Nikkor AF-S 18-55mm f/3.5-5.6G DX VR II * Nikkor AF-S 18-300mm f/3.5-6.3G DX ED VR * Nikkor AI 20mm f/3.5 * Nikkor AF 20-35mm f/2.8D IF * Nikkor AI-S 24mm f/2.8 * Nikkor AF-S 24-120mm f/4G ED VR * Nikkor AF 28mm f/1.4D * Nikkor AF-S 28mm f/1.8G * Nikkor AI-S 28mm f/2.8 * Nikkor AF 28-80mm f/3.3-5.6G * Nikkor AF 28-200mm f/3.5-5.6G IF-ED * Nikkor AI-S 35mm f/2.0 * Nikkor AF 60mm f/2.8D Micro * Nikkor AF-S 70-300mm f/4.5-5.6G VR IF-ED * Olympus M.Zuiko Digital 60mm f/2.8 Macro * HD Pentax-DA 20-40mm f/2.8-4 ED Limited DC WR * smc Pentax-A 28mm 1:2.8 * smc Pentax-DA 18-55mm f/3.5-5.6 AL II * smc Pentax-DA 50mm f/1.8 * smc Pentax-M Macro 1:4 50mm * Ricoh 50mm 1:2.0 * Schneider-Kreuznach Retina-Curtagon 1:4/28mm * Sigma 8mm f/3.5 EX DG Circular (APS-C) * Sony FE 28-70mm f/3.5-5.6 OSS * Tamron SP AF 60mm f/2 Di II LD (IF) Macro * Tamron SP 150-600mm f/5-6.3 Di VC USD * Tokina AF 100mm f/2.8 AT-X Pro D Macro * Voigtländer Skoparex 1:3,4/35 * Voigtländer Color-Skopar X 1:2,8/50 * Zenitar MC 16mm f/2.8 * Carl Zeiss Jena 1Q Biotar 1:2 f=58mm T New interchangable lens cameras: * Canon EOS 7D Mark II * Canon EOS 750D * Canon EOS 760D * Canon EOS M2 * Canon EOS M3 * Fuji X-A2 * Nikon D5500 * Nikon D7200 * Nikon 1 S2 * Nikon 1 V3 * Nikon 1 J5 * Olympus E-5 Mark II * Panasonic DMC-GH4 * Panasonic DMC-GF7 * Samsung NX1 * Samsung NX300M * Samsung NX500 * Sony A5100 New compact cameras: * Canon IXUS 220 HS (CHDK's DNGs) * Canon PowerShot A4000 IS (CHDK's DNGs) * Canon PowerShot G1 X Mark II * Canon PowerShot S95 * DIJ Phantom Vision FC200 * Fujifilm FinePix A370 * Fujifilm X100T * Fujifilm X30 * Fujifilm XQ1 * Olympus E-PL7 * Olympus Stylus 1s * Panasonic FZ1000 * Panasonic DMC-GM5 * Panasonic DMC-LX100 * Ricoh GR * Sony RX100 III Additional/updated data for: * Canon EF-S 10-22mm f/3.5-4.5 USM * Canon TS-E 24mm f/3.5L * Canon EF 24-85mm f/3.5-4.5 USM * Canon EF 50mm f/1.8 * Canon EF 70-200mm f/4L IS USM * Fujifilm XC 16-50mm f/3.5-5.6 OIS * Fujifilm XC 50-230mm f/4.5-6.7 OIS * Nikkor AF 24-85mm f/2.8-4D IF * Nikkor AF 50mm f/1.4D * Nikkor AF 50mm f/1.8D * Nikkor AF-S 55-300mm f/4.5-5.6G DX ED VR * Nikkor AF-S 70-200mm f/2.8G VR IF-ED * Nikkor AF 70-210mm f/4-5.6 * Nikkor AF 80-200mm f/2.8 ED * Nikkor AF 85mm f/1.8 * Olympus M.Zuiko Digital 25mm f/1.8 * Olympus M.Zuiko Digital 60mm f/2.8 Macro * Olympus M.Zuiko Digital ED 75-300mm f/4.8-6.7 II * smc Pentax-DA 18-55mm f/3.5-5.6 AL WR * smc Pentax-M 28mm 1:3.5 * smc Pentax-DA 35mm f/2.4 AL * smc Pentax-A 50mm f/1.7 * Samyang 14mm f/2.8 ED AS IF UMC * Sigma 19mm f/2.8 EX DN * Sigma 50-150mm f/2.8 APO EX DC OS HSM * Sigma 70-200mm f/2.8 EX DG OS HSM * Sigma 105mm f/2.8 EX DG OS HSM Macro * Sony 50mm f/1.4 * Sony E 16-50mm f/3.5-5.6 OSS PZ * Canon PowerShot A640 * Canon PowerShot A720 * Canon PowerShot SX150 * Canon PowerShot SX220 lensfun-0.3.4/docs/website/_posts/changelogs/2015-11-16-Release-0.3.2-Changelog.md000066400000000000000000000051261445356770400265030ustar00rootroot00000000000000--- title: Changelog for release 0.3.2 layout: default category: changelog --- * Incremented binary version number * Improved vignetting interpolation * Internal code cleanups * Custom install directories can be configured by CMAKE_INSTALL_XXX variables (CMake GNUInstallDirs) * New LENSFUN_WINDOWS_DATADIR CMake variable for better windows compatibility * Support for parallel installation of different database versions New interchangeable lenses: * Canon EF-S 10-18mm f/4.5-5.6 IS STM * Canon EF-S 24mm f/2.8 STM * Canon EF 24-70mm f/4L IS USM * Canon FDn 50mm 1:1.8 * Canon FDn 24mm 1:2.8 * Contax G Planar T* 2/35 * Fujifilm XC 16-50mm f/3.5-5.6 OIS II * Fujifilm XC 50-230mm f/4.5-6.7 OIS II * Leica D Vario-Elmar 14-150mm f/3.5-5.6 Asph. OIS * Minolta MD Rokkor 50mm 1:1.4 * 1 Nikkor 18.5mm f/1.8 * 1 Nikkor 32mm f/1.2 * Nikkor AF-S 20mm f/1.8G ED * Nikon Lens Series E 28mm f/2.8 * Nikon Lens Series E 50mm f/1.8 * Nikkor AF-S 85mm f/1.4G * Nikon Lens Series E 100mm f/2.8 * Nikkor AF 105mm f/2.8D Micro * Nikkor AF-S 300mm f/4E PF ED VR * Olympus M.Zuiko Digital ED 7-14mm f/2.8 Pro * Olympus M.Zuiko Digital ED 8mm f/1.8 Fisheye Pro * Olympus 9mm Body Cap Lens Fisheye * Samyang 12mm f/2.8 Fish-Eye ED AS NCS * Samyang 35mm T1.5 Cine Lens * Sigma 70-300mm F4-5.6 DG Macro * Sony FE 28mm f/2 * Sony FE 24-70mm f/4 ZA OSS * Sony FE 55mm f/1.8 ZA * Tamron 18-200mm f/3.5-6.3 Di III VC * Tamron SP AF 70-200mm f/2.8 Di LD (IF) Macro * Vivitar Series 1 70-210mm 1:3.5 SN 22... * Voigtländer Ultron 40mm f/2 SL-II Aspherical New compact cameras: * AEE MagiCam SD19 (action cam) * Canon IXUS 125 HS * Canon PowerShot G7 X * Canon PowerShot S100 * Canon PowerShot S110 * Canon PowerShot SX130 IS * Canon PowerShot SX510 HS * GoPro HERO4 Silver * LG G4 * Nikon Coolpix P7000 * Panasonic DMC-FZ150 * Panasonic DMC-LF1 * Panasonic DMC-TZ71 * Sony RX100 IV New interchangable lens cameras: * Sony Alpha 7 II * Sony Alpha 77 II * Pentax K-3 II * Pentax K-S1 * Pentax K-S2 * Samsung NX mini Additional/updated data for: * Canon EF-S 18-135mm f/3.5-5.6 IS STM * Canon EF 24mm f/2.8 * Canon EF 24-70mm f/2.8L USM * Canon EF 50mm f/1.8 II * Nikon AF-S Nikkor 18-135mm f/3.5-5.6G DX IF-ED * Nikon AF-S Nikkor 20mm f/1.8G ED * Nikon AF Nikkor 20mm f/2.8D * Nikon AF-S Nikkor 50mm f/1.4G * Nikon AF-S Nikkor 50mm f/1.8G * Nikon AF-S Nikkor 28-300mm f/3.5-5.6G ED VR * Nikon AF-S Zoom-Nikkor 16-35mm f/4G ED VR * Nikon AF DX Fisheye-Nikkor 10.5mm f/2.8G ED * Samsung NX 45mm f/1.8 2D/3D * Sigma 12-24mm f/4.5-5.6 EX DG * Sony DT 16-50mm f/2.8 SSM * smc Pentax-A 28mm 1:2.8 * Sony FE 24-70mm f/4 ZA OSS * Panasonic DMC-LX100 * Canon PowerShot G7 X lensfun-0.3.4/docs/website/_posts/news/000077500000000000000000000000001445356770400200645ustar00rootroot00000000000000lensfun-0.3.4/docs/website/_posts/news/2012-06-23-Release-0.2.6.md000066400000000000000000000015521445356770400234610ustar00rootroot00000000000000--- title: Release 0.2.6 layout: default category: news --- After more than two years there is finally a new release of Lensfun available. Version 0.2.6 notably comes with many new lenses and cameras but there were also several changes under the hood. In detail: * more than 40 new database entries of lenses and compact cameras * new CMake based build system for better cross platform compatibility and compilation fixes for MSVC * better integration into hugin for loading and storing lens parameters via the Lensfun library * several bug fixes and stability improvements The source code of the release is available from BerliOS project page. From now on there will be new releases on a regular basis to frequently bring back database enhancements to the user base. Frequently meaning at least every six months or when there is a significant amount of new profiles. lensfun-0.3.4/docs/website/_posts/news/2012-12-13-New-release-is-on-its-way.md000066400000000000000000000011631445356770400262170ustar00rootroot00000000000000--- title: New release is on its way! layout: default category: news --- We promised to release new versions at least every 6 months but the next release has to be postponed by a few weeks till the end of january. The reason is that some severe bugs were discovered and although there are already patches in the bug tracker, some further checks are necessary. We want to be sure everything is fine and no new bugs are introduced by the changes. The good news is that over the last few months the interest in Lensfun did grow and many people send in calibration data for quite a lot of lenses and camera updates. Stay tuned! lensfun-0.3.4/docs/website/_posts/news/2013-02-10-Lensfun-0.2.7.md000066400000000000000000000023561445356770400235100ustar00rootroot00000000000000--- title: Lensfun 0.2.7 layout: default category: news --- Here is the new 0.2.7 release of Lensfun. lensfun-0.2.7.tar.gz Most important: some bugs leading to imprecise results when processing extreme values, e.g. from fisheye lenses, were fixed. Thanks to Torsten B. for working on this! Apart from that we got several new lenses and camera profiles: New DSLR and mirrorless camera lenses: * Canon EF 50mm f/1.8 II * Canon EF-S 18-55mm f/3.5-5.6 IS II * Nikkor 16-35mm f/4G ED-AFS VR * Sigma 18-200mm f/3.5-6.3 II DC OS HSM * Sigma 50mm F1.4 EX DG HSM * Sigma 70-300mm F4-5.6 DL Macro * Minolta/Sony AF DT 18-70mm F3.5-5.6 (D) * OLYMPUS M.12-50mm F3.5-6.3 * Sony DT 18-55mm F3.5-5.6 SAM SAL 1855 * Tamron SP 24-70mm F/2.8 Di VC USD * Tamron SP AF 10-24mm F/3.5-4.5 Di II LD Aspherical IF * Tokina AT-X Pro DX 11-16mm F2.8 * LUMIX G 14mm F2.5 * Sony E 16mm F2.8 * Sony E 18-55mm F3.5-5.6 OSS * Sony E 50mm F1.8 OSS * Sony E 55-210mm F4.5-6.3 OSS * Sony VCL-ECF1 fisheye converter New compact cameras: * Canon G15 * Fuji FinePix F200EXR * Nikon COOLPIX P60 * Olympus XZ-1 * Panasonic DMC-LX5 4:3 * Sony DSC-RX100, RX100 I want to thank all contributors who take the time to profile their equipment and share it with the community. Keep up the good work! lensfun-0.3.4/docs/website/_posts/news/2013-06-23-New-website.md000066400000000000000000000016511445356770400236320ustar00rootroot00000000000000--- title: New website layout: default category: news --- Lensfun got a new website. Although the layout and design is quite similar to the old one, a lot of things changed under the hood. We moved from a dynamic blog and CMS engine to a static site generator called Jekyll. This has several advantages: * Much more easy to maintain. The whole website is now part of the SVN repository. Everybody can participate and edit. * The website will run on any webserver. No more need for PHP, MySQL, ... * Much faster! * No more security trouble and time consuming updates of the CMS software. To create the website with Jekyll it only needs two steps: cd lensfun/docs/website jekyll --server This should start a webserver and you can view the website at http://localhost:4000/. To upload everything to a real webserver just go to the new subfolder
_site
and upload all the content. lensfun-0.3.4/docs/website/_posts/news/2013-10-20-Release-0.2.8.md000066400000000000000000000005471445356770400234570ustar00rootroot00000000000000--- title: Release 0.2.8 layout: default category: news --- Another minor maintenance release. Most fixes were related to the build system. But as always we have many(!) new lens profiles. Thanks to all submitters! A detailed overview of all changes can be found in the [Changelog for 0.2.8]({% post_url /changelogs/2013-10-20-Release-0.2.8-Changelog %}). lensfun-0.3.4/docs/website/_posts/news/2014-04-03-Sourceforge.md000066400000000000000000000007451445356770400237240ustar00rootroot00000000000000--- title: Lensfun moved to Sourceforge! layout: default category: news --- BerliOS will shut down its service at the end of April 2014. Therefore, we moved everything to Sourceforge and at the same time we took the opportunity to switch the version control system to git. The new website can be found at [http://lensfun.sourceforge.net/](http://lensfun.sourceforge.net/) and the project page is located at [http://sourceforge.net/p/lensfun](http://sourceforge.net/p/lensfun) lensfun-0.3.4/docs/website/_posts/news/2014-09-30-Release-0.3.0.md000066400000000000000000000014701445356770400234560ustar00rootroot00000000000000--- title: Release 0.3.0 layout: default category: news --- It took a while since the last release but it was worth the waiting time. In the last 12 months we nearly added and tweaked __160 lens profiles__! Further work was spent on: * Streamlined lens names for better auto-detection * Command line tools to update the local database and to manage mount compatibilities * Higher accuracy for fisheye <--> rectinilear transformation for lenses with real focal length data * Many bugfixes, especially for the case if sensor sizes of calibration and image to-be-corrected are different * Removed the old proprietary python based build system as it was not maintained anymore A detailed overview of all changes can be found in the [Changelog for 0.3.0]({% post_url /changelogs/2014-09-30-Release-0.3.0-Changelog %}). lensfun-0.3.4/docs/website/_posts/news/2015-05-10-Release-0.3.1.md000066400000000000000000000010351445356770400234470ustar00rootroot00000000000000--- title: Release 0.3.1 layout: default category: news --- Lensfun 0.3.1 maintenance release is out with more than __60 new__ lens profiles and another __30 updated__ calibrations. Other changes: * Improved performance when used with 32-bit float image buffers * Introduced automated testing * lensfun-update-data now also works without root privileges * Fixed autoscaling for panoramic and equirectangular projections More details in the complete [Changelog for 0.3.1]({% post_url /changelogs/2015-05-10-Release-0.3.1-Changelog %}). lensfun-0.3.4/docs/website/_posts/news/2015-11-16-Release-0.3.2.md000066400000000000000000000016011445356770400234520ustar00rootroot00000000000000--- title: Release 0.3.2 layout: default category: news --- The new Lensfun 0.3.2 release is out with more than __50 new__ lens profiles and another __19 updated__ calibrations. Most important changes are in the build system. The preferred way to set install paths is now to use the CMAKE_INSTALL_XXX variables from the [GNUInstallDirs module](https://cmake.org/cmake/help/v3.0/module/GNUInstallDirs.html). Furthermore, the library binary version number was incremented to fix various compatibility and packaging problems. Other changes: * Improved vignetting interpolation * Internal code cleanups * New LENSFUN_WINDOWS_DATADIR CMake variable for better windows compatibility * Support for parallel installation of different database versions A detailed list of changes can be found in in the complete [Changelog for 0.3.2]({% post_url /changelogs/2015-11-16-Release-0.3.2-Changelog %}). lensfun-0.3.4/docs/website/calibration-tutorial/000077500000000000000000000000001445356770400217315ustar00rootroot00000000000000lensfun-0.3.4/docs/website/calibration-tutorial/.htaccess000066400000000000000000000000451445356770400235260ustar00rootroot00000000000000DirectoryIndex lens-calibration.html lensfun-0.3.4/docs/website/calibration-tutorial/dist-hugin-controlpoints.jpg000066400000000000000000003700451445356770400274320ustar00rootroot00000000000000JFIFHHC  !"$"$C" i !1A"QUa2Tq#RS356BVWstu$4bdrc%CD7&'Eevԅ?!1AQ"2Rabq#BS34CrӢ ?= t7~uzYo ߺ"u"Z|{kW=ҸKpqCM+:a=qu 7niǏVU-j' *-"MRJ/VS--ԬU] )TVu[/fB%ĸQ 5n呝_K`ە*vB-h}=Ϭ*6fgU +=;l>}:WOQ~)D?~Emz6fgU/,|Wx~t*z'\lki{5?ʩx]|ReX|>tO,}׬*>lkT~3G^t>ʷB?~DYnMٟ[T}ϭ*>tmJ~v=_YlMٟ[T}ϭ*խjOukoSK,}ϭ*>lkT5'bIة%[>lkizʪukgGZ|Tyx~GY^Z=ϭ*}խiGukwyx~ߴ?YGmެZ|>>3SYmM՟[T}ϭ*}խgGTix~[~lgizʪ_ukkҴCN/weެ2V}oU<+4ةHh>L{џ[ULL_U昿;I\,giz3ʩgV{Q>w^Qk:/.iz3ʏ?Tut->Hg>L{џ[UE=*=m|rOWJrnoTI~_Y}Lџ[T}YϮ*תNO*M])^.U:?6?mތ6F}wV=(_=`u>k/U/Q,giz3ʵ6Wң~E+U_532F}wQh>X+"~37q>ں{}m?GGelYE?g ) :oymo?GelJxoq^}q?-,Uע׼mϴ7^}Y׮*J%W9X)5q:Χ׼f^Kͯ]U~]uszb7']mz.6wVW^9rmbx:WҨ/'u}׮*>,gi?[ǿ!_Jėr7jU@nϴ7Geލz~\okIZߧQ^O FLѯ]T}Y׭*^?wi~Gg/yy?5msbxB9ETs}:eo?Ҩ/'{}XbL_Z'}*}q6=hOy3UJxBͳI*eHo ~ۂoVW "$dXpߖ΅Xޑ} ͱ?rN']G\}Z>p06$yTN(nRN^BN^Z$%8&ɵ?9$O5GSGepVNJM<-Jb*PH|!LtEQ8bb=nWo[`el8} Ue(q p]q,9swR$=ԥ<^2ulv\5[2HZ‡Q5t7mRv땉"+(m ^%>(c'69;пF-D]+jSq:@R*(`n_ ҿ5nPDUDhW pFTS T Ӻcp9x-bJZe}C44OV|uha;I,rgmx6Ɗ%E֘Dnk!) 팚Wu-k<9-} [kN=lhN^Aըl韈m<$vvmlKR[HZV0)@cp{m(9}pCȭK÷.b6 Qp tsmt ˃˵DXJVYjMR}!)*S⼿ԛ7 ?Q%:R?$ qҜTxB6tT@eW<5 #N̜[m,`KxtT嗂K:BBQH#HdHԍqÚ5i33^}pBȨ~o1nmW"ZnOj/@' Z 'E?E ŽtNAT?gxq[o ZPihJ/O%Wϣ~"5/W˲@_GvY,"C%.+MqSZ81%c\=6\Wkmi!鐭%&ͱ7>a >d~oYX*lgjnN/֩/ )}G8g5]e4ɇBudaCڨ~B͹=D-<$Gy尫|襌J$:!ڪ \w/q˨yD mj J \,iN=WߟYbtk-LJRN Vtd JT9[ [엸U/ru2U Ғ:G|Gh1^bIg 49h;xUvݪ2PAGo_FK~U-<\ǽ q,9QM_l*,r2u6GTU=c#*Q4V$WiBR6T*rtAfϒXێ*;y^N`mA+q$oQoWZի[ki1ϻk#FِKAƍ*gi UQkV&8j4%@(zT VP c$ߝs\ݟӐ8i%HHwWd;"rʩ?aF~|si?7(_OSg.g.EYIQo']3|?Q3|?S?(̵>55>?џ8qџ8qu55>55>?џ8qџ8q?uu5w>55w>/џ8qџ8quN-^z-{OKg.g._4]nFZŻ]3|?Q3|?S?uqvmFZŷ+h;~;=}F5o?FM{Ѯw(w*{B^QM{h׾-_FCg.g.{F3gWѣS^z}џ8qџ8q/9}F53gWѣS>z}џ8qџ8q/9}Fͳ+׺ͯ+g~;~;=/qy4c|Bͯ5߰?>qwE?>qwEOjK^rLu}53WkaF~|?aF~|v/q}jͫ5ٿ?>qwE?>qwEOkK^rjg6ѩ|ھn]3|?Q3|?T/4e}ZnF}ivo?Ϝ]QG?Ϝ]QSPq}iէ5ٟ?>qwE?>qwEOlk_h8S_FL{u}џ8qџ8qe5/4i}Z>lF=hv_?Ϝ]QG?Ϝ]QNڗלPq=hգ5?>qwE?>qwEOmk_hi}Z>l^cv+e~;~;=?9~4|N5Ǿ6Wѯ51G͕kaF~|?aF~|vƚգ4jcV+e;~;?9~t|N4Ǿ6WѣS|_F/g.g.mKk_h8S_FL{u}џ8qџ8qe5/4g}Z~nF}ivg?Ϝ]QG?Ϝ]QQ22Ͼ?7WѣS>|_F7g.g.{_h8S>|_FLu}џ8qџ8q/9~-Lu}53WkaF~|?aF~|֗1Ͼm_7WѣS>_F;g.g.Y{_QLu}'Yۘm3XTyEXڹ'W_~;~;I{_PtZ,[u$-r+ő|2pd%5??>qwE?>qwEGjK^rEg&pdxOv &K+Sm4 o5WO,I2 .PTe ;y+?aF~|?aF~|iK^oCěO]]ŋ eGXqrtr8)y>{/eN9)K9*Y9*;d~;~;/uym Q%϶8j}!Q_ uMV|>zdqEKZQRܒHg~;~;~UGc]|[}Bŷev?Ϝ]QG?Ϝ]QU^o[IӯZ`e] ; яzU-qwE?>qwEOhK^oWȗ%_R\^m +Ki@Q)H89ƜAjF*tq؉uGpBԂ/џ8qџ8q:(Qqxψc0ЙxƳ:RI';al*]KNAN9ʺg.g.:(YIVCk/+VKu:SaYXpvaF~|؁Ѡ9.\KrT⿿Խ:#DǍ)8PZK/u뒒\ZYHJ;%t1>(xJ|ؤ?aF|fQvE_N8zlp/ ;"q O%\WÜI / \w:0m  ⮣@.?RKAn5)v1b;}i41UGf!XIC`nj=VKWSpu#$eJѧ8q thE)UIRj=$+nKJڛ`*//([0 o(;%|Q7;sH@qv1G2Zr7&-?qEbIѿa1)ʂ jBF2vm*[0Aƕ}>)"*GY;mө;  CE*-9 \8< Ez.o1-Jҽ:EZq "gSK>u68HRBT0H~u\XE]gyqٜ!:FyŐR#ޘ\vbOۦ"oޥ4) Q,--žN Ty !9o69;KjŽ?**eJ/-;nR;ƪnv]GY+c^uzYqcnyRqX{IcGEbB){+Squ~<}rq祥iV [m`KIqP([noQ3)N2Ʉ;YԢթ)V怴"ԭnH%[iy *$1Ө|[a18*1KeԒ޲^)sdPiJ\/8]dL+mr5`ϑ n;KanDZLqAtu$xڹc:IjU5RZ@+T5P U%TIjU5RZ@+T5P U%TIjU5RZ@+T5P U%TIjU5RZ@+T5P U%TIjU5RZ@+T5P U%TIjU5RZ@+T5P U%TIjU5RZ@+T5P U%TIjU5RZ@+T5P U%TIjU5RZ@+T5P U%TIjU5RZ@+T5P9m?qEܸϰN&[{gJ1"II[e"?}:StW3k*:_oS(\yַ{~Ous=Zң5?akJg[TW3k*:_oS(\yַ{~Ous=Zң5?akJg[TW3k*:_oWŢ춭H3Dyp}k 'JzNg[Tus=Zҧg~6^ :_oQkJ@0{~GW3k*Eë5\yַg[Tus=ZҧP :_oQkJ׉!I I(Ah=\yַ{~Ous=Zң5?akJg[TW3k*:_oS(\yַ{~O̍Zr3oGs=Zң5?akJg[TW3k*:_oS(\yַ{~Ous=Zң5?akJg[T$)!I A<{@0{~GW3k*Eë5\yַg[Tus=ZҧP :_oQkJ@0{~GW3k*Eë5\yַg[Tus=ZҧP :_oQkJ@0{~GW3k*Eë5\yַg[Tus=ZҧP :_oQkJ@0{~GW3k*Eë5\yַg[Tus=ZҧP :_oQkJ@0{~GW3k*Eë5\yַg[Tus=ZҧP :_oQkJ@0{~GW3k*Eë5\yַ͛O\oE.7h:;#"b-@ o(+œ#u|t!hȊ!n~eF菌y^j9mڊT 7SCZ@G׃N쑉_6zWRuiDP;?40;d *od(JFAJbόsBBu #,HIҕ`$$NnJP 4/"2߸Ox;Zɣdֲu. #nv8mz$6-E%he]RpÇQuJSI5kBp݊'\˽90Zn2I]iXӈVBwN?6iݹZm#եHei YjNBSlճۇuۃs%dj[` >5Ttdfx#Phn&V>Ү2|B; |HHP) NYcеQvL{,"m:ꞜN$)$jA զY\ӬqSj8vfZ4D2 >eDq4%Ǟ 8Rr⣈=@Ϝ,tvx;qKPO **{ \mVXI#n-k=cs a'Ul|_ҜeZnvYpeqR+ZR SbYs?hqcKJοɗvp̕%uq.[mvꔵxYq 5|iRto7`Ca(L %,8ūQG gT%26,W!.Gx!JJ$ޖ8fU]êzðۖ\ɬ\qBІKKI:-^oh)- 2Ttnڣ-Rٗ Ka^iZD}Zˡ-Q\CNmY]Js׺Iح]rw'2q qA#CsIy1q #Ze%(Br2#$ @6:3]O훍%;" %r:* 'P7V7Hpg$)ݗWűV:)ލ I!D8pI FqLw_j[:uuiKmJQLrs7J3 2(ELF(_E ԑ es\a۠LH  d ]=<ѷ 7z0{z˓\SI.JrYV[9ޯ}67qN/vu 6ǖ% 'ͶʕhB^T7)J 08|yi3e+&s$ yh&\u-еÉ-rtCx)4lZZcWyy!iBegJZu+Mp59DQlz'Sa[ȂQٽ2=9qZJcW.%7CjUvktTmҽ(qm7ęDgHn+ͺPĖ*IRЀ:%Gƭ\#q)&\]WR\FR[JIʶghF^f#E=ż[qې-Ï!P▔m.J'_xIv \“HymrjI0 n$!Iq>xx݉fF!孷-5D Ҵ7*#eUu6ӿb*Hԋwuqxh͑`LJLԛAFniOw?]VI_Ͻx!]li\Rޔ9 !$d?l0Yeq4;[U y -暹)R-hH=Z|5hiԵt T -G\BPqj7RG 9Ӈ.h_|4ҭWVcIRFǼjel~'D 82ܠc Ag,YڧxN6}rgKZ8J# ]\d7$U*w%nD$6nzaSWmŤNE ))APϣjU\:W)_W%jp=D=t\srIV |RqݜWI\-xO-'Wҷϝ2ڹ0ZnZNئr.e%[\' 7܅Jʂ Kudjm'wyn E+!,8-hRBԅ) JUK @PH\ք:suZa(_E Vimj4a8긪y,R:Ҕ6::SA9@ޣs.uq_y\mV ZWՍLl%E!+4)GGw^O[FkPY8<]Zٽݵܣrc. ujN)')$ZpǓ%?RJ>ҷzymm/|#klr[[(}4BlFiW:/g?좬uq8,ƹ&ד6Š(KQ@QEQEEPQ@QEQEEPQ@QEQEEPQ@QEQEEPQ@QEQE͛O\oE.7h:;#"b)}nm$*''c>ݺ#BZ= X5ۼg/}};f|u;yy8mhj(%9%v'b;*ۡ{?;t/~GDVtW"\+ O")mq-,Zeg ۡ{?;t/~GFAc ,? ޮCv*NA`6|l7:ݺ#BZ= \Uk$ bLI28{! \y (Zӫ ߑhۡ{?ڲt_:zw B7{,`Oxjx~$_F|NH/=*Dn'JBdbn{hн֏mMZZtnXwz^/. 0Х%VR N;ߐ6e7н֏m#v씩QG2/ͺƺ+n04#$t@*DŽ8;/ľc- N]q8uv^G ߑhOU_pQ9oxW Tg8-&Dbi]P=[QV07la н֏m#3V:gS{~)Zoۡ{?;t/~GU,8J<13x]vx7&E F tH*B}#BZ= ZB' Ek2-Zu畩ǝqen8ԥJ8 0^G ߑhԥ[ 8s_Fq/Y/ ] ԔN8IK!hq*_t/~GGn{jeoKS~ ߑhۡ{?ڐ8QAK 0BFEaۡ{?;t/~G@1Oȱݐ>zҶ֗)%+BT=-b]z>㫄KreEf/ qRA QpyUԽ#BZ=Lj|9\xg[z'Um4IEx(F p9y+ctSoGxòlL· $v$ӎ(^*Qꔤz;BZ=v^G̛ڇzjf_mW MutFe+R_\u$꒕# b н֏m#MJHV728R:('7@ՙtwiƜmmS㫏WEKk2cٰ2B]'HNºSBZ=v^G\L⚊J8'*J" )(J0{jUc=ߠJ÷BZ=v^G*|)qޅ 4GDwDt2(Rԟvrr>J^G ߑhS\^y{1p%'Dx}謸II JJy<ۡ{?;t/~G@8|[es}dY.;S IJAlNн֏m#5ދoR/h475%paN,Y޲_F|H8JNJy?Vн֏m#({x'8qܝΜq)IY JJR0$l/.IS~ ߑhۡ{?ںI*EnQAK 0BFE+Mt/~GGn{jA+6TeJ+ R㮹niKZRNI'rM'ѩ ߑhۡ{?\o,e:8xŎXEl0m4BPlin{hн֏ms6۶\qE7н֏m#)n{hн֏moۡ{?;t/~G@8^G ߑh(#BZ=)n{hн֏moۡ{?;t/~G@8^G ߑh(#BZ=)n{hн֏moۡ{?;t/~G@8^G ߑh(#BZ=)n{hн֏moۡ{?;t/~G@8^G ߑh(#BZ=)n{hн֏moۡ{?;t/~G@8^G ߑh8m?qEܸ-!8I¦u y+쾮$82?PY$J JFI' >|7/8'xvnPYee+R!aDdB|SAc 6!Ho;쾮|7/Ln[e%6Du(Zd`d`@\n>)5Kkq;'Q8dP=o_WGb>qzZ!1ڔ9䥥߬mwxq vJ# jT[-8e.F Fzj~Md6Ru%)nTUWnJO?@g؏fetv#}]6ݘ&ݥ!ձ <[#'3_LGΨ2( +:tXRN9<|7/8Kͪb"%Fx >yuilAB\'|7/8魾g[%$g (ɑ`ޭ3 D۔̄7V܏:b>q)/BYCJX?^Zkrr9 +TgIqJ%_U,@g؏fetv#}]21"\J):Aq#*;JWȂ컳NaaEU!؏fetv#}]570w"%$VppIp>JMq{]u]!.h>$⼹_-[ju kL l #4|7/8n}`$%#VtO~c˃䬮wm ˄F=B}(/"rwq;\Nx -U3eR $gM;!SθBJ̓( {쾮|7/_l];%dd="~H.aHuIBlP88#[UX 8Y *Y[PnQt$H2 Ubde>|7/8:j Bqe#R[5)KRRNN3@Kc1B,!J,CK$$tA)7@H#}]o_WH Ŭͬ\j1CqFsXG٤MXvRaIB:I A|7`.1d.3!- T2Fp@;*s~;gTIVoVKwjr>5*5ή4FVt  _yF}1 Ju(6J0)ʆmM &p53-%.B|: u$aX܁@O}c|ѿe0xz<1ZZRx%ӆI\)>Snwgi(ܻ+%u dX vϚ7~;gUb\eXlv]>E'' $jqvϚ7~;gTC\ide &eH}rzETePJ<Jn̹q0ܨt .!%)lu+Q$h)X( ߵ4oQwU#䲅!e=KӸ $.N@엝mŶZ HwOVH k)8ro_WGb>q7{[U l22TNNnI$2E0č?pntS6u)Ƭ-@%$%{쾮|7/ -֟qչU) 3o5m 6:ڗm-!։hJue 98g8G3`aA閃 ;-F0 Mɏ-!&X+x-^.#(`8G3ao^K/r0OTĴ-xԤ{Dy2c-!IB9 <:b>q1#kRK7↹%jH< 83#KN,RqȌ4[ՆP#}]o_WPw΅D);4@YBWRRm"Jݟ!2 H {9Eb>q؏fet홹ɂ%Ψ0(:sI8-g&k=nPٖL8R_8G3lǮ[4FTUXFr%*.p tTP:.kѠV:N|7/8W38Wx u-(*B*QlOqڕ\lXSGu.'#I,g\mJmH5;Մ'Y9q+:w{8G3i&jbj* BCϹyz) qEo2lmJrdnV3@Kv#}]o_WMmRf?=c^eҥzG^ۯuPKRp-RT 8, D%[GfN?8 (((( (((( (iˍ(oM@}%C8I H\rG8rEԢSn 2Ҏ^ s$V$ƍ|`Ra*$N\z Z ק@SQkl1d1 =JQVB19MrHWYn=3PDBB uջ–9KWzh X8'#])j/^myOH]W%hd'Nsz>nEmp)Rd=t: +pd'O#jxR8^><)j/^mI3bqطW^>޹mRg 9rHcj{Iv>TZ6.8POύ7Y)j/^myOaFxeO :\ZYxwԛ*sKb{IR8^>IIMĐz/2s7K=z ۋ27u uږ:Ԕzdj`s&K0^f[UdBZyJW r9KWzhpz}9-8մ MܺiR c:ژp;txe'Z7)­Y ('ul Z קIƛcUm)z[u Jp2I'I -zH K͎uIRYl, IN lb#̎%-q;Ƭ$+*HH$ίP ]=D^rKQkL;ҫV19Aٖ Jyg|LY.J%1SvfviPzxwp{kpz}xR8^>7kڧΆhϸ f#j% VIR| g+oTڻ3nKҳ$^0 zxR8^><)j/^mdvxm!)Bv `XS]"? Z קIE\ȸ?%Un:7e?f 9/e 2|dvdBswmY3mNg eYFgyO Z ק@k07' ]\mv޵0C K s:B.u![q-H:ٝ -8'WPV {+ulͷ6:PZ`ppz}jL+V6nTƜ]aQ^BR@֥a)`3Lliqm~L/6S&g^Hj -^s–9p|6}k'e!h˩e !Iʐ<`G G1R\ixCI_o\l@P/#)j/^myOP)/V{;}P] 3N\ֲ%'\A]j;_oZ%OP8Χ6pz}R ,w\]jڜh8klJRBaDd3Fjn˶RnL^oSaa,X%)$dmW Z קG-^s+HKoo;iy&dzoBÊRl6,e1CD NZ*+Nq5kpz}xR8^>9vn[u DTTڒH+9»I8ɴ<<hyT{( ̶ߚ@Gv_.ҿ|+ԏl^e<b-Pݥ~Wˣ u#m5Gؼm=wi_+¾]H[oQ6/2~jeW|;JR>yT{( ̶ߚ@Gv_.ҿ|+ԏl^e<b-Pݥ~Wˣ u#m5Gؼm=wi_+¾]H[oQ6/2~jeW|;JR>yT{( ̶ߚ@Gv_.ҿ|+ԏl^e<b-Pݥ~Wˣ u#m5Gؼm=wi_+¾]H[oQ6/2~jeW|;JR>yT{( ̶ߚ@Gv_.ҿ|+ԏl^e<b-PJ^uO6/2~jeyT{(λ5w/j ̶ߚGl^e3G]b-Qm5GQ?ؼm==Uvdt z_uO6/2~jeyT{(dk%~ZjLvGei JAeprONhj^ͪ2$KÐ|)XJ@y`d/ؼm=wi_+¾]H[oQ6/2~jeW|;JR>yT{( ̶ߚ@Gv_.ҿ|+ԏl^e<b-Pݥ~Wˣ u#m5Gؼm=wi_+¾]H[oQ6/2~jeW|;JR>yT{( ̶ߚ@Gv_.ҿ|+ԏl^e<b-Pݥ~Wˣ u#m5Gؼm=wi_+¾]H[oQ6/2~jeW|;JR>yT{( ̶ߚ@Gv_.ҿ|+ԏl^e<b-Pݥ~Wˣ u#m5Gؼm=wi_+¾]H[oQ6/2~jeW|;JR>yT{( ̶ߚ@Gv_.ҿ|+ԏl^e<b-Pݥ~Wˣ u#m5Gؼm=wi_+¾]H[oQ6/2~jeW|;JR>yT{( ̶ߚ@Gv_.ҿ|+ԏl^eIv{f7vWfFJF9(}~Wˣ u#m5Gbv[oQ#k%`W˨)EJ, NI8mV"]N:V$i_+¾]H[oQ6/2~je$ tLju\=q qdT&LqK B/ 3$|u_WP:-?qEܸ???]Uӣv!W1}1ꮝrq|_iV&reə0C @*$ jJFFHȭ9"qe\d$cvJ'O-A(V~4|15[a4CBrAZ\EE{qp&JG +x!E:Gc_ykQnR ,)$)$&͜n oKM\S-zu4uL$F5!C qA*/Wa,h*|9s䥶֤K)I EBX77U ۄ.3x*|۲x -RB6; T5,ˁ m,#/-hh,a)E-w:IņuMTJV\uNDINÐ@#iETm YAaY;%Ĥ>Uf+E6piY.%W) !JY(Q*Q%$NN7PK웍 z,gRZSӔAX)$@#Toqr2#.η P ($⮳!5.#_JNA+(8>B AA( &[opꊖ$䜁@1(LoYj)Ҭr=MsEl-d[Ρ.VdNa%.TJiP$jlW\YSn.O$.JBe<𒬄3od2EnB/={S}dNKÉmFV< pm{LK ***R Kj%j%I s@TKt)yN1=iXBJ 1) Kbr W K-uK%)R i8QόENڸ>kJM)NTIIym[ߋF5)p9@W0:x7.\ݽS^&V5-^P3/ؖgKn! Kq$($ߍBw%G#Vfݚ+K v˫mH@-$(wM09\\xI-6(%HJuijƬ_Dޙn3&*! :p{YsQ)u d{BT͋T6n.m3\e5 gwNПU?󪣪= Q*::ПU?󪣪= Q*::ПU?󪣪= Q*::ПU?󪣪= Q*::ПU?󪣪= Q*::ПU?󪣪= SGd'Ε~7Nl 7Ft\`J"9sn-D8WuJI@# 9l:|tz.AY;r_ЗqxGt;P#@5#Xj9%wOat-eN0Nj;1v)ݭ)Muw"qGqMߥ'UzRu 㠐FV Riܧ շz{'B[ ʼ,CBk0K&\xJ%X斕c) I /+jO[ +y_WP!4Qiˍ( ~c]]5!Kfta)ho-;dC%qtOUu-yR4P }2aKzla!ԭs ;'@7S2%r"Nz"JR!Zstj-En}Xf~KQ@#e>y_cRP~Fn}X9y_cQe>-En}Xf~KQ@#e>y_cRP~Fn}X9y_cQe>-En}Xf~KQ@#e>y_cRP~Fn}X9y_cQe>-En}Xf~KQ@#e>y_cRP~Fn}X9y_cQe>-En}Xf~KQ@#e>y_cRP~Fn}X1Sku_[<X6HaKQEٖfAj%Lvu)AҀ*%Gu d}n}X9y_cQe>-En}Xf~KQ@#e>y_cRP~Fn}X9y_cQe>-En}Xf~KQ@#e>y_cRP~Fn}X9y_cQe>-En}Xf~KQ@#e>y_cRP~Fn}X9y_cQe>-En}Xf~KQ@#e>y_cRP~Fn}X9y_cQe>-En}Xf~KQ@#e>y_cRP~Fn}XQDhGh{).muzHSPƥ^JVo[?YG-h\rڵeJuw\JtI=ۈ{È{>tZr7&-?qEa/Ì~g^'sk??]U̟ LWBc]\/6sŖ{i#-lP8#=&;pX(FJM@pit-@s O(dɴ)*ϻ5QMFU9nI Tq-uO4$IJ^&<`6P#ɕ@i< F.*8ښɊ횲!8 M&? iH7%V E [EٛC 䡚o&2{H69 Փ"Gucd2AlZ9hCME9R A(ەd1Kf&U[Q" &I )GBHiv]$cZ&ǩdJ5mPFH =F;"dC IqQRc ƞUoZV#;U"$Nv  )4+ P?|][&f1;;Sr‬ 9 aG;բ4Ey ˫S y*TnVaAu,Q (RH(IGӽ)zP E(RFNmv{d觑'H*DsYRIBR F"onUoR7Uk6A[V k"Zە`5*q DG{}_]R\[{gr7&-?qEygtK蟮޷(eSV9kE}1ꮓu-geMVZ0yAFMY*UoXY}%u -SuZyV8 HEhH)-!|?TO&qI0\tᦏ⩭I%GrRE]Ȅ`RJjTPy m"F> WXXudsN@.DWxV*dI29V#dȢ0ݵbAR*m@r4яt4JO}*(ADYTM(PI V-c(<ե';SJbsا-?9hfOuVY/*uN/̐QIJJe;I(4RH +Ÿ.F)L EzSSE VW4ujN`(R}5d"aXd AH=tQשE* #z](ueP+0Y(ڳT E*+4+0/IfZ d'>QQI9ajBg$Y1YeQan"0*ӌ N޲4W`w>eÖUSf!6:+QJ҅DHX?>i^Hc^@<wT6դ+9WR6@P sν lK%ĝRLaSw;"2 SzU*SXyf1cɊƉ9' O#rd Eh RtY2gYRIA;ʉy+$?%Nܫ0 B+0T4qw8 )7Q) (q8HGXxҡSk*4~!mAZv;/OR}Kyo& HԎbYĬk;b_JSM+TŪF'駁G#O#%r= 84>u8R甔N {.-B#xd×&*\R-JkK7x6W(г2VI!GcK##K(wCfF;msr>! ӷ#E64g&4춱Um$S91[Q9BIV!W[PjEL)'cVI6>bKGvޚI37ykmC\a@e*Dho4.iu4yV=@Sf@ X4B-<60I5WB孶ڱRcntҾx]o)8R<uKskc*H0|ldVKN#5)b% b YJ˗,T3xx"(j|+YdUuO y*H B}G *QY]-K{RhTQRUI8B;fҐ7^P9G(FimnϢP9pMg(RG ޤZwakK#)k R=`\6 RN^WphS 9HRv95HŻ@BRkJ5>ZDX RI|k@ZC=4,~KPQԟHU\K&?mH):A:r0E6h$[@8#cQEM!\M~ ve;R֏,/qV,cIZ)%ML IMթqWֲ E4UŕI50G!R!8q5-9QB.A:qywcˊdq.sM9 aLRچ4Ӷtִ)P;OWkd*a]PRiHRn7ޥ$$[Ik$UDYI|ĝ[)"yCc=k$4~JQ$c,qʳڀD'a'KQ-B)d7)h*$IEHFl sX!GYY-(sH B*J649ȯRl Ny5LM:2Q*SC>h,FEdJ,e=خ!MRE,UеbhS}@H$ /ryoNnS5a]jX9WU+,#(li>sZr7&-?qEqA1ꮒTGY soK蟮-.3D,ltg]-\J\8 MќH!%0ׄclj :CCK+T-y x}eO4SiFۊ3FN$ vJL9`U 6i+.܏RTwp'zɦH!xkB Y)GӖY>z$U\$1o4Zdo%I&:O >PPp0j},JFwSi"T'9, 5")cjpuRy]-C*QܶR <%^Q’yբf񔮥IA;?.YN>*nī DdhFvV=@Zy[9:3RF#ɑSihnӃ^8}58W҈"j.MaR qBBU&XtEc繩 9IWI8(4J2qYi"ʔK~A5wTj& g՚YS-89K4 #Nଃ^Zbߩ,|e@g(& q<ơWGmS)**e6(W=1l~̤Ttih *ICd%$m\=8N7I#HP8Q[A*5"YBό E^f纽J=A9d i՟ߢs4DzZ5Y>J~p=Ȭxb|m@yE(8q[pWC- j:v5 gKXAU֯2r+сJPryj2v&Wb"'myVyঝGT5)I@G}MwBF " SAdh8&Et1Y#Tt)6?Y[(D,j)( O8"")u1=mCcWX5ig~ob:ѱ T~U/h,TR|SNb}8YΔs^sEaJ wJ9htՏ(ՅI:NI>L&xW-sS+,Q+YKj)q:vjM X;]ɦVdSW"*l8[cdVnt]՘Agu]fM,)@J!BY7YnH#zI=EP-i:D4meYvޜDx0դ*"/CΧO'+z:m)v1768ƴR$}B\.Y$ GRA.un>ʗn5^re'*KjytwG4|uj"5{gS/9O:o4Rqzu:dI殒"gMCΝ@lS+/㼅!zFx#&w548ŞDA.qwlW!:]'%D5VIK5s#EİKu֣: T!.K V:)9HQ$dԥ \RӝH4+b׌OJ8UH$7I1Eئ<(貺/;JEP"iʆ)wf2ڴy\Q6l&9N>]B2:` kn-;ukW]/g%<6C-IόqS(OZyʪ$U$Kq7EV} VKNJO*RD8ec7g$sC"k)fJe6.<|`M"m >|\$Tf>rca ֽ=r3诙$sl tEO k6Y` `|\h9zj`p$5Uok%!gm i8TJucNB.AR(уݬm]K9r+{=Y#z-TS(PZG> \|LH(PRyӇ5 [ ˫#F $y)vZ3@["%J|a4F)-|u*-fGĿG/T|%'4ERMJ zk72tn:'Yc ?&PN9 mx  sI)e'WHrdrjR^#Uwօ'rNwª(P->sUY)+66T|oMZr7&:%qtOUo2':qž~CZ%qtOUmk&4ocR.9;ͥJRV|uAO-JFsuW "}~y+'S%qZ:!80g4JybJfC5!IRRTwE[\R|sW)IlV:⥯Sws/:d>#ų-Lf]OcHc:+O1Xj꬇er;9?*ISG09vs7 Ɉrq éCDMV= e16.RJmxTO@# YM]%uQQ6i;1!'`2=5}h#7uG)N䂓 ΟSh$ ZγJG9ԅ2eq$H|20jetVvkQJ jQ)P8OJˆᬵ/șwI PAiIcM9 ܀}5ak/e2zR% *"!t|ziP]ZԬc4Tp4o%z#$!A䓹i %S}Z)9NH*Z65 i sSMq خND +Jqj c$oΪڭI3uy[)՟ /q %KM:o. 9$2}MINXD49ײ.n+PHf4OoI|lj!r ULr3TxaSmg'ls ⴧ+L<$y/<QޅH- QũrAsF9Im{PsUK!E'gͫO\oE.7h.tK蟮Wħw65~_߇WDuUG7 Jm HHm_,9FN<ee KJ"ޕܦZ}*N+'pw8!c47u۽ۨ^`xw.$tL<_z*+vAAT2{˗爎8ꮋ&dGRqN'AR$"['`0cA%IFT3cv{=Åx |;ҙ )ߌV% //qTAø\ܗ7jGTPS9 !:;"mh۞iMPPFT{9~Jy`્JT+mACn'+qsǕ8q\-2?~kQ) JY sL&Z\Efo 2P/>Ϡ(";Hu'Iq; "U1 gŹ6ݾHuiX-ܝΩ}*pJk RqnS(KEJ\H$=qh\,nVr"M6Yu6 m$)jrFp'[{gSEts\z_> #J2tSjI쯒m+,#u~R- l= q^#w j8^~*})S wv[qdyOopgaG-}YpH~!CYrMgz>^+Ѽ>|8Aۊo sߟM`NfJ +8e=d yc6w-Mj$zNlwU5#qdV;ȥCvWex(ȁm qlsJR]!Xug:q>rk[*WT  t ᅫQT+{SHO٬׻E,6F۪*VtI.8ʎca\`̐9gv}WmkS0dq-]@Q-+`>^L_8zE%JD`cL[Be`SI=IV>-z/r駸_[]g-h}Zt6JXNpFt'Hx %y3b.<]#m+Q liI<ό0 )9$* XAoB򄓏/:ې.%¢¹D.,):W+gNOQ F aKHY.CjRU{'SVF{nr j uDvq $G ۧY8ez1R$[8189)Ӝ$ۇ>Lt6zm,ƷnP zRV=ʓseǧ6lv7n:T)8Bz⁄0&)ͻ~%[<Ӫ҅h NBY?xHB^'a*Y4oB85Rn Ky'.EEq,B-\`V}-BFFUJpu&(ؚB pyR.h0ž)q =Մrpr0F5 5tשwQ5=5]8Ti$ cqc~E"'j7]ʙ_PLj6xn[侖oGR:N2' -!mFɪ +-> W~ ReAMYO<23aJ? <c8an 5`7;dL-ׄvqJƜkH a4<*wnLe Cn,lJ?Y5{ƟqA2Rb-RZN>)Ž3@B")neD-?TvL1/D5O%4C0JySSVHdIR_Zo6[ʁըi#挒3k5DsB2Y_R8N D~pTG2]eJo.7ᵩ?*F #b ^nq S3<gJEq R z e1V?Y%@kG9ZȎ#E F e$?\ޗպw*\Q3OMu*;Ykd!ҔP+[a `gC YS8K3؀KIlo頻91Du汜+˗ D诮bqmje jJ*Q:|bjC*I%j)JZdga~tқoW2%O-wGO AEƑ-ZAVCtrODrĐ6c~-ٹ k2c؛e l:BT gyS$mGa|W J.nFV;pQbC;sM u-եRT W/%s`MCX>$9zWϑcÞRM&Sn7LJs;K.4t$!j9aL"rme=RcK61]얹-;q Hm)ZsT33ݾ* .k7xh: D;[̰SGfō$*1*)D{ *}8VL=t6lN2ޜpw=XX/6&-.T:3_tIڒd8˼鞥HeͰ{N)4sGRD2L*˧ ۲ӑձttBˣv fաaP|ĥDhq+>\_cM,=k$L|Of=j2z2 aZm獼rۣ2"LLhA,%GQSΡ:FsS1] @ui `stbCR-vBS8m XG8dvGLs(s:J7W~ӱ;\6zYKoJsu]m Ԑ uS #R}"'I/oWq7KsȌIv0@+_ShZy -ZYN4mS[Z[BqrRA$I#c{j"hV."xޭzԻhokTv_')F9 &c'\vkuJr1\'j}ft>T u((BQ9)~3nKjCI)NTR:Fsȓ+:JIQM !@(AErtųm 5%l4ȵ(&˽7~&@uw"JR S෣sswt":;q{mVvTjJ\m p{ˑ+'Lw Ү6!uᰂa;O3yaI'\z{`9?{wZ]\㛄_WMkTx%VK [y7*&ɴua9BB?,PI9J鳌]m)i (T#kJ<qW#%Eӂm!Cr&-8j\ @?%U>xr⋩q4-HAC@1[(gGa!VZB0 wiki?iˍ(oM.tK蟮^|w6GB} ]RR!m6IO }1꫅q-W}%(r!IR)N:N٬Eawʸk+jZMKI B(:v)gm[_-Rwm=xt@X #]۸: l,qw%MP'㻝;qX ǜJGoQRs r%[F7Jm?{W~;FTޮRSYq%¬ ^72fuJIAKk\8e<П$w{sT8ܙtPm=Y6rS5JŲd  `mUs.,:\ʶ=i:9W.X5qG }ozc=5z]zs๕}smMîH sJ~K *Ҳ `LkfsaL?zV/qԇUūRq* n-=-1[$GdCVFFrysF~_͓3JYJӲR ӹ)Ipj{RSI % Z%[ gٌ8XI|Fq>Zw?EM⨲]zm4c{_AC[lsnIj~]!.orB#⒧1Ϟ?+ WJ L">ͺRiQ8y(ckbi17D) `u*Gp95B2•ք$2g%Տrbm|\ޞx/ vAq Hi1TrwEMZ cV.knsDŬH&+GZubCnUr c˩)ɓ:eQ# l)8r#;bms︔6i. %-<9M{ }'xFmU$9"s46 tö 2tS:.+N G3nu+C:MJQqIv;RupNqǦ? 5>.~+zl5 DnSm(jtHnB}\6gNMg RYNw ѼdYOSn;Tmޜ:O]J8?gj;neSѵrՍ*QAҝ+2n"_9>*ԃ! $iC<癪7>{Z6ɋ0FÁigY.62N8Czb$>דjEpÇW|~6'Q%JIr޼ pϖʢÁ.a!&>ȲmɊXS:JS#~V+ME|<;=iJyN'{|/;s",q)\AJ']*Zb͒}5 =ve(o[`:T4s޽.斥{~G>\g*fqƐui֔ $ J2;;2 *i% PYL'(Z/ЛC7$TV1Z4Nw!0yup#)1pͮhs%[Iu*Dd4HI#$?yk\g(wӛmz6€O00;=e6CɶMǖ7\%_7s㮗-ƙ2Ҹf+bRRotIR'(RC (t]i+m(EWߛX'vߌOÙ|<\⫭q[tِ:>C  V[9j ȑ6g&TxWU""R@OT ԑ|nzU6jDtġb#k`R@I#NGwGmf$QƵ)6bTFHNNj9x*l⫣n1 x?*ZFs'I1Pnc#9j`+)C(W=6災gɗIpծq\aŽM}Pܦ.DdugrOXw *Hereʼnqٺx=cL7) ФgJpNG#vQUr8Q{)7rIm4$&C p%(Rq +PoHP؂s4OdD7ye[gR&u":QpHo RB'a@d]_[1w޲'`c8c1,G֝w'Z8 AHl`T@ @c܉&┩_S,*+O*$s;֐W:"\"q!/*?!*$HߊqFarG` fq4ۙZc$;lacHՖ]V(>qvDɍ܉x2(Փ)'pyr'/\ bNOR|m!n1rU[I(N CÈJ yZqݞꉿ=Qk5n㌫JDY8ooHwxYNcoNj )Սy9Ս^t&:\tq ^:A1%(,ۄ Ӓ|ޅ/H} /;ώ?gp71NnN彥.{Tp_ȓ,,nA_:Z@(8en6;%Z—h%杛 +{8Х+*AI%9z \#f'JD ܐղ-&KsK(!(ό|T %ʮmi^wdžYԖ^Mh!^)ӂ9wyj옱[l)qPppǖnRED;mbFo4N{|үKCNrhARF;u4kn\ogGeW-uIKiPO[I?vPv(BjiV6 B'ҭ?jfCbtfadxd&AIF:T`w}8`F}'V[dKj\RP|P,&@ IԢJqc\7HjUS2!fB|ngVH;z`eHZ:JOqkh[yv ݢA#y=36>8GY)ʛ}n;_Uy"I״j{`;kmR`Ilc-rp,co85+ I!´ԜǺ4G௮b!hZpp*Vm].z=Q7)2$i'Q؝COS ~?w~!nK1Kec4!c0IHno퐦ڔYs嫣g^)YݘȞ#Z@"G9'=p-iv &+:²_tcա}qlZ(m*ui(lg9;=s6jY:p0rzlX=2'[PZG S.*I/;r$8r׊;F7)wѫݺM-!⑍)HIM:BJ=)BBFF0;ÅmS]gPiIu`PJSG2uzTIɇ?ú,=&kwca8A fA:VO}ڢ(r;Zܻ mF 5fĢ RҰ򻱔;c;)j"d@۳Bkld_y* Ѓ|bգVWDPwa|sXgj( &mciˍ(oMu8'몮1!\Girfg-|BfuNנ$YX9a/Ì~5Gq [>\K]q.,`J5*dxZdno蘾īGV!GV{eG 6fpՖ, !WRO0G6jUcRZR]zԓ0 AyIG)T/Y'$q5*U:TL2g?$N[}^ccp{㾓L;%| RtJ-@Pv-] )9+S^Ds𑿥ī1K ˁI[hQJ؍$10N)HR_jEY RѶ'Z$'nޠ.i16xٛ8%D`}nsfԙ׵ʗ[FqJU Ooui/ZR6wӍٹacKir f*(x9iwl7=sJЦRTrfnsb̛2Ҝo_V@ V02)lJ:,6FGz TIKl%'h֤ulT}ʲ D. 4OC R9ڴMt3beIR[-x`Þ]\So9e`N LN񌘲"Q܎[mE$@-( NR ިK AcN>f: r3jrH+֛jf欤HCp >㰤1FlXqZqQ!jCQ ҇`JE^8cb廃ݸ*列7v)_bD|\J@ JI;$_-ٽ7Νm}<{U귺{4:{sOLFWKT2J'IƯɷ~^j-23ȸo+wt>9N n).2TK5 fuIy[턨vZ\)W~4L!@)Fj+0@} ɠwI\Z DE'9jy+ GI ]H՝<5Z[R23[oh NӒ1T"/K W]Xdeg%дnTZ S1fbC,!H= ~Nfa[ip:@( ‘ sw?8.jU͕i_]4H<3{XV!$gɢNHl.&f=vf$V jRJ4B8rqTKbW q+x[|M9Էp0qCHKiŲT%)N7>2e%(ΝZ'&g{ 8N8an*1>QQqR×[&'E1o+Rn-m $ aG: \є yk@)o 5fnfLn:4EBIJ* `]'FSZ:*8Lw[W%-N(:_eH 7&Iuq/x$ϖ4^<&8pĐ*JTrJ :vΓCEĀ[^ 3>验~(Sů-SҏʝVҤMGrX\vC<<_-6lؕMriʳĎ:Ai#nǦˑ3SBt-0PZJvՅ;G/q.k{֧z٪J Wp{۸VTYRK:{Ppn(VÆHST R)ۚ*tus\С.M-U:SRR06;dkDcrC6x9G+ ;ьAFMNć q+J{3H+C#O.X"[pѶٷJqjJh[#I8{;g5Ug 99C`d2AP 3] , *S [BI,#K{/ܒ&;iocZ}2\jjr4ʊ||t}!Pu|ϼ2O^ԩ.Y8 5m?gq.ߕd\uRWMʴCT3UIXxJљɥܨ>%;uK7t*j`Oˊ!ɷ%AIIq8\z)-Ĭum&3>(wGnGCҰOߒg'4HW5)Hz$%(P' =[rRѺEuաT$sߍ5m8Ul2a^N|ژG~e@ ei$F|kx'őn r%@|gZw %;Lqug8'I&N%EW'TuV9Өdխ{! ~C q-cmNNwE0.Mm8)tc׬`I&WwG);ekGQJː#Z7Y9aC[818LHs5ámk8ڭ̲*-=!8^^Rch^.ܔov8Bh[JRJ3c$g$y;Vн^]JmJQm6\ W|A ;-@B-8|@LY2%–R%kP"#7#^ n<f8\d*jL^$ $?0w-c\t+BBVA яR!oqavT YJN=f9ӓ;D6+C$3(QRcs."$hXJp T0A¼yjO_YN<#(qSv9I;Dd(I.%9o+M3{v`᧢! %iRmNA9 RuqDr8ru<)ŭdD[d_c8Ÿ҃|OŤu^kIJ}Rt4O2$DkKDf;@>6sE;޸vbO^YRJy@ kPݏEUEokRFJ MhYINpi~Q$7q҆i]bHƀ߹i{4d 2RRJrP'RɌŲtW;ZՁ*L$MQ$cGe%f;Bz0uuiVps8:MqҷרeZ=<ޭR%%I+r[JJT$:;%HuK ]-aK@p0yFO:IrE [UY@>* We]x/ x)[(Uýĉi=Mn jqH?M*פ5ѓJ^Op?-؀WNpet+;dgVZ滯Ew܌u7&CzV$0T T7IX VB{6ϔV.]yT;c@sXxG}W'"qM.7h4V&A1꨾4'KчmR] %Iq,jS%qtOU{{ $3!rTNӌ+Q=8JOr$r{]jJ-+ u,Qs ?Mu gP$X wڢxm>⒂'X9Z+՗>oc_k(+^BIP;QFƵz/2EF+GG9 7XJ0prۗ.C˂A_X9-5s# '}f܀n(o 'R}IҔ%RHRFŽp<1ݑ3}*ê[8ZI.r8B@(b#;J;227 uF2Ns * `9C"m^BJVA$ǰ\W;x,;aqRk$*ZuM[.ld%[^¹PpFFkL#>xfBghd!iJR$–Ʈ@g~UbaiPe ֦EsBsˢh]]ȏl5-Y@P o+0F4[*p؜z[ωh]ŔJN^ NNUkB-w7q@2[ˑjcN%a$gZ9N N2x KDBnƐrRO3Ν6q \|tRqҗXlE@%-)Xs1UYvK8*%JYӅFtƬr&(0.;b]Ҡ#e+)+(NS`ָfI i5A!(+|Gp7zӄ:*ƒ$)wIq!1jWX 6d) '4"t"ϭ@.<7ܶAI cÌh9PQ<7{i>"¼(] TT@3H#\q5|Y8diY':v˗wmœ+@|/)X] ^lKb:[e -><+cf|4;Zh75NZZCAK #B@57`ZcJ#9F6-vUz4pL9NE-gp"D8P[=JFw'yJԼI QY,pn#oO*ZVSyXNIl8hm->mI41n+^ħ@#8VRԃsgSho'0 !G8u<7 %ƒNs$ꍆ !whдOsj:4;%'IZ8=iB2@{ȏKw彡h5Nqh&C7BWigp>,֖Yy䤤$oFn+rkCH:%G;x5!]Rc; d 5jǒ2u[c}zcn26Br'5rm"s&i:)[M%NU4w#VɸE,(O'xiNܭIO̎#6B[B%JҔU*IQN@$`T-['D75:QY0~5zzmMl'3__?O\n8R`%(G$V`Z ƊBH8'm2II>SQ18r,ĔUu)Dk&5(Sl((h$V6vc*ݻNYܻ2]fu_pw'R3G0Ael~>K}{񣸖d5c8+0m׮RBV;^:u:AeZR|E g/ȵ%K]jhq#aչ䃱A'$Hl۔mn[Җz̹H^\.tf/6%RIyiYA8={ :TB08)a6lŠR ;~A^^h|IǨI$#BH#@}o?r̉m*t ?{ I¦\2l%3%hۼ_y'>PƑiI>_M1:LBBB F ~:hLc\8q:%?~pgF7J6.2Omw+.ԁѿݝ]wɐ/%]cm䩣uMNҢR<-a]FKLٻ;-6S)񕐐 8R܎QϣNrdjrӾsoMC2. $d@oWp՝m͎4HuJIrvΜ Fc%yPGJ E*ǒajedN j-Ao3ޠypq$o%ѫu+[D}PHrSE=}j} ds)9N4sӍs-)::ӂJ|9#yVلY}CDXQP5Gl0 mθ5oHʒ JuhI V m[g9S0 Xt1oOtTE.Xr47ӀTixZPtRUeP;?-a3#rRqFyC˲08Ÿ$v>{fg<8Ju'‡duS u% Apr?y}̺ϙj~%)\r۫`' V9mNہNe 1֕37ҷ=$5YEW2NW-" QVGb:;"!JvCHtaI\dU3q_lٱ^Z$Dr PP 8ocM#]/V:-^}mbvs0{˕Vz7dƗ!-Ѥ(C->ҔCN|UaCs9\Ğ|E*:+N= k$Jgg =c4* YDcqRJRq ߐؘwzBЬ\V̐eA:N35ML9oMs=8=Fb+I9x??oC-Iq|֠Lf(wsȜJܸO\o\A1:o*EӉaCj8KN2RIN'E/8'몜x58Y! HluxD`dkl0Rm3,hвS-wIl(èudr<ϕlk6rdJm%eV)';܌U?ٔn&Rʐz'{xvfԲվ#6Ay+EptVs7\kCo8N2wG-85pw_]!k@hJs I$C$yuB&I .7jB\OTBsN{ɷ!ңuz+MISK[-O[7Yk A-'| 0ʳ [o۹aMx,jNI$wŖ|>?(AWe$%@lA8mtMœ.Jnd%Ǻ!I9wTRLfx}Jú1rJqM/QI9@*[ti┴Zye$ ZΤ8W r~5`$ )$gIH$;rjoҫˍ ZLV&wcjfu|RʢZ*nwWSZ[#JBAArA姌̘-xyN-KGmFֺAqZsV~yvx} 4Xt I99Q9}l.VYoHU9_qnhQBUD9Swclb Nqnqw$w} n$rBHZ\^!C {qu$쳅 õϚowtr"2_Gө#QH:NAު\I9ze7!E店VhJrwq@nijHBm8|a1Rss!^eA L-I;!$c1l$kQ\`/IR}n1r:yCl! n%אJ ؐN9 [3 1 Qi +$ c~G;wQ%d]3`w\YFji!I#<sr ێې6i) yҷ-b/ˏ&H8 #_5=䙎Î7JT2'<=Ⲕuِv=eРRAZXjBln8BP7,rIbBl,M<밊;'ϓqi hYm)Jsw%4KZ8-qd*SE#;`]wn3ke=d7 .M-MeW)sAC(Zt #4}/0n.M)I%k #; Vi"͕$ EW(oϖ*|vs PYA958j{ٞ!VRAWqgm#ڂD.g)ԭ'?$KNx OSp]dk :CVqTE-^'YRBZ9Wn]_beqzmBCnhY\y~r1*6;ϓoSiq;ԠOw~>*5"|$rQ(շxO,T><8M:! /6003݂ʣf7*[>/[. $$!O%/s@Bc1Е)*IPp#9n34;3tUI;cḋn0#-*hd m䦿j>"o8O2F?EJ^䇱Z`q`eRbqӄ)vJstᗔlY$e/$11Wm6EKg[Im! r<:W ۆK#=#H*lA{ MŕjIb\nM)X =DB3'nFX햺fJCʢ]SYGR}7:i6y_dz)c:be):Z%eĤTN\A"dS[\J3E.tܐs3ٯخ!3K__ZPPU[!q񙰤!ɫRTNCU1m=,6rDޝ&o&%-|H[-LXep '87 ED9=RF,+mCY]nd\A? R;޼-Q3UHQ@^B~N DyL)pVb5vF:HH8N0>:ӷ2fǟ: O~sϐTS,N\,UJv-=Lv(H Tpwn%ʗ6/YX(*N c7٩ ˄ŷ^Z:ԅ#PA*;dlp6s4)#íbFu + ;l:︫cuM6ܤ 2p#pq_,AaqÁq/K@A8u9>S튉$en4PHRr9HSۙARJ`N24]4Mȹƺ2ñu.4A ;VpYAKN)(V2)Ύ}5&=_B\'[?]sq]9֛R-Or5mPDe){C*4y*(V:eK џ:[^)RzwkoHW&28)zAЩx+O~)FIRI'JV"ݚpqc<=%MD&+̫kzqH"Kvpu-ۇ +?3wW+c() =;Sq-8jJJ9:]h'yKoیWYf=կ Bکs:>j= 9*${3騕po!A-NY!z{9>\c>I_}wH%:A$!Á616P*m'z6aiKIgpMc=d(ˊ QMoRL1ca•&7^Azs*pK}eg8!$a#UNӰ=Ruc9ƬjwqVRkV9 ﮜ*J^rӎ"ow(LA,Ҥ na pp+yZ7["l=jܴ嬥`$pՂ0:տch$]$0ꖤZOvA &0_ ܏ȺGH'΄$,o)x刾0Rqs \bdK^~QZ(NN~%- uMO'%_}yn+8򨓍rAQq" #I;x=pz _gzv0\JN1*.CG:i~ Փ5ooi!*˩m$̑|ߑ"dE/% :#HJ p+g?:etI2`OY!- 8ydrԓN)xr-m#N5\ DX*ܜP>䤌⚟kxq --!|!Jo*;Y5ڀRJGy84ފX ٧FH ohmA0 ƹm2Tbu)܀o(tG~4ʒ+0-JW"9RDdVfp(ISd(>ST2o6ܸO\o\A1;&:iHApU;ϖ ~c]Oɤ} ܑO\Π2R+* N@ 9uj!Ι6ra%$hpTT ޮU8څERu:u ⒤=VxrmEm_^BRBJNrH>/e4@;ow"Z)P!VO?p[EȅuJ\RulN *{,)(,o$H#4ѭ\z(_hƹ4"aM*V Pwz3ƻ]mT*NU ;@~E>ڑ |8 YnylА-R`y88R5ųԼΗL)J#*U~nM΀̆\TSl-)m)Vp1jN%*:C./q*(n=o^n2"1 ԆR Ix$cm8MQ0zfV@S02)JHoDSfZ%c52 .! ooUx;l6%ڐҾ %E*e>:Rc}qmz" ,qnc RGrHrasj5jزTe%(ڨm;=nTguB6BZI>Sm}je8̼J! *#cR"(mX}oa7KejYkYAJ/@AV9gFw\Z#эasj܏:Q䶵jJ >Ziř0 uIJ9W9{SƟ ;Rw#}U4k䫪(:(nxZEƳΊo eD:U*\Ȑ2yNTEr<%ea*>AOpպ] vMP2!A wߖa; ! Z⃟y8Vx!:2(GA M OW8 F0f Re;a#GyҶfl7nyQN #8#~SiPߎ0$ mI½k=[QZ$̈Zc}Q*l99;5n>G3)A9jH .A9u<I1q?F?:+u@m3<=j]V-ǓʔHx|X>#mz n8@83(r&+Eq 9jCN$=#{觳mvم`%,*ѹE>NEX?u,E  Nq;>A;'>g툝lz'SJmMJAgNA1UÚE>^Xz7R[Ts3y]iÈ F'Q$F[) $yqv3>$!RU7iPR)'8 ϢВ褷OpqZ-RJp+kz};Q[)mA­j6%}kk9e/u [;DB뎩'XBpS-)HW*|esfܚ-J Op44] \5 Y =;e:ceEd$Ȓ*ӎ՝֣$l8쎡ǼVP6R6*c)He#ZBBu/،ӑ +v_mIYϗ㸕)R}Y2AP|2EdnJWXFU{Ne*%ۛ1ipRBp7'Ow#n[K&iu<Q̸U&*F^* wZzKEN({ɭ9PG 0qGLeۦ:S/{>=^V%JX {]x? hyG+2i)\2Lr~<{#.orT0ni%\N~~*鴌y*Uۙp}UQ PevMi,|):H~E!\Td[d`je,FeQxe#):w?637lZzISd@$寉}S^mT ӷp9ߗpV5N56 ywV☡|W|a}LLjghj m'!Ccc+ ]rCkH`ygZˉe^lTfB[I:J6όw6:ۆ'ljce}&d8L7BGPi%JI55t.a^)[~1>qk$Qm] Qۙ J`d7[gFD)8ԜiUpؿ>z2[aMP@P_y('p& >B]yE@6Un_`͔,/h!^Uo $TvCΥ [g']ի&j]%p7n#ҕIgm;,QOHLʦ\ HAbRN`1y9{d'1ҵ9s*UZ@ kNm roew"| [voS&,Z瑒21<yPR ɹɧQːi Y$a8H }Hv.1.LEE}]^FB7u`Tv# BNRs7A:f Cͅ)4BGzؗ2ZYR H#*Ƥdyi[hX:,#ӡZs@rjy2o@:"CwZʟ*\vXAnjpKQK fI+IR#VlJ(8l1AHR~I <$m3-5)V2 :0wjKG*۷ڃHVJ=5kB6 sE܋ LQ!u )@c'r{q4ɷqIekSl%H268H:5_QH\s\3-V AvsX=&62n=Nsףּ\ hTO,'sP\Q6aT7 i:F `9 $-2q5Ɗ`M2yR:'"wǣ8.6D]C!n-y^̝P|%V\`9HK*CA]nmI& RUJtbd)t4V{jNUÅiFs :^a6FpH+.Nw |7r%tL8Ȑ$4JJa |q9s# ,iн qȏ%tǑ,7?%&gkjQiFyË=5$Y+Z? ;(< ݊xkz9:ĤQag~ L(>Q܂lEJYI3ȬX0g܇|b6)9GS9O\!τ'=ümR=\+w-!iZN) 7>NdgTX!Ml[ (HEj/o<ҒH 1?Mm>WE%@2$l?hoTȝO\oE.7h N ~c]RR#/I@)K&_߇WDuT*8~l7$EJP+#ZɵLybF-vymRQ&Jm\|-R:-ADFNI9=9kbeZ:[;؜waQo!td; *FRI<c$Ԩ.Ւֹ++ُt,+!`w\yumɋpa$()Ju$7wj] 4c@'rr<8;V (€*$DY6Dfg9!d!;i kT[WT@ v7: !@=lsc\rvS*:R){pzjiXU;m#Vt!wyyGxq+主\%mze䤤+RI<'zB"H*Q<[Ֆ-m9:Ҳϴ5դV8Vwe&so;&L$Rլ' $H-bą2w[dzoy>[wפ^La[7vTԜ{5kZƵSCV d hBBP~BBsrfӎŵ^ᮓI.JiAX!oiFIP dU8Ĭ"›wPRp{${j{E%2<z |Qϸ~5ƀV #ܿXtM!(` B@*߈t`@O W<KPq%0ozdXMTY:wQQ_cnaohݺ1y'@yX4M@) mLquhXm VX$i9]<8eT2+^?=h;+wy?f+VR1VPܐZڡJ П'e;nzB6 5$V;sh싈?^h;uI%@ µ$Li#l[8qO$s.sS rT(ZPNJ s<`Iq*VEQxǣh[k15Xwr<͛khyTҬITdg'dm|aHw 3'ߌXv}[z>,N{ee[SHvHAJzP:~ɩwp1G ޸]y CmEouYHiiPY7Yk)ՒES7n!%0 {*Jʎ7*QaҼ/ m|Gq֬qW2isU73ދvtA!%  FTR1sqAj7RPpw)V#^v{D H4@e pqUp AVdF79OR~ \}kg>u$1<{=;MW5-O$A%c'|Dc۾c}ܭKk;y^Zj!q[ZS9WM2{&uȤqugIpoRG#Sl6Gd>-/3JтuhSw5_;w ǒK9<~O՞>Cw%,uU͹"4r㍀HRt&Pd|r pXBJ0qMSmh}BCK V#!@ ѹE]ikdlHuMgn2W IrJ1ߊů)ٱRچn)ps-R_p,N1}g-\-w28b - hHRrF1*}apRk8|cKBtT]"I*+qmrwHVvxАT$yЋw&#IKXaĤy}MZ{+Ec(/Y8uvY7)v]5 !={E-ǪhBl']E +i|4*!pV%8Jx+tSnCO×$˵VK=pA#&G\^Wm2ZZy *C%$pFSW>9W⻿-Y_&}HJln?->[!%͙V U@J5  ~!j\/rZ{[fGXSg,Hɿ|0[Ov h9RrT6Ig#UJoi¥kQHZF;O!Ͷ,Z!ާ 2>,b|ʦC?5$emӕŞ57hҖBӘ֬I8Q'$ l;>*\t$w [\je[y7%Z\H9I)P>a#$KOhI@ζu#IN'9>V9|ԖM/JDqIAܧ:  KA{lDE:ҬQƯHN" Tid րá A%HP9/.2X6h}a9 }-莨,yW.6qtu(ZgJ]O`uhq'H9#ǖ JVwA ')1,! }A% i#<ށUσ:G[p'u v`GqYY1nn,ֻjը2֤/aiOTGIBd t  5mX(yhXHo[VF2%z0TOz҇R6Pp|MY2m l QYI/IJq~m)(?#p? \PQڷAZ&)k#S2J$7oMZr7&: ~c]RLQ޲ :=l7|CL[1K Ғllc8Ϥ% c9gqH۞r*;VLu$U(0Or}"vP|^:JAJyc:"3[8aAͥZ#9''˝wsTE/ p)^(³vU0aڭHj m}Q%\?meؐ%iE$S˻V[X$\Wly E.mV(2ިBJN7HT[#!se2IGW7_-<* xx2ޙ=w[E|Kuʙ!XL) qj BrcR䞥׺ jǒ `gQɹKe4Ԙţ}C#|Mޝ*"ɹD>ϩKX yGc|B?ފ= ,rjjWm=-;5Υl[q`<*RRANGvUnÐYpĈZ^8Ov$V .Z[)ZJV9 {R3fΥB};M"%qg Vh°qwMPSĔ60A*NDr4}7p~f/%*}#Sbv'rKeĒI@_ᥢoNv[,ZI8a.л|.5y,$ YP>)?291Bkq Rmi# cv)_pQ>U+|+r2/3ŕN-[S_uŷ"Jc-TwY$d&XC)VRerϓaE191,6jS[AJr nj b:^ƺ6,R2_ V3? jO<גVw/6^iH񂲝#UB*l8%*8?u=M%RCj(@Q )MF2S6::ZRjMՖێkXARwӞD8&1PzXҖ(^ڱ7p}m.aƩ(ɓK@Ӕ@;?dEVQv*8|P..|RI%D5xل9KSssXZbٶrt>g+)Ց+reBǎJ\vcb aĐ(xhZ#C&2%PK^M)מU~5'Z??U_-^ϗV8߫\~'z;ʽkr5- )46j@ {d~[H6Rٛ=Ŗέz y6|l+XFlFPG~اO}uюC_{&HU:ŎJчHq[1]e)s#Y!YՅ쭎Ԏ%bm7(:d|cCAs݅}߳ tGk\r~g%#p:e6l sl.l *qLc|agnY?j)7v"Rp)dlO~;:Zt8s |#eƜqRP NrH9ǗmU:)1lZo`6OwpնXJՌ㒏6;ó:4yupaC8Xη[ 0Dx~/8pTKei%Zp⻁r3n?N7փt)e V|1T/ qGAĶ9NW)enJXBJHV +s -960n,+H7Txn 8w\,p4 |IKz)tm@ȑZxgVH !(Q;`՝9PHN3[x-*F {=;iB[[IB(;=<5e?\=kCK[!$m$8Vr~ z*H)Z@y{cZ@CdOVTV 'N`3;LƟyb49S.9d!G|H֪;2*ӤyJy_ ZeOoG {]H ?[$gwJyc'sqqW_U m\֝In!-fpsӭ$# d8kWRf`_}]yxOS'8miEol V@N㸔Hyzr5rjv7폥5 .BKG#ʓO +R )m6#Ox$Wr/D֦ !' VA GdAA%Yc* 8IJucP; d2,Il) ~3'BSmyH>0rG < :Ce'pHI7w=w3&KAn:4I)̨ds#97J[¸O&۟^(!հ$O/'5ww ޏrvk0uGV25+ J}}art3!%:;`%%ZjSyq$P#c+r˟ '[Ԗ:FSIFP#ҝ!ԅ#8k . ѓښ8u1u%'NF4{f;l}o O2'V\e@+ ?mR[p-m%gƑy){LF㼚qEb)=%\Q(gȅZORĖhh)i)wR\KmD()^Q`Ȫ6jL̙!%X[#l.^1Le!)cvQYE^S]\wLĈJ֥ Zsgd$w{ gԇ`AX~YЖVRrtUp=eX!Dpw8 loZK3ZN) AZsϢɩ%ƷF̚W6‹η: c9?k^RƊ˚7rElR)%;:PޒxROv`; 2KA)tr5h #\27o϶\c\[.愨')RNnF=" b̼69,Л_sdCi; 89VüPJ Rs pX\edf"`I8?UƠ/ oBSV:u^C$/o/sPRFn,kj0P {HU9; cVSłE:{(RHR2Fs5}[[v)Z[9+BGv[Jbe~81~K:cR4㴁nO1'#p=%qbc(ZUupvA]&-րܷ Nl!=MW.,B:(JUy`w֎-+!IY\K3p:r8@SV I=-;m*qF!Q*œo#s TfTKSn徇UJO$N{TaN3Uȉ-ġi!-YʇTS>C1q*-+H)*qܭNHYFpu$+u2oC!xmk$ Sߟo%ݛjABJJѧ@gַ$_eȣϿ&呐%iylu`V@I *ʔJjFg\\9VJnwJ[lr bf(fZIu#NF6S;ꃽc%Lu-ju|N>fj m رHuQqkJNp8¶d^-mMPKYjNǻӾW4%%>mѝ)o:$s|C.@O CXTeOrNv ^3id[,\nBuNS\Vq6c5P1qLܣSnP5''O\Sb-[KZw |(9.ֻ̋ H<|\εor-ϠP25h'wwAV;ߋ8KiQJ)e慃4#~A!6 Y#<'> c$DTv/bD5-@ @9$ +jc8LZucs(}*yAŠAۿpA܊{;Z]w2ФEC' 98 ظ^#vWPޖ[ 8R㢨wCƣNJ"ft z9V 8ElPgs/QmpIǔVν٥B`iWVRJ2G:A&w# si#\;ZW1 HVZ[F4 ]eypE:iŐRdDoRCg:T{Ͽ71 ‚ HHJsdZFw\j{%LBJwGM5ɦJ߱{Z;#WGZp՘6BA:@$1k`6lh @+#w1iXK:&jX|>#|O5\@wm֒O<:<1kVt ϗJP炥=3ߎBj\n9B]$a^*@yU2-#LSQB$A[{lǀ99Wx3TIR0rҽ+e@=/Iyi2ptXQ\q;'®*i)ɕJVR^#$d$k.]6g海oob}]%pqJ+ʭ8[\^u+)OY98kr8YAVHRd&up|[YTurN/r#;|N-Z.:K 0. ҐNs l ':@,Ŏեy}k-9EUjN ).8p?}3[2'qKq-Z՝\dnc_T감:@?ݥUM=!}fp49%JYH9ӱ:F VCh<ҐJ~H'%'ԟ[({@J7T*ߒrAǐNpk Ե&,.ye>E$ʽw!g뫑C!ඓ̐6;}5)fqc)m$gi|l2!3$I0ls#HDa@+p$aC4+eK{<7j[rKpB66> 2 ^F;g%?KW0`LYNvU(ŷmOEVBoE-Ѕk %=!+ i̦$)z- N;Ƅek WwKsrsN\ax' `xL_MChVCl s$5Ϫ>Wх?Dq76YZ)iVNcܿ ò%<ʢk'm>,n[,RDtZ!8Vr';3<ۜH]!^RRHҒN A+ln5ܽeDzS׾J׹S#าeAuBAdm׍FZwcYC͘D'y` EuW4C`S7!]tڜHcJRsu δ6 coOSTޒGb1S-o,`" c8údl`i(g'9GshH@pKoB$U:mn6;eKZ]Jm4@m V\h) $<4P%AJ{ E]̦pG ˳ǜŲ'N>Pfr7V^@wZ0 Rrz*J*''ejt R-y4IZN}nWx*BPRhktⵔ@' ;֗ForEAΕ@?O\ ȓ4q'~Vȗ*K-sdKjWC$g bHoMZr7&: ~c]HbJԷ5:^荻o??]UzG_ZgUFZ5 lv!\p9imodF^li`.%B8ʂF TOL7bd 7IVLSpӰ޶ pmŻq#2uZl:<[)c؉Xt( @dup#娙 ƙ p(5NIX-o5_3 2Fl4bC H# jva؏ (I5lZ8Ŵ8V2 Ny `dm˸s/8N+-F^7݋\J{Yr(X^Zp@;pGne[qM<2!C#y0M[N2%VJ>'mN`^_28/H'* 89wuZ".Qi"7EY.6 *y JuFwFqx[ d0!4P 25`e?%p']~!."_Tm|Y |>z2n}ǣpzI":H ̌fOkSHARJ$7dlZ-EMxHI ܏ʐ{8l=pn t+K``q9 ՟1ݹ@nreA Ck@zV;nj6 bGͮnÏHyZ$t8ﮥwoFHtGUs:\#Bۋ.8Gap%aXNw ޙsQ&)zN5BrG$;w}l)ۏaeo>őԬx)G$jwE&OG\S?kKTYP$IBF`ձ̶qO2B o 9N7mta`F#oN4Rsu8㟁4R"ޭm†Z\ |kHP—qt:[tOsIQ4'R;#;[_V@QHREB!ŌLpNqV-@(9ӆxoWr3ϰMzjWmh"JX9H5J'sq751↴Ax+8Km%”mwmOł{.HS]q)6rrrJSˤ4G\U$̄W<:5[])]!I 5@Uauk'Cb#O6]圔2=9ˍTz3A=qhOpMGЧlts[#qNw Y >+azJV%8njm N}ʓ"đ,[ԗq(OpCŷ:EE{š* l@F1w}-ۮW]\}]TO3} 9{;jŲR@' );r'dWkv\i)f;\1}O#,,[KNJHH!ܭkmBb!)mJyrP;m9jnuKL%E+QrIG57u.6o~8ݽ #:3I# G qF5~6mnx9IʈUZyBlDqѐI.U3-bIJqz'y'x.]N1K>onrs'WKvJ%Ȥtga/55Pשx"A#+'pdwZk8/aT0W(qt! Sg&N˄b1k*sɸ!jn;*qA=[$$FX2Thg.F[uIgpTyE!RV +8tD ^Q67˝ˑGx/hY"o)6IOw[b6;\7 &͉<7FU<޹ 8{!^5(8!x¨qU]GxBfȽK$N ;kNN7NxvH) uzB( @sHqbP1 <|ɚzlK JFeKl0֓?mn̺\!T8.c ' _'IZM8擃QR2 |oGŊUȷPq@tyV6֮ar;⃚)nUoqHRnHRBpNJIQ*ZIm#S[$EbMZ8%^2V_k5SN[Zt7er< ]c9ٜfPlIVv֭cy w8S6w΄NR+{w8I7J0Q@()vyui;(5F6fy"J?| @!s;N'{ʷBa;:Hu8ЮKʒSUHMMboNAfNC e- )@<0@ǤI\zui0M6U׃k#w͒9t\ldS4.-n(>G,y͇`AQC($ $B@$p^-BH SI'ɵ>w}p!溥-0W;}=8kdQR[qBHmFUݸ܎65 ԍ$ ';R>2,H{4mPJqt{😫]BZa/8A!$j΢q BB2Z(iINr<>.-DF/on=Օ,PJRds* c~Y? qXW79(: `'=pj/ZQsZc\4uYМgrBmon'XRo!gAn*upNjΫ$̘G#;l9 @$pqSB|۟:yݦx8R繷= Ut.Sثha/ą >V/\v$A wt" 2ΔJT)|e{~:apb\K=CN>m-Go*={Lpzs'kLKO2dCY%)AWk] ~J! OԤ ( lv,₢ ϣUqc}-L/H. ܀OwxTb_ML)ղuh%(Dd'm'9Saǜj\VB0BY'$'Ӝe4=wxr>8Y*R[rЭ΂NB5m5K!})ԭ 0'Ɂ8hC<]mĭ I9yEx%AI v kh 3œ`m(' rG3GU J>ýSttmEQ^p Nv< Ӻ[/Jڑr|Y|Ж3vwԞ{n`k_ ^ O0`j2ѧ.sYF2:BA 5s34C(tyl;H?&yFŹYxZnH7ouJAP IOrqqԘmR tZ%9'7L䍾u9]['WC++eH#;uǭtq8uks1>.43뫾oZGhZVneٌ  NByd\7vr.7h4VA1ꮦꗁFFwX?a/Ì~cp^T|W,{k ( yQǶ^T|(3G:yQǶϪW,{hGiprղ+I<a Q diuQegIZN7烶xQǶ^T|_#p( yQǶ^T|(3G:yQǶ7{Lf_V3! uĶrFPϣ@HJmRcXTQn1)-FG%IhHsFVOX܊+ʏ=uJmaETg(cGT*>XПR}RcGT*>XPJmRcXQ@g+ʏ=uJmG;s1CIJ[RA9rqqPJJp2MT*>X+ʏ=M c%duJ N_`hҥ`}+JS}RcAic(ߗ=fo4+ʏ=uJmaET*>X+ʏ=}RcGT*>Xwm$- %-6RH^T|W,{k ckǸIJJΕա̧h ^T|W,{i)&-PFJZNFӚ>^T|pJmaY{^T|W,{k ( yQǶ^T|(3G:yQǶ8cl9!hI)i @@uJmRcXS]=MņPUWfte8<@HJmRcLO5lw\7ƒ4/BW*r6ޜJmP{k }uJmRcQ6Ř2 r[Pۀ"26#v+/d5TVt AӀB{'|'+ʏ=uJmaET*>X+ʏ=}RcGT*>X٩HeGm]oIR`By> T*>X[P>XPQ@QEQEM.W+uq"tO iGJU*HP6ٛz_ m_;G0ھvmZ޹nzknh&:l:5%>)9JHR@["}{hk hﳱHH(m|1a|>cj={~%))F \-Ķ9 D%)$y4'?6G_ m_;G}ķE#)VJ!n%”-J JF{ H+?6G_ m_;G}ķEķEDk hWgc-Ggc-@Q>cj=}{jK$QK$PO0ھvmm|1a|ڽv?vv??6G_ m_;G}ķEķEDk hqxAR$%C>M]{;o䊏7ij`17 m>sGm>sWLhϦ1tYftgQR'8q촌n8qE.7h4P8'몺v?O 埰??]Ud8F ,xGQ 7s@8GQ 7s@8GQ 7s@SNuH쨩suMټIinR*ZFvyHezRnIʔJHpjZ&=w=vGPB?W ‘3Y꒝22OkH߶3>n粎HW<6(ï)7h.(6-(I=Tlg$|ew=g}g-L\xS钋+8~ڂ[JH|%H_ q_I;1w@ ~s[33>n粎Hũ<,[8mC7 IR:Bn粎H߶3>n粎HƐxNY$BPƁQ#'>z`Tt;1&۫!K.IucΣvlg$|ew=[Q&J)gД%[9(mH\ b4cH!m`Tlg$|e2G]&;XRJBWRw' Fy3qD۫O4kƄ[O-X &vGVKJL@-E7죶3>n粀qE7죶3>n粀qZÝUgq (T$i9klJJyձ;c?#{(5oIpEeɘVi!)!0*I#PW}|n> y۠m*.&3:TΰFSNqv[ɝ{%$U 24`A^Hv3d ͓8ȍ-04Z:FVNN7"36hS5iڋb\Rd+3 425׶3>n粎HwQ0Tl8:H8`Qi 7sY=5: ѠGQ 7s@8GQ 7s@8gi]X*Zaw%I%<؝w=vGPlO]m2udRo $+Y>p~7JSzB*glX#)8[v-ZdΏ=⒒Z*QIJB|ԯlg$|eT;d ݲfɜdFJS-j#+ J'' xBvnU*̋J%)/&]w=]bZGIK%HxB$jpqPmۭѭ,v~#H2^ Đ qөԼi:''oLm֋xqƼ=#V64R)$[O3>n粑Yq\%n'J4Bh \%.4%?c%[(\+R[Si$9wW+m6Y eHkWiW\!(*#>ZYڭ){GuԾ05-yQdRw=-<#j__.ضvSu!>97ywlLfvev͎g~rٕ֝ *i݌>H;c?#{( 4>n}N\,PYnD]jv$W=m67\%-%nSD!=ZP Qհc?#{(QMc?#{+iJ $vV:HwYjq\ҝ@rd%0Y~֘=WitgƠq^A@ShF kTt̐t5 dܞfotPoSC %@ 3V ۢ5%!/B]8 xsiX\8 <5[ 0@J^oc^Lcζ6Xl -$vczv%o6d<#2|`TX4+P D쐯mV{DXit<[8!a cP y p#F Gh<\5-)Δ́XOY. =2̷%hJdc9n'[Wl׏K rbvvzJ NSJB'[Wl׏@V7{U.18 GYS1mBU*y&)1mMrړ1T46jW3FN *mWY]kYItpƄa\ƑKM[!G(C0J* {ۍ~q-3_} C]SZIҀH†BFrrL .lcy7Gh4 +! 'HJudsV_Z*!xAH̾=qO-:z3^ZlHtZp` k>Ui')}|/Z$ޣ2JubB6ZUr|/7kAœFUoK]R-lrl g;~7ǖFum +I;#cbnjn7fn uK uk1jj Sg/ߜyqʄc2S $'^BFA9%\nWHqn2a}Ƃ_TJ;_XB*#JO#[@[-2c |@^ kNXƭ~6yߝ ܞ\*( r ABW7w.q"Է-YΞ i:8ޘKdNOg7)eq]y' mҲF3y5.-PEȧI##Ƽj6^i>f3L+a'% 2 sDLm6Ңo [RxŮr@nBB0w3gZ2UXJrgj\nPh`a/HXN6*_< Rϊv|˂^g.K+q"Ʒj#\DHqq# Nr@MkcMGv;@MFi=TU{pGIڦܺ@nʫ[/ӫWz&w̶mM]dNFl̖z )֟r })/$/aT&=RVέFrA 9To"r9thR' 44{ VIM51Iuq:T22ju_x [MJï6淞(*Xԯg :¥1oW.buԘv .㍭jNuI1@[(fziv?W)!P6Z 9'ql.,ʑ!ٳaM kZzHPmxCzFrB\=#SGX^:!x*U,oĺ[^f"8700SH##jya9vPC,ۮnۘ\rRS EkNIм%9WvH/7u}dBGˍԜiR *w opur&e]1PDN(J Nw`&ƹ[ba9Ɣex#RA,V|NsT(tf%n 6[d*;_CiuK 1Jkg xvG Dhd6JmEc%R' ][ZD`[%38pZ-^-Y8 U›BnEGY:2tqK ]J RI5W]L7ܾ"_9ԜƣeİvGFr:$RWzq=ة)I\IJ'orZ PkJ5I$s$X( &sjl(&^P{H:TAِ㴗зfG>ϭ;s{><ϫd so$B[Ez3hh#ߗS>ϭ(ϭz3jF;z3hh#ߗS>ϭ(ϭ##0-%k)kIZp 'OhN̏|\?8?z(Df$NiPPKq9 R8 \6/+i0/+hܸO\o@tK蟮HП; ~c]]՟QEQEEPz#Gc<Vuˆ~1se"dNBNtrQEEX˃x] Fe޹NJQQ)HBtހT+r )(vX̺KPZD$%${>!In1^"EvE-?z8ĀR[2N:ESx8Z8zc8r'm@0ڄ_}')}Γ8Mr 'd! %} xA )="u%HZSCIԵUŬXeS2ֹŲeq-)А4$4h uQ@QEQUnvҋ.=mj%1 -܎Bu_3mQr3IHK\>,uiQGyjXQBJAN5cEjx#C& UPU8phgOY_O͏yJq5wnUluqT۹n5h9Uwga%(z?*JP)ˎ(!# 88oթ"LjWjU2YԦ1Nf#N; EW":[wh7UpABRնTK29 Q@Q^(@{EPWn#ülJrqu=cA^"2Q3^f>"r}6(\YirX5V JVT; ES,/'668E30 zcY#BV%^)RH$a9>5+ÒIv HTeJrJpP*R֬oKQ@Q^(@{ESN*N)_U1=M .Zsm cbN@ސ^!u_T$Pz2( D6⊡ۭ.7@/هե[%,%j $#zSWkQU!F8SF `((I⊨cup&BFHbrla=6GAUXB<Ԡ3gzwם$[.W+h7]j3)DkOVH:RCVfd&W)0l3n٣3HjFԟa#~t9,+u-p;hXKC`?'Wviut[#ANVI+I땡M;2Iq0*Zlb.lcGlen$yI; Jt]vU$5icjjReDyWiN#Y εdx:CJ&NAw:tgI)ӧN2#'b$f\yQR*SipN_OS8μ}4|=gev}yo}+v`ˋ:#rIfTwFeahX64QEEPU٥\'/3qQqJ:I m -ə!]TcOuMo|$ugI9@9gkܑlCK-wP)%$@ (NXN"-q@Zc4x),3EY$ GIqR%,DlRJssNN!bLwl2^jR@wRv$ĕE_WҎME۫ I' g(ND% ]bTDē&:K /-,$jV1Njda!֢VČ)lY n7b^/Vj%CE`c8Fqk晸߭pym"DRy|J$$WEPPHp3@U"b}{t_[2-Ũe0BrF3޳p' Z/3n֛{62&01m5M;()j]mV~q=-ϥĥ`RJI^[/]rXVy p6|N@EET-/y#uM%Ci@$$NkO"wYW[ dHZ )J[B2BI:I:FSetimX3`uQ!(|ufEԜ;dӤ|t3llNrr}nFg|l)wźMɔH2Zi$h[ dH./6;mɔԽQYݯC(~t.L *#&}QEv="iJ[.Y<.$)+BV%C)P9ykon8nhݭ#\%.jAW GTdCcꂆg 9Ä|s4PPZ' mE<")9^S|dݵ5VO?%Ŕ]Jl c BS<'ɋ=^63ڟRds]̭8Ht[xhn0̃KꙌ$ZP*w/-; (֍լMF#L}&>Z`7_KY~_xx|fsY<]ed*8Β3~S_4{EQ*ؿ?{Qؿ?{PGW調bGb@Z:E_zzhu~/Tv/TT/IN.=sJD$%8Prq@8$gh4QEQEEPQ@QEQEEPQ@QES""iˍ(oMA1ĉ 㿰??]Uؑ?Y?@+EPQ@QEWKM*|[hHqҴ4wZqWz5q7c@v)MZ@Xl8PH.++$$d'&EQEEPNu<~"U@! _W5#ZnK\ҷ!Lr15wʇfI]&N*9ys5k)%-k2'Nv Xt)ow:@P*OUR^\b.Ȉ=)8@w]٩jqI|6\ưT[YuJ%)w;;Q@QEQEx5c.lbZ2XqyǢFsIH@ڋtmjaK[Aε$e#jQ@k8CxMs5 (Ғ4 І²U7cL{Qʎ0Tߺԥϫ1\B}) LMZLc˿ҷ唟MU S7Ŕ`d2b%NUHWOU!bۥ]z ZeVb?$(a.(wJ?Zq{_.E0 8ACQZ^H)‱EUx#drcpUrqDK^[ljqjVc|$w՞o_Vq-4pKjZRJ:Nw {Wo[Ee?p%)Z8ʊFӋ_b`A}؈Zݑ8ЃJd\8eifdEzk.ul)=V0J@Nuem$'I׺\NqgML*G\JFN$ӁU8q-kb d-[wBeE`:N689evUsQp8ė}K,kHʎIi1k]=~SJr (-Kvmum PQҝ+IR2G0QxNr -+֖pԔ7sR6E|F F,X^n8NKhFqh EQ@QEYq q$vg O?[^,Ձg $lk?xj4ILTęA)P`QKd)'|Ljݮl!0M 1;:˶3pq[ur> Sm!(I 2@(iKhZ%Jgb Y\%H^ Wdxv/NJdӮmdJ =#_>-j5'ʓiA e VZsg^q%t%[`RҽkZN4[HGep@m$/2JhZz@'Cap|Y&8[9[- wp(J#\\EQ,ukvun+FI IR6{ѬE|XpVjY(hRVZm7x|Ivb @T6Ðq6ZpRހψxl+M7'mJPBQRկ./Lb ͭVkxJJօ:. 4aX9g.~/޿:#cie˧ Xӧʬ $6ĻkۗT">uem$'I׺\D76m4À\;'*X"+Vs##'zǎmIxطBL2P~{J˭2JTD'Fqw ݯ!pk\r#9Q[4ugRFp};@ {w[<+-s#p(3F8i?o)*; Ly↔T΄'VO!q$YlaK#md/<$[VI)K`pƊruMʊN0O# ]8aRgqjCD,uMqji{ 8HK$e'*'lůmɐh$PJuJe'8S8I$A2z1A0OXLp*P=by2z@9-GunS}dUOx8LjMJl)7 pn/ӾlJ( l/&?OQ+:!1_\P*jܨihJ.;jRG5W2H i+54H,=p"rsV;܈(h"w]LpWiHN;1_¶RbMA:֏O嬫lS R_ --V $CTr|%D\RWQx:04`]ӊ lj웛lv7]NCVz[{{N^f{wo}NzL61=ݚ@S ]] Y]B&}2}eIH؅  t=lكע4dv@)Cd@BnN¼mWhiz*HReέDnBr9N1K *6-qҊ .8s*Q@R gb v1 xʓ!Iln8=ދ](DDb 5I:P 2|Q@QEQEEPQ@QEQEEP0/+i0/+hܸO\o@tK蟮HП; ~c]]՟QEQEEP Cl.\d-yjug Y)$=uncI |N.J'K}ap6#((&!昳\#ϟƯ0Yĕ䦒RH*" /ʷDhzp׺!)XD!I>"榾oa ZۅM{K;EH18vKMv[f\%IQ 쌄UʭgESFT>C-VNlϸyWːd2PNMo-&Y-.R!m!i*'HXq^(|Q( Q@QEQT[u5"خwg똉39eD-zJHVwC#\mMl0$]Xm"!zŁPI$l+_qdk $^d>OX:zJ$6مr]_gnߝ0!,B T JQ*'U_^<=ijT\}DXt,:8)*SigXDks!(revt2C}nu_:9zgUߐS|=%M[.E-mwQIqI$j@QEQEx$dds=!_{n-I[B XR jR9 Àc$\.Rb-6B\թ;Di#Ek۱{qo\(MH$^2vұʞpCym=zKqְXRr6P14Ś|5yΆ$8%4$FF桸D\&pj=781+sﮝiFի9 EFJkL9ס26)|VIPQ@QIgEv?Z]jiZr1;Fn,Z.7i>k!^2ËQPНaE$'QnG;n._աm?$ m`)g;P6Ӗ26!gcj#3 :$@ b}Ыg;*x"Ε!׮LCJҕV ibq@]_J[5ʏ"In1cqZP֔:#8N o-\&cϼ֋,CpdJP$ 7cF׽#i-,45)GrN2Iju3UxYheu<qK[ ZpT¤8EIAV)zsg)xBi뎼pk%GaV^/cz{$Fͽ)\u``(>մ' (y3#.k؉[mΥ(V%A@$)V7nܝ щ-Sm$$)HJJc#}ez+\!-)܄C@(FF#Sk q; p-Ժ^RJԤ(*AVB^JxvCKpl7!)hx)P #NPQ@QEQEEPQ@QEQEEPQ@È{È{>tZr7&-?qEa/Ì~"B%qtOUv$OVOP EEPQ@xc HPin?5qӓ_$sBQ*006Y^.0WKLH)U 'v NuuenjsiB* єN3u)$zF(*#xnHf-6'?%GZuR':HKo_<7hr{ )…(|@@ \-g23`G.Rlw9W5˄w;Ci,,0 mR&CW)km6^)m(l'B+Y]jzS)2Z9RBARQz i2)i";1IԏNGl"#(2t$d NX8f'I{ um[o$k_VhNA񕁱T&E\DE5ƂgVyc怍җ!u8ކp(> wYxncq-CBZ+vC)-:P $`%ag/ q%:p|qγ%dPwRVt!iH88P>ZZ( ([Hę[]R[q܃6Fi#6;w%2Zw8 wVjk ̄z:1uZiϦc/߳g;*;KŻ{e ҧB:t'uw.DS27 uH dmFz<֞yp) mAYkrO2r{؈zCCunzI׫W^n,]Eim!-ŭj8 J fx,vbޠ˅=_U^hӫ@= V:BjRr)J%JQ'$Isw&Y*RP)*I’%@@"PQ@QIyѝB Հ2p 'h[=lpKr_/ܤHKFP*5c8(fșm'%D$j)q!#V3Ⲷq=)،)-2_S2= .%IcXٸwqBm$ɓδ%* EڣY޴5  .Z)EDYϖx^g0ש~cϭ : y+;'/%l:PgYQl Hq)*I†GDgkaƊW*}szlp\EaB.RVJC@$)Dw$ Jĵ8aYҰFY$Kg L\ ֙+(AHRi i8+˿ZmRDg*LTLǷ!e ) QKhQHi)bj,f 6hJJWPZFAq^Q@͂)e V )$py4lVJ 74ES0B6 S :!1}6JvK'[Rsyg[=6}b jFbIBV@BI#;fq-1QݔԤ4^,Jg `V$FF@9M֛e" :NJ=zT*Q(9;ާj>wo (rcukGm4)iCiGm J) gX\"O2\!&"NRpyPؖLSHb:Zդ(J.{U2ueaKyHFq03[L/f*ČQo,0JqD %R\ZK  GvƵ=.g0l[dܣqH=Ϗ:G:ȱW8xCxde4=2&Ss%&a{05 :Kj|4[B9J9t"-Y#ڝ$V׆m6VCU u+B]Q%@aਏEl\/#.xVhZPS$[R_e`䓶06%} hz"c-3=ƞ Rqegp 'TteҝuGItkנaY`ӚEDp)|HeG7V4-gHZ $p<27˺f;*PW=LPp @!+LKKi.,$(@\xOS90ҹkiO8z#I'>(EVeL78g)v2䡤.Bꄅ(g A(c3E՘ѯ 3f6*- v2xaJW(J%daX)vX+/JTf5 ^I6(((( (((q~4q~4΋O\oE.7h:%qtOUv$OVOW1ꮡtfBs-)C@Ʀ䑜y-UJ&KIGpyL2 n> '4 W"zVv8~džY/II9:*ڧ"/ڧ"/ֽO!Xt}w"Mw"M:A Xxr|[i2`jCQZZ(;'v z , wYujՍ;u~;u~O .U/N1~D_N1~D_S: kSq|~5%-NJXy8iZ# O6;u~;u~O ܹ[xs7;1n K>*h$i RBH!Ĭɳt{VY.3&D~^p^K% $gu`5'ڧ"/ڧ"/өb7 q _tyVbrR8zФ((c!}YX2oEK` S(TYe}HGUn @'|X;ȋ4v;ȋ4yX }q .lojؗQHx A=YC)'zq[V"C.#\UK8ڂڼaڧ"/ڧ"/өbҊ;ȋ4v;ȋ4yXt}w"Mw"M:A cs]-!]u@a*ʳ89"[q-T!76T%%0PGSH%*oդΟv;ȋ4v;ȋ4yXBN\JN24+_OJp{շh8=4Յqlp"qlm!hl$@;sw<9{?lmی*l'V9NN-.>p{շh8=4H~m7[s5"-* iK_|Vi>0J8fL!/l?lB_yh2חv.%ZNFWv}[Fqޭ@S,<?GaV[yPTv5PKcJ'Ԭ-mI<0%19ˈN*'ݲ[Fqޭ@Rx.ynhCMC\`&fr(qjl6V;ez[FUhR$ON?ulR6ⓜuDNOK]{\K$n"Uoa%C`qF' Hw\=-2[H)Z9)'򍈬]m+.S\<%ŗ$"FP-%~zJR;X+d)%Nt%AA.uRp@<0a]ex\[SO%ZJr%*ќE"QRTtpm:]  H8sjnX[KM'$JF)z*3Ȫroe!wQEQEEPQ@QEQEEPQ@QEQEEPQ@QES""iˍ(oMA1ꮓ6UR%%ZU;>_߇WDuWK?j~ ~E 8fxyaE/$m@mݶ*&{o-҇VҮlt)6Dtm)a8ڍP$)qC]uvsq?L <ǽOfkQ?=K>֢z=)1_4vy?{嚰}D',{hZOXӵQ1_4vy?{嚰}D',{hZOXӵQ1_4vy?{嚰}',{kVCt!Cϒ'|GgY̖ߚIcEܥ)A HNGg|gY{,Ճj'>'cGO|ORǶgY{,Ճj'>'cGO|ORǶgY{,Ճj'>'cGO|ORǶgY{,Ճj'>'c^&g)vÉ VFh kb{,=ja%Qa%SQ1^4vy?{嚝nkyN1 Rc0p7qO|ORǶgY{,Ճj'>'cGO|ORǶgY{,Ճj'>'cGO|ORǶgY{,Ճj'>'cXio=PT:@ܝkb{,=j®A[vG-5GgY{,; [m]p&3`=֢z=vwW<ǽOfkQ?=K>֢z=vwW<ǽOfkQ?=K>֢z=vwW<ǽOfkQ?=K>֢z=vwW<ǽOf`iw8iRA=>dv;;+ݞOf\G0P|m=}|m=폔vw7`+'X mFB0=ǫNZERH( »J%A)Hm9$M'ԟ1Ҫ8'c3OgP(IL*:1T)R|>S?J|~oԟ1ң>c)@8'c3OgP(IL*:1T:'&ަ~WV\΍]{ՍS?xdyV̔(I;Fqenp QT ?E*a*I!,%t6ZTw VЭ*B$dr"Re%D%)'~SJ[lIghzm{ֵyZҧ߮׽k_Jg^}*$\aGs23+#:VIM.$AyZң׽k_JrBM)^;)@5^IP m{ֵyZҥu.6ZVRx5@7yZүzٞm{ֵ}F'}P4n+@Z~2)d*b ,- byY[s!GockV ;qTt6ZTutZr7&-?qEa/Ì~>_߇WDuV|V6"=eaV=wъbSԝ_޺g{O[շWYc*ƜNWjK?u'4(( (*/ ek"tNJBf6OY 턭jA4##늨[ȼBųXɻIdFm[l-hIYZ|\,5nJgl(( (*vYڞghVosG+ęvޜpQ1|Һӫ[iե>^qqW~[_TCp+ ((wIќSO)g?Tد5^ bڛ)%3cH!m`S~ pnR.YK(sNKA)ԑ?ͻUYfEPQ@QE];iNH$u%WY\mKwbZPR[ 6u_=Pi]c%qLT,VXRTb_u裬wE_~a;_~5iX~: P uIa%*)=sc RDhⰑ{.;'5RC6AsAH#mzl-:T# Z)^Wu(^ 0<{nIxnuM.3%M;/8G>~JK5R<(m\؇rœn8JTIPnq?(N+󖳩jdtA$%a[ݜԪBTf@RN69cPmаJ!#Lz%? }Sq)Og^V IBKIzk!ЖR #H :[-Z8#%Dy aՄ8REWFDŪcFIW[(I[2% Kp%ԐTrOŊtVJR\Y#W/uNAuŬZ!]`-O VZ+&Q(-B:*C k&GwX )I5h?kh#CQ6y,͐w|p}eurR Æ;'d`1mrh+C8ps#I9 dyjh8GVXF(Që 8ހǴ4v~4Q^agk1O2;@;(( ()~?]CO~?]C@|oMZr7&_߇WDuWQ.}0:cET A%ń^q|+ХJ#4υ^s֯9?XW壬_yO Z קPb _@LxZ8^><-j/^mC5~Z:-1kWzj&gY+Kn0Vym/`6Ԃ9oX@%;"3IiPm =WIaj %2RX$E-@89pz}xZ8^>ڇju5~Zc֯9kWzj_/h Z קG^s~GXW&<-j/^mD}7']o7ԴM(d)̌z-xTUD&(LMDL0HԐ$ Jpz} 0@kޱ@LxZ8^><-j/^mC5~Z:-1kWzhpz}/hjDž^sLƚ҄%䒢Rpu5~Z:-kwaQ. f6VA$jNN袀.6 --T%>"H Z קPDGk.@LxZ8^><-j/^mC5~Z:-1kWzhpz}/hjDž^s֯9?XW壬_:oL.%)ZNB IMEPQ@4Y8JiJ>@ ?v>G85XW"{d~FGl޴{j[_/hߑh 7ږju5~Z'AoZ=v>G-b _}֏m#znGXW"{d~FGl޴{j[_/hߑh 7ږju5~ZC]l#FNgP>_E) 7ږju5~Z$̄NL{iյHqmAhS*8mq>*y/kNI'4IeeC 'r(? ;:keg(cУS(v_B;/?N? 2DٟN1m m4!!) ܙMtIyN? ;:keg(cУS(v_B;/?N? V; d]c)`p6ZV(( ()~?]CO~\iˍ(oMejňڛld8o$mUѾkR>vE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_x~"JE_ 9Py qpOJY! >_STj|_G,ԣ#?TG,ԣ#?TG,ԣ#?TG,ԣ#?TG,ԥX2hg[A*%-ۂpFG-JXoiˍ(oM@}߷oSW.:JL;vr-4. Փ֥D(1]1(6%tJtJڢ+lO+lO;j_L_ͱ>L_ͱ>+~]1(6>]1(6%tJtJڢ+lO+lO;j_L_ͱ>L_ͱ>+~]1(6>]1(6%tJtJڢ+lO+lO;j_L_ͱ>L_ͱ>+~]1(6>]1(6%tJtJڢ+lO+lO;j_L_ͱ>L_ͱ>+~]1(6>]1(6%tJtJڢ+lO+lO;j_L_ͱ>L_ͱ>+~]1(6>]1(6%tJtJڢ+lO+lO;j_L_ͱ>L_ͱ>+~]1(6>]1(6%tJtJڢ+lO+lO;j_L_ͱ>L_ͱ>+~]1(6>]1(6%tJtJڢ+lO+lO;j_L_ͱ>L_ͱ>+~]1(6>]1(6%tJtJڢ+lO+lO;j_L_ͱ>L_ͱ>+~]1(6>]1(6%tJtJڢ+lO+lO;j_L_ͱ>L_ͱ>+~]1(6>]1(6%tJtJڢ+lO+lO;j_?tm_Ϗr+lOWKju.S:kz$|+~]1(6>]1(6%tJtJڢ+lO+lO;j_L_ͱ>L_ͱ>T6X#'<-.tD?h绿q˦/W؟WIߥ#{-AZ-<`HܸKԙAc! ;6ɢlensfun-0.3.4/docs/website/calibration-tutorial/dist-hugin-optimizer.png000066400000000000000000001756641445356770400265550ustar00rootroot00000000000000PNG  IHDR<]sBIT|dtEXtSoftwaregnome-screenshot> IDATxw|\ŵloEml6؀ pB @BBK y=PBL f ^d˶UWھآVb޹3g̽w3JdaĉvH HUR`VA0@  `0H]]]/ fee%^2v ƀˈpR߃x}+m۝[\|e\>h^);Z~>̜"gd@*J0^pl{M!eoIm|g}oϻcxltvvR__o!v'R]]0 %%%X, BӂHz#%IBU%N 4mF `oD A⻰дvqYĠpM4shZ`X^/x<hkk# fQQ555nt]0 ***?~<.v8ۍn4M4M# ,|>"`0.@ |Yò^px}xPT iA Px4:$#44Mn7555 LUQJJJzi/E$JK`YBuvhGrDʫQ(arh4$KLPsgt:& 03AC?!gBF3}sƢ#qdrDّj :p*wONm!6Cd(FV9Mhopr Wm?k%D[(LiI >o!tUn;Z {8a4H,p:3L00 JR~]ALXEeE ^݊Ȁn@\ӈtuiʮ][Q(>vb:::"^VUaQ>|LH N뵘v6JJJhhh@8:#ux}6w2qLڧH(HSC-t$]nsRPPGZfH$2i dUX:M#-whk.(΅!|CeXwΌD{/cQ6oa[nfXbF>6?i膞0L^W24,mHl!!нƚ6w*^x,NWWvvnEޜ1 &6TU% H?>FizSjӧpGqݿ^TrkWco JҠ%Ea@ EEbVݰ˄**I8&i:xH4א"h$:E"H,+zq8Khlډfg3݆a$f(dE8*/khncoKH,zr5etuw s GcȊBq"nuTivςgnp*l6$IFbLzC6:mv'4fh[ *nc8 aty\$@ ؛Jge˓ߏ޲{g{\]wf҆|Q?]_J/ ݻ&21vm^z)K.IO?ͥ^ iXt)vhƶmx뭷xزeK 'm/_ۙ6 Νi/.lz+8q:aOy'Yj?OxXt)v'Nxw{裏r9&M?NUUGy$;vHK~ƍ9#grsY?z\saٲe~9V\ $#8OR XG8NJISM3h#6=DL街9PqPHl)762s[vw;/%`PC7 ]O08GNNI#9exf֑zbIb>I6q[{`dkZ<~ 4=M3ZO7rg2hnno\Et?;b1^zx<.JKc=j{ɵ /w>vxm.<|YsBKJ4㌯-CpcI=E,祗O1kvw܉gʫ.69ʪ[9&8qqNq<7%U_+SLWӟD[{K:.c=o-my8篙TȔ)S"Z[v٬-Q w>go >d5v6-[夓eo쳯QX[>?+TVV&upg{}?p 7o筤0Y@dubiOv{ѮUUNEj)  C躎EUU6l+@QQ!AV^ÄIbyoŇsΛˋw?V & ē+4R*K%?,'?z,+q8]R,Lgگpr%!_YD~6:.j?8bqnDӓu:~-)#9o/QY+ׯ1eJ)ַs7W6ox*W_s)yk>p)TKhjH8.7%WPY馨 T\GKϷp0qAT[n=Nc~u׾GtqJ[v;w'1*Jm'`iifS6jⱭ"! قjAQ@℉^ntD4\.+}B:?;N[%k1~ttMb&Ζ)EVQ,EƈG [MlRkQQ~V۱VIP|NZ)*! ,wl@ASQVA,fackU&~+Nae8l޼0())IPXV @4~?_|k֬Эҵ2z 5I2H$k&bͻ FzpZ|*Lwap:C%Ĵ,ȊH,K,HLOMEȲ$ɨLWP%ጘ&H^:f=c_J~r2^)]$I6I{s cX-[#UktR#iG{qdl'5(xֽ{FwH2V2fɜQH9/}|3ST;2f*RՐ&Ԩr+JɧP/3i0:okK{ _@}h9<8##498]Y䟙|3-pyr/L= Eߟ^wYYYsnl_@8G[*~M[[`ƜCޣ>>YU` X-Ӝp ܘ~kz@]m袅ȣ0kzx-6l>8]ekV%5oTZ;Fۅn4I5)pO.$$Y 1;PƖM $d.O(%?Ll8"v±.Z6+J[1ͅVWҼ#_ĸJ6q>*д}e6D0"uk&h0 Պ2 X,F(J(xuQ39•X9nF|̞;}awblӉc44rblݺ>3Oi#떹0+LFl:>6%c7}o [yoX悶ދRWl{랙73;?Mt~K #IVVԩxV֭[GUUUUU / [~'Eii)_]֬zhz 0BnZVN[K\#O;w+N\'ϊo3TTQRjs~۱+cЍ՟(.rdE#5PUA\k#+W>Ihjjb{g`hgwӖ~{sR߰!},iDv+4K:Q]c(lrw%;;m̈́%d 4;EUhZ+YvlVp6[YN*?mESE:ugR~ٕbE#5ױbyh41_YBM$*Qd@ >e~Zx HC:8bA{ki85tF002?EɴPeY Y0,dtD"!D244Ht%F8{8C c/0#;{*i Y9$H9ېr"rpr߱ϵ|ߴ>e=EfZh9 g$p|\nߣЮ1(R9ՇC)opb>7 jh`y6ر\<|q8?+3KfINSj~u|V|>'N͛NIm)\{6g}w?5uxwz?M̢ 1QjINA{|86~n|b ^qک&[R!Dy%@vuGrr^yiUomAښY sЛ{p2_Ypw6doh$F8lETŁt?fwb1dY.Uljb455Q__O8F4.bJKKx:::hm_ @  \0+]B$-8qi:y_xb`r%awyShjnK~?W{ :fckZ{+;inuP|c r߽l2䟚>]X}t<{pF;;~/{1_$ |4_}[kZؽGye+K9# " g^Gǧ_ؑfOSTN6ּ"ϾH{>|v+=6ݫKpO+|ڝo9u+Ũl 0޽H$^Cv)*fl۶Z:jw^=Ҿ}дCQ8i4v3ao+mϐ/)X%c`ԩQmEL0=}gVl2>XFYFWƩ ]Yf k׮eܹV~?]]](++ OEE<# EUUE! 2@ H-N<bs]@ GuQ1yS?Lq sʩ݅᝿/;;Ca:P^3O(,ȡ/EQ%CTF! Q3ܺ yʧO[!O  ]G.u-#W H 'HN< Mf~{o5)0CyF&&`Һ~uf-KC4{!v>zcMiC&/d0Q*[Wn`+q[N%ۃ oY!q j4ݎ_DYDkM>̦"Yt."բv+gZIP904 _**մ#@qJc}-e;(,ritW@y|(Wn'| *#%\DTVf~ųpIX- S8E̚YC$eڭ6]Ns:BN~sU1 %>6+=ZЍf8(xxrRqX5yL0͛7#I26B]hjju#X#>X`E  ?i5h6ԲCI\ԛKѾG? Ue_o'##r^> &o$d 9a\H`jx[gn2׼ kK`gQh__۽S9L;d:Ο^q>ּkv+GiH28<'m G5~!7`kewWg{V<bA{6|b XТ>rD`X^쇧~QiFZF}7: zr#>5>츦paǙu1qBO4)(prYx|j^''c&۶0 2sV%׻fBX40%d1P Æmc;vEijEKzbXZ>&qdTO,՟!i4#/@UlJ'WISS@ k8G` Arfj*X,xjrg|lݺSQQg۶hؾW?S &#:@>xysZOa9R򅽡tW[` )..&QhPmNݎEM ˲ZNuH4¶Z:P^C4S]2;λ>w<0qle]tYQ]=b7Da>b%֐ iwaC1y7o[7o"a&v^zQիwRQQ8}Ptuup'㶢ɷZPlb뮻 ^;naƌٔho٪|G%_h3#c(eG6vۇ[f,ѼnƲk,t53;);V:^CO=cݖJ:1 `L}۪ZR=dr_K%tDTQ;O;:R36[b]VTYBV$b(P?-ͭXT=lŽ[x՛K\N}9dP{Un>}I}}[k@r/W=GOPeږ?<>s8~?W?g$7gӫoxrӸIEQA_ 6~GH؍$4R}:`>;~9`'NĐp-IJ5MdYfQYYMYy!~ZU|xF YrIULij|ťn2cyou3o]cp Jn|ʎcPSX%cю|e}r>ۿGl6k?\bz::I{8WFN _^'a{p=H躑ag͞O7 ?Aqq1D3x8D"tu9z8NVU5Ly(,'iаߟ~t@ @e$a9ihN={ Kr@}'j՗~I(nxX/8`0/sC @ 23]E"@E @ Ό=eM@ @+}f(r*1@ YfP1SF @ |!O@  or^'@ @ f(@ Aވ @ @7bB @ 䍘@ y33;vફB4K4m,U藔>su{۹@ yP D]]z+6GW\m6UT>E]4h &Lɺ;Qp|ϱTTTpgI FMu](5@ M h!/_E<|}Աϑʥg$\h83p8f6ogׄD?@ ] Pd:#A]]vwqGcHgyիWcgy&VuDuHy'G[Szx}\}|~Ck̙x<>C8t˩Gߨ:`Z^x_+\}v~q7lB+ծ>W_}P(Yg@ `aTee;Ob&_=$ /pg@#=_b1|>ev;^z)~;7tSgCaŊ,^]8䓇QXXȺu(--e,Z3uTdY&cݺu\}b1>^|EN=!@ `"\k՜xYV^5\n`ɒ%<y9Xx1_bӦM\s5l6l6_WxGk09-[ƶmۘ4iVBu8>yٸq#?MMM~]Eaaۻ2| '~<3¡@ 7`TCn> {ىi~=5M4M$I3(((HUG|>f͚˙4i˗/gX, ӧOgÆ 8Njjj9s&=hm۶o|cXf;w)}/}]\\L ~@ "vu >oHu vhkk˪[.0^p!>(~87oOϺH=6mZ:lkn|>׿p\o..)#[[[qb@ b=F Ü9sxBtuuaÆQoԩ+b1ofּ. a;c N'<&M_돚"1ӦM`ڴiLW_}h4J _U@ cC!O.7m[?<7x#xǢEe^PZZʕW^ 9ÓO>sXh۷ogaa!vwu'x"zh:-\W^yc=߾ɥ?Ez***ҳoϰG|e6mr PٳgsNj @  6FZ[[YvmN#(&w`ǎqz1@ pSQQA47e_~YѨ.ZcS|t@ yFeQv Vf$#`#xk@ 7"E0L0!''E @dTf(@ >6V @ B8@  oDȓ@ @ ț>źu@ KHCz@ /!} ߿'@ _BĢl@ @7¡@ y# @ @7¡@ y# @ @7¡@ y# @ @7¡ 4gyp8y[n>o5F"sd)yHϲt!˹+QeiRUUEPŸ=|aۑ$iO4{n{^{>C4_jHO Qu(.]Δ)Sp8bl߾뮻6~P-w'|r${J=dmo2.]ʪOcʔJy8۷{xҥ4z)b&W\qŰ~n6\.VuN@ͨ:@NjĉٶmۈhA]]K.P(Dggg<*3gb \ yg]w\sQȊi $H$L#)hVwG~8wL>hv;::}'|PS<|+GsW:,=e!sL)c]u&NHmm- 2,Q4M `"I,Gc1gf?= U{8\ F{5:jBa+2d:k"O5:&NÞuGyr)n<ψQr&LFC1i$jkkl24M/)?k~%t3bؾeͻ;-#&p' #ab* Ӯ/B>Q97Al""8tLr& @e Db.郣O.d@͘1Ϲt$t]ﱝ߸q#TTT2O~~dͯofɒ%{SQYYICCÞVC #^h$ɘiB{{/>~y X::̙3-=5{z#ϯ.fŋjs#3z;^p1Al6i1m8b1ۙ1cW4Ml6g\H9I=((p%7{8c,_mns"+2nbP(΄=̛.'2ٱT>Y!4 יFZig_T8d%)! (rb_@3$P:6t!h<^P T2E#0D $侙6JKK9#y?w?|np(NKW3cdw:`&#߮j(|ݯ\~UW%FcQ:\#c }RNt!֔ӿW"`1umDɗ>D[ok<3<)S`XҡFi`V֯_G ~ga&vػLG"=#`&@-6XZ㨣_9{2Q?z\^R__ލANP%+(eGq>% 4E}}}ٌ a1$_M2IzX,FWW]]]st"S!˘8T$%GLX,NAAAVoZb{ټeP]7QdEX,H9u|ߤ͛7gus'c_Oå?}RDdWs;xϟkQXXHEEEEE,#O>q&vv&@-lٺc=ks=75ZNEʙXl\prf?N|Zv1BxNΝ˧~ 8a 2Mu˾Upav&><9%b+w!8]^N#a\p̞ZaQ֮zG})ᡧnfܹY&zXQkm9ʏ~maILuu@0u$.Sn&[HT,AU,TLaQ9.kO>~luO>[Ov*=z$b{ue5Bo\Faa,ST>_;~aOC3ru8@::I=q%ӑHmKHK8v;k:elK@ L\3hk sBsI'Q\\̷u6w|aZaD tȻ<$ #7Si()GL>`&[laʔ) >r$TN ʓO>ɹ瞛)"e .[ }$I?-eM+ IDATs{~zVձ%%*'-ȫA"IQSq8>ێek"v}8oQOHds*{6baw0t2vm1}Bʹ䚫NMoCSqQݳ#} Dc c+u'0fM̚5SO[63e$=7+9‘alBt=Hi"󱱘f?Mud,'el=f3=$ڊab1h5k0k,dܾ=oϨ\xr}l6,ˈ=9x G]nvZx E٣Y\9_uP\Pys%N:4[(s6#1N]OxCg G‹g0kReFc"\C]T\S08;6.g::}/,QQZU!p&X2!O;ו\~?F͚89Of31gg!ZlTSUVaXM>PXw,+ !('婤BJe9Ǐa߾e`Z 4|X1 fڵkǼm~z6l4G&Ѱ[u/˪U7{~'#lذFCll,HU*^ -A:Y,26O`x~r|#;yc#EXDM 58W"e_/6>>8>Xņcѹwy uD RD_׾-kZvXvʵhܸF%|~JE&M|=ٳƳ ֑L}E(Wi\ѡCBC#Q}~G2}p<1j*AQJe"Z, Ǐw}P5ш`"ʾ7t#Z!Xk|ZVL9Bq쇼'BQʼB8!!!6BQy"))@q²ZU*oRXsIKԩS-[6a0\(Z?-G(KÏl@nN999X% yԈ c0aZ0]Jb+VxJG}Dߧ`h41t:u<%+KAAAthn&ф( כt@`˾^oyJt0t~z4lRP?p^.6YrRxILL$##éնx4 nS\|4>/^$3m67E<3$$:u\BTMe^ع'u*^WaYo&^j?n{ {;N|0}'$cFf(C C#j*'ÐG0,h̹Ba8xR:U&P8|-U lEWbl[}vөsR* nF}l%qJ|CњBQeK BTSeZ5k5To]??Zӝ/q/n)-[dIW/K?pz}+f*QwOYq B!gRB!BL*B!Bؑ#G*"!B!DTBѬYC!\ZZw0;Qa!D T(B{nFQaT) .gϞB@ի:u"bRȨ0UuLj۾[lJPToIWFQFCTs*N{XM6U|ivUmWx/C,:6mCvylw,UF@@999IivUmWx&-$epyw]B!|yS:YUm_(R WfQ9w(B!>':QuLj۾+'R#$Dő !(Wr[g(|PkV4 ZBEr>_,*'yB!B3ycU4 Z9s7xO???rWR#$DqBTD{9L&SQԯI\gϞeԨQ Z,}-v9p:CeL6$?y$h4*n&>3ZOtγ+|*Q QJPƍYz5ÇSN%(::";wqqq̚5 t-/eE|UEbb"6lɓL&iݺ5<^PUOUeoylC:z=jFѿjժUoUe>駟sΘf֯_믿N\\k.7s/z+cƌ)6N>ͪUHLLD<@۶mݖo(/%dضmc۶m~\Qv[Z5.i"ʠ?~s3l0HKKc֭;w͛SY,4MEQh姴}Yo.lCor2}tZ-999X ꫯ(Q-Zģ>ʝw Fo߾$%%_r)^yF͗_~Iff&:u駟d21qD|I BƍyWXt)+?+VBz;v,.]bٲe\tz1n8u.]???qE%n@~0`|ٳJǎyꩧryK\²e<7GvʨDŽk0={6|86l --x~B7?_Vz`ѢE>}Z^&Rvaٲe=zFCׯFgȐ!lذlڵkK|ЛYdl9tM΃ 䮻bƌJÇ~ȟRjj*.\sq̛7eXBB3g$//)Sl2 ƤIxWON:U`vbz>#hڴ)&MR͟?)SS>t3fPn͙3_T*ӧOgɒ%J`߾}L6Lxgdd0uT}Q:vŋIKKgEc!|f͚ERRd2zŕ+Wͥk׮J, 4 775..c7 ZF#<z<8\֬Y|NeD_hӦ uԡql۶W_}ų>K&M%-- V8Z+WN /{{ァl635kɧ~ʒ%K5j섄^z%Xt)K,ᥗ^Lwii۷ǣXt)sΥQF ʰK2aB駟´i0 ʉֱ> ʤIPT|G|7߿mPTz<… o߾FͫXCxj"ח=- $..қz'ԩSk׮V?xוWo߾e/Ul9;wJ\;w槟~˰iӦy/^d̙޽ 7n @֭oؿ?:t $$!C}v֯_O:uٳ'5*t3osv!~'\jjb2D:)ӕ')jXjuiq4焇+_v Ƈ~BmQ $_qQQyUTZ8u풔-r!<6bmv/5j(pger<% 3qDf|YvqSeFԩS={ЫW/q{Yf.ҨS`o1q+fYfѲeK^e#S2ЩS'6oL nOe2Te8箒lך5kү_?^9oXd ǏiyJoaCO-!*+*6={;C Zܹ:вeKZllf˖-|g[Est`?} 4-Zj9u%8ūY&`?@:8._|E'oFTT)]&%q;WzztϗWwH IDATrw_zz# -K\0yIX,߿_ya< ֯_mБ˗/t:?0ڵk_|!C ڵk?-ZxҪl6/_Nf8w{!&&eOeě2 8*8Ari߼]wUpėTjU^xRJ;v<3 '$11d^ɓ'ZhZt:jJU86cgLKKS2XV#==~AY9sLw?oynXQi aÆ|frrrغu-Z~zPTdeeq"4T*y6o̎;0T*]ƍ9~xaEEőWҸCCCiԨ}&l)]-?SzUԶwP7n/[lnsY?2]vexR<%Y/,m۶<3㏌;^x'N+c7okƿ/իY&ݻwgʔ)3-[x~oرG2fFŨQXn#GDꫯ2j(}]|ZOa؛i6oLFF bȐ!YK.yU +7pܹFFF6mRu{Q7_ ==[r5T*ݻwS~}Wwッiٲ%k֬!33JEjj=Oqr/>%DYb׮]hт oҤ 4`Νtڕ7r%V+jbȐ!"8gMWF :wٳիwqzbٲeL&j׮Mǎ9}W̊QdZ_|[oEDD;v$11Q9 8u1m4L&aaatԉ[nmP\5bԨQ|wfhѢhyRXZ&K2; bDDDpXVX*xj4hWf˖-DEEѱcGagOJr|Dӑ?|ͅ^S8ﯞڵk9s&&5jh*t QQT1116^Orr2,^Q; vۗ%$$z'PY,^En8_)eڶm "77:s &M?~h, e˖)/p( cMuiwt54oޜH0 <+شi[਄B!Duv+ZEQ^^K,!33VK˖-y4N8ʩKYtly3U=~!پ)W>`(::Ϣqy B!gRB!BL*B!BIB!B3P!B!|vi 6;ԧ(gUIB!~|Pdffa|#G0l0:uTj+tWfJh%B!׭[իWU*Z~+Wrm ߱c/`ܹgӦM?Dxx8?0111Yf ~-7+h׮K?ǎ#11u2l0ի7ŋL2O<ə3gSÇO :tAh4.'?z]ڵk9tӺuky]ysYN8All,>e !BOe:tN:)w}7>}vɼy8qu֥k׮Ԯ]+W믿o%22 &xL?@TT$&&2o<, WW$f͚ѽ{waDFF>}:;vYfFoΝ;=XOݩUaaaL&f̘/Bpp0]t!,,m۶1{ll6˲6n@ΝYf !B̧LBCC];?++砾[bbbx' yd֭˸q/q܎iuF~?2e W\ɓ4i҄yf%Voyy 0͛7rJ #G$::dΝ;ٳgҥ]ǖ-[g !!˗/Rhذ!Z ș3g8y$rv1rHB!"?*dddp5AAAnZE.?55CҎ.@ɀbʄqvʰWݺu(0L sq>4 GVZf86[/--}^!Bg>U(Zhݻ{tOBQF`X0 _DFFre;rbT*:uoիJ%OZlt'޽rwÆ ]q{%esJfJT#a,'))Iz5rHHj5KE+--@KB!%d޽9|0ɼ;4iDy@~s9lBZZ?sٳ'/fϞ=\zzꑚJFٳ2ݭJ7o+V@Vӭ[7}?|2SLYfJ*+q;lݺ\N< @DD7VGDDORR4{lrssU'OTb߿?m۶VZ\|w}VZpΞ=|P B!BʧyW֭_#GV5j;wV4hk&55ӧOzpw0j(7nٶm/^T;kٲ%O>$j˗.nʯٳgi֬ƍs ĽKJJ DGG3zh{ڵk–-[g*RFF/_f@1aNj5;v~l6ӣGiB!Jc$''̙3V\|͘AQ 3B!JjEvfa6jK~ڑ╃j-t !*}8>;^%T+yc22!PKСC̛7nݺG >}:)))(ĉiݺ5saҥL<N>]U UpU]T~III|GG}\țL&F=.Bw∍eѢE|r-kźy%f4 bUluBr5_rF'99uOp92d6l ;;v)M3f_O>tM1k,O9r$֭#55( ƕ+WXf )))DEE1b֭s֬YhZN˗F#z$//+WfM6 4NWfo0bJƍػw/K.%%%3РArssOؽ{7V;Oݮgۗ^z)n L,_\b 4 k׮eڵdffL޽ѣ4ٓ ϟρjtڕ#Fje|\|3vX._ҥKINN~7o@3f +W$33N:1j(% RVj5Z駟&<<\geʕtR6mT<ōX,m) 6F=uVyW2Vض޵k}g`\9sPvmN8IXp!c_|;еkWt:ׯgXVs…׏;g}QΟ?y=b6':,[bu.[ NK/ą  +~XK/\P^^^^omB2oHOOҥKo߾nÇ ;|0'NdҤI$%%zj0a>tNj/Ȍ3[.sa޽L03gR^=,Yvѣ m۶,^lLԩSIOOo)I(ٳgs.]LάYQa޽L6ŋVq{^_a]W\q|;omݢE .]˗l$$$PNߏfc4oZ]逸"&&Պbh4ҪU+\.s(Mtܹ.]~a#>>ٳgsY-[F``dzv};v`ʔ)ױO<ŋs72|N>%Kd^}Ujܹ|G~U;wxb7o2α-Xx9hٲ%.]Rz ߿:up8@h4l6TUQuy"++ BCCvֻwoz=J}!00PF߾}];we\t 0bׯOVV ۗѣ{)Vl|#77۷/* D׮]9}4999\t]vѯ_?e9l۶?GNs;yfj5gΜ!55pxŋ}`Zt<l޼e~V4vBc~]?+4k֌Prrr.?#ې'v Fͻ\ԶVT4hЀ{JRR<#''5klʯ|~F㸼߿iѢrq2!p̻<Yڵk Qwdd$Z_hhakʌVUt';;j l6\u&T(*tB. Cl !T(*9 !DqS!*PTrbBf!B! Vi޼9˗/P\5o޼E.b EtөSE!ʕZ.B!T(*JBWtBQeHnUNBK*B!i٭JIQuIB!D -BQ9IB!gRB!BL*B!BIB!B3P!B!|& !B!ϤB!B!T(B!> B!gRB!BL*B!BIB!B3P!B!|& !B!ϤB!B!T(B!> B!gRB!BL*B!BIB!B3P!B!|& !B!ϤB!B!T(tyyfsӞ;wѣGc2|㮝.*bvTƴNcyeΛ7g}Tt.i/,B(1,/LaeB!_V(6nѣٹsgyTDGGVP.ӧӏ5 &ʺe];Bʩ*6m۶Q~}~Zmn(TָBQn>Lvv6cǎeʔ)\puqqqq<Ӭ^4>|8c֭l۶^{MY^JJ o'O&""e]?3W\aĉL99$e؎;[ < ..'rI֮] @&Mr iii9rZjqQ=-R2뼞F~ .ŋ&>>QFT@ˈF)V:۷_|3fPn]̙޽{0a3gΤ^z.q9r?ӽ{w2pBz==v*4=O|rٱc'2%+oQZ8}t֭u8s#=ڶmUZKZ&BK"==CѩS':vȮ] <Vk׮$&&@ؾ};V;wz+H6m_{w;wҥKeVZq 7BϞ=9rrzM@@Voݻ ,'++K@@у={jQ\t\_tޢ,##G %66;vmѣG%99X%9B&M˼ʆ|VZԨQXq(n)N:ӧJLiiieseײ}v?{we50.;` hC<&mbi)ZX}-3˲qX"Khc) FR";܇e{aGv/}uo}oa}YǷj3cu[{cbؼy3|VW̱eYs۳cǐׯ?Gzz:z1ADD!<9r;?br⿽jj!ˑ>SLAAAZ-nv1b֭[zhhhϾ7Tٳׯ_ th4t2-eaaaiWNUUAEZMh45kߏ۷G|xWZM?x`”hɓM \3gԩS2dx}f̘( ?+VhKׯDdd$z @FFxV$$$Xf .]j~ƶkɶڇX]~~~8p [nF˷e]cTZZj*9Rƈ5zG}oooL<٢:V[|4h.^#G`ĈVc-{`Yo,'VO>o7&}t-O *++K/W_??pE}ٳn_2 ÇGNNZ}yџPQQ,aYYYPըAvv6-xl߾n~iQVV|R4{߹VK;$5l0q}Xݻh[5& زexDҗ)cĚʖy!//7o f޻vBee%SOa˖-?*#L[1=s?eeev/C6lL:tG ""r~СCǭjzpp0cUDl۶ }EDDlt z#55֭FAdd$FBax뭷PWWxL4`yӧOǶmC 88GF\\t:233q5hZDFFb̙&gj֌3i&,X^^^HLLlUB@~PTT$))..999fe]SO[wށFi'KI#ִݐ̛7+Wė_~{lg̘_sE|y۷/"J%{k֬+RiQ95fZW,,55vG\( ̝;W6~xw}6WbٲeXt)RbcxGķ8AD<^ŋGFjjEYh4xKhWA{n̝;aaaZvPéSԄwvUȀ(|VOw@m\&x饗 裏K"""""W2/^U "h^ADDdl"""""r?L(H2&DDDDD$K&W^Ŝ9slv˗/ch4;:Xΰ/pjΛ3gonO>?]e߷l/gl;Go1o<̙3kgWcq,Q?'֭MfUQQQXbj+΀7n@ff&^zV?ZIDDDW(F'O"))ɪ 9&pwXoAڎ+r}syBqm!00ǎ_WqCЫW/w}*xyy!&&ӦMCppx4==vByy9͛ŋgQM]vwqyg`eA#-- >>>{E}}=1n8}o233k.,\tV\%K={| ***ӧGjl۶ yyyhjjBhh(|Ibmh4&ۨ-s;UUUذa~wcԨQEEEb[\Lꓴ4G^|E|XL(Z-=|{]vEMM ֮]7bb9gϞ/ B?6,Yܹs@cc#VZ;vࡇjW 6@߆L&ç~SNEyy9n݊^xhhh@yyAYY***|DDDFBAA~^^,Xooo|ꫯK/+{ū7nܰ)m/hb}GuPTXx1j5>c`ORƆ̵>7o-Zd.S['z[||z?nGT<kGs֮] ___,Zj~!233jt߬RՒ㎵z QqC#F@qq1.^8uZ- 4hv  Ą ߪT*_r,]_T"88ǏGnnnrjkk|* q B_T*>T*DEE (..z#&&:'OJBQpu|@.]*ڶӷ6Rߖ˙*u1yd(J{5V"elXT[Y'R˷&Nlc-:Rc,L=%(((h5NǏG7C,)jn])28䗲CBBB޽q! 6L×={::N,ԗk CMMMr Bi5 A@pp0f͚cѣ&OW\\ ޽{nöm۠Vq…vVmw?qUU_ 1Vֶ6dVr]Wh5_maذOom1K֑=cdy,14N ̍]KGʾ[WJ!""<I( )) }ƌ_U}f̘( ?+VhGKׯDdd$? @FFx$$$Xf .]jpX]~~~8p [nf-}JKKm>c'-i#)5WnGU?ZJd16̵>1e-kǘ#iT;Xbh;cq֖2ȱ;?֬Y>}{ !B@EE,.VQSSl$&&[&((ؾ};C- ~R //Mطo_444 77W%66{|KK@@eaII/R\Ir;0`v؁&`߾}&˴zT9֥omes:-jG{Kjfggcذa8kqGJmCDDXB!ɐo'N#55֭FAdd$FBʵtX[C||<&Mdӧc۶mxסhѣG#..:vZ-"##1sLuS(ׯķ!''ퟱ:nݺ4ѷ&#M-5UnGuƌX~=^|E-Og}:RG ~5'={DrrT=ڪCc\ڱK.v=̘16m‚ D0Cl=ΚWKX[ssU,[ K.B?cDDd,11QP*(..Fyy9/_Gy]7"rU,^=zt7Դf@"""r `ݘ;w. Z+D.**JS~iԆ9T""""" IƄ$cBADDDDD1 """""ɘPdL(H2&DDDDD$ """"" IƄ$cBADDDDD)!Ahj-Z^.ǧkEDDDDDp F}8R|2fϞߖȶz*̙~1ȶlַ:jNaW('x¢7l\nvܹd2 TDFFT_Ore,Z~! DEEaŊ-۷5mK79]_X'""wP={| tR,ZXd JKK;zng㛈lOMغu+>$&&}݇bܹ3f$>oPQQHL>=zhU?^7… jyCg)VZ\C]]1n8}FlٲyyyHKK3Zƶmې&'DϞ=QSS7r2e r6 Ųe<ի-Ztڵ P__ot;ca׮]w܁G}Tl;K?a$'' C?nN~pp0oߎ7|]va…ǥKrJ,Yr05ߚ1vv֬Yعs''xeeeرcJKKttpA|wbbb @UU֯_/"<<F͛86W5siii 1sUUUaÆ v01oOś~~h4FСCeee… Q[[xh-򬊇YȪ64?Qs+UUU~:vsε `޽;v%&&/_9r Kc֭>}:V\ Ɗ7l؀:xwQUUhyׯǵkꫯbŊxgXv-`ѢEoLmR0o<ҥKb $''={/2}rcʹs琑z EEEoy֖m kjm?&&eee#""n޺׿񋆹aرds)̟?˖-C㧟~¼y|rѣUy!!!xb hlll5ڵ%K0g8q{ƕe \xxјScc|}|q7w19궰&ڲe]Smhl+s[ܼmP7noooohZ '%%>)SPPPVo]R1k,߿۷oG=0yd 0UUU-jF dWUUhE',, 555 Zjyebl])e[?ں;cPPP_m6j\pӦM|Ko},9Cr]m^-wBѪ<ٳׯ_ th4tbl[kcjɒv ǜ!34ƍ%'Xۧe|[#FuC HHHh]Kʲ4 e]cmh,9FR/""W EHHnp|?-oഔ477#;;k֬ҥK?jOS˔;/R|UEE7f1=3?Bj]bڵ ݺu|kNGg}3f !! ϟNJ+ nՈ?+s˚9C}liW&h+kɒB3gp) 2ޒ˲$콮1ǒcTGԋ-Ob׮]8qZ-{n9s)))MJJ¾}pYnT*tķ~+/++C~~xQTf!>>۷oG}}=g @BBl"~+))Aee%;v 555ưa,_soƲu;Z-eS}!X{ ELL _@+%[;v:Jv dee󃃃ѿܹطo8W\[TcKmxvư!. //#F\`-Sc1#ED \ ~xg ^^^ׯϟ/ "11۶mC߾}MP(-[`ѣF . Fff&]VH̜9S\ضm^uh4cш3ӧc֭xwhķ$6n܈  4iEd,Yhڲ׷z uuuoeڟX}am]M= CQQV8䴻fnlX;v:Rxx8RSSn:h4DFFbȑ(,,IOO_|#<<#GŋDg\YΆbgϞ\y3f/ox: ScKnFѫW/eYmٲ)1z]z˖-ҥK]j̑%&& J(//#o}pή`#[s1 """""ɘPdL(H2&DDDDD$ """"" IƄ$cBADDDDD1 """""ɘPdL(H2&DDDDD$ """"" IƄ$cBADDDDD1 """""ɘPdL(H2&DDDDD$ """"" IƄ$cBADDDDD1 """""]w1{lO<Çwrmu'"""%)p/555صkΜ9*(J {/bbb,*cرnݺٽ~hoSetd݉Ƚyj{Dxx8F2;wx'p]w] XkrQ[B?~}~ŋѭ[7L>OƁV1dA.~wl޼hll/z쉔j??8qT*x[θ߸q8{,jjjo3Z;wxW _ݻ7owRj/]B?+Gq\p]vœO>V aի-n?sez=z`ر:th>7U""""rov({޽ CPP^%KѣCSS>cǎ@TbHNNFnPXXUVCĮ]ZmS`ٲe8t0rHXjA0Z߳g.1\p:#F <<]g߾}G@@i&qv$رc[M̕Çn:\rHHH+Wn:>|ODDDD ERROqj5f͚tzK.'$$o 3MMMG3?8fΜjyyy())L&C>}P( xX!555V[~;?< em}F'xǏ\rEvDo5͒3WF[w5 3gSO=QFgiȽݻT*UiJ6mڄ~`Y7n"##[W ***7 6Z&-OJ}BjMߒ%g-}Z޶DDDDP蟍04ЭGƍCjj*/Z>88())\~Uaaa///; UTT򗿈a;VLz8fbԧOV(jd2A~h+44(**nys'""""oyҥ JJJpi4552Æ Cvv6rrrP[[DDDAO\t (uٳ())o8!??2 ߍk-1$44سgz2ں{qF5McI\2v? -^oЁ5#\QQQXb <>K㘱KxnP8pC\.xPDGGѣX3"r[ǎ/Vkű~{NxPxwZM+--s= o`Μ9;w.>STWW믋fffb(++\t s5x?3bcc6=g_u8|0^{5̙3_|xB?ƍXl`3g{ZƍK/aΜ9x뭷PTT$n̙3x7wa.ٮmCquqxjQSSO??1|:0mo8uxBR\|Yv"44{+VoFlܸ2~~~>"""PPP(((@ BMM ufU}GrEEE;wnޖAnΝ; 1oZüyK.Ŋ+֯_k׮W_Ŋ+_\7// ,ѽ{w|W`8`ix ٳg/߇\.ڵk-BFF~7dffZU8n=KhPT* 2t:;v F4hv  Ą /444Ǐ#&&2 z˗CP&D"%%JAAA?~|G}Ǝ{˗/ٳ@<#??Dpp0BBB@RڵkG?DTTȣTVV@```e _(--Ǝԏ"cʒc).c9-OIIIطoΞ=#GW"P(PQQV oo޽{[\|K]"Zdgg#1123-$$$`˖-ՊV_J,e8`~<&88111رcX6lU嘊cCD射"11eee۷/"""HMMźu0gYuB~APGn 3f ;\fqyX[?{4iRe%K`ܹӧOG׮];`Μ9O5f?~qTx 3f@ax7зo_s=oKxDATX|9yVPA :Ԯe_{;vEꫯЭ[V._E?t [,DDG޽sEXX"##VP6:u MMMj:$D琄⥗^L&ã>g+>DDDDD!ߦ/^XCnzήQ^?"""WⰇ0 """""ɘPd}"933ӑ#"إ=`y{Ľ_qdrȹ8q®1+Pz뭎$Y_,DΏqOy\6t$u2=ay&DDqO9PMQ'cy=p+CmDqO9\.-;Ո:0~A5]psP(|||NLjzR s:_=RFu rf{=y=< //wYyɀ{ǐ)oO(vw=2 3ST*Vh4\.o?I~ s:_O_GCu rf{=y=< c |K? ˷Q[y ]-QJoe@XX|||p5sk׮[n ?_`Ie[zѣVa309 b܋[qd\+ WKtyЫW/466СC{7h oTmWXXo9#=<qOi 9 Y7/AɕDFزe x ( 9Ç7ѣfL8Qh"\. m_YY+W`ƌ|cƌ[oK.x߳g&L???{B3ɕ1gܓ+rg(^baG}e#jYfٽ}q۽l{pYqo׏Z{~M6!-- gϞEtt4|}}ݝS$ KF믿[n\.7˗qI<34ZO?Ǐ7&LiӦ-Ο:u*Νcl=<޽ݻ7 =养 3gδh,$''CO~_9-[3ZmߵkW﷦)<0y @,xy%6mڄo]I6'L(t{=z0 E||8Mb2e T*0qD۷`斷u^||<?.Y0B¢  5Q]](qZII ѻwoqZ^p%e[z%)1<1}x j*+TxO(jkk} R)NEccW[z~~~k؈lĸ'<{Dhx4p5TaμEL*<'zqJp)FB&+׫:Dq !/ uuxL*ܜ'aaa իWimu ҥK6XmwG0Y MS#P(Q__'g2pcnPh4477  IDATh4d:t(N>-N3f n݊#++ s2-o|Æ m0KU%h@:]t:5t͍xĤҥKPt.yk ԩS+.S]vĉ#<<3gܹsqƉ/\4eny[痕cǎq0F]뿣}i&-o͛7cԩ.#7D¸'<{\ߑ*6[da߾H2UUU/T*v Aď+>3B79MBa/bv{So?ή1Mcܓ;bܛq܄?x㛯sƾ&RR\.L&c2"5kVgWqOyȡ3g`##NCSS# RRP(d 3DDDD ""5553g0鉀Váj^^^ cBADDDD6d(((\.G`` Q[[QC,4ѣk_hX7Äl"p뭷AAA  AP]]>#Ѐ[n|]aBADDDDd2xyy~~~TXXOQ[[?K.… .V_|R|稯k]bܸq0v~a8q6 r{=y=܏/2gp@}}8MR^cc#|}} ңmW__???$ =<qOi vUoAnqKTzJoۿ?VZW_}m!((W^EDD׷%K.!::`斷uޕ+WЧOsN2{<{=I(;^ ŵ\Ԕ]EĭqU @i;vZddd ..2 Cӧircƌ֭[Ѐrdee{1Xm?cذa5 `30~&@ޱ%5_|-<|hhh@FFďN3ĉ߷tc̙;w.[B… HKKFhy[痕cǎ\qOqϸ'4Cq?g$]B[8s#NXnYY۷oj۽zw܁l)J%y6m߼y3N!¸gܓa38MBچ_ L_(?s [*4=#ƽi{rENPή90ܓћ$NƸ'<{"Є"%%ő#"''<{"[H2&DDDDD$ßH :򼼼LfS9W1 ,2 21oǙ}k?Õޭ&TUUܹs]7p@@TT~'c~1Ø7~Uޭ Ns!--6mڄr'c>q7cc1&N6mڄÇwv5Ǚc?UPvb{v/[ۓa_؞nu%W gQOs{); ǘt11-q&޹r ÃaPGs.r3q'8Ɯ ̹r0V7>1\g U6'8Ɯ ̹zCٮuNN//i:O ǘ450q& ޹Cܻn]ozbRss\r>qw1U1]ǘ[UƝ3Wiܡ?PRh\~0 c̹?Hq9ܥ?'NSSt:0 }C}BcL:<*31Bff&233QSS`ҤI]t:t(~i(v[_|?Z]b֬Yx&L?:MMM.=2v/B={sN  O?oX`ylٲظq#rw>quرcjkk;5g̘qVGYХKƼb;7ƽaBa_o zWZNիWC&×_~z]Y]r%jjjdڵk… `_ޒEh4opnZ-gꫯ"22xzj+b?/^ BaƝĕ9Sܯ[>>>]XG'|˜@{Ǹw>n M( xyyuuuPT cAR&M¡CZ Kꩧ A0jhЀz=CW银K\[n  C=ӧOjiӦARe0k1杫?޹޽G7UMK[Z.Rp-.lDE@AsF.[sd˳zTPFPEDHˠ)k/9-MdB_ke&{?!읔>p#8# }lKZkiinwWܬ%%%)..=i*몫dҹs_,Z6lPUUL&TYY={JN>mhuL.u4vdp8Ңݻ+11Qڼys~ϑIٳg}>[/q_^^ޥXǟc>zpG<㸏(át׿P?M4)ѹ8'Ο 맻K/ oQEEEdy8# <>pfsZ,B+W̙3UYYyz۷Owu#ABBuujG036̱#,88#KW8Nvܩ *==]}2 B9Y<,{0Ljnnv b$0Yc G`30qYEeA!?%ӕFdPcE@80" yĦh!цLj̱BYd!g( ؑqo'Bu#a|XqYQP l,p`EMh3 dTFwq+†Lj̱BYd!DA!sky1y\!yWWè*(4rH+]ȑ#I+h `1DA2r."gyFU*(뮻bwˋSbbbI+h `1WG#`2d28`GyGW>0LX,hLj̱BYd!p((FA0 QP0a `((FA0 QP0a `((FA0 QP0a 3Yi{GGjK||zꥫJ?Opz|b+VUSS/B;wTeeΝPMMM2vآ~\!yx9mݺUTuuz/\ӧOWn$SLw}N}ܹs)I:|l٢jiiQJJ _Wfߵ0`l٢~6mڤӧOAIII4hNaÆ~#=zTGє)Sӟ5kK}Guw+>>k^x6<_ cP8=SOԣG3F)))ڳgVZ%f_{V=TZZ^{ڵkuQ >\cǎUffOMM{=zﯮbѕW^ǫ:rVZ6mرCt׫w~k.+99YVX{*;;[Oo>o„ 5a}fi1~A?CQPP2L&]z22d?b}7w%nwܡ?P6mݏ9Ie]C_~>R̘1{nnT\\ZeffScc溗+4o޼6qtwhϗn׼y󔙙R;vLG՘1c|o]wl <_ c􂢼\t:{ $%%%Iݏ}ڲe6m$I2Lҽޫݻwg(㕖/\iii_{56gee[Ɵ]hZgX$yo/@zA.I?Tcm~܀'W^yl6jkkUZZ_|Qڷo&Na?.|B{$M8QӧOWmmxIjwI)}twd o vTPl߾]{q~kQ߾}UVV5j$DGߕ̒%K4l0^ھoT^TVV/R:rHX&77KKKSEE{=8qB&I~_mxʱ@C*..vߪEiܸq޽{矫I&M+IG'NO>_Wkʔ)k$i4h*++uaM>={yׯN>?`dʱ@0l6bQii***rJ͜9ӧkө;wj…JOOWFFv{6@젠`((FA0 QP0a `((v ^ ,PSSSXa޽;dˣcǎ= Gbqιrv8ߏ }2|wh"-X@?|Vgz<I|,Eff~iok?u~k۶mabũvB=s|=.ܹsںuMO?,O瀮#E/(飏>5\xIKKӐ!Cw zg)ܘs)`dJ>ѭ̩={VNSk=> !?-?Y|?}_yy-[G}T555ӳ>544(??_r:w߭Dh/I֭[}v=ݻ=g}V+Vh7ANkΜ9>-==]/R&LPE*_^~zcǺ;vX?ڵKuuu޽&N1c詧$-^Xt-h񪮮֫"fiƌw={lm߾]eee9ѺK.M|iz-UVV*##CfDiIҞ={Jqqq1b.9~m߾]+4sL%$$Hx.̯B-3px}舷|:= }yeo@JKKܹs5h I1Ξ=\3f5\#IzWTYYOqqI܏ezwݿ8qB+WrVWn:YV-_\v]?***oSVVUQQ!ժE)//O+VhnڵJJJR^^v{9mݺUӧOw/sA=2*))iαc×6 tR%$$hÆ ڸq,Yn<9IJMMկ~+GZv^}U͟?߽L̹CiٲejhhЪUon8\߅륗^oto)z jݺuу>TٯhS)))3g֬YX҃>豘k{NNNzyi:ѐW0l6;!CH>3eeey,&"5^g![ng}&|Uo>3ݲ555*((Э*ժ$M4I$YVeffH*--Ք)STXX dIDAT(I*,,Ԉ#<݆}KJJR}}N$iРAZreLO_={VִidXɓ'{\l6+..NNR}}VvQQQL4ԩSeZ>isڴiZ2;v?=OsNF>}Hz쩛n=]eM:UE)))2e~̗q_:{舷|:=}y嚧wyRSS%I}U^D˜ք  /hӦM;wnn|ђWXV]}O%I---ڷodz;Rdf'dYX/nMGQ}}rss-WUU%ө6;9NL&eggHݻw~]vez7ew鮻؇ݻKeX[CCV4|S]]-Imlsk)))7o>Cm޼YԴi4|pNOOwigϞܬvgƼ͹{:uꔜNZZZp8~/Z\Gc8xZ}=gt[>[|B$wI4ͩqiǎK'qOY:)`7ny͘1CEEEjnn_qHޗנ{"++Kꫯ_ꫯQrr$iٲewq~ hsq/x{N.ђO(pܷWO> L)өW^yEFRqq>3]^|y)+_oLC Q޽M=ztx}= ˷$''+''G7oV]]/k׮ 1LÇ[aarrrXÇVcc{\\w,z; m1bDwءkkzǵ`븣eN>|X͛'ŢaÆiZzv{;?P.yΪ-yfSyy}z].RdٜEʕ+5sLUVV^쾅Ć 4`kƍ߿?_Øs| +s@8N-[LSNuup$#{9NܹS .Tzz222dc@oӟ'=1G[AAȒ%Kd2b"8|\D!/(nM LNd=>v}"E]r跷 r=!c.]df/v}"FA"Ec.ma)(Ng86Dc.]d8C" 8c.m)]f_XX~)111H=Bp.]d.ZAcڸ馛^{M v0Dz|ADz|);ӺI5T\"}l#7&HG7oOYW_}%٬cv81KJJt!͘1vyyuQY,7N? o嫪?IǎS]]z)ǻ  '{sFB-mnjllTeddgΜQMM5s::ym}Љ':pܢ9`gў}c]/>Q9jh4}fhdOƍ칅>{ hhh$frjllTKKL&S$IŽ|zzӵsN|r8ڽ{ }p?-B6]ۋ:Tx= 5VI?Bδdo #=ه #"<> DHGmXVIRss{9á6rv޽isjzǔQF} ?gyAn?]}+dl}%Z3I'uu8rL6$dd6 C-,j8nќ} h$II"}J}u?L2))A$}4fhdOƍ칅>{)Lַ`ẙfl6}r8'|ѣG{\>>>^F7|ӧOp(..N~?kɆ[knnVKKKǏ9/-v>;MRՓ~=t~Ud̒Lј}m=7(IO|=23fFunAWO~ZwVSSYfiȐ!>oĉzgFf٧>-^< Izg$IgΜ5gΜUv>'KI Ҡdwiʎ)c%3Ip!qOldۢHJJsTvv>Sx㍒Qɓ'Oէ{cn&u֭6"YW>x4g_\g ,4G;Рp_\q.d8=Noma)(]f͚~L3gμ]={vn)TS 7;ncE;Cӟ4EFSܗvzp㸏]d>uK5}"EcǶz.]d>v}l Bc.]d>QP >v}"Ec[X Ǐc3@d>v}"E-,Ennn86:pȾ#Ec.KFA0 QP0a `((FA0 QP0a `((FA0 QP0a `((FA0 QP0a `((FA0 QP0a `((FA0s86f͚plc.]d>:uj7Ec.]d.y`((eD )áfWbbb{t]1p裏>Ҟ={|}GX,Añc4|577ׂ m"vw}W-҂ #(} @/q )3sO˯_^!Off~iI_gUBBBȶi۝ WΝ;[jɒ%KB`46'v31Kٳr:8p#ug(Р|t*''Gw}UUUZ~[[cǎuzw'SO=%IZx$[nm>Ю]TWWݻkĉ4i$n7TAAs窹Yyyy={o߮ -ZH˗/׳>__}v+̙3s$ipsXK/ގbO}Z={ o~ب5jT[oJeddh֬YJ֭Sqq{.nڴIV2|& @ׯWKK{1L&ז-[twH֭['ժ˗no׆jբE+VxBo>eee^׭[=JMMUYYt9Il6]ҲeРUVmS:k񸝵k*))IyyyzuVM>ݽ^zL.6cǎ_|_ڸqy :T-r߷qFwaڃ>Zzrss=)((ҥK 6hƍZd{?b v f .y@MM t뭷j*))I&Mҁ$Ú6m,5yd3͊өST__/ժA˝wީTIR߾}իW/SNjZL:UE)))2ewXyrY)Sh޽/6[nEݺulرcUYY[o} N:?={; M6MVy|JLLTϞ=g TUUt*//CNSՒE}y?͛5p@M6MÇWUU$O>^lۭOOOwlL&S<~~نٳgf~;G?ҨQ|NBBMWSRRδgee6:+O<_6=w;n#ccTss^|E9R&L0ԆgϞU߾}%]Km޼Yuuuο`+,,tÇVcc{l{r+//Waa/Ţ/z\_(y-`<ٶmvcl6Y')))1bD۱cZ_1jJLL_hذazwp8TSSu.35k|M=Cr8JII 7ܠlIҜ9sn:-^:IOOb Iu 7YE[nɓ'ܬ hӗ7xC?[|GyD7s:k×dΜ9z״tRfi6!Ct?߿_fY .t7e9үvfϞW^yEz1cƨ]alNŢRUTThʕ9s*++ 7 gtGpQ$?W~~xNu:ڹs.\teddnsw_ucir:߿***c]yIAbbԩS}#^jll q𨫫/sl6+770)~q ?ril.R=Amoy`((3r: .cA[ovM7t1 h׺%>C ^{~As=;mwᘺt&Ok'QP0a `((FA0 *%%e((xtuu9 ={e8CeN\//s'~i}<蔷˜ @]%O:2'.y/9q|)K222 8jLdٜEڳgO( 7N:p}ttjر}$\Ll6311Qtԩ0w @ׯ$Q0I |Q!I%v$ 邂UXKBm5IENDB`lensfun-0.3.4/docs/website/calibration-tutorial/docs.css000066400000000000000000000023501445356770400233730ustar00rootroot00000000000000body { background-color: #181818; color: #a0a0a0; margin-left: 100; margin-right: 100; font-family: Verdana, DejaVu Sans, Arial; margin: 0 5em 0 5em; line-height: 1.5; } a:link { color: #f0f0b0 } a:visited { color: #c0c0a0 } a:hover { color: #ffffc0 } a:active { color: #ffffff } a { text-decoration: none; } h1 { font-size: 150%; font-weight: bold; text-align: center; color: #ffffff; } h2 { font-size: 130%; font-weight: bold; text-align: center; color: #d0d0d0; } h3 { font-size: 110%; font-weight: bold; text-align: center; color: #b0b0b0; } h1,h2,h3 { font-variant: small-caps; } img { margin: 1em; } p { text-indent: 3em; } table { border-spacing: 0.5em 0.25em; } td.img { text-align: center; border: solid thin; } td.img img { border-left-width: 0px; border-right-width: 0px; border-top-width: 1ex; border-bottom-width: 1ex; margin: 3px; } td.txt { text-align: center; background: #282828; border: solid thin; } pre { margin-left: 5em; margin-right: 5em; padding: 0.5em; border: solid thin #304050; color: #909090; background: #282828; } dt { font-weight: bold; color: #b0a090; } em { font-weight: bold; color: #a09090; } b { color: #90b090; } lensfun-0.3.4/docs/website/calibration-tutorial/lens-calibration.html000066400000000000000000000132551445356770400260530ustar00rootroot00000000000000 Adding new lenses to the database

Adding new lenses to the database

Often I'm asked how to add new lenses to the databases, and how to evaluate the distortion, tca and vignetting lens parameters for a particular lens. A few years ago I had no answer to these questions – there was some commercial software available which could compute some of these parameters, but I had no access to it so I had no idea what it can and what can't do.

But in the later years the Hugin open-source program have evolved, so now it covers most of the functionality that Lensfun can use. In fact, it was an oncoming traffic, as Lensfun was also modified to be more compatible with Hugin models. So today it is possible to create a complete lens database entry using just Hugin and the tools which are part of the Hugin package.

Let's try to create a complete lens description from scratch, step by step. First of all, we have to create the basic description for the lens. For this we will need to know what's the complete name of the lens. First, let's see if exiftool or exiv2 can decipher the lens name from the metadata of some raw or jpeg file:

# exiftool sg201196.dng | grep -i lens
Lens Type                       : smc PENTAX-DA 12-24mm F4 ED AL [IF]
Lens ID                         : smc PENTAX-DA 12-24mm F4 ED AL [IF]
# exiv2 -pt sg201196.dng | grep -i lens

So, exiftool identifies the lens as "smc PENTAX-DA 12-24mm F4 ED AL [IF]", and exiv2 was not able to identify it. We can use just this name in database, but for aestetics we'll change the name to the same form as used through the database using knowledge about the rules Lensfun uses when doing a fuzzy search of lenses in database:

  • During a lens search the case of characters is ignored. Thus, Lensfun does not care if it is "smc" or "SMC".
  • During a lens search the order of words does not matter. That is, "pentax da smc" and "smc da pentax" are absolutely equivalent. A "word" in Lensfun interpretation is a sequence of characters of the same type (Lensfun senses three character types: digits, punctuation characters and all others). Words made of single punctuation characters are ignored. Also, as a special exception, the word consisting of a single "f" is ignored too. So, "[IF]" is really split into three words - "[", "IF", "]", and then first and last words are discarded. The full lens name will be split into words "smc", "pentax", "da", "12", "24", "mm", "4", "ED", "AL", "IF".

So, looking at other database entries and trying to create a similar-looking lens name we'll create our first lens entry:

<lens>
    <maker>Pentax</maker>
    <model>SMC PENTAX DA 12-24mm F/4 ED AL IF</model>
    <mount>Pentax KAF2</mount>
</lens>

Now to make the lens description really useful we have to find out the mathematical model of its distortions and fill them in the database. For this we'll need a few test shots made with the lens you're trying to model (if it is a zoom lens, make several series of shots at several intermediate focal lengths including the extremes). Also, you will need Hugin – the best tool for automatic dealing with image distortions I know. In fact, Hugin will do most of the calibration work for us; our task is to feed the correct data and click the correct buttons :)

There exists also a shorter tutorial for Lensfun calibration. It is not as comprehensive regarding the theoretical background. But it includes a free command-line program that automates most of what is explained here.

In my case I've used the Samsung GX20 body (crop factor 1.5, 14 megapixels). I made three panoramic test shots (turning 5–10 degrees after every shot) at focal lengths of 12, 15, 18, 21 and 24 mm, thus in the end I've got 15 test shots. All raw files were developed to TIFFs. For TCA and vignetting calibration, these TIFFs must be in the sensor's linear RGB colour space.

When making test shots for computing distortion, choose the aperture that makes your lens maximally sharp (usually this is something between 8.0 and 16.0). Since distortion does not depend on aperture, this will make your work easier when you'll put control points on the image.

The crop factor of the camera that was used to make test shots should be added to the database in the <cropfactor> tag. This value will help Lensfun scale the model to fit the shot made with other camera with possibly other crop factor.

For example, if a model is made with a crop factor of 1.0, it can be used with shots made with another camera with a crop factor of 1.5, but Lensfun will have to scale the coordinates accordingly. On the other hand, if the model was made for a crop factor of 1.5, it is not a very good idea to use this model for shots made with another camera with a crop factor of, say, 1.1, because the math model was verified only for the smaller portion of the image in the center. However, most of the time this works too.

lensfun-0.3.4/docs/website/calibration-tutorial/lens-distortion.html000066400000000000000000000123031445356770400257530ustar00rootroot00000000000000 Calculating lens distortion

Calculating lens distortion

The Lensfun library provides many different mathematical models for lens distortion. They are mostly of theoretical interest but could be useful when porting calibration data made with some other software. These models are described in the comments to the lfDistortionModel type. For our needs we'll use just two models: the "ptlens" model, which is a fourth-order polynomial:

Rd = a * Ru^4 + b * Ru^3 + c * Ru^2 + (1 - a - b - c) * Ru

(here Ru is the radius of the undistorted pixel, Rd is the radius of the distorted pixel). Another useful model is the “poly3” model, which is a simplified 3rd order polynomial:

Rd = k1 * Ru^3 + (1 - k1) * Ru

If you pay attention you can see that poly3 is a simplified variant of the ptlens model, with a=0, b=k1 and c=0. Thus, poly3 is suitable for lenses with more predictable distortions, and ptlens model can be used if the poly3 model does not give good enough results (which means that your lens distortion can not be approximated with a simplified 3rd-order polynomial).

As Pentax 12–24 is a very linear lens with very little distortion (for its wide angle), we'll use the poly3 model here. Computing the ptlens model coefficients is almost as simple, you'll just have to click more checkboxes in Hugin :)

So we now will run Hugin and load several images we made at one focal length (three to be precise) at a distance of at least 8 metres. Now switch to the “Control points” page, select image 0 on left, image 1 on right and make at least 10 quality control points. Try to place points in high-contrast places like corners and edges. Use only “normal” control points, don't mark horizontal and vertical lines as we aren't going to make a panorama anyway. Try to pick points spreaded around the whole image, and don't forget to put points in at least two corners of the shot. Here's a example of how a good distribution of control points looks:

You also can try to use the autogenerated control points (generate them with autopano-complete.sh or from Hugin directly), but I had little luck with it.

Now go to the “Optimizer” page and select “Optimize the custom parameters below”, then click the checkboxes for “yaw (y)”, “pitch (p)”, “roll (r)”, and “barrel (b)” parameters. If you're opted for the ptlens model, also click “a” and “c”:

Please don't check other boxes (like “view (v)” or “x/y shift”), because this will introduce distortions that Lensfun can't reproduce! Also make sure those parameters are all zero (except “view” which should correspond to lens angle corresponding to your focal length), if they are not, go to the “Images” and “Camera and Lens” pages and clear them all. Also make sure the “crop factor” is exactly what you use in your lens description: sometimes it could differ a little (like 1.47 instead of 1.5 in my case), focal length must be the same in Hugin and Lensfun, otherwise they won't match.

Now press “Optimize now!”. If everything goes normal, Hugin will compute new values for all marked parameters. If something goes wrong, Hugin will display a message that the values computed seem way out of their normal range. This usually means that the control points are wrong somewhere; check them once again. If nothing helps, try to make a new series of test shots.

Now you can go to the “Camera and lens” page and collect the computed “b” (and, possibly, “a” and “c” if you need the ptlens model) parameters. In my case “b” was -0.01919, so I can start filling calibration data for my lens:

<lens>
    <maker>Pentax</maker>
    <model>SMC PENTAX DA 12-24mm F/4 ED AL IF</model>
    <mount>Pentax KAF2</mount>
    <cropfactor>1.5</cropfactor>
    <calibration>
        <distortion model="poly3" focal="12" k1="-0.01919" />
    </calibration>
</lens>

Repeat these steps for every focal length at which you made test shots. This will take quite a bit of time, but in the end you will end with something like this:

<lens>
    <maker>Pentax</maker>
    <model>SMC PENTAX DA 12-24mm F/4 ED AL IF</model>
    <mount>Pentax KAF2</mount>
    <cropfactor>1.5</cropfactor>
    <calibration>
        <distortion model="poly3" focal="12" k1="-0.01919" />
        <distortion model="poly3" focal="15" k1="-0.00774" />
        <distortion model="poly3" focal="18" k1="-0.00345" />
        <distortion model="poly3" focal="21" k1="-0.00199" />
        <distortion model="poly3" focal="24" k1="0.00061" />
    </calibration>
</lens>
lensfun-0.3.4/docs/website/calibration-tutorial/lens-tca.html000066400000000000000000000113641445356770400243320ustar00rootroot00000000000000 Calculating lens transversal chromatic aberration

Calculating lens transversal chromatic aberration

Hugin uses a relatively complex model for describing transversal chromatic aberrations (TCA for short). This is a fourth order polynomial:

Rd = a * Ru^4 + b * Ru^3 + c * Ru^2 + v * Ru

Since Lensfun targets more or less realtime image processing, I decided to use a simpler model that is enough for practical applications, with the a coefficient always supposed to be zero:

Rd = b * Ru^3 + c * Ru^2 + v * Ru

Now the good news is that Hugin has a tool that will automatically compute for you all of the parameters for correcting TCA, and will do that based on a single image! This tool is called tca_correct.

So, you just take a sample image at a distance of at least 8 metres (make sure it has a lot of high-contrast objects on it, for example you could make a photo of a white building with dark windows or something like that). Then generate a TIFF with the sensor's original linear RGB colour space. For example, if you use dcraw, call it like this:

dcraw -4 -o 0 -M myimage.RAW

Now just run tca_correct on it like this:

tca_correct -o bcv myimage.tiff

It will print a lot of inside information, and end with something like this:

-r 0.0000000:-0.0004356:0.0011037:0.9994399 -b 0.0000000:-0.0002375:-0.0000052:1.0006518

The format of the above line is "-r a,b,c,v -b a,b,c,v": first set for the red channel, second set for the blue channel (green channel is left in place during TCA corrections).

If you have several shots made at the same focal length (aperture shouldn't matter for TCA), you can run tca_correct several times. You will most probably get different results every time, so choose the result that looks like average. But don't try to mix coefficients from different images or average them randomly!

Also, note that usually it is enough to provide only the b and v parameters (e.g. limit to a third-order polynomial). In this case Lensfun will use a optimized code path and avoid computing two square roots per pixel, so its worth to try first a simpler model:

tca_correct -o bv myimage.tiff
...
-r 0.0000000:0.0000916:0.0000000:0.9999904 -b 0.0000000:-0.0002397:0.0000000:1.0006490

Now let's add that to our lens calibration data:

<lens>
    <maker>Pentax</maker>
    <model>SMC PENTAX DA 12-24mm F/4 ED AL IF</model>
    <mount>Pentax KAF2</mount>
    <cropfactor>1.5</cropfactor>
    <calibration>
        <distortion model="poly3" focal="12" k1="-0.01919" />
        <distortion model="poly3" focal="15" k1="-0.00774" />
        <distortion model="poly3" focal="18" k1="-0.00345" />
        <distortion model="poly3" focal="21" k1="-0.00199" />
        <distortion model="poly3" focal="24" k1="0.00061" />
        <tca model="poly3" focal="12" br="0.0000916" vr="0.9999904" bb="-0.0002397" vb="1.0006490" />
    </calibration>
</lens>

Repeat this step for all calibrated focal lengths. In the end you'll have something like this:

<lens>
    <maker>Pentax</maker>
    <model>SMC PENTAX DA 12-24mm F/4 ED AL IF</model>
    <mount>Pentax KAF2</mount>
    <cropfactor>1.5</cropfactor>
    <calibration>
        <distortion model="poly3" focal="12" k1="-0.01919" />
        <distortion model="poly3" focal="15" k1="-0.00774" />
        <distortion model="poly3" focal="18" k1="-0.00345" />
        <distortion model="poly3" focal="21" k1="-0.00199" />
        <distortion model="poly3" focal="24" k1="0.00061" />
        <tca model="poly3" focal="12" br="0.0000916" vr="0.9999904" bb="-0.0002397" vb="1.0006490" />
        <tca model="poly3" focal="15" br="0.0001253" vr="0.9999184" bb="-0.0002858" vb="1.0008241" />
        <tca model="poly3" focal="18" br="0.0001204" vr="0.9999075" bb="-0.0001990" vb="1.0006258" />
        <tca model="poly3" focal="21" br="0.0001063" vr="0.9999562" bb="-0.0001477" vb="1.0005692" />
        <tca model="poly3" focal="24" br="0.0000982" vr="1.0000005" bb="-0.0001137" vb="1.0004136" />
    </calibration>
</lens>
lensfun-0.3.4/docs/website/calibration-tutorial/lens-vignetting.html000066400000000000000000000100121445356770400257260ustar00rootroot00000000000000 Calculating lens transversal chromatic aberration

Calculating lens vignetting

Creating a vignetting model is a very tedious task. The problem is that vignetting depends not only on the focal length, like TCA and distortion. It also depends on aperture and distance to subject. This makes the number of test shots required for a good vignetting model grow exponentially. The TIFFs used must be in the sensor's linear RGB colour space. For example, if you use dcraw, call it like this:

dcraw -4 -o 0 -M myimage.RAW

Hugin uses the following equation for modelling lens vignetting:

Cd = Cs * (1 + k1 * R^2 + k2 * R^4 + k3 * R^6)

(where 'Cd' is destination (resulting) color and Cs is the source color component (does not matter - red, green or blue)).

The good news is that Hugin can automatically compute the k1, k2 and k3 parameters. The bad news is that you'll have to use at least two (I have used three) shots for every focal/aperture/distance triplet and you'll have to align them correctly first (e.g. compute the distortion parameters as described in section Calculating lens distortion. If the images won't be aligned (check this with the "preview" button), the vignetting parameters computed will be absolutely bogus.

Now after you align the images properly, go to the "Exposure" tab and select the following parameters for optimization:

As in the case with distortion, make sure that parameters that we don't need are set to their default values. If this is not the case, switch to the respective tab and rectify that.

Press "Optimize now!" and if all goes well, you'll get the computed k1, k2 and k3 parameters. Pick them up on the "Camera and lens" -> "Photometric" tab and insert into the database. Repeat the above steps for every set of test shots you got. In my case I got something like this:

<lens>
    <maker>Pentax</maker>
    <model>SMC PENTAX DA 12-24mm F/4 ED AL IF</model>
    <mount>Pentax KAF2</mount>
    <cropfactor>1.5</cropfactor>
    <calibration>
        <distortion model="poly3" focal="12" k1="-0.01919" />
        <distortion model="poly3" focal="15" k1="-0.00774" />
        <distortion model="poly3" focal="18" k1="-0.00345" />
        <distortion model="poly3" focal="21" k1="-0.00199" />
        <distortion model="poly3" focal="24" k1="0.00061" />
        <tca model="poly3" focal="12" br="0.0000916" vr="0.9999904" bb="-0.0002397" vb="1.0006490" />
        <tca model="poly3" focal="15" br="0.0001253" vr="0.9999184" bb="-0.0002858" vb="1.0008241" />
        <tca model="poly3" focal="18" br="0.0001204" vr="0.9999075" bb="-0.0001990" vb="1.0006258" />
        <tca model="poly3" focal="21" br="0.0001063" vr="0.9999562" bb="-0.0001477" vb="1.0005692" />
        <tca model="poly3" focal="24" br="0.0000982" vr="1.0000005" bb="-0.0001137" vb="1.0004136" />
        <vignetting model="pa" focal="12" aperture="4.5" distance="100" k1="-0.19267" k2="0.09379" k3="-0.38938" />
        <vignetting model="pa" focal="15" aperture="4.5" distance="100" k1="-0.08756" k2="-0.28192" k3="0.06908" />
        <vignetting model="pa" focal="18" aperture="4.5" distance="100" k1="-0.05982" k2="-0.45748" k3="0.25039" />
        <vignetting model="pa" focal="21" aperture="4.5" distance="100" k1="-0.28874" k2="-0.06687" k3="0.09488" />
        <vignetting model="pa" focal="24" aperture="4.5" distance="100" k1="-0.44227" k2="0.2599" k3="-0.09436" />
    </calibration>
</lens>
lensfun-0.3.4/docs/website/calibration-tutorial/vign-hugin-exposure.png000066400000000000000000002021171445356770400263650ustar00rootroot00000000000000PNG  IHDRstsBIT|dtEXtSoftwaregnome-screenshot> IDATxw|\ŹSj՛m½mlƄJ)wHLBh)\B K' %i@0IH `"[.=]y>y93;3w=s$PSSc:tI@ H4.Kbx !E@F a_fUUX,N |7VA*2X.L aVWW3i$n7GY$I(frb۱Z-ȲD"QB`h4aC9P)V>쎬o#c59362I=c%03g|[/;s0m|#cw=̑3x4H\~;ױno&e9`c4s$[c}ΌwnvroǧoZ\l.aI"C׉DbB!Ph`=uWoHP(x<ۗG ID"f( !,eY6KJJ8c(..p`( ˁfC훩m0S"3G0 #N s%_7cO?cGc%#egdu̦ٿ'Z2ϗ6Ѯq翔I6`o2Y]C[˛ʉ'>l}xy2= 3gE`>EXli\|w%PÖEV$INOj/fֺǾ2}]7Ä~ߞoq62Qxb1Y$ 4sE}탦u}MdB< Q:n7cL<EGGX łnc&C`c 2^p8L H@ v=']TPP0.m$<^Jx<(4F@PO,|D0MM]] ASUR RjU$JtRYBulGʤU!"rH$$KL⸅q:<ӧ-4r ˥),x,B:'RH_6gg>.'rg'2#Fn7k/yFZ~,F3s 6f9-8Ψ# LKK+>$InWۜV)pphhgݖ͸6Ti Y x,2Fjs-z&M}Lg,Cʺ83]l֓ c!T-3uLEt Hi+L?L#o-a`&azOL3@ʣzj;_gcC$ 2*&ڇZ@n1gt nb~:9zMsH??3KUU #X}:c'|֬iw >Nj\Nnbd覊"+ȲzOzo(,H`=m**bp ݰɄ*VEU4 DQ4]G%ĥ!K2 HG(@Nۭڄj1g fLf?iEt0MdE-pR]QLQ͛ߧ 4)%I^o^+MDcQjNP05FPh,(z())@L]GfϬhR;:ETÁtvvbِ$ ::20Aӆavd_DI(%qGgE.@$L3ͮeu@0-67J%'3Wm m>oɿmOwLJ7 H#Srgrxo}:ꪫ9s&VSNMؿ??8{M;[(,,d͚58p3Od…ho[۳#ɵ^EN'PF{=z)6mڔu;=Vc555@o?Yn]F6saԩ<TWWsgpTUW]wvgWiN8q!7`V^sׯO .`l69믿3J-o&[I,96@}7Ô?R}L>ԧ-f\ԍV|Ѝv7C`Tgm$CrF o}-LvO D7t4MK̔ 0t #|Or02Ya,gnGK+l<Ȳo~,_EE^V8H$'>m8]N^| 4Ms? <7eմ}qPRR~N=*g箤/'T O0yr/;MʻnߺNV| 9n}wH~L6 Y*GXڬ^b1ָH\d۴|[ذa3>v ~O /Oryq 7rݵߣ*tݎZ)]w={| כ7d0 >=c&n,+Z,liŢA@]z vjOqI'`mNƚ͊,Ib1 \7KNXʅCyYwbQP0DQQ5SbٳnIy!MIiobǑ]D#TU̠vJ5јF/@{knθX,F$Itg,MӤ6/_Çٹ0%e4DU,(.K?! jؑՔZb؎9?@)*FQB\.6H8$HR4Rħɶl>2965-Dhm6"dFu,O8 ۙB}{DR))arBt%& y f`Sj?.yjirVo={ sTl:4Pueghħ@6%r#wG3ioJK`u <>t->ϱxɜ~Z{盛~ץI4j勱{'xg| xkG>jO#?dorES:T~_y"?lDU}_Z|krU޻vRbQ._]>clZc}x:ٶu[7X-wٷD;L0T1Mdv>Lvl=;C~nxWs{Wj/}>J57vQYusү XXj,v\xbl7}@nG/N8ūVl҉8,u}}>~I؜TZ*Kis|{"Z8mSp:l*]7!E`ZP U" \v#B4rp8Tildb;eΤz&ZLb.5hZ5"-Xd+"kB(n N95E+tv]uUtZ FޢFa{4QXfZ,*+F vjf͛Mldt8VΏQ__Ϟ={0 jMM}|>}n݊[ʠQԘ& IxJ+! Bu4i:ԎiM/b;쫯OCKh9߬JqENmK,K NxxT>YA$dENaIRq IȖ2Ib7-I$:ޓob2V0ٞQH^af/dkzj;֧RFꛞvGw?+̤fE{u/OZFZٿ 웽fB>둖˩w&{ 1 ?{7|x9Ai'xzOǞ% /0[hlq ~?dԺCG` tBUnf>ݧOWȒ%rY-UUl|IWֆTZyhoISOo6l M4zy.Lo44ojSO/ _װ;Ӳec?cs84GuP=Q7n+jTF'fM(" DI.p „vah7Mc躁^}ߤ+X,ȃڷDk,ӎlo8vBn[w-N{?<-,S3Nz왕hZu6Wٵ}'-ABضm[No*VX,h4J0J0X7t"3 o|!3b[o3f,lj4$b~٦ Eij:$pޞI my't{'md(pwo Cnta C=SIL&2١_7m& &wcIjGώs>MY3]@O$Ij` H>8Sw}v+2n VPVVWW]mx衇} `ZiZ|c917g5kWӎ ȳv,YrU唖:40OzmG:tgRehmm%r@VtbZ͒1y-_W+>k $́MC`UHqoFӟ ظ+7i-5R.EA5,MI_д>_]]R'Hi3MQT5a)nf ubŐXb;pNMDם E5"gTUW$DڷٱmZ,a$1~.Gbf4MC4:͘rwbŎdpXł,YȔν+>?p6,UcxH3bQ 5TWXe z͸Ja[ ˱}66"N zI}2ch4BJɛmn6ymXw4?!P_~;& GlL*{{v6u g#˴_<;|ʏ$PeiPyFb/6FGRo+_ccLlj} gNmf.^N=S:/zqɥgroѨ6~X-K9sB86.|r#י[z_1_ < R{y] x?a-tsgٲczv`ѢSU9{Lt<u_97_AYy1^.'殻~Q\x,=ϸ-gM pۭJY9x\eZfZT.7.g!v M ØȸN'iѢ8l6<.76k KJZT<)X+!m4nNG\;nt݊$)mpX1.=jQpV}?6礞Tk)6=jѣG ég n7e-S__O{g=N4)Z;5M;E{i|엔25ab1:}Gw{ٗ,RtA-sNgwS?ELsN`*V^kE,@Vig@UrRunʶm8p Gww7~v˩QYYy睇 `&( `0]@ AFğ 9ia:*e;L}< N(^NO}/|=*' p IDATIo=)6gщjxh_S.6_.kE`2 QPPuVtM!ՐW-ng|Ɩ*fUr`-eRrHz۬4)dfڲ 4lG62 gŽ$+G#v$!x# ,a.2|Zw=s,Ju,2=N}9T3#Y&v8߇'cIe|نm;K(l&aن4r${,#]pe ]ޡCvII1?ԝ66QwF-²D(loek{i?TCEI%\ȁ,+Id*J^\Rk{ǰ9^. .!Rb>κ^s@X鮗{fUsY4meشԕM(l0_-Cؤ,LuIwP^%v돯fފ;kngݳos`aʊ/1|3cE,9VPw}뷳op[. t_s|S).I æfft,Mm{WmvE5g.fI8V$YFQz/4_m[袲ʪij 駤ԋf~K%컉E5}Ut4&M*x0W'nՕUhBwW .W%x"&PUNzJ;(*. bXPbNC̼uC6oGSXKVQQ^cfr3ټ)HMs !,u/F0"+J*6Ż4:T52Ҕ)Sسg$SVa'>Lii1^M&(C&7=.-a9\fr~iFdck7#;r <I55)5\IglgSnlʏ8Te6MG=# W?b<7`ۚg ;L39x?4<_>rLD- &n\.+-P|D Ld^;1eJ)sUcl!)Ĵnln]{'R'F)j] Go{/1TK+ߠ.J?xQȜ9YxՓ W_ϡC aZ)**7eee#!]kJ5}t:Y+U9r_'& b&v6L[k͛7,b:@F8x<x!aņ,U utӏXt1OF-̞=rQTgzM>f.~ 5k1uƺr)?f˱jx֟W.e{{v"ԝ|7PGZ.?Ԏ{gS'Ob KMt4L$ EAe àc{[h?^PTU<* ٲe/aFYQKݩvt†ټi7բ2҄A' KMPq9864 k.$p}vdYa;b*JinꤥWa^=גIe~=X ֆdz#}Fop#L\ɶ|,koH>1c1CaGOG;cs_6Գa6A UWy-r#ѻߙݟB>c៱o~pƢv2Tg3VvV͸ okhHr8/dPfRUUCyEMM]6x]Phau!v֯1h>iTO.̍iGVd hC -tucLVZfP]=uu]$UpX{KoX(/.Zj)p?A:K6&Bb1dكf-vVJ*d&tM 6 ˉ& ŧn;}o3a6Qg>lem곱\ʏr=FgZv|gd[no̜@  +@ xU_@ @bR @ 9"f,@ @bR @ 9!f,@ @c:cyAz4Mh6. J]9VGD[@ @0d=c9 ql>ǯZѨ2g̘W\1l)SLں{Pp~@ڏc*++Yrp {EQC@ @0R)YSC&nb,3a?X˗#O|Ñ:ž={'>1aB9@ `1-$ACCwy'w}p8O?͛1 c=+WbZCǓO>I}}=%%%}ښ[nnࢋ.SOQ]s;p駧YZ􍪪CǦMx/^z%^~eSRR~ƭ:jW]^z)/2`;K.$`@ @0{F2~ꩧ0MH??'>}jph4ʃ>8n窫⮻G?QJe3 wI'vZN;4t]梋.q̘16)**b픕c/_Ύ;>}:,Ln(ؾ};7ph￟^x~#G@ @0:6禮kkk l޼o+x'8G>Bww7wofa83yGk8N:$V^:u*6mBu/^< pp8K$a|Stcg8ѻKJJ9'@ &"v^II<TTTޞַ6s]fٲe^zh4{ڼ. ֜={6NG}SRUU5G]]pw}3g0sL^}hxD"~?_9GG@ @0vd l`|f?sq-z,_<'92:>SO}b/_΁YTT)½ \'O˖-㥗^so2EQȑ#TVVf1_{5f̘lP3W3gn# 2|;<1c)@  -]Դl455ƶm2*G5;@ EXx1%%%TVVDr(暴Ѩ.ڏ$c`||@ QYq|2XcGi0k&@ lDl`T2eJFbU @ |pK@ @ 0F@ @ !,@ @"V @ 91@Xn߾}<@ N?@ @e|@ @ >{@ @BX @  '@ ANa)@ R @ 9!@ @ rBK@ @ 0M*x B躞۷z7?"S 43ϰjժkPe 4&x2)8J}]H4.4Dmh4S"IR?@ ¨ UVeM2o4tM|w]Q{f?9^x!dՎlZN%+`ɒ%g?㢋.ڟ|ܓ_޷$VZŦ 3mZuȼHr͏5j*~f&Mf;%t_=4z)b&^{mv|>wy'. :a@ Q@Fj 7܀b0 XjAy嗙;w.%2/ x~ƍ`F0}-IӈJ2/3>5}\b.guvUğX(HDk>;vx}<,.V]>;kERNMM (,Ȳ<7ib'OIe956QDC&f ߾U5ܛLD%jƥq:jdBkvcD?]S7MAU՜gax|4/ۍɋ=@ <^7`sicDc&FoGCurw_Fdk6qy.ᠥF EeW(t6@͆iX"bl޼4lLH I$ g)8s"y{smNdEML;R;EKߕw2=[d>YF'!.sHS2" d9/KȽI( D"x<JX&E@ >c*,{ $7S7eeeq<|_:տnP0yITT0{1~Ϝp‰XfˣpM?q_$כ͡IFDpk)a}n_(..]ߎfԵ-DekzOV\ɴiӰX,p;vpYgIuB!?ŝ{lܸ4e|g4M6[<ˇ>t򺜯᪪x}ޔ6]^Q _Oɞ={z ¤g˕I go6+PTTDee%Ũ,y'C/Deh<p9p7reBcGK\&EիҗGY>_<~ .02L d8iB,SR6rGT%| +meμp CC\ɆcX3i'˖vmG g/hSKrcjQ"E':˞xf5~ g@ {1&0g2 $g~CĦM tpwsWduEڬb1"("ZTL0LMa88^,V $aٰ,(Jgggy 4zn{D$ H4G?4M,YBp ޵?x?9ιc$Iʳ?Y !,᯦ò%E,1p,EUu>;_-Zƍ$)X ޳NݰIcS;͝lڼ`N0/Nm'75tw̾=r'_˖\?{)(r0nFb H*蚁nD1oat;|BLgRd/ktvvhѢӟGȥ'9 q`i_xM+SYYIII VYy饗HIc555ҊLyx,_+Wx-~%|̟^aPFbzO9'ne…lݺ5\jhhu2οݷ+yo^̟1uUTT:ٶ{3 IDATݤ F¨IPT\@Ɇ;J7Saf$)qI -VJ0_?+vj e⊙8o#=nkf,")@ 2gHaOrނ2-RX"Tp4 ])++g"L1r7R1͠H,?--G۳nυ^HII ̥{y6e#41MEQCe'Ld޽L6lN(3(]BմZl95sj\Zbi6]az g)gnQci0Z,eR!5 kۯ<^2giGթyvm\#inΜ>CXr0-]Vp iYm`1[;s,X,V'}L:()hZ :"Ta`1s!ǎRMbQ27xSrw^ZhAHH:|ӧcqrN>CD1[Vܹu?Jo15t]VmcR \qƞ}:,x͹Yۨ'NI`/ N:C䨰H !ֵ {(Nh<ҫZN`YY&l6Jks;v9YX;xW) / 6 33ڽA$%^`wIIIl&ǔMY7kUj!H`)DS>\8 G9ʼs9<ߣ(gxfXXժU#44X1 !*?l8/ԤNCqn\(t~g˖ح?L{$,2uofןPfMƎM*^@d;9'Pt-9XS<[n:tH}n^WQ{f=˝X*c1wزD3VHo}H*y%a0:Yr yAqxȕ;F!$$nRsk=bj] Xf]b)BT`XΘ1~DXe Z u`IuWlڴ)KI߾W~ѧXs`_[1cFqxJ~FW$8ŵ>N>F$wbYeƌ V-ފDFx\U}B]rB!Bb{,"QEgT꾼[H݈ ǕBKWWXy駱Z~IN>ѣl~zo~/qRDoY7k]^U\\dذanɓ'*8][O.eAYn=#FCVZL>9s)S0c $Y]8V+4oޜ>}ʅz/xEa4jԭ[￟*UۺV#GXz57o-zRKӧ~J@@(Vɓ'Ybzbbbӧ-[,x)d!VQnJ5غu+rKWж]/v]g~)ʂرc̞=~1|pHIIa˖-9sƍ_Ht:1RҮԡ/eq2m4z=,[ /+Quys>J֭lڴiӦ1~x*W|M-mYt?<Ç;࣏>"))W_}SN1aƌ_MFF:tSմ4>cۇ^cǎ1BMV^ի 44{}r &Lŋu-]ӧO3ax k.^ȗ_~baܹAyGPɯf33gΤG|E:?Ʊ7ЫW/ڵkNgϞ?իW{lX|?\sɓILLTX,ݛ>}4cƌb7QQQ 88y+|AyWi֬$%%*ݻw3uTz=:Yfp8裏h4L6E#.^dSN깣vL|)Sx=f3+V`Ϟ=X,y߿y#BQR_-ZPZ5ի֭[4h|7 ,X0NlfΜ9n/p8L8Füy󭃂Ǜ4ڴi|–U~Z?~cǎxꏈޮ)\KPP?L&L@dd$IIIzӁJ)B=YYYΟ?i޼9YYYhт;vJVVVVٳgINNpY༜5_ߗuM7DVVZΝ;seul6Ӻuk]WA˽.w}7`6iӦ )))mӧ}ڗ?NnrreggȞ={ѣNNعsge[}vJ}/uT*h_]ڵzRPE۱c֭6 N߮W~/_[,{OѣG;dy=ǎ|R2ȯLǏϳ>ĉ1L :PPR@@DztlWE=xӧO3|x"##|NTV_|̚5K}]K.]HNNv4j(ߕ+W&##p&͏`رܹgyI&qbvQNMMEQ&Nرc;v,gd2yM\eqeZ;v,,[^x)SpB/}U` C:F\ljBEKcBBBW͛7c޽mۖ0 ƶmXf ժUgϞԭ[7y8?ŋq88V˧k.J[~=@^WcjK=wHtE?t5iQʶ !W+lTVK)(]ĊwcU_c:_bg݃~{*(233.i~iklE9 ꫯz\ufJX *Ubw}ǢE7n\j̝_穬#BQX*Ν;7T;~wڶm @ӦMiڴ)6͛7_8/7_//!CФIz='N`ܹEM*h_\_VTT p~Q.{9 l}All,{宻*~/Z8RSS:]-U?Orҥ<#445*\}(cr۷Wpޯ1ӥ'?v? 3]Q_[,j*RRRx8}4ӧON:~=?0f5k֨ӨQ#VXQa͚5t$iРzѨ0yfRSSYreFDDЪU++ FHH={&MXEDDpw$nդW%y!DY+,8O^G%55'xgyF}=#ǓKp1 hZ4Mro?N)))j\6 APPO?oyZ/e=mӴ%<<:u?bf˖-n4iš5kAѐI\\\e[}h4ߟM6}v, t֭[DZcNJ]G/(_ō;<LϞ=}:6 *חe/_`_~yʽO<GV_<F4h@޽9s۽7楗^/5jpJ;zhv;O?4/"{o'|3p>c믌3Yfi)dԨQF^xFɓ9w\Wlٲt4 f;vPfMOCCCiڴ)+W$##FCrrۏގ%#BQڊbФIj֬6AԮ]N:n:.\J* 6 p~y[~nc̙ݛ[o޽{dV+UV}>^jr[AAA,Yħ3I!ƍCll,f{WXQ%&&r=gƍ4oQ !B!*?OJrrrXhz6mJ>}J5.ԽkEHղ$8FyRVPW g@ڵyVZCAFqB ˫Gh\CW2,[ݗx+“*XEne!9# !B!(Dz*bU}N[ԍ亂g\e$ǕBX !e$K2BA,xPEgT꾼[H݈T+RQhڵkFHNNwLB!ʅ!!D3n8bbbl6{n:t赎K!dgg;2O[dʕy{'%%TB!( 999A!ʕϳsB/׮];bcc=X !B!ܹG}EQp8(h4h4uF!''˗ӷo_R!B!* ͆nnp8ԗFd2t|%É !B!nj9I,B!B`2 T$B!B!pV^pEQ $B!BQ)ѣG'11ɥ$B!BQ)‘#GHKK㦛n"==Pɥ$B!BQ>|LnV"##_>;wuFƌù[KsS^y,^[!BPre6lbfW޷HEE6mӧEY-@Qcҥ ժU+322Xv-'55ȍ7wM b.\Z.B!DyWre9994N`f\ŲQFTVLvIIIG)j+WE^WZZSNҥKTTn/r!>СC DT1z6B!(rrrZE^XevԖիw߱gϞ>^~z:uСC b֭_;ή6m[J oAi&/_lfԨQԪUΜ9ӧر#{!11FC:uԮ]xN:E\\/0FVZ1jԨ|~Pדk+$##pzKΝ8p 7&MŋѠAj)[O\Tw͛ 'Plْ@N:EVVjɓX,hٲec/1-B!DYVvm>"-Mc鈎yDGGy_VQJJ [7B߮y(z\1f4J( [lm_5lذ$''p}ԓPHOOw; s @ժUiW/_X)[o;Ƨ~Nc̘1ԬYSd ǏcZ!BlTcXm`b Z0A8=O~Ptt4IIInHq}uj¬[LiW?&&V˛oIdd:/%%˨J111$&&rQ2<6mv3ҥπ3ѫS2 \pAӗZa֓sΩ]rG7}vvJb„ y_KB!<ɥ 96gb@əT`9O>ݻwglݺt4:PMrr2?#ΝCѨ& jٲ%UT!11ɓ'ӬY3N>￯&qX={d…ܹK.QF [.={=ILLdҤI4jԈ/ra5W.[ld2_^=u~IOa̜9D*UScsm7**DۇbSKB!PHH֙Pߎ``ӦM3jբK.r-n}oHJJbd0),>իٿ?۷o' *UЭ[7b,[o`6lٳg9y$QQQn#^-22^xA}o`QFtޝFY{?~djժZJj #-- D>9r$/=z0gΜ<)Ly!BQ^\[v)Fy:th勧m!B!{iyž_1;X~=ƍ#&&Xfs/ƌ֪Uӧ._^x*v Lȑ#:t(Gfkqqqw}X/kAOQV;wsrEΝ˹svv{'!Ggڛ/̘` +xN#sKo]-BP|YquB\߮Iby̙CΝyw2e kfڴi$%%]4JyWi޼9fbżrIW&/l8wͣGL<=z0o<5ZX,Gc_̚>]zެϙT>oOzDZ8Pd!Wפ믿W^kNG^HHH`<Ü9s)S0l0֮]KVVZjspr72ef̘͔)S5jW&99XŋYr%III2rHWnsƌzz-ո- {{!''˗gEE 2g^9r$k׮%99>՚66nȆ "$$]ҭ[7ve׹sRm?> wʕ+3l0j6~x.]J_c]Ӗ-[NcժUZ BCC۷/ݺuW^`ȑ1vX/_NFF:t`>걧ji֬=O=˗/'))ŋq)l&O?;vp8h߾==vky[h4z}ڵy[lZvmj_|̙3Xt)˗/g֬YTZǏ3qD>3t:oĭY{ЩS' k֬aĈ$JB^ O?e劥k8}*ɯg#cYr23hݮFj[G0N=&>/ܹ3L~}<=DUɈGbR"}UÏ=I7hR\HGb1ӧrrL,[)w@q8h٦=CG:mѢEOeW\޾RRRcǎ~qxRQ.\g}kFf&)) x Əς ԤDQ}7`ҥ<꺷oohdܹL< 2qDuڜ9sx7Ƽ{n}u/fDGG /KZZӧOgL0A]~׮]L:^Vi=sLfBo_#x-ŋ=Q~u_}_]7i҄ .HʕٳgժUc޽tޝ{ҸqcZ\QkzGjjknYf4jt)Ӷmymߑrvpn^<sNL{Y#x7x3Sqy<$#_~6O y7i_~6;襉Կ>h>x&[F0|K/d X0/a«?}y꾮\{ A\L@Jr19t`/UV}~gwGդ~s+ǂX q}*NVV۴}b4 G~Kppڒ€ܦyJHspgȑԬYLÀ "00nݺs|Sоۗ  ܆+p& j֬ PJ(\t @L&y^999^l6Z-NRʕ+{]߿{Á`O>lڴmjZtԉ<_~n_4jԈp O>۷m.S/\:ѣ[nZ~.;ꨰeW kFCڵٵkɜ;w>}{nٳg5%}Y,rrrd2v,Bs'3{#/<" i7`0Fc ;?~RmCSn$'qݦ>y"4yr C,(EBBB1LfC0LinM9&[0헻 nv;יɌw'ѽW?5hdByEo6˫S,-ƙ$^Hw_7h́}a0]4%ɸc x`xBHV_w6ﯿaÆn.]Dll,VJ ŅngΜ94nܘ.]]ꫯJdd/-[ҲeKl6֭c޼y;.[eg۱X,vbbbY&\foWi׮ڵjj*>C̙^p`q%)))T^dw߾Lsq6RSS1ccǎM6p!z-.2MsoÆ+ho⭎- Yf|GЬY3"##bݺu-B/YfnڵCl}]]ssæLDXyRJ2aVZ&^n9iԤwv<4""?u۾4l܌$8$IDd[6#$4jկckX.*ksM'ς `ڵܹSMD֯_۷{׬Yl&##u֩Z6Ksم b07N-ow}œqE>nGa4$eKv;VUrFʕ+ٰafFåKXlZjqFE!%%p~$%%qAv;jh4jrn/22ƍ_cX`ʕtcbYi}j\;hn\!!! owLA"##iӦ K,QNOO_~xf~uTز+}oĶmhyaجY3֬YC&M(/yڽzپ};۷~zzAQ!vr ׯ׭^b&+3 V9,y59)1O̞uZ|1p{xD$Za%.?339vײoo؄/jھ{Ի?FFh44h܌?z׏k2*l͚5kXhZzsQJ%ʢEjWLL ;wf4 v%;7N֣Gzň#oxװZDDDpw۾x6VvbccyG}ZSq,-gWEO_ 7W^aŊ|l6BCCiӦ u`0㏳pBVZEZ뮻8~8￱T^z FC*U޽mrȐ!t֍'|㏣j4hP_־LsqiӦ?Lڶm;/O_޻=zg#cv"&2Ehظroz%_ƢiiӾ#{`Ns 5j:ϱ 7 ?Р9li>xL>LNI*^iڵkFHNNcС\@~Gyv=Kn&cٮoɓK,\PQ!wv8"|n/fС^Jp|r:t@PPPݥ( +jǟ>ۓ^b/r%G o#3ES!DZ yΧ;cI`ЁAŘ`7bcc1צR\GQ!o|9_֨Qg}{J+#| q}RIERB|9_zi4=m;DSfڵk3{lQ"}}!ԫWe˖; !(7J2y(8[+ ׍7c֧r/9T q*3(_KA!D~Z( V!J$HłB'GlV|j;̯4eG!DɐR|!!(o4z)!_X"/!kGKZ,>Ib)|jiܸ1K.w(B!*ƍXh4,OJ!GX  "##СCBQhZ C!dBQz$>h4F!ޝGGU' @H@$8D (x Jnv-2ikL"**؀."AtC(H2TʄԘ*ZsٻvS)j"|(i -"͇KjjơDDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,]t)&NHUUӲ'N`„ v:P{򄳘\}^cn'vZxg1QJ]q4&DDDШejj*&L`Ϟ=yZر#`04u(RiΜ9 >>,'Oʹ1a+]WCHhlfǎtЁ;w6iB‹3u4׸DDDDh]>|R{9x ~WϜ9dzn:󉊊bԨQoߞ۷cXW_enݺι;vY|nn.)))L>v-[(,,ח 3zh6nH^^'Of֬Y; [ݻ7RZZʭO>dزe 7oȠA:;Wm|'dddGbb"#FϏ4֮]kٸq#ӧO'22Ǐ`fϞ_z96dž干/?rg̜>}:&8~X?g2;w.SL`tڮ_~sk7ܹsx+++o|>&DDDh+;v >>hnFvQLZZ/"#::+VHNN'NݵkJKlN>mݶ{nwNDD}u˗SZZooIaa!9yyy^QF`RRR\Zd 3g$%%~Cnn.Ӷm[222Ƞ[nʆkol\jٲe9s_~v=s-8)S;w.,\~ɓ'3o<ڷo_缞t,X{ 8˖-#00Yf /w^TXXcƌ>#;;ݻwsaz)Jl[pqt>h0`Μ9̟?|8֘ylJCΝ;Y|9>,u^EEEdffwǀxYr%cǎ'x׏ݱcٳg裏=z4:th1!"""WFv׮]hтnvZTWWS]]}fĈdddP]]-bzbҥ<#deeQVVf4.\}ל={LMM &k[_;^=ffΜYgdl6Ƹqضmk׮} 6ݻۍy"m###t7̚5kѣছn^];=&DDDr/CAAӦM/?cǎ/\W߾}ټy3sY-u]lݺ:ZVw,ap 6PQQAqq1$&&+J||Z/"""ru+;w$>>믿n]jȚ5kh۶w}7DGGӹsgHXt)&(zMVVKqz|ll,:C٬oԨQYW^yDXX#..֯_ϙ3g&**~a|\;v,| /"$&&֩`0p7riUغuyr#Fb̘1TﮰjqӱɓY`41cưl2Njc\933oSHnݸXh t5fjk~/""[DNF}a04iu=Nbܹ̙3G)""rILL4M^^}91ͤ0tPHq)f͚?#))ɥ-ZDFF&zOF.ƴ8~$gCETVC ʫ + P]شi&M"""(***w,TVVrm5u("bCǎǏ шHcbiӦSEDDDDD]1ڬY:ԩ~S!"""5""""""ruSb)""""""Qb)"""""""SN1qD=q&L[,W%j&Nڵk{m}WL<'rȑ皥("""7 b[k׎{̭:;vaws>w =EEE_iӦѹsGDDDwW,Ï?HYYYΝ#++}U$iWR_Io\}Ο?lCH?΂ ={n:󉊊bԨQo߾*REEk֬!--JZnرcc}oc2ѥj_X Y|9?3fɝqisg [Irr222#11#Fgm~~~.?gNCo]iz=w|IJݻws=G6m(..fɒ%X &X9t/_9\9äPQQ;úuxGŻ|rjjjx7??G%//իW /KYYyyy6Cnn.nݚtڶmKFF}!##nݺ/--_|b MVe˖QRR/Lxx8Νߟ"iHn,^Wrźl2F#f͢ l75dlY_{N&O̙3^~w^'}pI19pڶmKVܪݾ>jH9۱ɰaìcWҐ.G}syXx2j1 9ד~{IQQuٽ{ݶ!muvlCo(wofΝt҅;wҳgO@iii|ל={LMM &k[[+(""zb6td2a6 cܸql۶kҾ}{ FmGFF!!!t҅o5kPQQѣGݴTWWQaa!D[ckݾwG>>>njގղR{l\yݱ.G}s}gc̕cr {'G[{Hpސ:;!7d Hj>ۗŋs=pfϟgŌ3 ̟?wz|AAQQQӲezuY0JII~*"55E1gecccYd tM֭[iѢڵsھKY+}Ԑx{9b=6 .ذpW[I{K;7KlS{ax>NCd Hk߱馛 aѢEtڕh' ٰaz T %>>krjr\ӭn2GLL p1o-ZUΝkPBԐwG Y#Pw_|Aee%l޼ar9ƆrR<6GPbbbTzR'; 1$"""V,}||۷/֭A@ IDATn$))Kb2wdeeTSZZJ||<=FŚ5kxW0Lѯ_?⨩a9sjxf09}qqqlݺգЍ5իW3c L&ݻ:оwG1cXlSN]r pytЁ[VD~ܪ׉-^|E|}}ILLfﳎ ww?NbܹNo2%"""'11Hvv6yyy̛7MY9ufߟ~չem-"##[o?|EDDDYYwL?3硢 *U~`M`~lڴI&ATTb)rرK'9~FFDDDDЗVDDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#J,EDDDDD#:ld2Q]]Ry???.sT""""""F[4L|رåǷ~K``eĉL0~.O:u'68/|Yɕ]i񊈈Hh+?|I/_???222/_{$%%QMǎ?~Sq8q3gw`:Q_vZ^{5֯_ƍ>}:?~ 0{l<+XrYnzn6ٖƋ/?YbӦMS&11ĉt ]v[/tE^^W^ 662/_NMM o>>>||<.LB@@+V`…p L<ٺmŊL:p{9ڴiCqq1K,aŊL0%Kٳ߯s>G:kge-[FII /2;w&O̙33gNKa]h42k,***XpKϕ+㰶ÇBEE֭G?t/???ٍ?11իWsi:tݻ޽;ܷ111撟O֭IOOm۶dddЧO222֭Jk{)-[JiiimÆ h4b0ӧ'Owh;={8\r`0ٳg)++h4Z/))!--~HPP b.?|pmĉ=zM6~2dC=D@@-[,^Gm\⬬eȑ# m۶jf\+**"33aÆHhh(w6k:t\f߾}FL||] ϷBi|.669pwq kɒ%sM7Jxx8[nEkέȕ늽fƍ߿j*++ٴidС o߾l޼CټLh4}vjjj(((૯%==ݺ". %>>krJRBoLZ.gÆ aaat֍/DII 7ow^[l-HHH`ժU$ܹsXWk=Y}tޝ/Ja***(..&55z*[\;___.nJZZzjp]7peee۷b7X_DDDD W%-3<Æ XbxL2źYna=ѣGj*6mDիG.~Gs9sjx駭Ǐ55k+`2 _~58v{"##IJJbҥL&ݻ7YYY2G?fʔ)DFFһwo;fM묭y_5jWfƌL&ZnرcСg$%%ѯ_?3e˖1uT]a;'ɆX^uJKK硇rXޕIMM%::Ν;7.7ӧwc֭u8usέw$z$&&&//y㏓c|I/_$jIc2ͤ0tPF?sUV׿C)oXwL?3硢 *U~`M`~lڴI&ATTbi]>~TVVrm5Jvv6fvڑGjj5"""""FK,:t˿kgdc6m>>>\pKRTT` !!KDDDDDF˜f3u5kVSdvӛ: ݉CDDDD%W]aEDDDDD)((((((((((((((((((((((((:k„ <}^;!QK%50`ڵkHDDDDDD\f EDDDDD-MXZV1~~';Fv5jo; 99???~gV\INNѡCJn>cFҥKVMX~=-Zp-Dpp͘WXΝ;ILLdر>}3fnj3u_?~,̃>XouוZ2o<;Ftt4O>$۷Wڟ/BMM aaaDGGsiVEDDDDmM~oBCC9ugfQYYϞ={勋 nk׎,}]JJJذa;wn79dbܹܹ-Zлwoرc.ff} --r @= s)>TzEddsS7|C6mhݺ5'O>^ɒ%?~ݻӧO:vȱcl)"""""׮&O,˨Q8p 7ѣGspqkر#O޽{?Son.*bQQQQQul6۬+??n}O>a޽qy"""s9>Xp>K;:6K_jYr%>>>SOR<"""""rjI[l]jY8p IIIK/)FAAΝٳuꈈח3fnݗ_/uwf9b=_>}q9> yS_vvv֫vm$&&RZZٳgyIOOgϞ= 8z: ȵKwjՊsJٳ'lݺ=ZgBBm۶ܹs/=z_[KFnvvő#GsWv{-oNYYR֭[s7+jMFnRkKaA75w,5zh:t@~~>$%%+һwoHOOgȐ!}~~~0yd틯/w'UUU 4J&>7|3aaanZ{䐗Gǎ0aaWӧٹs'? <={z&$&&&//y;asWUU5:q3g`ԩtڵ)i2 ?Grζ+WdbҤI<3la;vdo;#dӶCM>C͙3犟(k0DD İrJiݺ5DGGiM,'f3ݺu#;;)Cfѝ?3f0bN>cy8u3g7n[o'xš'1šnٲ͛7SZZJHHdРA6?l{w9}43gdlܸ<~mL&V"-- L||<4M'eMXXՋ9G6md-I.]\sA֭[G~~>QQQ5[眿̝;)S0|pOyys޽{Ι;v`˖-KLL Ʉ֫QYKǏ6 ֬YCZZnݚcҡCKDD^eXXcƌ>#;;ݻwsaz)|} äsi֭[gݷdfΜIJJ ?ׯ //իW3j(,X@JJ nx!^z%z-X|9[˟>}I&;*""Wݻ ɓ' [nܹs\pzLZZ/"#::+VɓW̟?8slq4gs1|^{5NYGm[lgΜ_f<쳄.ͥ""S'ӦMcҤI_|aǀxYr%cǎСC $44o>`ذau޽/gϞ H܊}СF)))!--~HPP b:t`޼yW""RW\\o ]tȑ#q)eÆ h4b0ӧ'Ot|9؛3zA6mhٲ%C !==f=6K#G$<<mҪU+ͥ""W&W5kɡ_~ҵkWbbboժ#""(...&1n8mڵki߾=Æ {.n. @aa!f3g)c20\\Ybcc)**̙39r}tԩq?,jkcoN+_5gϞl6SSSd^=׶BkbvHk̲eѣǎc׮]իNϷi2@BBUUUhѢ:7*//Eu&_[,KII~+""׆VZѶm[:ѣGy駁ҥK[n ћds9,^1cƐ` 33c6NY[,ԻRHsȕ/u䫯ѣGSOj*~:e6l@EEŤ\bbb/ٳ'[hu]hdPPPW_}0PYv4EEEv/#Kll,7oM66~[X{c9ޜiYm `0φ lNY[ZhABBV^;wͥ""W&_΢m۶dff70uT֭w-|ll,:CY;O>_|___kjjX~=gΜ('ѣGj*6mDիGuؖQFf^yL&aaaSN1wܫ'VDD8onM|}}޽;׿XFDDпfϞ @RRs:boΌ$))Kb2wdeeիÝ5իW3c L&Z\*"rILL4M^^'??csH?-"""""⾅}#9s**LP^Y9&ǦM4iDEEQQQѼ/Ox䊽SNM5O+""""""%""""""%""""""f7u""r :tW|&""M[YC4"""e^O󙈈4ogj6_!53i J,ADDcDDZRDDċ4ȵ$fC35𖗗hDDDF+""r-jt:XȵY'ItlPI&Ae'Yj'O?hz/+1fy(55խ: p47xSDfX|;99M*+++Yj`0ЧOÇ1búݭY'O2o<{1nV ?'psZc$&&`Ffo7nK/^Q3gst3-^͵""u5IJ))*yeC#qoӉxݺu+P^^λKxx8wy۷ooa물ӧO`)C=Xbfξ0:v޽{۷>ƕ359K=]ќ\+"RoS`a6=*˕KnNܝayTWW~H@@Ӈ={,_SSáC֭Wulْ={ҦMuƮz衇s8[+st+Z=У9=Z_jyGH?'v IDATߠaTVVҮ];k(+RRRB۶mZ+-Θ1j6lXKm.-_[TT7oM$DD^|h.qwGsWsoMbi/. &H57C@P05fohV̭GE:O k*++ǧN .z])ߺukNJ6m(((`ŊYf > f ""rxS㦘}윞o<\+"fXھ*~gܷ;FJα;s8h4P]]m-g2k~7ݮו-ZEDDD0x`>zLbYvtc>Gs7|fh.qwGsWsoMbi>VSkj%ghծu@:b3gqgΜ]v6 '$$gfny \o}||Φ}UDy}1Kek.qwGsWsoMbiSGqQ׳kld C KLLd˖-tܙrvɽk=zO?z])Ett4!!!_ӣG:UUUYQ]}Zw[n'""˽b\9=p)͛ٳm͵""52CX|f6߭͹Du!TX$%%j*^}U {[_~,Zxe.=}4 ,7`08-O?|rL&r-$%%iԩSK/oPPPɓ'3f&;FvK|h.qwtaa!:t n;SkEDjV$[fSˏ%ƺX:,rL;v$..{^̙3CeСc{w2dk[󙣹ݹ 2aۛSkEDj6'ellǦϳlO<:/7{w\xbDsϒ:h$>MHٚ|&DDD4RDDJLDDE&ԭEDjLDDE&'""r5|&"""%"""^LDDE&g""=K눈GXGXGXGXGXGύزxbʏ71{tԉ|u{CsODD4]ԟ""u5\\]Xp!GիWg'yg***ٻw/ 2{n{GeҤI 0`} ""Mgq3oYH㺦.宻駟v ߿?oLNN}soe˖-vpVmڴod۶mt\1[ϜinjJ,[jŽK흖5۷xjmƈ#0DDDyfu8+~xn+u4|6ki|Tb鎼<Ο?OǎΝ;Gyy9]tnܹ3ǏYԩ?s[*""W3[k>Ϳ""O%%%u7QVV@``u[PPzu8+~`.\`3ٚXhi|J,hѢ.\n3/[O:tŅ \lgj[44>%vDDDʩSڶmKPPPKa?NNlᬼ-N駟>|[WDk.|G @rr2>ݲ<}u=z4ɡk׮7͚EDyڵk].۹sgnVRSSy_ӵkW>S;++W裏ǙED1gh,--v7x5ŋ7{&=3ӟ:q3&L!EH]:7n\S ""1g""rc)""""""ޥRDDDDDD\ĘEDf/vqRլKoR~p9$tR~rssncر, ~GyVTTw^2d=G[V^M^^!!!7={)S^^ĉ9{,+WG}I&1`\~&$ޘXp!GիWg.O;\+"RW m?2N`_p#Ĕ)SOYp!̙3n 6п LNN}soe˖- .}v֬YôiO7o]tWG}Dtttmڴod۶m+73___.~ilt3-^͵""u5IJ *m?\9ȥܹ3>>>lْCraef3#>>al۶#F`4` .'0vXzBCCi۶mzѣG9rdzw^ȕYV{i߾9<Z4IJ奏wQw߳$$$!%PdMl TfE- [zw-qCkV""ȢE KDdK 6~Ќl3If&y= 9:u\g|E}!kAugee8(JOO'NjVcǎiP'O:|~_?y*&***ҫ{キۀ222t:c4R@kxkG!XZR]**.S]*(S?z?\VүW&r}n+N,g]TTVn+=zϟ^xAEEEz饗<y]Ȩ5xV.ZSX ? hoXᄂw:xܦ?۪c2$_+o߮_\c8IRYYY'O,-+YVEEE`Y}壢~V[obQ||&N?\L&L5)&&̓?/hM/c-(K$EַԺm]EQ%6nܨ w]LNNV||rss_dgTEEEU=&''ʧz|ԩS5e=#_ڴiÇչsZ73_x3v=К*^ZQ'ntSt$szawE(dKSV^^{MgV,k0tWjΝu3Lko\Zz~4dҰaôtRv_JIҽޫ gճ>3gJ|I_]IC3.nX7c?%i0aB1Zc-+H!uM7)^MUQgEyX*//ٳrj,?zhmڴ3fڴiJIIѝwީ3gjС>|g5ydX_Stjկ~ggZjdReɞςk߾}6lwV5M4I?#G=&M'OsΞdI(X UyOv3ICյb ر맵knbo~Zws7#""tw7Ƌ/Zl&M6@3z|ݞn/c-T}W!ZnFo{i6͛д.\C}<뮻OkN,3!3f;UH,~!K_H,vu9N\.`!n[:|***t:I.$upr\VN-*! $Xԣ2\dwﮜYVϭҙ@K&O;wSN$_"G)#Z顇"Eb Ȉ%&g?,*x)"2Vq.Pi)=?/iɒ%ݻ>|@KŌ%"#Z))%CYs%1s x^2-MTBrM*-=_f.xXx^aU%NfEnCe5eڝrXx^'TQZ [\ \6.lr7xK qXxn+U*,8jO>yCmҪ⋕N:h4XhH,T(SQ^@}ևnVTTT(EEE)::Zmڴ,$3nQ+^TϞq_Y X+..NQQQ2L E ҧ[>VJrk}7"o~8RQQ"##XEEEl6ThH,QXqqqot/GKNhr:> r!X`0hϞ=2LjժTRR]On?޽{eK-%@= .Bg(իW/>]ΜvT^^ .@C.Kn;a@!`hTDDbbby}4udWf`0ThqzT~V2a|kURRS ժU+b-%$" "-٬HK-%@ fFEFFzUnXhIH,`0d2h4VY- %H&t<K_H,vhH,̣-4_$XBb %/$XBb %/$XBb %/$Xbv.\% r̘11Z*nen[r\MڮhTdd C먌vv0  cV8 <-%P i׮]Mn=(:9v@`α-%P˥]viM%KԿpA}M&n<&X |hƚVPkPcČ%LJs 1!c3f,s 1!cA$@,ZHÆ rs!nќCstmM]>DV/M{[>թ ٝNYuDjvD9v|.[QlɎ4`Xgg@CX>)r|}hq***wܡ__Krd#ۡbzjZWS>d͚3GNXzH6]4)YW|Ah$@,ZHR{(?^BQJDZ[[CZlr.K'OV.˥%]]ʯc5wܐ8g`HgKb ]{:n?wV'5)ϙ(DM/+ϼ޽{Wz*v*ͦ;S?G6ds8dsU+_^;oU~m,33 H,r\lr8ڹs jejݹN*s)%"Eާ 7P ڹKŋu㍚ۯJ|/kqlc*ecY^ L01@b 4REE.]Tn] Śbv+n2 ԎxYKJTphӚr +*T8hP7kv ($nv{wZ|^3oz.LO>׃pch5n0SEE*/-{E~v՜?'unW!éNZn;π@2; 8޽{kd2dstxaՐj~vO51].XׯWBB~+]lS2Y{B@bbn}'JLL=~kС믫mkxx4Knށ&11Q˗/oW_쉉;vl222X@3 9v@`α3궘h'cV8 ;МX>A&cV8 ;МX>wI9v@`α%pd9v@`α%p΍cc]s_Db h4Gz뭷=zh!h3@h 1!b D߿I5 dg7 2 ~py,Z KA%a4H8p9v`nK_H,~!K_H,~!K_H,~!K_H,~!K_H,~!K_ w]wIL9Ӑ>w&K,v>#}:qℜNճgOM4hqZr4l0IR۶m м5IbY^^g}VX,ݻbbbt1}!X:L솓ʿM7PI2_C=϶Ǐ{~>p-['Oj***J:tИ1cԥKI??mjԩڹs>cl6]q]&KK.Վ; &oq+^=*] IDAT˥kNsOڲe2335}tIґ#G4gL&͙3G>8ovl/|͛7Oj׮L7w|Z2_<端$ fW6mÇ_l1If,Ϝ9#IJJJ\߾}l*==]TEE߯}zӟ$Iu 5IbSNrK,'|RYJڵ$EGGW[gX$}T:{[$??nݺ[C?**J̐U&穩6ǥ&Ow}W˖-$ uM/ŋ}v%$$JNNV%vjϗ$U=Εsy{ ;>{$e~[7ovɓ'զMI֭[%IÇUZZ~XݖYɚ֝_699Yd45g%&&zV]R%Wk"8qBRϦ6ǥ.2effTyyyz嗵{nm۶MÇq+B9 `۱Kԗ'qi6cXl'>>ʛ%@8hn޽{u=㞧ž8qB{Ղ $I[։'sNUTTh߾}io߾JMMՉ'ի$~PNN}Y,gm[^ӕW^kƍ*++}͚5ڼyZW^yǥ҃>.](11Q*--:h]~Ow^L* _OT^^9III⋫V}ǧVXp$o[7NmڴQVVl٢ 2SnڴiС ki?22Rfe4uV}r81bW] -Pi̘1e4wi|egg{J]vՑ#Ge}JNNȑ#uUWչ_C|$K/UBB@𥾟':y [oaC nŢ<h޼y[<$ &˛udsHNfiI)$E麥!ZnfΜdf5͌%"K_H,~!K_H,~!K_B:}'P|Ibp:M*BἫ?O?{NsQ֭k02v7|ߠMܳgOjJ۶mӵ^YeuQ۷vQQ^uegg+%%E Ҳe˴`9rDs/K\RJKKԩSվ}{Ij˕%ۭ>}hr:zg$I<$iԨQZfMu&LPǎ=1=z6d25P3KjȑUIRRƏ9f5ŔTuM5k֨@ϗn9ۼy>#h4k׮#}*--Ull#Fx۵f_~L&rrr /h3fL1$$$hƌڸqVXkܸqK5sڦBsvK%Rak…kw^M4rӧ**;ٳg+11N~;ct~v?רQj,S먏vpywi-\Pwq+٬^=\ߘj9OA:utR 2ī}phڵ_~ڳԩSJKK$zʺkڦBsȳex)%V$S0If)xSXw}A=z(66V_չsZ;.]ߗnWII>CۉW>}b MϜ9m#66VtI>51h:EU|Zn6m$*l2rJڵQo_᤾rFB^گ6r"())I6l7|޽[NS&IڬիeT\\kz>]SEEgUW]UuMpv%mK,ղeK_KfRmXT9K;K|R-^T[/iSkA4 }xڮuԧYkQ4w?~n+--MԾ}js9%%8L&FŋkԨQurj*;vLNSiiigV֭{1O>;vgӵxb=C2̬.Mp:Z8rsskft[,婠@ӭުz:C˗'v(^ ǘ-pwANvv}/77W;vԺu4sL%''+--M6-"//Oǎtk׮e]1[83aNYY̙32۷o/ E3y1ַ|oK_H,~ Z*!ccƌ H=EA_ /UH$;v3f>-… ZE"E / vP0;Ph,\hKI.+!Kup2v!"&d@3gZhK$w\E$MH'_8վQ%+^S׀wK,Qv4tЀRp5%/222t 7`hng֮]SF T8gm\!XJ҆=/>z}4ޤB˗/7|#٬Aڵk&N:|-u]zJܦmMj+h튈ШQt-ZСC/_uZ+?i$͜9SÆ SLLq-Em4Ex]j1ӼẴq|biK5Sr^FY_n]rN:GyDVU ,Pbb'e03ӧuZ-ߧOm߾ݫ&]]}g(^u 4xui0Lbr-T8;kywY~Z\UQQmz֥~STRRkytb`au 7'NjUN<:v쨜JOOopwogdd^4;C(ԮcyܯK)dn-ö:2{z]k"bt(S?z欻WHlTEE\. Ceee$)k7PmbjzܕK:{^TjvHR!Z111*++* C]u 4x.m11Q:~x𵼿j{yyyj߾W1TEEEU-4''G5ONNV||rss\VΝhiwuQ]O󌧹_S$F"IntSt$szawE(d1^Gb6>Hv]ڲe Pcyɤ^zi ÛGլYr93ڷoz]߇K1Lko\Zz~X`0+Ν;\7߯ &nk]uU3% DWWEvC#ݫ.]T˸Ф**[S?WuJIK$KvR3ҥpB۲xn!uKK/~R^|Eo… t]F?>M}S[K.ήyocǎZnfΜdf{ jX;D͓U^&Oܨ[oI… =Өu]Z&m7]uQ}:>SP2eMoR"cRuQcݱ҉%@Kup2ecܮ.nB&9.nH,B EM$v!"&d˾};ahǎ" 뢐I,D6ly:ԺZ#G;$ns>'UKkZ Yj`0d2l6l;ucIg˒9N#HV\.X@ sNI***$INZ={襗^RYYN˵h"۷:xx`7t-[{N;wձcG7:`0hҤI袋ceddhر3 M0A۷OIČ%@fS^|N*%Khl6G'B6ͯ:%P.KFQr\+ HKhA.2o~1dff-TPPyiܸqZ h֭[3g*99Yiiil5X\cjQ L̜9<Z޳~jʔ)Ni: {u5Z@qBb %/$-}'BڡCt]wt;SOt!͝;WEd4uE馛nRjjjNOOs=נ}k矗OO?-٬2-]T~U+t:e2$ t5h/&&FCO?-YiӦi͚5*((UVVŋkϞ=2Lĉe24ZV-_\YYYrӧ&OHIf;C,UTT())I'O?/Iz$I&LСC\\\\o,~֬YROvg*/+WPiii:uڷo_TTTEJIIѠA&נIJT6m҅^Xe~~XfY&I4w\l6=ZjƏ_Er`+w}W&M$*))~;%&&ĉЬY4w\ljme׮]={gʕ+̫$)++K="""So|A__tt|Il6 @@޽[ӧk-{|A͜9S>vf̘Qe1c9sF{ѸqdX#Gj֭-))QVVnFEGG+**J#FЎ;l曕(IJMMUIDATXƌSeg}U|ƍhf 4Hj3g￯u]kԿz4cO9+̙3T%KNNVqqqv5w*vn$Imڴ%\cm{}U!)Y5m J$ԩSJKK$UV={gF\N<:Tf0KmkۿN:s;[a}]SEEvZ]uU5ӧVX2Iggw-IS߾}|r't)J:tիe<333ϛcQKzU7ڹVX_M>]/C=$ѨL;ƲSN;CGyDv] 2dwokΜ9JJJաC :TO=$i2dHb֭{1O>U_};믿fgg{U7ҹ kt[,婠@v$_Q S ,w^'_ZZ<7vjܟ+i=4lƻ>GQbbbГJ@VڼڵkWOmzs+lPf,N'xB_~y0&##C/hQvޭMn7}+lw*@s@Sh~>A}2͛#N@31x`awaXnn 4H$!+*tGFFJ?ġ\ IЎ; 9t6$Bf$OR)XVL08׹ e K[IENDB`lensfun-0.3.4/docs/website/calibration.md000066400000000000000000000033261445356770400204160ustar00rootroot00000000000000--- title: Lens calibration linktitle: Lens calibration layout: default weight: 5 --- If your own lens or camera is not part of the database please check http://wilson.bronger.org/lensfun_coverage.html for a daily updated list covering the status of the current development version. Maybe it is already there and your local Lensfun database is out of date. If your camera or lens is even missing in the development version please request an entry for your camera in the Support Ticket Tracker. For new lenses, the preferred way is to upload RAW images at Lensfun's calibration service. Lensfun's database maintainer then creates a lens profile, includes it into the database, and sends a copy to you. Alternatively, you can do the calibration yourself. Below is a list of several tutorials that can be used as an introduction. Which method you choose depends on your experience and on the effort you want to spend. Please upload your new profile to the Support Ticket Tracker or send it to our Mailing List and we will include it in the offical database. Lens calibration tutorials: * Torsten Bronger's tutorial and supporting python scripts * Hugin's lens calibrator tool * Original Lensfun tutorial on this website lensfun-0.3.4/docs/website/development.md000066400000000000000000000013611445356770400204460ustar00rootroot00000000000000--- title: Development linktitle: Development layout: default weight: 7 --- The source code is available from a git repository hosted at Sourceforge. You can check out the current head revision by >$ git clone http://git.code.sf.net/p/lensfun/code lensfun-code The build system is based on CMake. Enter the Lensfun folder and create the CMake build directory: >$ cd lensfun-code/ >$ mkdir cmake_build >$ cd cmake_build/ >$ cmake ../ Beneath many other files this should have created a Makefile that can now be used to compile and install as usual with >$ make >$ make install More information about the build system and available options can be found in the README file in the root folder. lensfun-0.3.4/docs/website/faq.md000066400000000000000000000050621445356770400166750ustar00rootroot00000000000000--- title: FAQ - frequently asked questions linktitle: FAQ layout: default weight: 6 --- * __Why is my lens or camera not automatically recognized in image editor XYZ?__ There may be two reasons: 1. The camera and lens are not in the Lensfun database which is available on your computer. On Linux Lensfun is usually installed system wide by a package manager. On Windows and Mac Lensfun is usually shipped together with the image editing application. Please check for updates! 2. The image editor was not able to properly read the EXIF data from the image. Most open source programs today use the exiv2 library to retrieve the camera and lens information. You can use the command line tool `exiv2` to see if the retrieved information is correct: $> exiv2 -pt 2938031.jpeg |grep -i 'lens\|model\|make' * __How do I know if a certain lens and camera combination will be recognized by Lensfun?__ Please check the list of supported lenses for the latest release. Before you report a missing lens, camera, or even start calibration by your own, please also check the list of lenses of the current development version at http://wilson.bronger.org/lensfun_coverage.html * __My camera and lens is in the list of supported lenses but my image editor does not recognize them?__ Probably the Lensfun database on your computer is out of date. On Linux, Lensfun is usually installed system wide by a package manager. On Windows and Mac, Lensfun is usually shipped together with the image editing application. Please check for updates! * __My lens should be supported but the camera is missing. What can I do?__ The camera entry in the database only holds crop factor and lens mount. As a workaround you can simply select any other camera with the same lens mount and sensor size or crop factor. * __The lens is wrongly identified by the image editor as a different lens than I have actually used. Why?__ Most open source programs today use the exiv2 library to retrieve the camera and lens information. You can use the command line tool `exiv2` to see if the retrieved information is correct: $> exiv2 -pt 2938031.jpeg |grep -i 'lens\|model\|make' If the lens name is not correct in the above output please report a bug at the exiv2 issue tracker lensfun-0.3.4/docs/website/imgs/000077500000000000000000000000001445356770400165405ustar00rootroot00000000000000lensfun-0.3.4/docs/website/imgs/logo.png000066400000000000000000000531101445356770400202060ustar00rootroot00000000000000PNG  IHDR,yIsBIT|d pHYs H_tEXtSoftwarewww.inkscape.org< IDATxw$WyT3fVFJB$A &k5tƘ`,6\dadIsݕZ6N\u{gb穩:/9۔R_d KXgoVxg KX"LXg4`_%,aN /Y B6+rՎ-a K8gFǟyxȟ:Xo}:#SJXĂֺ )`}h& O@7Jy>t,ұ,a KxAk}0Ocimh  ~SJM[j*\n` I@*ZӅTH*"~+\.5)Z;]u'*PdRn0Z8|Rjݫ/֫҅2yۀ{RyyQJo`+pRKPJ_ xPZ߄%o*=;AkamLgu"%lX)gW@-ZD?h,G]w>9:ߙKJ95n;b.V o*ӝJOR)5ݸ#I-7a-Ovľ!z1ܽJ7`U)ޮ>K\/>|Lk}V͹+Qa=Zk%V*JCw5~7G)o1 -|Z'Ru^m’#ǵw=){so(Ī:ނ%`cJZ}RZ`ӆL~^gǒ=X{SMQ1 6jQTS AX =J_Fv7C)?/ !xUhHIk}8O"ؘF+Մg|b'{L+g4ª1]\ <{u}!ؽ,W5^j/RJ=0߀'|gh7uRX ~1!3O;ߥ"{AQut!i>kIuGYwoZK/DX26؇CX VxG+hP\ֺKd+ϕYl$p RJ@g1 콳PJű{UZnaZ_uCc7\Gu}ocʕRjTkU5ZahncUmǁq%h2 ,&aݴu_4 +=P%|"ZMUJVJݢzAIQ߻/>}^X ,䱞 6o| 6Qx-oc^*eIX:-5zs)<-an| k!vcb ]醅 \O@|>b MXǖj*a ?RjC8! =,E |>f뇇*I42aǀanYKxLjc9-`Uq36vҰ֫!%y䆇lbRny=y[,{vڵzhի8D,L_˖o1;22x#a-vu*"jp%,vRJעѩ-t%J#`F397o3׹} dpp\T*d2I2f)=ʑ#G8q:`߼y.w_wuxuVcX>D}TÏ?Y#i ݡk6|d6ưbŊ2IRke\qbJUÖ-[d2e]566K:|-۵JXIu\^%z|"zTJ;Rc-[T-o rr_޽{<)O/.~ Vuttpgp饗r饗ϑ#GNs]om۶kxxݬI~"w샫lXB)5/@)Ok6 !nx^0/q]U?ccV. "z륯ty蠣t:M*"p5p5H,1X24Ɣ¿N Qq1n=9k\8Dg{;ek`/V8jPJx:*!]Z7< sB!P{:묙ƛ?:tL&ӱuV6mڄq2>^00Ɣ|t+Lg2:{꦳V4?z[IDtU*fittL&C.T*qs nv8Cׯ_J9qrK)1]O3$MƘ`1&.;sR]tQ$aˆۊ˔Rpm :y&!f!&R;JƘ_dY.0MޤbBK_zÇ7$ V^Mww7qSa:Rp31<|2tLe:[b:Wb&#satbtvvՅwcccq8q]vŅWtMNOO5wy|^jb=VJ}-lBg98Ol5X ƘBx,)%Z%z({1`g'Xn fS3l&CwW!(JU$~z:;;aY;vx=ywW۶~O_ ~[bgcI6&ѿdt?DXTIk[%{Zہ!poO;v,>00^H"=o} @ A:rۑtJ π$.z6ZO~ɇ݅5R_~9z+ڑ翲m۶w޽8m6iΝ{Yk׮BBRXé(a-ٰAXay'ip9lcǎmܰa\rI]*J;~'O24/Gv.GJ峓'碑t$#ㅔqwBJLzӟPL.cbbl6["H\ve 2::n||g}\@&0=oaazXc8,dxx{zzG=sÆ wyu\.ljQ<'MznPEP҉UI<4e,[*SM۹-/"K%1 EqfժU?~|/F mVyDKDXSkz.3<<,'''Gs7qDZIѕljSH" L<)Y ˎu ,,aI ط\bN<Lm !CCCtwwss:<<\3PʱDX$DX#(' V'8d2Ʌ^X#Yc`jj gKc "Y%9U ,[ +LTLL'&Q )aEAvԵQb1vI<WLMM}9Z JU"yxڰLX*ھ}> ;wج1aUԽĐ#H!p ሲ4VHcդ"/!A!H2gv'Nٴv\iĖY +%e)Tqw$$H !p$ )6(_’b fY.DZ T_q}V/ۉ;vIguVl-JozQlJ.aZeQ w|DkMX~ZwS2?ҷUDK|,t?޲(noL%Z+C5{h_>ZJ)uG+;%'8&o jRId:B:&,Id]0cmSHAJ1A1$c)iKC2  &!.!&%+:y݅q ##ߍ1xyVbs=Crڲ$e[mZOe629_c'Y|S-87o{M^7<<|3CX4&xHXQRXCZ|uƯvRvwBkpF|M-*aa$ԢYh{]MkQ߇QJWQ+%ynJTSz$̹===]kC$I+לFЋHuI$8bdLA*fJ[K J$%$bV(Z;3_$2P)=yNH:VZڸX\@6avvBPNg֭r9:۱ݟaqXOš|_Yw)KZOOVAxIkJV/`C zߧn.mkLY]-z VZy h79mAhԯ-&~_ K.dF%5oah֛`sVJ ?c1MֺxkȟEؒ7αeqHf&,AUPC7Q-P9ac R4Ɯ4ƜBB<樂''b8~ז&&&~|eǮ]кCLOO-& B"UnU.)%Hr%AgܐtIiH H:0ą({ -qzc]Hyd$ MFg|Ox2\|?d2tttyG-Ox_|xBcBcH$Z !n8sg#)/a52*ՌZjĖn ?PmG2XhRZ` ΡZUXF*^="O |o)$TJP1?>̕;׶j |cǎm* WvQ6^(K)X?cZĆ )V s.)滎VK+uV W5J;4 TG߇Z[#\333l6[azzc Yv|RN6F*&) )i+!!X H)pA\& pQ p|B_!/e#n a QEFUa͓33W?A*Vϟqxx}11柁Zo1FTByR3a>pgs֗S+]}G)uP.l&wRj@(z·}{,a;\$cЄjCZZ?ZbKXR*?l [9=R >2,Z\AY,T@ȑ# !%+ 1 0B@CE1RzW"ap<+<@R STȔɪ"eKXKYcrP^O&{S988Hwww`k؀ꫯv&կ3|1c(G]Zx sbOi߯ߥR*Vª|ZVS= ~2آcu5 T0LX$0z [%iڰar9yxW  m·9K`|!Gw{Yb|J lsc\cI)}P%e".QpYaX s\|rmp:2 a6 UZg{n:|-2Մ>L}m\jo^Tj#bGέ>PBjQ&@8!|VJ226z Ӎ0ML&sVK󼲄U(rULG@\x`/ L@&C)HY!Bz/\ #)c!/έNXu>fff٦ʹfjK%kXF h8P۾'2o7; 2`Íu2U'VR}<ROQ VJmSJQ)u6VcmkQKX mFacLXRIe2elE0ar91䊭Q'E`HC %⡨RAj$ "+a:\^vQ D Bk}3VCa3@9I5yĦDj37{*6! ֫%:*P}BXojao3N蘕euu~k`Ba{X,W VPDoD9gπ4HcvGز.OXeyH T7,Exc(X/` «G IQ [HX^!ϗ,R)٬>=e 4Ӳצz/WHJG]vT{P,ٳ.QDfo/[ y{4%V5uaͶiO|^T`h^ڣzwzX,^ EAԢonV)u~kGkJt kѲu>.an U@Sg-?ZTd|GLҎGwHODw&-_ަG[j}FGXqװUVv2|oV l'?yIwwwa+dzzB}c%&s0LI+Ir獃#$@bpɆ {OAT@ZNtg<<J[Ȭ9P<\Wyu x* C{!*?cBovRSZgcM iVzR{n#hVFwZyϣlЎՄ\@88:CXmw+vd<2W]u'Nl}3m\gMwww4g}"{:aHJJ-HsKĐeRJXV26fv^ yWْ e@$HTØc[jy9h`ړq@s8묳ʊeO:ڵVdnbIXV֛":YXI$ aPF5|c"ygQ,ĆU_O֟> Z닔Rb`– {l`׹4G6vb\KLתLJ9Y,q]DZ Ƙr3Ƥ,QyT! 27}56ީ$m,VԳW6g#lk/cղ #5[+-UL*eL@[o`{{mNLeK>=V\IOOW^y%CCCR)y:) Z/ߜ a-jf  Fid:7B#5(*([} K X67}Y a=!(ngl4|7B0f83*Ch"WS!F?{F ,PBP EWPDs-85[ FP QεKr_" w f:Xf ^VV%d2,b}>|׾<܎-46 u.VV방%gα0LԯZ~f햹R_Ş\l^;e>rk&ZY"_6R}k42:1/SPIA "aMJY&$]'C4]v 5W}wG\ȺD˗-Yn+o!qEHӿJ`ȘOY`=yz!> 2c < ߯P.pazE"W{G~ {JKR̶C [~>;(6\C)6ld٩ETM^(yMP_YTވ`mFsٯ`q..LB-a" qyՓku ףb%Ȼy|Pt%!zJ2u6̡TrCgW_ER:JG5V8t*VpǙRJϔRo <]Wk?|[7Tz> ѣ3`72%+*BO}w佐>dopl9l(aWJRVJ=k>\ ~p:0Y {IEl}r#k ʍz٣7IX|x}6}H5mhwA%mRYKYãZBװ KJ`,:.eOڮʾgC orE.spC\(i?#f(a%ߞΘLAT1 +ϣFګR+j! V*Cԃlj9yLX0T׮Kk\lޣ 5+ 8ͤ[ll1Atp{RjOT 撰Ggx<ĸ(a=V"/l6+bR2a% S1 &ۍ%7ywp $S*y8A: 1[V)_{LETyIڞVMZe-%HD27(ΐ!dY8DJ@)wﳰVbv+ڠvn :8ׂ]DU Sjh+qjj[G>s׎J `NXXlD¾{JRLOO#NޏYu",'3-+sdyׯ.<[9@ۉW<u '2FWCDULfP|@/O>T>`W㌏?JJU󵯯j/aejVW`SZwjE"j<xqmzZӛX|{fBc ]X2 Gfe%pͤ3-a8-t:P(€8҉!}`076ci'SFQp=WEץ躸w])<ecՓGNRazTD&EW3 ^VJ篥8,fm([%_%JS&2$lяr]ܒo4U }rLVƗKZˣ3!ͻTbV- XšСCttt|Ӽџ6V=,ӿKuJ,%,A4f[l/6Tjc7(V[ @CGXOk$jɸ| ]c%}ZUJETKGV*^GFFoذ>q.j +H b& ^+I)BH1΄a2I w R b[]:Rrʎ?p:\ChȖ ٢!W=r;ιq I#lrtzv(7\\~l y +KWXɲ9 VkJujI4`Dk|aWJ=^vl~^+KXGBE;_pj]R;jKAgG3c{)>J }q:bá7Г$]IkZ'+vM j[Rt'+: S_{^|К6NF`:XK 6i+ku6_:^-(6MnR[{+ hKJ*"CXV3t&D(z#i=3jj"ale*ttt\|kuֱl2+WL>fgyLlaJt&%MLͫZZ;;TAt%$!_pJr=za:qx۳xʖncܶotVu9}y3V9}EW]Uh|޻8t<{!ɐN7>حfa*.EOxcG:*T>܁~bI?-s/CCC][ CBqݸ˶@D%VuKM<aƨA_j/6US|js {/odppm۶m6.R7WXiR0_݄^d) W0 u~|,xkȗGm|Q#~Q)|ڟv=)W)C[?v7Xu@d'ߝK8jSo+} ~l: 9VS ։T_)uRJ);Toytuu޽؞|DԁX9 4Wv86UYP*^߽eSɬ[gEC"+bL\R0's_J =7'> /[c"qqĖֺFUBXDSqnAu~i뱥%RwXID<NWJ]dK>Qf=QM.%Tu3K):u;_u+/Rzy}|}~O=[)C)JGR7)k+We&Y`vy;b*>*KCoT|rnޔd"듘\"P-T8TKPlʞ't(Hc 8iOیily=Zo&F>/aP[vֺϲ?Vej[[ݸuʸB;(+J){q^ x-0jZl7FߵF+C.,73RgFx%V9('CCԧR4lt=}}}'[qKZIRKJa ),ԑŸ됖 &2j!.:X4H*UqNWdJt6IDATX6_#˱o>naR(ނއ-97Ș){pٰZMߩhLmG56?vO~ECNkv.2?Ja>7ONF[}t!iAF[! uw߲iӦ&''_x}q9}:}LL yQqڻՄBy"r6l؀yh{pTu?wHHŖdd*vlDyI%id4M!C6ӡM3Ƶ4iLb8KfLLMU*yD#0aZWZB>ݽ;Q8XA>bddX<Έ>V1R<a4n% r6= )-xyV9%W.IGFr2Ν;訴ré X?αcxw"+*c0E0%hW Aj#ܦpݳaⲲe%;o 1qQ8r1c].Ww"~';xX[[K]][l|t(`^Ex3ef`#V `paڷCFp)1CTTT0sez7nٳɓ'immHh>pĕ*-^ eֺ i:) Ջçȗ3Kb˲J卩eYo9b9x-ZtHYݻw/z|)I^/^rbD"0K fOoR__NS\E(r6mX󽽜イ|ӦMr-B!fϞMCCKJẍ́Bg"7>8g=}j9tg XSS lDu/pJ4曆:|zXR)utt0::ڔH$-˺k%-?&d [S [r}Gݱ`&x׮]L6 ?Tn|+KgϦJqCۦfΜɓ'ٻw/O,Y]n]xڵe9`'Wj-C$"k'}*#7٬Z߆{^Fzp}c[q+-j64#reYaEu1FcBK,wH~s_~y_$izH{q͛7s >|x̗*|>~}o044ĴihWmmm߱cKc1_ PUc;87e}ZF,WE S  B-7,-cV˲8qƍ3pW!Y}^u̚5V]o[TWWS]]&III %%%)åK(/[W^yjjj~\ZZ-iop!ą---n߿߲bX΃imZ)ú$h227m?ga0{?2ƴ,o90!khh:+r~QFk]#9rȏӧspppc__E+"c˾_ /^ܝ{C&L}/9V.DQD~M\8|>hylel SVٷ x`k 3f|axxxp8|GwwwIww7gLY\\߱O>Al#X%Iw>ξ;oc,ZV˲!]wA3@ fʰҍZߊ/!W;yFj,2ZʩO9L^g}[P3{'NrСJ 7X,6cҥ+gΜy(Hccy<v\EEEᢢw\+ iW!ћ$灿nii*7ƘP0Ƿ666NS~is&)^Z)RCQ ֵ R?)c!7R~WJ.:ͤ8uځm3g| V0L52BUSڛ;::vFo[/ >_C Rߕ q-R7!-ZF"s eVucCMr$;ʷWTanڶ-qȎM) \'88[ٲFNUjI ZY@).r~5>4jD!CJݤq8H2鴃CV/(Rwfz4*$w6ZɎ YN(' ԏ^L$ѭ͸1׈ȒoR*ir?ҹ\k=S*؀O22ɗos\g_'<‡.YK<-D}}u oq9"ҁ>XN#Jf< Rk } ghFi#]8.7het9@O]H #s|F fj[)Z{Y`M}rd^l . 2LxLg|@oksRyb?qGʟSeu1#jdmwcCU)u=̖f"#rCQJUׯ@JI?TJ=}tFdw SJG&΅ﲏUȶ>H95%ԱO{ﳏܦ㚏f pu9D:0̹KHq9&GkY1!vϥn;J Xv6."8X#\Pc/6#; TΞNrpph!7>d:Oqppp[@,~O'`988| zH?{^1lmIENDB`lensfun-0.3.4/docs/website/index.md000066400000000000000000000020361445356770400172330ustar00rootroot00000000000000--- title: Welcome! linktitle: Home layout: default weight: 1 --- This site is all about the Lensfun library. What is it, you may ask? Digital photographs are not ideal. Of course, the better is your camera, the better the results will be, but in any case if you look carefully at shots taken even by the most expensive cameras equipped with the most expensive lenses you will see various artifacts. It is very hard to make ideal cameras, because there are a lot of factors that affect the final image quality, and at some point camera and lens designers have to trade one factor for another to achieve the optimal image quality, within the given design restrictions and budget. But we all want ideal shots, don't we? :) So that's what's Lensfun is all about – rectifying the defects introduced by your photographic equipment. --- ## Latest news ## {% for post in site.categories.news limit: 2 %}

{{ post.date | date: "%Y-%m-%d" }} {{ post.title }}

{{ post.content }}
{% endfor %} lensfun-0.3.4/docs/website/lenslist.md000066400000000000000000005153121445356770400177670ustar00rootroot00000000000000--- title: List of supported lenses linktitle: Supported Lenses layout: default weight: 4 --- The following list includes all lenses and compact cameras that are part of the __database shipped with release 0.3.2__. Before you start to calibrate new lenses or report missing cameras please check http://wilson.bronger.org/lensfun_coverage.html for a daily updated list covering the status of the current development version.
manufacturermodelcropdist.TCAvign.
AEEAEE SD19 & compatibles6.0yesnono
CanonCanon EF 100-300mm f/5.6L1.0yesnono
Canon EF 100-400mm f/4.5-5.6L IS USM1.611yesnono
Canon EF 100mm f/2.8 Macro1.611yesnono
Canon EF 100mm f/2.8 USM Macro1.0yesnono
Canon EF 100mm f/2.8L Macro IS USM1.0yesnoyes
Canon EF 135mm f/2.0L USM1.0yesnono
Canon EF 135mm f/2.8 Soft Focus1.267yesnono
Canon EF 16-35mm f/2.8L II USM1.0yesyesyes
Canon EF 16-35mm f/2.8L USM1.0yesnono
Canon EF 16-35mm f/4L IS USM1.005yesnono
Canon EF 17-35mm f/2.8L USM1.0yesnono
Canon EF 17-40mm f/4L USM1.0yesnono
Canon EF 200mm f/2.8L II USM1.611yesnono
Canon EF 200mm f/2.8L USM1.0yesnono
Canon EF 20mm f/2.8 USM1.0yesnono
Canon EF 24-105mm f/4L IS USM1.0yesnoyes
Canon EF 24-105mm f/4L IS USM1.611yesnono
Canon EF 24-70mm f/2.8L II USM1.0yesyesyes
Canon EF 24-70mm f/2.8L USM1.0yesnoyes
Canon EF 24-70mm f/4L IS USM1.0yesyesno
Canon EF 24-85mm f/3.5-4.5 USM1.0yesyesyes
Canon EF 24-85mm f/3.5-4.5 USM1.611yesnono
Canon EF 24mm f/1.4L USM1.0yesnono
Canon EF 24mm f/2.81.0yesnoyes
Canon EF 28-105mm f/3.5-4.5 II USM1.0yesnono
Canon EF 28-135mm f/3.5-5.6 IS USM1.0yesnono
Canon EF 28-300mm f/3.5-5.6L IS USM1.0yesnono
Canon EF 28-70mm f/2.8L1.611yesnono
Canon EF 28-80mm f/3.5-5.6 USM IV1.613yesyesyes
Canon EF 28mm f/1.81.611yesnono
Canon EF 28mm f/1.8 USM1.0yesnono
Canon EF 28mm f/2.81.611yesnono
Canon EF 300mm f/2.8L IS II USM1.0yesyesno
Canon EF 300mm f/2.8L IS II USM1.6yesyesno
Canon EF 300mm f/2.8L IS II USM + EF 1.4× ext. III1.0yesyesno
Canon EF 300mm f/2.8L IS II USM + EF 1.4× ext. III1.6yesyesno
Canon EF 300mm f/2.8L IS II USM + EF 2.0× ext. III1.0yesyesno
Canon EF 300mm f/2.8L IS II USM + EF 2.0× ext. III1.6yesyesno
Canon EF 35-105mm f/3.5-4.51.611yesnono
Canon EF 35-105mm f/4.5-5.61.611yesnono
Canon EF 35-135mm f/4-5.6 USM1.611yesnono
Canon EF 35-70mm f/3.5-4.51.611yesnono
Canon EF 35-80mm f/4-5.6 III1.611yesnono
Canon EF 35mm f/1.4L USM1.0yesnono
Canon EF 35mm f/21.0yesnono
Canon EF 400mm f/5.6L USM1.005yesyesyes
Canon EF 400mm f/5.6L USM + EF 1.4× ext.1.005yesyesno
Canon EF 50-200mm f/3.5-4.5L1.622yesnono
Canon EF 50-200mm f/3.5-4.5L1.0yesnono
Canon EF 500mm f/4L IS II USM1.0yesyesno
Canon EF 500mm f/4L IS II USM1.6yesyesno
Canon EF 500mm f/4L IS II USM + EF 1.4× ext. III1.0yesyesno
Canon EF 500mm f/4L IS II USM + EF 1.4× ext. III1.6yesyesno
Canon EF 500mm f/4L IS II USM + EF 2.0× ext. III1.0yesyesno
Canon EF 500mm f/4L IS II USM + EF 2.0× ext. III1.6yesyesno
Canon EF 50mm f/1.2L USM1.0yesnono
Canon EF 50mm f/1.41.611yesnono
Canon EF 50mm f/1.41.0yesnono
Canon EF 50mm f/1.81.267yesnono
Canon EF 50mm f/1.81.613yesyesno
Canon EF 50mm f/1.8 II1.611yesyesno
Canon EF 50mm f/1.8 II1.0yesyesyes
Canon EF 50mm f/1.8 II1.267yesnono
Canon EF 55-200mm f/4.5-5.61.611yesnono
Canon EF 70-200mm f/2.8L IS II USM1.0yesnoyes
Canon EF 70-200mm f/2.8L IS USM1.0yesnono
Canon EF 70-200mm f/2.8L IS USM + EF 1.4× ext.1.0yesnono
Canon EF 70-200mm f/2.8L USM1.0yesyesyes
Canon EF 70-200mm f/4L IS USM1.0yesyesyes
Canon EF 70-200mm f/4L IS USM1.613yesyesno
Canon EF 70-200mm f/4L USM1.0yesnono
Canon EF 70-200mm f/4L USM + EF 1.4× ext.1.0yesnono
Canon EF 70-210mm f/3.5-4.5 USM1.0yesyesyes
Canon EF 70-300mm f/4-5.6 IS USM1.611yesnono
Canon EF 70-300mm f/4-5.6L IS USM1.0yesnoyes
Canon EF 70-300mm f/4.5-5.6 DO IS USM1.0yesnono
Canon EF 75-300mm f/4-5.6 IS USM1.611yesnono
Canon EF 80-200mm f/2.8L1.0yesnono
Canon EF 85mm f/1.2L II USM1.0yesnono
Canon EF 85mm f/1.2L USM1.0yesnono
Canon EF 85mm f/1.8 USM1.0yesyesyes
Canon EF-M 18-55mm f/3.5-5.6 IS STM1.613yesyesyes
Canon EF-M 22mm f/2 STM1.613yesyesyes
Canon EF-S 10-18mm f/4.5-5.6 IS STM1.62yesyesno
Canon EF-S 10-22mm f/3.5-4.5 USM1.613yesyesno
Canon EF-S 15-85mm f/3.5-5.6 IS USM1.613yesyesno
Canon EF-S 17-55mm f/2.8 IS USM1.611yesnono
Canon EF-S 17-85mm f/4-5.6 IS USM1.611yesnono
Canon EF-S 18-135mm f/3.5-5.6 IS1.613yesyesno
Canon EF-S 18-135mm f/3.5-5.6 IS STM1.613yesyesyes
Canon EF-S 18-200mm f/3.5-5.6 IS1.62yesyesno
Canon EF-S 18-55mm f/3.5-5.61.611yesnono
Canon EF-S 18-55mm f/3.5-5.6 III1.611yesnono
Canon EF-S 18-55mm f/3.5-5.6 IS1.613nonoyes
Canon EF-S 18-55mm f/3.5-5.6 IS II1.611yesyesyes
Canon EF-S 18-55mm f/3.5-5.6 IS STM1.613yesyesyes
Canon EF-S 24mm f/2.8 STM1.622yesyesno
Canon EF-S 55-250mm f/4-5.6 IS1.611yesyesyes
Canon EF-S 60mm f/2.8 Macro1.611yesnono
Canon FDn 100mm 1:2.82.0yesyesyes
Canon FDn 50mm 1:1.42.0yesyesyes
Canon FDn 50mm 1:1.41.534yesyesno
Canon Lens FDn 24mm 1:2.81.529yesyesno
Canon Lens FDn 50mm 1:1.81.529yesyesno
Canon Lens FL 135mm F3.51.529nonoyes
Canon Lens FL 50mm F1.41.529yesyesyes
Canon TS-E 24mm f/3.5L1.0yesnono
Canon TS-E 24mm f/3.5L1.622yesyesno
Canon TS-E 45mm f/2.81.0yesnono
Canon TS-E 90mm f/2.81.0yesnono
Fixed lens IXUS 220 HS5.58yesnono
Fixed lens IXUS 80 IS5.9yesnono
Fixed lens IXUS i4.843yesnono
Fixed lens PowerShot A4000 IS5.6yesyesno
Fixed lens PowerShot A5206.05yesnono
Fixed lens PowerShot A6104.8yesnono
Fixed lens PowerShot A6404.79yesnoyes
Fixed lens PowerShot A650 IS4.67712yesnono
Fixed lens PowerShot A720 IS6.03yesnoyes
Fixed lens PowerShot A856.5yesnono
Fixed lens PowerShot A954.85yesnono
Fixed lens PowerShot A954.85yesnono
Fixed lens PowerShot A954.85yesnono
Fixed lens Powershot ELPH 110 HS5.58yesnono
Fixed lens PowerShot G14.843yesnono
Fixed lens PowerShot G1 X1.85yesyesno
Fixed lens PowerShot G1 X Mark II1.93yesyesyes
Fixed lens PowerShot G114.554yesnono
Fixed lens PowerShot G124.63yesyesno
Fixed lens PowerShot G154.65yesnono
Fixed lens PowerShot G24.843yesnono
Fixed lens PowerShot G24.843yesnono
Fixed lens PowerShot G64.843yesnono
Fixed lens PowerShot G64.843yesnono
Fixed lens PowerShot G7 X (3:2)2.72yesyesyes
Fixed lens PowerShot Pro13.933yesnono
Fixed lens PowerShot Pro90 IS5.28yesnono
Fixed lens PowerShot S1 IS6.56yesnono
Fixed lens PowerShot S1004.62yesyesno
Fixed lens PowerShot S1104.62yesyesyes
Fixed lens PowerShot S1204.62yesyesno
Fixed lens PowerShot S2 IS6.0yesnono
Fixed lens PowerShot S2 IS6.0yesnono
Fixed lens PowerShot S2006.5yesnono
Fixed lens PowerShot S5 IS6.0yesnono
Fixed lens PowerShot S5 IS6.0yesnono
Fixed lens PowerShot S504.843yesnono
Fixed lens PowerShot S5004.843yesnono
Fixed lens PowerShot S5004.843yesnono
Fixed lens PowerShot S804.843yesnono
Fixed lens PowerShot S804.843yesnono
Fixed lens PowerShot S904.67yesyesno
Fixed lens PowerShot S954.67yesyesno
Fixed lens PowerShot SD4506.05yesnono
Fixed lens PowerShot SD5504.8yesnono
Fixed lens PowerShot SD950 IS4.7yesnono
Fixed lens PowerShot SX150 IS5.62yesnono
Fixed lens PowerShot SX150 IS5.62yesyesyes
Fixed lens PowerShot SX220 HS5.6yesyesyes
Fixed lens PowerShot SX220 HS5.6yesnono
Fixed lens PowerShot SX260 HS5.56yesnoyes
Fixed lens PowerShot SX510 HS5.58yesnono
Fixed lens PowerShot SX510 HS5.58yesnono
CasioFixed lens EX-P7004.65yesnono
Fixed lens EX-P7004.65yesnono
Fixed lens EX-Z46.05yesnono
Fixed lens EX-Z7504.8yesnono
Fixed lens QV-3500EX4.8yesnono
Fixed lens QV-3500EX4.8yesnono
ContaxContax G Planar T* 2/351.534yesyesno
Zeiss 21mm f/2.8 Distagon1.0yesnono
Zeiss 28mm f/2.8 Distagon1.0yesnono
CosinaCosina 19-35mm f/3.5-4.5 MC1.0yesyesyes
Cosina Cosinon-S 50mm 1:21.538yesyesno
DJIfixed lens6.0yesyesno
FotasyFotasy M3517 35mm f/1.71.529yesnono
Fujian35mm f/1.72.0yesyesno
FujifilmFixed lens FinePix 38006.3333333yesnono
Fixed lens FinePix A3706.03yesnono
Fixed lens FinePix F114.5yesnono
Fixed lens FinePix F200EXR4.341yesnono
Fixed lens FinePix F601 ZOOM4.487yesnono
Fixed lens FinePix F770EXR5.43yesyesno
Fixed lens FinePix F8104.5yesnono
Fixed lens FinePix F8104.5yesnono
Fixed lens FinePix HS20EXR5.71yesyesno
Fixed lens FinePix S55006.491yesnono
Fixed lens FinePix S56006.03yesnono
Fixed lens FinePix S70004.487yesnono
Fixed lens FinePix S90004.48yesnono
Fixed lens FinePix X1001.523yesyesno
Fixed lens FinePix X1001.523yesyesno
Fixed lens X103.93yesyesno
Fixed lens XQ13.91yesyesno
XC 16-50mm f/3.5-5.6 OIS1.529yesyesyes
XC 16-50mm f/3.5-5.6 OIS II1.529yesyesyes
XC 50-230mm f/4.5-6.7 OIS1.529yesyesyes
XC 50-230mm f/4.5-6.7 OIS II1.529nonoyes
XF 18-55mm f/2.8-4 R LM OIS1.529yesyesno
XF 18mm f/2 R1.529yesyesno
XF 23mm f/1.4 R1.529yesyesno
XF 27mm f/2.81.529yesyesno
XF 35mm f/1.4 R1.529yesyesno
XF 55-200mm f/3.5-4.8 R LM OIS1.529yesyesno
XF 60mm f/2.4 R Macro1.529yesyesno
GoProfixed lens6.4yesnono
fixed lens7.66yesnono
KMZMC Helios-44M-4 58mm 1:21.538yesyesyes
MC MTO 11CA 10/10001.531yesnono
KodakFixed lens Kodak CX63306.593yesnono
Konica MinoltaFixed lens DiMAGE A2003.933yesnono
Fixed lens DiMAGE A2003.933yesnono
Fixed lens DiMAGE G4006.144yesnono
Fixed lens DiMAGE Z26.03yesnono
Fixed lens DiMAGE Z26.03yesnono
Fixed lens DiMAGE Z206.05yesnono
Fixed lens DiMAGE Z206.05yesnono
Fixed lens DiMAGE Z66.05yesnono
KM 20mm f/2.81.526yesnono
KM 24-105mm f/3.5-4.5 AF D1.526yesnono
KM 28-100mm f/3.5-5.6 AF D1.526yesnono
KM 80-200mm f/2.81.526yesnono
LeicaFixed lens Digilux 23.933yesnono
Leica D Vario-Elmar 14-150mm f/3.5-5.6 Asph. OIS2.0yesyesno
Leica DG Macro-Elmarit 45mm f/2.82.0yesyesno
Leica DG Summilux 15mm f/1.72.0yesyesno
Leica DG Summilux 25mm f/1.4 Asph.2.0yesyesno
LGfixed lens6.34yesyesno
MamiyaMamiya 35mm f/3.50.577yesnono
Mamiya 55-110mm f/4.50.577yesnono
Mamiya 80mm f/2.80.577yesnono
MinoltaFixed lens DiMAGE Xt6.5yesnono
Fixed lens DiMAGE Z16.545yesnono
Fixed lens DiMAGE Z16.545yesnono
Minolta AF 35-105mm f/3.5-4.51.523yesyesyes
Minolta MC Rokkor-PG 50mm 1:1.42.0yesyesyes
Minolta MD 35mm 1/2.81.529yesyesyes
Minolta MD Rokkor 50mm 1:1.41.534yesnono
MitakonMitakon wide MC f=24mm 1:2.81.538yesyesno
Nikon1 Nikkor 18.5mm f/1.82.727yesyesno
1 Nikkor 32mm f/1.22.727yesyesno
1 Nikkor AW 11-27.5mm f/3.5-5.62.727yesyesno
1 Nikkor VR 10-30mm f/3.5-5.62.727yesyesno
1 Nikkor VR 30-110mm f/3.8-5.62.727yesyesno
Fixed lens Coolpix 48006.0yesnono
Fixed lens Coolpix 50003.933yesnono
Fixed lens Coolpix 50003.933yesnono
Fixed lens Coolpix 54004.843yesnono
Fixed lens Coolpix 54004.843yesnono
Fixed lens Coolpix 79004.86yesnono
Fixed lens Coolpix 84003.933yesnono
Fixed lens Coolpix 84003.933yesnono
Fixed lens Coolpix 87003.933yesnono
Fixed lens Coolpix 87003.933yesnono
Fixed lens Coolpix 87003.933yesnono
Fixed lens Coolpix 88003.933yesnono
Fixed lens Coolpix 88003.933yesnono
Fixed lens Coolpix 9505.408yesnono
Fixed lens Coolpix 9904.843yesnono
Fixed lens Coolpix 9904.843yesnono
Fixed lens Coolpix 9954.843yesnono
Fixed lens Coolpix 9954.843yesnono
Fixed lens Coolpix 9954.843yesnono
Fixed lens Coolpix 9954.843yesnono
Fixed lens Coolpix P3304.706yesyesno
Fixed lens Coolpix P605.62yesnono
Fixed lens Coolpix P70004.69yesnono
Fixed lens Coolpix S33005.65yesyesno
Nikkor 50mm f/2.01.528yesnono
Nikkor AF 10.5mm f/2.8G DX ED Fisheye1.523yesyesno
Nikkor AF 105mm f/2.8D1.528yesnono
Nikkor AF 105mm f/2.8D Micro1.0yesyesyes
Nikkor AF 14mm f/2.8D ED1.528yesnono
Nikkor AF 18-35mm f/3.5-4.5D IF-ED1.528yesnono
Nikkor AF 20-35mm f/2.8D IF1.0yesyesno
Nikkor AF 20mm f/2.8D1.528yesnono
Nikkor AF 20mm f/2.8D1.0yesyesyes
Nikkor AF 24-50mm f/3.3-4.5D1.528yesnono
Nikkor AF 24-85mm f/2.8-4D IF1.0yesyesno
Nikkor AF 24-85mm f/2.8-4D IF1.528yesnono
Nikkor AF 24mm f/2.8D1.528yesnono
Nikkor AF 24mm f/2.8D1.0yesnono
Nikkor AF 28-200mm f/3.5-5.6G IF-ED1.528yesnono
Nikkor AF 28-200mm f/3.5-5.6G IF-ED1.0yesyesno
Nikkor AF 28-80mm f/3.3-5.6G1.0yesyesno
Nikkor AF 28mm f/1.4D1.0yesnono
Nikkor AF 28mm f/2.8D1.0yesnono
Nikkor AF 35-70mm f/2.8D1.528yesnono
Nikkor AF 35mm f/2.0D1.0yesnono
Nikkor AF 50mm f/1.4D1.0yesnoyes
Nikkor AF 50mm f/1.8D1.528yesnono
Nikkor AF 50mm f/1.8D1.0yesyesyes
Nikkor AF 60mm f/2.8D Micro1.0yesyesno
Nikkor AF 70-180mm f/4.5-5.6D ED Micro1.528yesnono
Nikkor AF 70-210mm f/41.528yesnono
Nikkor AF 70-210mm f/4-5.61.523yesyesyes
Nikkor AF 70-300mm f/4-5.6D ED1.528yesnono
Nikkor AF 70-300mm f/4-5.6G1.528yesnono
Nikkor AF 80-200mm f/2.8 ED1.523yesyesyes
Nikkor AF 80-200mm f/2.8D ED1.0yesnono
Nikkor AF 80-400mm f/4.5-5.6D ED VR1.528yesnono
Nikkor AF 85mm f/1.81.523yesyesyes
Nikkor AF 85mm f/1.8D1.0yesnono
Nikkor AF-S 10-24mm f/3.5-4.5G DX ED1.558yesyesyes
Nikkor AF-S 12-24mm f/4G DX IF-ED1.528yesnono
Nikkor AF-S 14-24mm f/2.8G ED1.0yesyesno
Nikkor AF-S 16-35mm f/4G ED VR1.0yesyesno
Nikkor AF-S 16-85mm f/3.5-5.6G DX ED VR1.528yesnoyes
Nikkor AF-S 17-35mm f/2.8D IF-ED1.528yesnono
Nikkor AF-S 17-55mm f/2.8G DX IF-ED1.528yesnono
Nikkor AF-S 18-105mm f/3.5-5.6G DX ED VR1.534yesyesyes
Nikkor AF-S 18-135mm f/3.5-5.6G DX IF-ED1.528yesnoyes
Nikkor AF-S 18-140mm f/3.5-5.6G DX ED VR1.523yesnono
Nikkor AF-S 18-200mm f/3.5-5.6G DX VR IF-ED1.5yesyesno
Nikkor AF-S 18-200mm f/3.5-5.6G DX VR IF-ED II1.5yesyesno
Nikkor AF-S 18-300mm f/3.5-6.3G DX ED VR1.523yesyesno
Nikkor AF-S 18-55mm f/3.5-5.6G DX ED1.528yesnono
Nikkor AF-S 18-55mm f/3.5-5.6G DX VR1.528yesnoyes
Nikkor AF-S 18-55mm f/3.5-5.6G DX VR II1.523yesyesno
Nikkor AF-S 18-70mm f/3.5-4.5G DX IF-ED1.528yesyesyes
Nikkor AF-S 20mm f/1.8G ED1.0yesyesyes
Nikkor AF-S 24-120mm f/3.5-5.6G VR IF-ED1.528yesnono
Nikkor AF-S 24-120mm f/4G ED VR1.0yesyesno
Nikkor AF-S 24-70mm f/2.8G ED1.0yesnono
Nikkor AF-S 24-85mm f/3.5-4.5G ED VR1.0yesyesno
Nikkor AF-S 24-85mm f/3.5-4.5G IF-ED1.0yesnono
Nikkor AF-S 28-300mm f/3.5-5.6G ED VR1.0yesyesno
Nikkor AF-S 28mm f/1.8G1.0yesyesno
Nikkor AF-S 300mm f/4E PF ED VR1.0yesyesno
Nikkor AF-S 35mm f/1.8G DX1.528yesyesyes
Nikkor AF-S 50mm f/1.4G1.534yesnono
Nikkor AF-S 50mm f/1.4G1.0yesyesyes
Nikkor AF-S 50mm f/1.8G1.523yesnono
Nikkor AF-S 50mm f/1.8G1.0yesnono
Nikkor AF-S 55-200mm f/4-5.6G DX ED1.528yesnono
Nikkor AF-S 55-300mm f/4.5-5.6G DX ED VR1.523yesyesyes
Nikkor AF-S 600mm f/4G ED VR1.0yesnoyes
Nikkor AF-S 60mm f/2.8G ED Micro1.523yesyesno
Nikkor AF-S 70-200mm f/2.8G VR IF-ED1.528yesyesyes
Nikkor AF-S 70-200mm f/4G VR IF-ED1.0yesnono
Nikkor AF-S 70-300mm f/4.5-5.6G VR IF-ED1.0yesyesno
Nikkor AF-S 70-300mm f/4.5-5.6G VR IF-ED1.523yesyesyes
Nikkor AF-S 800mm f/5.6E FL ED VR1.0yesnoyes
Nikkor AF-S 85mm f/1.4G1.0yesyesno
Nikkor AF-S 85mm f/1.8G1.0yesyesno
Nikkor AF-S VR 105mm f/2.8G IF-ED1.0yesyesno
Nikkor AI 15mm f/3.51.528yesnono
Nikkor AI 20mm f/3.51.0yesyesno
Nikkor AI 45mm f/2.8 GN1.528yesnono
Nikkor AI 55mm f/1.21.528yesnono
Nikkor AI-S 135mm f/2.01.528yesnono
Nikkor AI-S 180mm f/2.8 ED1.528yesnono
Nikkor AI-S 20mm f/2.81.0yesyesyes
Nikkor AI-S 24mm f/2.01.528yesnono
Nikkor AI-S 24mm f/2.81.0yesyesno
Nikkor AI-S 28mm f/2.01.528yesnono
Nikkor AI-S 28mm f/2.81.0yesyesno
Nikkor AI-S 28mm f/3.5 PC (unshifted)1.0yesnono
Nikkor AI-S 35mm f/1.41.528yesnono
Nikkor AI-S 35mm f/2.01.0yesyesno
Nikkor AI-S 50-135mm f/3.51.528yesnono
Nikkor AI-S 500mm f/8.0 Reflex1.528yesnono
Nikkor AI-S 50mm f/1.21.0yesnono
Nikkor AI-S 50mm f/1.41.528yesnono
Nikkor AI-S 50mm f/1.81.528yesnono
Nikkor AI-S 55mm f/2.8 Micro1.528yesnono
Nikkor AI-S 58mm f/1.2 Noct1.528yesnono
Nikkor AI-S 6mm f/2.8 Fisheye1.0yesnono
Nikkor AI-S 70-210mm f/4.5-5.61.0yesnono
Nikon Lens Series E 100mm f/2.81.0yesyesno
Nikon Lens Series E 28mm f/2.81.0yesyesno
Nikon Lens Series E 50mm f/1.81.0yesyesno
Olympusfixed lens3.933yesnono
Fixed lens C-4000 Zoom, C-4100 Zoom4.92yesnono
Fixed lens C-4000 Zoom, C-4100 Zoom4.92yesnono
Fixed lens C-5050 Zoom4.93yesnono
Fixed lens C-5050 Zoom4.93yesnono
Fixed lens C-70 Zoom, C-7000 Zoom4.8yesnono
Fixed lens C-7070 Wide Zoom4.843yesnono
Fixed lens C-730 Ultra Zoom6.52yesnono
Fixed lens C-750 Ultra Zoom6.03yesnono
Fixed lens C-8080 Wide Zoom3.933yesnono
Fixed lens C-860L6.563yesnono
Fixed lens Stylus 14.67yesyesno
Fixed lens X-24.9yesnono
Fixed lens XZ-14.68yesnoyes
Fixed lens µ-II1.0yesnono
Fixed lens µ-mini Digital6.0yesnono
fixed lens, macro (full tele): 12 inches lens-to-subject3.933yesnono
fixed lens, macro (full tele): 16 inches lens-to-subject3.933yesnono
fixed lens, macro (full tele): 20 inches lens-to-subject3.933yesnono
fixed lens, macro (full tele): 8 inches lens-to-subject3.933yesnono
fixed lens, with B-300 (full tele)3.933yesnono
fixed lens, with WCON-08B3.933yesnono
Olympus 9mm Body Cap Lens Fisheye2.0yesnono
Olympus M.Zuiko Digital 14-42mm f/3.5-5.6 II2.0yesyesno
Olympus M.Zuiko Digital 17mm f/1.82.0yesyesyes
Olympus M.Zuiko Digital 17mm f/2.8 Pancake2.0yesyesno
Olympus M.Zuiko Digital 25mm f/1.82.0yesyesyes
Olympus M.Zuiko Digital 45mm f/1.82.0yesyesyes
Olympus M.Zuiko Digital 60mm f/2.8 Macro2.0yesyesno
Olympus M.Zuiko Digital ED 12-40mm f/2.8 Pro2.0yesyesyes
Olympus M.Zuiko Digital ED 12-50mm f/3.5-6.3 EZ2.0yesyesno
Olympus M.Zuiko Digital ED 12mm f/2.02.0yesyesno
Olympus M.Zuiko Digital ED 14-150mm f/4.0-5.62.0yesyesyes
Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.62.0yesyesno
Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.6 EZ2.0yesnono
Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.6 II R2.0yesyesyes
Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.6 L2.0yesyesno
Olympus M.Zuiko Digital ED 40-150mm f/4.0-5.6 R2.0yesnono
Olympus M.Zuiko Digital ED 7-14mm f/2.8 Pro2.0yesyesno
Olympus M.Zuiko Digital ED 75-300mm f/4.8-6.7 II2.0yesyesyes
Olympus M.Zuiko Digital ED 75mm f/1.82.0yesyesno
Olympus M.Zuiko Digital ED 8mm f/1.8 Fisheye Pro2.0yesyesno
Olympus M.Zuiko Digital ED 9-18mm f/4.0-5.62.0yesyesno
Olympus Zuiko Digital 11-22mm f/2.8-3.52.0yesnono
Olympus Zuiko Digital 14-45mm f/3.5-5.62.0yesnono
Olympus Zuiko Digital 14-54mm f/2.8-3.52.0yesnono
Olympus Zuiko Digital 25mm f/2.82.0yesyesyes
Olympus Zuiko Digital 35mm f/3.5 Macro2.0yesyesyes
Olympus Zuiko Digital 40-150mm f/3.5-4.52.0yesnono
Olympus Zuiko Digital ED 12-60mm f/2.8-4.0 SWD2.0yesnono
Olympus Zuiko Digital ED 14-42mm f/3.5-5.62.0yesyesyes
Olympus Zuiko Digital ED 40-150mm f/4.0-5.62.0yesyesyes
Olympus Zuiko Digital ED 50-200mm f/2.8-3.52.0yesnono
Olympus Zuiko Digital ED 50-200mm f/2.8-3.5 SWD2.0yesnono
Olympus Zuiko Digital ED 50mm f/2.0 Macro2.0yesnono
Olympus Zuiko Digital ED 7-14mm f/4.02.0yesnono
Olympus Zuiko Digital ED 9-18mm f/4.0-5.62.0yesyesyes
PanasonicFixed lens DMC-FX96.05yesnono
Fixed lens DMC-FZ10002.73yesyesno
Fixed lens DMC-FZ1505.56yesyesno
Fixed lens DMC-FZ205.84yesnono
Fixed lens DMC-FZ2005.56yesyesno
Fixed lens DMC-FZ285.6yesnono
Fixed lens DMC-FZ37.6yesnono
Fixed lens DMC-FZ304.73yesnono
Fixed lens DMC-FZ56.0yesnono
Fixed lens DMC-LF14.67noyesno
Fixed lens DMC-LX1 16:94.45yesnono
Fixed lens DMC-LX1002.21yesyesyes
Fixed lens DMC-LX3 4:34.7yesnono
Fixed lens DMC-LX5 4:34.71yesnono
Fixed lens DMC-LX7 4:35.1yesnoyes
Fixed lens DMC-LZ26.06yesnono
Fixed lens DMC-TZ715.58yesyesno
Lumix G 14mm f/2.5 Asph.2.0yesyesyes
Lumix G 14mm f/2.5 Asph. + GWC1 0.79x2.0yesyesyes
Lumix G 14mm f/2.5 II2.0yesyesyes
Lumix G 20mm f/1.7 Asph.2.0yesyesyes
Lumix G 20mm f/1.7 II Asph.2.0yesyesno
Lumix G Vario 100-300mm f/4.0-5.62.0yesyesyes
Lumix G Vario 12-32mm f/3.5-5.6 Asph. Mega OIS2.0yesyesno
Lumix G Vario 14-42mm f/3.5-5.6 II2.0yesnoyes
Lumix G Vario 14-45mm f/3.5-5.6 Asph. Mega OIS2.0yesyesyes
Lumix G Vario 45-150mm f/4.0-5.62.0yesnoyes
Lumix G Vario 45-200mm f/4.0-5.62.0yesyesno
Lumix G Vario 7-14mm f/4.02.0yesyesno
Lumix G Vario HD 14-140mm f/4.0-5.82.0yesyesyes
Lumix G Vario PZ 45-175mm f/4.0-5.62.0yesyesno
Lumix G X Vario 12-35mm f/2.82.0yesyesno
Lumix G X Vario 35-100mm f/2.82.0yesnono
Lumix G X Vario PZ 14-42mm f/3.5-5.62.0yesyesyes
Lumix G X Vario PZ 14-42mm f/3.5-5.6 + GWC1 0.79×2.0yesyesyes
PentaconPentacon 50mm f/1.8 auto multi coating1.526yesyesno
Pentax01 Standard Prime 8.5mm f/1.9 AL [IF]5.53yesnono
Fixed lens Optio 33LF6.563yesnono
Fixed lens Optio 4304.85yesnono
Fixed lens Optio 43WR6.5yesnono
Fixed lens Optio 750Z4.843yesnono
HD Pentax-DA 20-40mm f/2.8-4 ED Limited DC WR1.526yesyesno
smc Pentax K 30mm f/2.81.53yesyesyes
smc Pentax-A 28mm 1:2.81.538yesyesyes
smc Pentax-A 50mm f/1.71.526yesyesyes
smc Pentax-D FA Macro 100mm f/2.8 WR1.53yesyesyes
smc Pentax-DA 12-24mm f/4 ED AL IF1.53yesyesyes
smc Pentax-DA 15mm f/4 ED AL Limited1.53yesyesyes
smc Pentax-DA 16-45mm f/4 ED AL1.53yesnono
smc Pentax-DA 18-135mm f/3.5-5.6 ED AL IF DC WR1.53yesyesyes
smc Pentax-DA 18-55mm f/3.5-5.6 AL1.53yesyesyes
smc Pentax-DA 18-55mm f/3.5-5.6 AL II/L/WR1.53yesyesyes
smc Pentax-DA 21mm f/3.2 AL Limited1.526yesnono
smc Pentax-DA 35mm f/2.4 AL1.526yesyesyes
smc Pentax-DA 40mm f/2.8 Limited1.53yesyesyes
smc Pentax-DA 50-200mm f/4-5.6 DA ED1.53yesnoyes
smc Pentax-DA 50mm f/1.81.526yesyesno
smc Pentax-DA 55-300mm f/4-5.8 ED1.53yesyesno
smc Pentax-DA Fish-Eye 10-17mm f/3.5-4.5 ED IF1.538yesyesno
smc Pentax-DA L 55-300mm f/4-5.8 ED1.53yesyesno
smc Pentax-DA* 16-50mm f/2.8 ED AL IF SDM1.526yesnoyes
smc Pentax-DA* 50-135mm f/2.8 ED IF SDM1.526yesyesyes
smc Pentax-FA 28mm f/2.8 AL1.53yesyesyes
smc Pentax-FA 31mm f/1.8 AL Limited1.526yesyesyes
smc Pentax-FA 43mm f/1.9 Limited1.53yesyesyes
smc Pentax-FA 50mm f/1.41.526yesyesyes
smc Pentax-M 150mm f/3.51.53yesyesyes
smc Pentax-M 28mm 1:3.51.538yesyesyes
smc Pentax-M 35mm 1:21.538yesyesno
smc Pentax-M 50mm f/21.53yesyesyes
smc Pentax-M Macro 1:4 50mm1.529yesyesno
Takumar 135mm f/2.5 Bayonet1.53yesyesyes
RicohFixed lens Caplio GX84.9yesnono
Fixed lens Caplio GX84.9yesnono
Fixed lens Caplio RR306.4yesnono
Fixed lens GR1.523yesyesno
Fixed lens GR Digital4.8yesnono
Ricoh 50mm 1:2.01.0yesnoyes
Ricoh XR Rikenon 1:1.4 50mm1.523yesyesno
SamsungFixed lens WB20005.69yesyesyes
Samsung NX 16-50mm f/3.5-5.6 PZ ED OIS1.525yesnono
Samsung NX 16mm f/2.4 Pancake1.525yesyesno
Samsung NX 18-55mm f/3.5-5.6 OIS1.531yesyesno
Samsung NX 20-50mm f/3.5-5.6 ED1.528yesnono
Samsung NX 20mm f/2.8 Pancake1.525yesyesno
Samsung NX 30mm f/2 Pancake1.528yesnono
Samsung NX 45mm f/1.8 2D/3D1.525yesyesno
SamyangSamyang 12mm f/2.0 NCS CS1.534yesyesno
Samyang 12mm f/2.8 Fish-Eye ED AS NCS1.0yesnoyes
Samyang 14mm f/2.8 AE ED AS IF UMC1.0yesyesno
Samyang 14mm f/2.8 AE ED AS IF UMC1.523yesyesyes
Samyang 35mm f/1.4 AS UMC1.0yesnono
Samyang 35mm T1.5 Cine Lens1.62yesnono
Samyang 500mm f/6.3 MC IF Mirror Lens1.534yesyesyes
Samyang 50mm f/1.4 AS UMC1.534yesyesno
Samyang 7.5mm f/3.5 UMC Fish-eye MFT2.0yesyesyes
Samyang 8mm f/2.8 UMC Fish-eye1.534yesyesyes
Samyang 8mm f/3.5 Fish-Eye CS1.534yesyesno
Samyang T-S 24mm f/3.5 ED AS UMC1.0yesnono
SchneiderD-Xenon 1:3.5-5.6 18-55mm AL1.53yesnono
D-Xenon 1:4-5.6 50-200mm AL1.53yesnono
Schneider 28mm Digitar f/2.80.577yesnono
Schneider 28mm f/2.8 PC1.0yesnono
Schneider 80mm Xenotar f/2.80.51yesnono
Schneider Retina-Curtagon 1:4/28mm1.529yesyesno
SigmaFixed lens DP21.739yesnono
Sigma 10-20mm f/3.5 EX DC HSM1.613yesyesno
Sigma 10-20mm f/4-5.6 EX DC1.53yesnoyes
Sigma 10-20mm f/4-5.6 EX DC1.62nonoyes
Sigma 100-300mm f/4 APO EX DG HSM1.523yesnoyes
Sigma 105mm f/2.8 EX DG OS HSM Macro1.523yesyesyes
Sigma 10mm f/2.8 EX DC Fisheye HSM1.622yesnono
Sigma 10mm f/2.8 EX DC Fisheye HSM1.523yesnono
Sigma 12-24mm f/4.5-5.6 EX DG1.0yesnoyes
Sigma 14mm f/2.8 EX1.0yesnono
Sigma 14mm f/3.5 EX1.53yesnono
Sigma 15-30mm f/3.5-4.5 EX DG Aspherical1.0yesyesyes
Sigma 15-30mm f/3.5-4.5 EX DG Aspherical1.611yesnono
Sigma 150-500mm f/5-6.3 APO DG OS HSM1.0yesyesyes
Sigma 150mm f/2.8 EX DG APO HSM Macro2.0yesyesyes
Sigma 150mm f/2.8 EX DG APO HSM Macro1.0yesnoyes
Sigma 17-35mm f/2.8-4 EX DG1.53yesnono
Sigma 17-50mm f/2.8 EX DC OS HSM1.523yesyesno
Sigma 17-70mm f/2.8-4 DC Macro OS HSM1.523yesnono
Sigma 17-70mm f/2.8-4.5 DC Macro1.611yesnono
Sigma 18-125mm f/3.5-5.6 DC1.53yesnono
Sigma 18-125mm f/3.5-5.6 DC1.611yesnono
Sigma 18-200mm f/3.5-6.3 DC1.53yesyesyes
Sigma 18-200mm f/3.5-6.3 II DC OS HSM1.53yesyesno
Sigma 18-250mm f/3.5-6.3 DC OS Macro HSM1.523yesyesno
Sigma 18-35mm f/1.8 DC HSM [A]1.523yesyesyes
Sigma 18-50mm f/2.8 EX DC1.53yesnono
Sigma 18-50mm f/2.8 EX DC1.611yesnono
Sigma 18-50mm f/3.5-5.6 DC1.611yesnono
Sigma 180mm f/2.8 EX DG OS HSM APO Macro1.0yesnoyes
Sigma 180mm f/5.6 APO Macro1.523yesyesyes
Sigma 19mm f/2.8 DN2.0yesyesyes
Sigma 19mm f/2.8 EX DN2.0yesnono
Sigma 19mm f/2.8 EX DN1.534yesyesno
Sigma 20mm f/1.8 EX DG1.0yesnono
Sigma 24-105mm f/4.0 DG OS HSM [A]1.005yesyesyes
Sigma 24-60mm f/2.8 EX DG1.53yesyesyes
Sigma 24-70mm f/2.8 EX DG Macro1.611yesnono
Sigma 24-70mm f/2.8 IF EX DG HSM1.526yesnono
Sigma 24-70mm f/2.8 IF EX DG HSM1.005yesyesyes
Sigma 28-300mm f/3.5-6.3 Macro ASP IF1.53yesnono
Sigma 28-70mm f/2.8 EX DG1.0yesnono
Sigma 28mm f/1.8 EX DG1.53yesnono
Sigma 30mm f/1.4 EX DC HSM1.53yesyesno
Sigma 30mm f/1.4 EX DC HSM1.62nonoyes
Sigma 30mm f/2.8 EX DN1.534yesyesyes
Sigma 30mm f/2.8 EX DN2.0yesnono
Sigma 35mm f/1.4 DG HSM1.0yesyesyes
Sigma 50-150mm f/2.8 APO EX DC HSM II1.523yesnoyes
Sigma 50-150mm f/2.8 APO EX DC HSM II1.62yesnono
Sigma 50-150mm f/2.8 APO EX DC OS HSM1.534nonoyes
Sigma 50-500mm f/4-6.3 EX DG HSM1.53yesnono
Sigma 50-500mm f/4.5-6.3 DG OS HSM1.0yesnono
Sigma 50mm f/1.4 DG HSM [A]1.005yesyesyes
Sigma 50mm f/1.4 EX DG HSM1.0yesyesyes
Sigma 50mm f/1.4 EX DG HSM1.53yesnoyes
Sigma 55-200mm f/4-5.6 DC1.531yesnono
Sigma 60mm f/2.8 DN2.0yesyesno
Sigma 70-200mm f/2.8 EX DG Macro HSM II1.526yesyesno
Sigma 70-200mm f/2.8 EX DG OS HSM1.005yesyesyes
Sigma 70-200mm f/2.8 EX DG OS HSM1.534yesyesyes
Sigma 70-300mm f/4-5.6 APO Macro Super II1.611yesnono
Sigma 70-300mm f/4-5.6 DG Macro1.0yesyesno
Sigma 70-300mm f/4-5.6 DL Macro1.53yesnoyes
Sigma 8-16mm f/4.5-5.6 DC HSM1.613yesyesno
Sigma 8-16mm f/4.5-5.6 DC HSM1.534yesyesno
Sigma 80-400mm f/4.5-5.6 EX DG OS1.0nonoyes
Sigma 8mm f/3.5 EX DG circular fisheye1.523yesyesno
Sigma 8mm f/3.5 EX DG circular fisheye1.62yesyesno
SoligorMC Soligor C/D Wide-Auto 1:2.8 f=24mm1.531yesyesno
SonyE 10-18mm f/4 OSS1.534yesyesno
E 16-50mm f/3.5-5.6 OSS PZ1.534yesyesyes
E 16-70mm f/4 ZA OSS1.534yesyesno
E 16mm f/2.81.534yesyesyes
E 18-200mm f/3.5-6.3 OSS1.534yesyesno
E 18-200mm f/3.5-6.3 OSS LE1.534yesyesyes
E 18-55mm f/3.5-5.6 OSS1.534yesyesyes
E 20mm f/2.81.534yesyesyes
E 24mm f/1.8 ZA1.534yesyesno
E 30mm f/3.5 Macro1.534yesyesno
E 35mm f/1.8 OSS1.534yesyesyes
E 50mm f/1.8 OSS1.534yesyesyes
E 55-210mm f/4.5-6.3 OSS1.534yesyesyes
E PZ 18-105mm f/4 G OSS1.534yesyesno
FE 24-70mm f/4 ZA OSS1.534yesyesno
FE 24-70mm f/4 ZA OSS1.0yesyesno
FE 28-70mm f/3.5-5.6 OSS1.0yesnono
FE 28mm f/21.0yesyesno
FE 55mm f/1.8 ZA1.0yesyesno
Fixed lens Cyber-shot DSC-F7173.933yesnono
Fixed lens Cyber-shot DSC-F7173.933yesnono
Fixed lens Cyber-shot DSC-F7173.933yesnono
Fixed lens Cyber-shot DSC-F7173.933yesnono
Fixed lens Cyber-shot DSC-F7173.933yesnono
Fixed lens Cyber-shot DSC-F7173.933yesnono
Fixed lens Cyber-shot DSC-F7173.933yesnono
Fixed lens Cyber-shot DSC-F7173.933yesnono
Fixed lens Cyber-shot DSC-F7173.933yesnono
Fixed lens Cyber-shot DSC-F7173.933yesnono
Fixed lens Cyber-shot DSC-F7173.933yesnono
Fixed lens Cyber-shot DSC-F7173.933yesnono
Fixed lens Cyber-shot DSC-F7173.933yesnono
Fixed lens Cyber-shot DSC-S854.843yesnono
Fixed lens Cyber-shot DSC-S854.843yesnono
Fixed lens DSC-F8283.933yesnono
Fixed lens DSC-F8283.933yesnono
Fixed lens DSC-H16.0yesnono
Fixed lens DSC-H16.0yesnono
Fixed lens DSC-H16.0yesnono
Fixed lens DSC-HX3005.58yesnono
Fixed lens DSC-P2004.8yesnono
Fixed lens DSC-R11.68yesnono
Fixed lens DSC-S906.5yesnono
Fixed lens DSC-T15.65yesnono
Fixed lens DSC-V34.843yesnono
Fixed lens DSC-V34.843yesnono
Fixed lens DSC-V34.843yesnono
Fixed lens RX1002.73yesyesyes
Fixed lens RX100 II2.73yesyesno
Fixed lens RX100 III2.73yesyesno
Minolta/Sony AF DT 18-70mm f/3.5-5.6 (D)1.527yesnoyes
Sony 50mm f/1.41.534yesyesyes
Sony AF DT 16-105mm f/3.5-5.61.527yesyesyes
Sony AF DT 55-200mm f/4-5.6 SAM1.527yesyesyes
Sony DT 16-50mm f/2.8 SSM1.527yesyesyes
Sony DT 18-135mm f/3.5-5.6 SAM1.523yesyesyes
Sony DT 18-55mm f/3.5-5.6 SAM1.527yesyesyes
Sony DT 35mm f/1.8 SAM1.523yesyesyes
Sony DT 50mm f/1.8 SAM1.523yesyesyes
Sony DT 55-300mm f/4.5-5.6 SAM1.523yesyesyes
VCL-ECF1 Fischauge-Vorsatz1.534yesyesyes
VCL-ECU1 ultra wide converter1.534yesyesno
TamronTamron 16-300mm f/3.5-6.3 Di II VC PZD1.613yesnono
Tamron 16-300mm f/3.5-6.3 Di II VC PZD1.534yesyesno
Tamron 18-200mm f/3.5-6.3 Di III VC1.534yesyesno
Tamron 35-70mm f/3.5 CF Macro1.53yesyesyes
Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro1.53yesnono
Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro1.611yesnono
Tamron AF 18-250mm f/3.5-6.3 Di II LD Aspherical (IF) Macro1.53yesyesno
Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD1.613yesnono
Tamron AF 19-35mm f/3.5-4.51.611yesnono
Tamron AF 28-300mm f/3.5-6.3 XR Di LD Aspherical (IF)1.53yesnono
Tamron AF 70-300mm f/4-5.6 LD Macro 1:21.53yesyesyes
Tamron SP 150-600mm f/5-6.3 Di VC USD1.534yesnono
Tamron SP 24-70mm f/2.8 Di VC USD1.0yesyesno
Tamron SP 70-300mm f/4-5.6 Di VC USD1.0yesnono
Tamron SP AF 10-24mm f/3.5-4.5 Di II LD Aspherical (IF)1.53yesyesno
Tamron SP AF 11-18mm f/4.5-5.6 Di-II LD Aspherical (IF)1.62yesyesno
Tamron SP AF 17-35mm f/2.8-4 Di LD Aspherical (IF)1.0yesnono
Tamron SP AF 17-50mm f/2.8 XR Di II LD Aspherical (IF)1.53yesyesyes
Tamron SP AF 24-135mm f/3.5-5.6 AD Aspherical (IF) Macro1.611yesnono
Tamron SP AF 28-105mm f/2.8 LD Aspherical IF1.0yesnono
Tamron SP AF 28-75mm f/2.8 XR Di1.0yesnono
Tamron SP AF 60mm f/2 Di II LD (IF) Macro1.523yesyesyes
Tamron SP AF 70-200mm f/2.8 Di LD (IF) Macro1.0yesyesno
Tamron SP AF 90mm f/2.8 Di Macro 1:11.53yesyesyes
TokinaTokina 28-70mm f/2.8 AT-X Pro SV1.611yesnono
Tokina 500mm f/8 RMC Mirror Lens1.53noyesno
Tokina 80-200mm f/4.5-5.6 SZ-X1.53yesyesno
Tokina AF 100mm f/2.8 AT-X Pro D Macro1.534yesyesno
Tokina AF 11-16mm f/2.8 AT-X Pro DX1.0yesnono
Tokina AF 11-16mm f/2.8 AT-X Pro DX1.53yesnoyes
Tokina AF 12-24mm f/4 AT-X Pro DX1.53yesnono
Tokina AF 12-28mm f/4 AT-X Pro DX1.534yesyesno
Tokina AF 16-28mm f/2.8 AT-X Pro SD FX1.0yesyesno
Tokina AF 17mm f/3.5 AT-X Pro1.53yesnono
Tokina AF 17mm f/3.5 AT-X Pro1.611yesnono
Tokina AF 19-35mm f/3.5-4.51.611yesnono
VivitarVivitar 100mm f/3.5 AF Macro1.523yesyesno
Vivitar Series 1 70-210mm 1:3.5 SN 22…1.534yesyesno
VoigtländerVoigtländer Color-Skopar X 1:2,8/501.529yesyesno
Voigtländer Skoparex 1:3,4/351.529yesyesno
Voigtländer Ultron 40mm f/2 SL-II Aspherical1.0yesyesno
ZeissCarl Zeiss Distagon T* 2,8/21 ZE1.0yesyesno
Carl Zeiss Distagon T* 2,8/21 ZF.21.0yesyesno
Carl Zeiss Jena 1Q Biotar 1:2 f=58mm T1.538yesyesno
E 32mm f/1.81.534yesyesno
fixed lens3.93yesyesno
ZenitZenitar MC 16mm f/2.81.529yesyesno

Cameras

Note that new camera models can be added very easily. Contact the Lensfun maintainers for this.

AEE: AEE MagiCam SD19 & compatibles

Canon: 35mm film: full frame, EOS 1000D, EOS 100D, EOS 10D, EOS 1100D, EOS 1200D, EOS 20D, EOS 300D, EOS 30D, EOS 350D, EOS 400D, EOS 40D, EOS 450D, EOS 500D, EOS 50D, EOS 550D, EOS 5D, EOS 5D Mark II, EOS 5D Mark III, EOS 600D, EOS 60D, EOS 650D, EOS 6D, EOS 700D, EOS 70D, EOS 750D, EOS 760D, EOS 7D, EOS 7D Mark II, EOS D2000, EOS D30, EOS D60, EOS Digital REBEL, EOS Digital Rebel XS, EOS Digital Rebel XSi, EOS Digital Rebel XT, EOS Digital Rebel XTi, EOS Kiss Digital, EOS Kiss Digital F, EOS Kiss Digital N, EOS Kiss Digital X, EOS Kiss Digital X2, EOS Kiss X3, EOS Kiss X4, EOS Kiss X5, EOS Kiss X50, EOS Kiss X6i, EOS Kiss X7, EOS Kiss X70, EOS Kiss X7i, EOS M, EOS M2, EOS M3, EOS Rebel SL1, EOS Rebel T1i, EOS Rebel T2i, EOS Rebel T3, EOS Rebel T3i, EOS Rebel T4i, EOS Rebel T5, EOS Rebel T5i, EOS-1D, EOS-1D Mark II, EOS-1D Mark II N, EOS-1D Mark III, EOS-1D Mark IV, EOS-1D X, EOS-1Ds, EOS-1Ds Mark II, EOS-1Ds Mark III, IXUS 125 HS, IXUS 220 HS, IXUS 30, IXUS 40, IXUS 400, IXUS 430, IXUS 50, IXUS 500, IXUS 55, IXUS 70, IXUS 700, IXUS 750, IXUS 80 IS, IXUS II, IXUS i, IXUS v2, IXY 200a, IXY 30, IXY 40, IXY 400, IXY 450, IXY 50, IXY 500, IXY 55, IXY Digital 600, IXY Digital 700, PowerShot A10, PowerShot A20, PowerShot A30, PowerShot A40, PowerShot A4000 IS, PowerShot A510, PowerShot A520, PowerShot A60, PowerShot A610, PowerShot A620, PowerShot A640, PowerShot A650 IS, PowerShot A70, PowerShot A720 IS, PowerShot A75, PowerShot A80, PowerShot A85, PowerShot A95, PowerShot G1, PowerShot G1 X, PowerShot G1 X Mark II, PowerShot G10, PowerShot G11, PowerShot G12, PowerShot G15, PowerShot G2, PowerShot G3, PowerShot G5, PowerShot G6, PowerShot G7, PowerShot G7 X (16:9), PowerShot G7 X (3:2), PowerShot G7 X (4:3), PowerShot G9, PowerShot Pro1, PowerShot Pro70, PowerShot Pro90 IS, PowerShot S1 IS, PowerShot S100, PowerShot S110, PowerShot S120, PowerShot S2 IS, PowerShot S200, PowerShot S30, PowerShot S40, PowerShot S400, PowerShot S410, PowerShot S45, PowerShot S5 IS, PowerShot S50, PowerShot S500, PowerShot S60, PowerShot S70, PowerShot S80, PowerShot S90, PowerShot S95, PowerShot SD10, PowerShot SD100, PowerShot SD110, PowerShot SD200, PowerShot SD300, PowerShot SD400, PowerShot SD450, PowerShot SD500, PowerShot SD550, PowerShot SD950 IS, PowerShot SX1 IS, PowerShot SX130 IS, PowerShot SX150 IS, PowerShot SX220 HS, PowerShot SX230 HS, PowerShot SX260 HS, PowerShot SX510 HS, Powershot ELPH 110 HS

Casio: EX-FH20, EX-P600, EX-P700, EX-Z3, EX-Z30, EX-Z4, EX-Z40, EX-Z55, EX-Z750, QV-3000EX, QV-3500EX, QV-4000

Contax: 35mm film: full frame

DJI: Phantom Vision FC200

Epson: R-D1

Fujifilm: FinePix 3800, FinePix A370, FinePix E550, FinePix F10, FinePix F11, FinePix F200EXR, FinePix F601 ZOOM, FinePix F710, FinePix F770EXR, FinePix F810, FinePix F810 widescreen mode, FinePix HS20EXR, FinePix IS Pro, FinePix S1 Pro, FinePix S2 Pro, FinePix S20Pro, FinePix S3 Pro, FinePix S3000, FinePix S304, FinePix S5 Pro, FinePix S5100, FinePix S5500, FinePix S5600, FinePix S602 ZOOM, FinePix S7000, FinePix S9000, FinePix S9500, FinePix S9600, FinePix X100, FinePix2800ZOOM, X-A1, X-A2, X-E1, X-E2, X-M1, X-Pro1, X-T1, X10, X100S, X100T, X20, X30, XQ1

Generic: Crop-Faktor 1.1, Crop-Faktor 1.3 (APS-H), Crop-Faktor 1.5 (APS-C), Crop-Faktor 2.0 (Four-Thirds), Crop-factor 1.0 (Full Frame), Crop-factor 1.6 (APS-C), Crop-factor 1.7

GoPro: HD2, HERO4 Silver

Hasselblad: Hasselblad 500 mech., Hasselblad H3D

KMZ: Zenit 122, Zenit 122K, Zenit 212K, Zenit 312K, Zenit 412LS, Zenit KM

Kodak: DCS 520, DCS Pro 14N DCS-14n, DCS Pro 14nx, DCS Pro SLR/c, DCS Pro SLR/n, Kodak CX6330, Kodak DC120, Kodak DC50

Konica Minolta: DiMAGE A2, DiMAGE A200, DiMAGE G400, DiMAGE Z10, DiMAGE Z2, DiMAGE Z20, DiMAGE Z3, DiMAGE Z5, DiMAGE Z6, Dynax 5D, Dynax 7D, Maxxum 5D, Maxxum 7D, Revio KD-420Z

LG: LG G4

Leica: Digilux 2, Digilux 3, Digilux 4

Mamiya: Mamiya 645, Mamiya ZD

Minolta: DiMAGE 7, DiMAGE 7Hi, DiMAGE 7i, DiMAGE A1, DiMAGE X, DiMAGE Xi, DiMAGE Xt, DiMAGE Z1

Nikon: 1 AW1, 1 J1, 1 J2, 1 J3, 1 J4, 1 J5, 1 S1, 1 S2, 1 V1, 1 V2, 1 V3, 35mm film: full frame, Coolpix 4200, Coolpix 4500, Coolpix 4800, Coolpix 5000, Coolpix 5200, Coolpix 5400, Coolpix 5700, Coolpix 5900, Coolpix 7600, Coolpix 7900, Coolpix 8400, Coolpix 8700, Coolpix 8800, Coolpix 950, Coolpix 990, Coolpix 995, Coolpix P330, Coolpix P60, Coolpix P6000, Coolpix P7000, Coolpix S3300, D1, D100, D1H, D1X, D200, D2H, D2Hs, D2X, D2Xs, D3, D300, D3000, D300S, D3100, D3200, D3300, D3S, D3X, D4, D40, D40X, D50, D5000, D5100, D5200, D5300, D5500, D60, D600, D610, D70, D700, D7000, D70s, D7100, D7200, D750, D80, D800, D800E, D810, D90, Df

Nokia: Lumia 1020

Olympus: C-2040 Zoom, C-3040 Zoom, C-4000 Zoom, C-4100 Zoom, C-4040 Zoom, C-50 Zoom variant of the X-2, C-5050 Zoom, C-5060 Wide Zoom, C-70 Zoom, C-7000 Zoom, C-700 Ultra Zoom, C-7070 Wide Zoom, C-730 Ultra Zoom, C-750 Ultra Zoom, C-8080 Wide Zoom, C-860L, D-360L variant of the C-860L, E-1, E-10, E-20, E-20N, E-20P, E-3, E-30, E-300, E-330, E-400, E-410, E-420, E-450, E-5, E-500, E-510, E-520, E-600, E-620, E-M1, E-M10, E-M5, E-M5MarkII, E-P1, E-P2, E-P3, E-P5, E-PL1, E-PL1s, E-PL2, E-PL3, E-PL5, E-PL6, E-PL7, E-PM1, E-PM2, SP-350, SP-500 Ultra Zoom, SP-560 Ultra Zoom, Stylus 1, Stylus 1, 1s, Stylus Epic, Stylus Verve Digital variant of the µ-mini Digital, X-2, XZ-1, µ-II, µ-mini Digital

Panasonic: DMC-FX150, DMC-FX2, DMC-FX7, DMC-FX8, DMC-FX9, DMC-FZ10, DMC-FZ1000, DMC-FZ150, DMC-FZ18, DMC-FZ20, DMC-FZ200, DMC-FZ28, DMC-FZ3, DMC-FZ30, DMC-FZ35, DMC-FZ5, DMC-FZ50, DMC-FZ8, DMC-G1, DMC-G10, DMC-G2, DMC-G3, DMC-G5, DMC-G6, DMC-GF1, DMC-GF2, DMC-GF3, DMC-GF5, DMC-GF6, DMC-GF7, DMC-GH1, DMC-GH2, DMC-GH3, DMC-GH4, DMC-GM1, DMC-GM5, DMC-GX1, DMC-GX7, DMC-L1, DMC-L10, DMC-LC1, DMC-LF1, DMC-LX1 16:9, DMC-LX1 3:2, DMC-LX1 4:3, DMC-LX100, DMC-LX2, DMC-LX3 16:9, DMC-LX3 1:1, DMC-LX3 3:2, DMC-LX3 4:3, DMC-LX5 4:3, DMC-LX7 4:3, DMC-LZ1, DMC-LZ2, DMC-TZ71

Pentax: *ist D, *ist DL, *ist DL2, *ist DS, *ist DS2, 35mm film: full frame, K-3, K-3 II, K-30, K-5, K-5 II, K-5 II s, K-50, K-500, K-7, K-S1, K-S2, K-m, K-r, K-x, K100D, K100D Super, K10D, K110D, K2000, K200D, K20D, Optio 230GS, Optio 330GS, Optio 33L, Optio 33LF, Optio 430, Optio 43WR, Optio 450, Optio 550, Optio 555, Optio 750Z, Pentax Q, Pentax Q10, Pentax Q7

Phase One: P 25

Ricoh: Caplio GX, Caplio GX8, Caplio RR30, GR, GR Digital

Rolleiflex: 2.8E

Samsung: GX-1S, GX10, GX20, Galaxy NX, NX mini, NX1, NX10, NX100, NX1000, NX11, NX1100, NX20, NX200, NX2000, NX210, NX30, NX300, NX3000, NX300M, NX5, NX500, WB2000

Sigma: DP1, DP1 Merrill, DP1S, DP1X, DP2, DP2 Merrill, DP2S, DP2X, DP3 Merrill, SD1, SD1 Merrill, SD10, SD14, SD15, SD9

Sony: Alpha 100, Alpha 200, Alpha 230, Alpha 290, Alpha 300, Alpha 3000, Alpha 33, Alpha 330, Alpha 35, Alpha 350, Alpha 37, Alpha 380, Alpha 390, Alpha 450, Alpha 500, Alpha 5000, Alpha 5100, Alpha 55, Alpha 550, Alpha 560, Alpha 57, Alpha 58, Alpha 580, Alpha 6000, Alpha 65, Alpha 7, Alpha 7 II, Alpha 700, Alpha 77, Alpha 77 II, Alpha 7R, Alpha 7S, Alpha 850, Alpha 900, Alpha 99, Alpha 99V, Cyber-shot DSC-F707, Cyber-shot DSC-F717, Cyber-shot DSC-S75, Cyber-shot DSC-S85, DSC-F828, DSC-H1, DSC-HX20V, DSC-HX300, DSC-P100, DSC-P150, DSC-P200, DSC-P73, DSC-P93, DSC-R1, DSC-S60, DSC-S80, DSC-S90, DSC-ST80, DSC-T1, DSC-V1, DSC-V3, DSC-W1, DSC-W12, DSC-W15, DSC-W5, DSC-W7, NEX-3, NEX-3N, NEX-5, NEX-5N, NEX-5R, NEX-5T, NEX-6, NEX-7, NEX-C3, NEX-F3, RX100, RX100 II, RX100 III, RX100 IV

lensfun-0.3.4/docs/website/news.md000066400000000000000000000003601445356770400170760ustar00rootroot00000000000000--- title: News linktitle: News layout: default weight: 2 --- {% for post in site.categories.news %}

{{ post.date | date: "%Y-%m-%d" }} {{ post.title }}

{{ post.content }}
{% endfor %} lensfun-0.3.4/docs/website/styles.css000066400000000000000000000034371445356770400176450ustar00rootroot00000000000000body { width:90%; background:#181818; color:#b0b0b0; font:10pt Verdana, DejaVu Sans, Arial; padding:0px; margin: 0px; text-align:left; } #logo { margin-bottom:0em; margin-left:4em; } #navigation { padding:5px; font-size: 120%; color: white; width: 12em; float: left; margin-right: 1em; margin-bottom: 1em; } #navigation ul { margin: 0; padding: 0; } #navigation li { list-style: none; border-left: 0.1em solid white; margin: 0; padding: 0; padding-left:0.2em; margin-bottom: 0.5em; } #navigation .active { color: #74A0DA; } #top-navigation { margin-bottom: 1em; } #top-navigation ul { margin: 0; padding: 0; } #top-navigation li { float:right; list-style: none; margin: 0; padding:0; padding-right: 0.5em; margin-left:1.3em; border-right: 0.1em solid white; } #container { margin:0px auto; padding:3em; margin-top: 3em; width: 75em; } #content { padding:1em; float:right; width:55em; background: rgb(45, 45, 45); } #footer { margin-top: 1em; font-size: 80%; float: right; } .news-title { color: white; } .news-title-frontpage { color: white; font-size: 120%; } .news { margin-bottom: 3em; } #berlios-badge { margin-top: 3em; font:10pt Verdana, DejaVu Sans, Arial; } table { border: 1px solid gray; border-collapse: collapse; } table th { padding: 0.3em; } table td { padding: 0.3em; } .lenslist-highlight { background-color: #51734E; } .lenslist-bg1 { background-color: #000000; } .lenslist-bg2 { background-color: #181818; } a:link { background:transparent; text-decoration:none; color:#ffffff; } a:visited { background:transparent; color:#ffffff; } a:hover { background:transparent; color:#74A0DA; } a:active { background:transparent; color:#ffffff; } lensfun-0.3.4/docs/website/usage.md000066400000000000000000000024611445356770400172320ustar00rootroot00000000000000--- title: How to use Lensfun? linktitle: Usage layout: default weight: 3 --- Lensfun itself is only a library for correcting several artefacts and a database for storing lens profiles. To actually use Lensfun to process your images you need an image editing application with Lensfun support. So far you can use Lensfun with the following applications: * UFRaw is a standalone raw processor but also contains a GIMP plugin to load RAW image files * Darktable RAW processor and photo workflow software similar to Adobe Lightroom * Rawstudio another raw processor * Digikam/Kipi image management application, supports Lensfun via Kipi-Plugin * GimpLensfun GIMP plugin * Photivo photo processor application * lensfunpy Python wrapper for Lensfun * Hugin panorama stitcher (version 2011.4.0 - 2014.0.0) If the above applications do not recognize your camera or lens in their Lensfun tool please check the list of supported lenses and the FAQ. lensfun-0.3.4/include/000077500000000000000000000000001445356770400146325ustar00rootroot00000000000000lensfun-0.3.4/include/lensfun/000077500000000000000000000000001445356770400163045ustar00rootroot00000000000000lensfun-0.3.4/include/lensfun/config.h.in.cmake000066400000000000000000000025111445356770400214050ustar00rootroot00000000000000#ifndef __CONFIG_H__ #define __CONFIG_H__ /* config file for Lensfun library generated by CMake */ #define CONF_PACKAGE "lensfun" #define CONF_VERSION "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_MICRO@.@VERSION_BUGFIX@" #cmakedefine PLATFORM_WINDOWS #cmakedefine CMAKE_COMPILER_IS_GNUCC #ifdef CMAKE_COMPILER_IS_GNUCC #define CONF_COMPILER_GCC 1 #endif #ifndef PLATFORM_WINDOWS //fix path to data works only on *nix systems //on windows that data dir is relocatable #define CONF_DATADIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/lensfun" #define SYSTEM_DB_UPDATE_PATH "/${CMAKE_INSTALL_LOCALSTATEDIR}/lib/lensfun-updates" #else #define CONF_DATADIR "${LENSFUN_WINDOWS_DATADIR}" #define SYSTEM_DB_UPDATE_PATH "C:\\to\\be\\defined\\lensfun-updates" #endif #define DATABASE_SUBDIR "version_${LENSFUN_DB_VERSION}" // add a macro to know we're compiling Lensfun, not a client library #define CONF_LENSFUN_INTERNAL #cmakedefine VECTORIZATION_SSE #cmakedefine VECTORIZATION_SSE2 #cmakedefine HAVE_ENDIAN_H #ifdef _MSC_VER #define _USE_MATH_DEFINES #endif #define GLIB_VERSION_MIN_REQUIRED (${LENSFUN_GLIB_REQUIREMENT_MACRO}) // to avoid usage of API that is not in GLIB_VERSION_MIN_REQUIRED version // and make it easy to detect when to bump requirements: #define GLIB_VERSION_MAX_ALLOWED (GLIB_VERSION_MIN_REQUIRED) #endif // __CONFIG_H__ lensfun-0.3.4/include/lensfun/lensfun.h.in000066400000000000000000002753161445356770400205520ustar00rootroot00000000000000/* -*- mode:c++ -*- */ /* Lensfun - a library for maintaining a database of photographical lenses, and providing the means to correct some of the typical lens distortions. Copyright (C) 2007 by Andrew Zabolotny This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __LENSFUN_H__ #define __LENSFUN_H__ #include #ifdef __cplusplus extern "C" { /** Helper macro to make C/C++ work similarly */ # define C_TYPEDEF(t,c) #else # define C_TYPEDEF(t,c) typedef t c c; #endif /** * @file lensfun.h * This file defines the interface to the Lensfun library. */ /*----------------------------------------------------------------------------*/ /** * @defgroup Auxiliary Auxiliary definitions and functions * @brief These functions will help handling basic structures of the library. * @{ */ /// Major library version number #define LF_VERSION_MAJOR @VERSION_MAJOR@ /// Minor library version number #define LF_VERSION_MINOR @VERSION_MINOR@ /// Library micro version number #define LF_VERSION_MICRO @VERSION_MICRO@ /// Library bugfix number #define LF_VERSION_BUGFIX @VERSION_BUGFIX@ /// Full library version #define LF_VERSION ((LF_VERSION_MAJOR << 24) | (LF_VERSION_MINOR << 16) | (LF_VERSION_MICRO << 8) | LF_VERSION_BUGFIX) /// Oldest database version supported by this release #define LF_MIN_DATABASE_VERSION 0 /// Latest database version supported by this release #define LF_MAX_DATABASE_VERSION 1 #if defined CONF_LENSFUN_STATIC /// This macro expands to an appropiate symbol visibility declaration # define LF_EXPORT #else # ifdef CONF_SYMBOL_VISIBILITY # if defined PLATFORM_WINDOWS # define LF_EXPORT __declspec(dllexport) # elif defined CONF_COMPILER_GCC || __clang__ # define LF_EXPORT __attribute__((visibility("default"))) # else # error "I don't know how to change symbol visibility for your compiler" # endif # else # if defined PLATFORM_WINDOWS || defined _MSC_VER # define LF_EXPORT __declspec(dllimport) # else # define LF_EXPORT # endif # endif #endif #ifndef CONF_LENSFUN_INTERNAL /// For marking deprecated functions, see http://stackoverflow.com/a/21265197 # ifdef __GNUC__ # define DEPRECATED __attribute__((deprecated)) # elif defined(_MSC_VER) # define DEPRECATED __declspec(deprecated) # else # pragma message("WARNING: You need to implement DEPRECATED for this compiler") # define DEPRECATED # endif #else # define DEPRECATED #endif /// C-compatible bool type; don't bother to define Yet Another Boolean Type #define cbool int /** * The storage of "multi-language" strings is simple yet flexible, * handy and effective. The first (default) string comes first, terminated * by \\0 as usual, after that a language code follows, then \\0 again, * then the translated value and so on. The list terminates as soon as * a \\0 is encountered instead of next string, e.g. last string in list * is terminated with two null characters. */ typedef char *lfMLstr; /** liblensfun error codes: negative codes are -errno, positive are here */ enum lfError { /** No error occured */ LF_NO_ERROR = 0, /** Wrong XML data format */ LF_WRONG_FORMAT, /** No database could be loaded */ LF_NO_DATABASE }; C_TYPEDEF (enum, lfError) /** The type of a 8-bit pixel */ typedef unsigned char lf_u8; /** The type of a 16-bit pixel */ typedef unsigned short lf_u16; /** The type of a 32-bit pixel */ typedef unsigned int lf_u32; /** The type of a 32-bit floating-point pixel */ typedef float lf_f32; /** The type of a 64-bit floating-point pixel */ typedef double lf_f64; /** * The basics of memory allocation: never free objects allocated by the * library yourselves, instead use this function. It is a direct * equivalent of standard C free(), however you should not use free() * in the event that the library uses a separate heap. * @param data * A pointer to memory to be freed. */ LF_EXPORT void lf_free (void *data); /** * @brief Get a string corresponding to current locale from a multi-language * string. * * Current locale is determined from LC_MESSAGES category at the time of * the call, e.g. if you change LC_MESSAGES at runtime, next calls to * lf_mlstr_get() will return the string for the new locale. */ LF_EXPORT const char *lf_mlstr_get (const lfMLstr str); /** * @brief Add a new translated string to a multi-language string. * * This uses realloc() so returned value may differ from input. * @param str * The string to append to. Can be NULL. * @param lang * The language for the new added string. If NULL, the default * string is replaced (the first one in list, without a language * designator). * @param trstr * The translated string * @return * The reallocated multi-language string. To free a multi-language * string, use lf_free(). */ LF_EXPORT lfMLstr lf_mlstr_add (lfMLstr str, const char *lang, const char *trstr); /** * @brief Create a complete copy of a multi-language string. * * @param str * The string to create a copy of * @return * A new allocated multi-language string */ LF_EXPORT lfMLstr lf_mlstr_dup (const lfMLstr str); /** @} */ /*----------------------------------------------------------------------------*/ /** * @defgroup Mount Structures and functions for camera mounts * @brief These structures and functions allow to define and examine * the properties of camera mounts. * @{ */ /** * @brief This structure contains everything specific to a camera mount. * * Objects of this type are usually retrieved from the database * by using queries (see lfDatabase::FindMount() / lf_db_find_mount()), * and can be created manually in which case it is application's * responsability to destroy the object when it is not needed anymore. */ struct LF_EXPORT lfMount { /** @brief Camera mount name. * * Mount names for fixed-lens cameras -- and only they -- must start with a * lower case letter. */ lfMLstr Name; /** A list of compatible mounts */ char **Compat; #ifdef __cplusplus /** * @brief Initialize a new mount object. All fields are set to 0. */ lfMount (); /** * Copy constructor */ lfMount (const lfMount &other); /** * Assignment operator */ lfMount &operator = (const lfMount &other); /** * @brief Destroy a mount object. All allocated fields are freed. */ ~lfMount (); /** * @brief Add a string to mount name. * * If lang is NULL, this replaces the default value, otherwise a new * language value is appended. * @param val * The new value for the Name field. * @param lang * The language this field is in. */ void SetName (const char *val, const char *lang = NULL); /** * @brief Add a mount name to the list of compatible mounts. * @param val * The identifier of the compatible mount. */ void AddCompat (const char *val); /** * @brief Check if a mount object is valid. * @return * true if required fields are ok. */ bool Check (); #endif }; C_TYPEDEF (struct, lfMount) /** * @brief Create a new mount object. * @return * A new empty mount object. * @sa * lfMount::lfMount() */ LF_EXPORT lfMount *lf_mount_new (); /** * @brief Destroy a lfMount object. * * This is equivalent to C++ "delete mount". * @param mount * The mount object to destroy. * @sa * lfMount::~lfMount() */ LF_EXPORT void lf_mount_destroy (lfMount *mount); /** * @brief Copy the data from one lfMount structure into another. * @param dest * The destination object * @param source * The source object * @sa * lfMount::operator = (const lfMount &) */ LF_EXPORT void lf_mount_copy (lfMount *dest, const lfMount *source); /** @sa lfMount::Check */ LF_EXPORT cbool lf_mount_check (lfMount *mount); /** @} */ /*----------------------------------------------------------------------------*/ /** * @defgroup Camera Structures and functions for cameras * @brief These structures and functions allow to define and examine * the properties of a camera model. * @{ */ /** * @brief Camera data. Unknown fields are set to NULL. * * The Maker and Model fields must be filled EXACTLY as they appear in the EXIF * data, since this is the only means to detect camera automatically * (upper/lowercase is not important, though). Some different cameras * (e.g. Sony Cybershot) are using same EXIF id info for different models, in * which case the Variant field should contain the exact model name, but, alas, * we cannot automatically choose between such "twin" cameras. */ struct LF_EXPORT lfCamera { /** @brief Camera maker (ex: "Rollei") -- same as in EXIF */ lfMLstr Maker; /** @brief Model name (ex: "Rolleiflex SL35") -- same as in EXIF */ lfMLstr Model; /** @brief Camera variant. Some cameras use same EXIF id for different models */ lfMLstr Variant; /** @brief Camera mount type (ex: "QBM") */ char *Mount; /** @brief Camera crop factor (ex: 1.0). Must be defined. */ float CropFactor; /** @brief Camera matching score, used while searching: not actually a camera parameter */ int Score; #ifdef __cplusplus /** * @brief Initialize a new camera object. All fields are set to 0. */ lfCamera (); /** * Copy constructor. */ lfCamera (const lfCamera &other); /** * @brief Destroy a camera object. All allocated fields are freed. */ ~lfCamera (); /** * Assignment operator */ lfCamera &operator = (const lfCamera &other); /** * @brief Add a string to camera maker. * * If lang is NULL, this replaces the default value, otherwise a new * language value is appended. * @param val * The new value for the Maker field. * @param lang * The language this field is in. */ void SetMaker (const char *val, const char *lang = NULL); /** * @brief Add a string to camera model. * * If lang is NULL, this replaces the default value, otherwise a new * language value is appended. * @param val * The new value for the Model field. * @param lang * The language this field is in. */ void SetModel (const char *val, const char *lang = NULL); /** * @brief Add a string to camera variant. * * If lang is NULL, this replaces the default value, otherwise a new * language value is appended. * @param val * The new value for the Variant field. * @param lang * The language this field is in. */ void SetVariant (const char *val, const char *lang = NULL); /** * @brief Set the value for camera Mount. * @param val * The new value for Mount. */ void SetMount (const char *val); /** * @brief Check if a camera object is valid. * @return * true if the required fields are ok. */ bool Check (); #endif }; C_TYPEDEF (struct, lfCamera) /** * @brief Create a new camera object. * @return * A new empty camera object. * @sa * lfCamera::lfCamera */ LF_EXPORT lfCamera *lf_camera_new (); /** * @brief Destroy a lfCamera object. * * This is equivalent to C++ "delete camera". * @param camera * The camera object to destroy. * @sa * lfCamera::~lfCamera */ LF_EXPORT void lf_camera_destroy (lfCamera *camera); /** * @brief Copy the data from one lfCamera structure into another. * @param dest * The destination object * @param source * The source object * @sa * lfCamera::operator = (const lfCamera &) */ LF_EXPORT void lf_camera_copy (lfCamera *dest, const lfCamera *source); /** @sa lfCamera::Check */ LF_EXPORT cbool lf_camera_check (lfCamera *camera); /** @} */ /*----------------------------------------------------------------------------*/ /** * @defgroup Lens Structures and functions for lenses * @brief These structures and functions allow to define and examine * the properties of a lens. * @{ */ /** * @brief The Lensfun library implements several lens distortion models. * This enum lists them. * * Distortion usually heavily depends on the focal length, but does not depend * on the aperture. In the following, \f$r_d\f$ refers to the distorted radius * (normalised distance to image center), and \f$r_u\f$ refers to the * undistorted, corrected radius. See section \ref actualorder for further * information. * * For a popular explanation of lens distortion see * http://www.vanwalree.com/optics/distortion.html */ enum lfDistortionModel { /** @brief Distortion parameters are unknown */ LF_DIST_MODEL_NONE, /** * @brief 3rd order polynomial model, which is a subset of the PTLens * model. * * \f[r_d = r_u \cdot (1 - k_1 + k_1 r_u^2)\f] * The corresponding XML attribute is called “k1”. It defaults to 0. */ LF_DIST_MODEL_POLY3, /** * @brief 5th order polynomial model. * * \f[r_d = r_u \cdot (1 + k_1 r_u^2 + k_2 r_u^4)\f] * The corresponding XML attributes are called “k1” and “k2”. They default * to 0. * Ref: http://www.imatest.com/docs/distortion.html */ LF_DIST_MODEL_POLY5, /** * @brief PTLens model, which is also used by Hugin. * * \f[r_d = r_u \cdot (a r_u^3 + b r_u^2 + c r_u + 1 - a - b - c)\f] * The corresponding XML attributes are called “a”, “b”, and “c”. They * default to 0. */ LF_DIST_MODEL_PTLENS, }; C_TYPEDEF (enum, lfDistortionModel) /** * @brief Lens distortion calibration data. * Lens distortion depends only of focal length. The library will interpolate * the coefficients values if data for the exact focal length is not available. */ struct lfLensCalibDistortion { /** @brief The type of distortion model used */ enum lfDistortionModel Model; /** @brief Focal length in mm at which this calibration data was taken */ float Focal; /** @brief Distortion coefficients, dependent on model (a,b,c or k1 or k1,k2) */ float Terms [3]; }; C_TYPEDEF (struct, lfLensCalibDistortion) /** * @brief The Lensfun library supports several models for lens lateral * chromatic aberrations (also called transversal chromatic * aberrations, TCA). * * TCAs depend on focal length, but does not depend of the aperture. In the * following, \f$r_d\f$ refers to the distorted radius (normalised distance to * image center), and \f$r_u\f$ refers to the undistorted, corrected radius. * See section \ref actualorder for further information. * * For a popular explanation of chromatic aberrations see * http://www.vanwalree.com/optics/chromatic.html */ enum lfTCAModel { /** @brief No TCA correction data is known */ LF_TCA_MODEL_NONE, /** * @brief Linear lateral chromatic aberrations model. * * \f[\begin{aligned} * r_{d,R} &= r_{u,R} k_R \\ * r_{d,B} &= r_{u,B} k_B * \end{aligned}\f] * The corresponding XML attributes are called “kr” and “kb”. They default * to 1. * Ref: http://cipa.icomos.org/fileadmin/template/doc/TURIN/403.pdf */ LF_TCA_MODEL_LINEAR, /** * @brief Third order polynomial. * * \f[\begin{aligned} * r_{d,R} &= r_{u,R} \cdot (b_R r_{u,R}^2 + c_R r_{u,R} + v_R) \\ * r_{d,B} &= r_{u,B} \cdot (b_B r_{u,B}^2 + c_B r_{u,B} + v_B) * \end{aligned}\f] * The corresponding XML attributes are called “br”, “cr”, * “vr”, “bb”, “cb”, and “vb”. vr and vb default to 1, the rest to 0. * Ref: http://wiki.panotools.org/Tca_correct */ LF_TCA_MODEL_POLY3 }; C_TYPEDEF (enum, lfTCAModel) /** * @brief Laterlal chromatic aberrations calibration data. * * Chromatic aberrations depend on focal length and aperture value. The library * will interpolate the coefficients if data for the exact focal length and * aperture value is not available with priority for a more exact focal length. */ struct lfLensCalibTCA { /** @brief The lateral chromatic aberration model used */ enum lfTCAModel Model; /** @brief Focal length in mm at which this calibration data was taken */ float Focal; /** @brief The coefficients for TCA, dependent on model; separate for R and B */ float Terms [6]; }; C_TYPEDEF (struct, lfLensCalibTCA) /** * @brief The Lensfun library supports several models for lens vignetting * correction. * * We focus on optical and natural vignetting since they can be generalized for * all lenses of a certain type; mechanical vignetting is out of the scope of * this library. * * Vignetting is dependent on focal length and aperture. There is * also a slight dependence on focus distance. In the following, * \f$C_d\f$ refers to the corrected destination image pixel brightness, and * \f$C_s\f$ refers to the uncorrected source image pixel brightness. * * For a popular explanation of vignetting see * http://www.vanwalree.com/optics/vignetting.html */ enum lfVignettingModel { /** @brief No vignetting correction data is known */ LF_VIGNETTING_MODEL_NONE, /** * @brief Pablo D'Angelo vignetting model * (which is a more general variant of the \f$\cos^4\f$ law). * * \f[C_d = C_s \cdot (1 + k_1 r^2 + k_2 r^4 + k_3 r^6)\f] * The corresponding XML attributes are called “k1”, “k2”, and “k3”. They * default to 0. * Ref: http://hugin.sourceforge.net/tech/ */ LF_VIGNETTING_MODEL_PA }; C_TYPEDEF (enum, lfVignettingModel) /** * @brief Lens vignetting calibration data. * * Vignetting depends on focal length, aperture and focus distance. The library * will interpolate the coefficients if data for the exact focal length, * aperture, and focus distance is not available. */ struct lfLensCalibVignetting { /** @brief The lens vignetting model used */ enum lfVignettingModel Model; /** @brief Focal length in mm at which this calibration data was taken */ float Focal; /** @brief Aperture (f-number) at which this calibration data was taken */ float Aperture; /** @brief Focus distance in meters */ float Distance; /** @brief Lens vignetting model coefficients (depending on model) */ float Terms [3]; }; C_TYPEDEF (struct, lfLensCalibVignetting) /** * @brief Different crop modes */ enum lfCropMode { /** @brief no crop at all */ LF_NO_CROP, /** @brief use a rectangular crop */ LF_CROP_RECTANGLE, /** @brief use a circular crop, e.g. for circular fisheye images */ LF_CROP_CIRCLE }; C_TYPEDEF(enum, lfCropMode) /** * @brief Struct to save image crop, which can depend on the focal length */ struct lfLensCalibCrop { /** @brief Focal length in mm at which this calibration data was taken */ float Focal; /** @brief crop mode which should be applied to image to get rid of black borders */ enum lfCropMode CropMode; /** @brief Crop coordinates, relative to image corresponding image dimension * * Crop goes left - 0, right - 1, top - 2, bottom - 3 * Left/right refers always to long side (width in landscape mode), * top bottom to short side (height in landscape). * Also negative values are allowed for cropping of fisheye images, * where the crop circle can extend above the image border. */ float Crop [4]; }; C_TYPEDEF (struct, lfLensCalibCrop) /** * @brief Struct to save calibrated field of view, which can depends on the focal length (DEPRECATED) * * The Field of View (FOV) database entry is deprecated since Lensfun * version 0.3 and will be removed in future releases. * */ struct lfLensCalibFov { /** Focal length in mm at which this calibration data was taken */ float Focal; /** @brief Field of view for given images * * The Field of View (FOV) database entry is deprecated since Lensfun * version 0.3 and will be removed in future releases. * * Especially for fisheye images the field of view calculated from the (EXIF) focal * length differs slightly from the real field of view. The real field of view can be * stored in this field */ float FieldOfView; }; C_TYPEDEF (struct, lfLensCalibFov) /** * @brief Struct to save real focal length, which can depends on the (nominal) * focal length */ struct lfLensCalibRealFocal { /** Nominal focal length in mm at which this calibration data was taken */ float Focal; /** @brief Real focal length * * When Lensfun speaks of “focal length”, the *nominal* focal length from * the EXIF data or the gravure on the lens barrel is meant. However, * especially for fisheye lenses, the real focal length generally differs * from that nominal focal length. With “real focal length” I mean the * focal length in the paraxial approximation, see * . Note that Hugin * (as of 2014) implements the calculation of the real focal length * wrongly, see . */ float RealFocal; }; C_TYPEDEF (struct, lfLensCalibRealFocal) /** * @brief This structure describes a single parameter for some lens model. */ struct lfParameter { /** @brief Parameter name (something like 'k', 'k3', 'omega' etc.) */ const char *Name; /** @brief Minimal value that has sense */ float Min; /** @brief Maximal value that has sense */ float Max; /** @brief Default value for the parameter */ float Default; }; C_TYPEDEF (struct, lfParameter) /** * @brief Lens type. See \ref changeofprojection for further information. */ enum lfLensType { /** @brief Unknown lens type */ LF_UNKNOWN, /** @brief Rectilinear lens * * Straight lines remain stright; 99% of all lenses are of this type. */ LF_RECTILINEAR, /** * @brief Equidistant fisheye * * Ref: http://wiki.panotools.org/Fisheye_Projection */ LF_FISHEYE, /** * @brief Panoramic (cylindrical) * * Not that there are such lenses, but useful to convert images \a to this * type, especially fish-eye images. */ LF_PANORAMIC, /** * @brief Equirectangular * * Not that there are such lenses, but useful to convert images \a to this * type, especially fish-eye images. */ LF_EQUIRECTANGULAR, /** @brief Orthographic fisheye */ LF_FISHEYE_ORTHOGRAPHIC, /** @brief Stereographic fisheye */ LF_FISHEYE_STEREOGRAPHIC, /** @brief Equisolid fisheye */ LF_FISHEYE_EQUISOLID, /** * @brief Fisheye as measured by Thoby (for Nikkor 10.5). * * Ref: http://michel.thoby.free.fr/Blur_Panorama/Nikkor10-5mm_or_Sigma8mm/Sigma_or_Nikkor/Comparison_Short_Version_Eng.html */ LF_FISHEYE_THOBY }; C_TYPEDEF (enum, lfLensType) /** * @brief Lens data. * Unknown fields are set to NULL or 0. * * To manually create a new lens object, fill the fields for which you * have data, and invoke the lfLens::Check() or lf_lens_check() function, * which will check if existing data is enough and will automatically fill * some fields using information extracted from lens name. */ struct LF_EXPORT lfLens { /** Lens maker (ex: "Rollei") */ lfMLstr Maker; /** Lens model (ex: "Zoom-Rolleinar") */ lfMLstr Model; /** Minimum focal length, mm (ex: 35). */ float MinFocal; /** Maximum focal length, mm (ex: 105). Can be equal to MinFocal. */ float MaxFocal; /** Smallest f-number possible (ex: 3.5). */ float MinAperture; /** Biggest f-number possible (ex: 22). */ float MaxAperture; /** Available mounts (NULL-terminated list) (ex: { "QBM", NULL }) */ char **Mounts; /** * The horizontal shift of all lens distortions. * Note that distortion and TCA uses same geometrical lens center. * It is given as a relative value to avoide dependency on the * image and/or sensor sizes. The calibrated delta X and Y values are * numbers in the -0.5 .. +0.5 range. For 1 we take the maximal image * dimension (width or height) - this is related to the fact that the * lens has a circular field of projection disregarding sensor size. */ float CenterX; /** The vertical shift of all lens distortions. (0,0) for geometric center */ float CenterY; /** Crop factor at which calibration measurements were taken. Must be defined. */ float CropFactor; /** Aspect ratio of the images used for calibration measurements. */ float AspectRatio; /** Lens type */ lfLensType Type; /** Lens distortion calibration data, NULL-terminated (unsorted) */ lfLensCalibDistortion **CalibDistortion; /** Lens TCA calibration data, NULL-terminated (unsorted) */ lfLensCalibTCA **CalibTCA; /** Lens vignetting calibration data, NULL-terminated (unsorted) */ lfLensCalibVignetting **CalibVignetting; /** Crop data, NULL-terminated (unsorted) */ lfLensCalibCrop **CalibCrop; /** Field of view calibration data, NULL-terminated (unsorted) */ lfLensCalibFov **CalibFov; /** Real focal length calibration data, NULL-terminated (unsorted) */ lfLensCalibRealFocal **CalibRealFocal; /** Lens matching score, used while searching: not actually a lens parameter */ int Score; #ifdef __cplusplus /** * @brief Create a new lens object, initializing all fields to default values. */ lfLens (); /** * Copy constructor. */ lfLens (const lfLens &other); /** * @brief Destroy this and all associated objects. */ ~lfLens (); /** * Assignment operator */ lfLens &operator = (const lfLens &other); /** * @brief Add a string to camera maker. * * If lang is NULL, this replaces the default value, otherwise a new * language value is appended. * @param val * The new value for the Maker field. * @param lang * The language this field is in. */ void SetMaker (const char *val, const char *lang = NULL); /** * @brief Add a string to camera model. * * If lang is NULL, this replaces the default value, otherwise a new * language value is appended. * @param val * The new value for the Model field. * @param lang * The language this field is in. */ void SetModel (const char *val, const char *lang = NULL); /** * @brief Add a new mount type to this lens. * * This is not a multi-language string, this it's just plain replaced. * @param val * The new value to add to the Mounts array. */ void AddMount (const char *val); /** * @brief Add a new distortion calibration structure to the pool. * * The objects is copied, thus you can reuse it as soon as * this function returns. * @param dc * The distortion calibration structure. */ void AddCalibDistortion (const lfLensCalibDistortion *dc); /** * @brief Remove a calibration entry from the distortion calibration data. * @param idx * The calibration data index (zero-based). */ bool RemoveCalibDistortion (int idx); /** * @brief Add a new transversal chromatic aberration calibration structure * to the pool. * * The objects is copied, thus you can reuse it as soon as * this function returns. * @param tcac * The transversal chromatic aberration calibration structure. */ void AddCalibTCA (const lfLensCalibTCA *tcac); /** * @brief Remove a calibration entry from the TCA calibration data. * @param idx * The calibration data index (zero-based). */ bool RemoveCalibTCA (int idx); /** * @brief Add a new vignetting calibration structure to the pool. * * The objects is copied, thus you can reuse it as soon as * this function returns. * @param vc * The vignetting calibration structure. */ void AddCalibVignetting (const lfLensCalibVignetting *vc); /** * @brief Remove a calibration entry from the vignetting calibration data. * @param idx * The calibration data index (zero-based). */ bool RemoveCalibVignetting (int idx); /** * @brief Add a new lens crop structure to the pool. * * The objects is copied, thus you can reuse it as soon as * this function returns. * @param cc * The lens crop structure. */ void AddCalibCrop (const lfLensCalibCrop *cc); /** * @brief Remove a lens crop entry from the lens crop structure. * @param idx * The lens crop data index (zero-based). */ bool RemoveCalibCrop (int idx); /** * @brief Add a new lens fov structure to the pool. * * The Field of View (FOV) database entry is deprecated since Lensfun * version 0.3 and will be removed in future releases. * * The objects is copied, thus you can reuse it as soon as * this function returns. * @param cf * The lens fov structure. */ DEPRECATED void AddCalibFov (const lfLensCalibFov *cf); /** * @brief Remove a field of view entry from the lens fov structure. * * The Field of View (FOV) database entry is deprecated since Lensfun * version 0.3 and will be removed in future releases. * * @param idx * The lens information data index (zero-based). */ DEPRECATED bool RemoveCalibFov (int idx); /** * @brief Add a new lens real focal length structure to the pool. * * The objects is copied, thus you can reuse it as soon as * this function returns. * @param cf * The lens real focal length structure. */ void AddCalibRealFocal (const lfLensCalibRealFocal *cf); /** * @brief Remove a real focal length entry from the lens real focal length * structure. * @param idx * The lens information data index (zero-based). */ bool RemoveCalibRealFocal (int idx); /** * @brief This method fills some fields if they are missing but * can be derived from other fields. * * This includes such non-obvious parameters like the range of focal * lengths or the range of apertures, which can be derived from lens named * (which is intelligently parsed) or from the list of calibrations. */ void GuessParameters (); /** * @brief Check if a lens object is valid. * @return * true if the required fields are ok. */ bool Check (); /** * @brief Get the human-readable distortion model name and the descriptions * of the parameters required by this model. * @param model * The model. * @param details * If not NULL, this string will be set to a more detailed (technical) * description of the model. This string may contain newlines. * @param params * If not NULL, this variable will be set to a pointer to an array * of lfParameter structures, every structure describes a model * parameter. The list is NULL-terminated. * @return * A short name of the distortion model or NULL if model is unknown. */ static const char *GetDistortionModelDesc ( lfDistortionModel model, const char **details, const lfParameter ***params); /** * @brief Get the human-readable transversal chromatic aberrations model name * and the descriptions of the parameters required by this model. * @param model * The model. * @param details * If not NULL, this string will be set to a more detailed (technical) * description of the model. This string may contain newlines. * @param params * If not NULL, this variable will be set to a pointer to an array * of lfParameter structures, every structure describes a model * parameter. The list is NULL-terminated. * @return * A short name of the TCA model or NULL if model is unknown. */ static const char *GetTCAModelDesc ( lfTCAModel model, const char **details, const lfParameter ***params); /** * @brief Get the human-readable vignetting model name and the descriptions * of the parameters required by this model. * @param model * The model. * @param details * If not NULL, this string will be set to a more detailed (technical) * description of the model. This string may contain newlines. * @param params * If not NULL, this variable will be set to a pointer to an array * of lfParameter structures, every structure describes a model * parameter. The list is NULL-terminated. * @return * A short name of the vignetting model or NULL if model is unknown. */ static const char *GetVignettingModelDesc ( lfVignettingModel model, const char **details, const lfParameter ***params); /** * @brief Get the human-readable crop name and the descriptions * of the parameters required by this model. * @param mode * The crop mode. * @param details * If not NULL, this string will be set to a more detailed (technical) * description of the model. This string may contain newlines. * @param params * If not NULL, this variable will be set to a pointer to an array * of lfParameter structures, every structure describes a model * parameter. The list is NULL-terminated. * @return * A short name of the distortion model or NULL if model is unknown. */ static const char *GetCropDesc ( lfCropMode mode, const char **details, const lfParameter ***params); /** * @brief Get the human-readable lens type name and a short description of this * lens type. * @param type * Lens type. * @param details * If not NULL, this string will be set to a more detailed (technical) * description of the lens type. This string may contain newlines. * @return * A short name of the lens type or NULL if model is unknown. */ static const char *GetLensTypeDesc (lfLensType type, const char **details); /** * @brief Interpolate lens geometry distortion data for given focal length. * @param focal * The focal length in mm at which we need geometry distortion parameters. * @param res * The resulting interpolated model. */ bool InterpolateDistortion (float focal, lfLensCalibDistortion &res) const; /** * @brief Interpolate lens TCA calibration data for given focal length. * @param focal * The focal length in mm at which we need TCA parameters. * @param res * The resulting interpolated model. */ bool InterpolateTCA (float focal, lfLensCalibTCA &res) const; /** * @brief Interpolate lens vignetting model parameters for given focal length, * aperture, and focus distance. * @param focal * The focal length in mm for which we need vignetting parameters. * @param aperture * The aperture (f-number) for which we need vignetting parameters. * @param distance * The focus distance in meters (distance > 0) for which we need * vignetting parameters. * @param res * The resulting interpolated model. */ bool InterpolateVignetting ( float focal, float aperture, float distance, lfLensCalibVignetting &res) const; /** * @brief Interpolate lens crop data for given focal length. * @param focal * The focal length in mm at which we need image parameters. * @param res * The resulting interpolated information data. */ bool InterpolateCrop (float focal, lfLensCalibCrop &res) const; /** * @brief Interpolate lens fov data for given focal length. * * The Field of View (FOV) database entry is deprecated since Lensfun * version 0.3 and will be removed in future releases. * * @param focal * The focal length in mm at which we need image parameters. * @param res * The resulting interpolated information data. */ DEPRECATED bool InterpolateFov (float focal, lfLensCalibFov &res) const; /** * @brief Interpolate lens real focal length data for given focal length. * * The Field of View (FOV) database entry is deprecated since Lensfun * version 0.3 and will be removed in future releases. * * @param focal * The nominal focal length in mm at which we need image parameters. * @param res * The resulting interpolated information data. */ bool InterpolateRealFocal (float focal, lfLensCalibRealFocal &res) const; #endif }; C_TYPEDEF (struct, lfLens) /** * @brief Create a new lens object. * @return * A new empty lens object. * @sa * lfLens::lfLens */ LF_EXPORT lfLens *lf_lens_new (); /** * @brief Destroy a lfLens object. * * This is equivalent to C++ "delete lens". * @param lens * The lens object to destroy. * @sa * lfLens::~lfLens */ LF_EXPORT void lf_lens_destroy (lfLens *lens); /** * @brief Copy the data from one lfLens structure into another. * @param dest * The destination object * @param source * The source object * @sa * lfLens::operator = (const lfCamera &) */ LF_EXPORT void lf_lens_copy (lfLens *dest, const lfLens *source); /** @sa lfLens::Check */ LF_EXPORT cbool lf_lens_check (lfLens *lens); /** @sa lfLens::GuessParameters */ LF_EXPORT void lf_lens_guess_parameters (lfLens *lens); /** @sa lfLens::GetDistortionModelDesc */ LF_EXPORT const char *lf_get_distortion_model_desc ( enum lfDistortionModel model, const char **details, const lfParameter ***params); /** @sa lfLens::GetTCAModelDesc */ LF_EXPORT const char *lf_get_tca_model_desc ( enum lfTCAModel model, const char **details, const lfParameter ***params); /** @sa lfLens::GetVignettingModelDesc */ LF_EXPORT const char *lf_get_vignetting_model_desc ( enum lfVignettingModel model, const char **details, const lfParameter ***params); /** @sa lfLens::GetCropDesc */ LF_EXPORT const char *lf_get_crop_desc ( enum lfCropMode mode, const char **details, const lfParameter ***params); /** @sa lfLens::GetLensTypeDesc */ LF_EXPORT const char *lf_get_lens_type_desc ( enum lfLensType type, const char **details); /** @sa lfLens::InterpolateDistortion */ LF_EXPORT cbool lf_lens_interpolate_distortion (const lfLens *lens, float focal, lfLensCalibDistortion *res); /** @sa lfLens::InterpolateTCA */ LF_EXPORT cbool lf_lens_interpolate_tca (const lfLens *lens, float focal, lfLensCalibTCA *res); /** @sa lfLens::InterpolateVignetting */ LF_EXPORT cbool lf_lens_interpolate_vignetting (const lfLens *lens, float focal, float aperture, float distance, lfLensCalibVignetting *res); /** @sa lfLens::InterpolateCrop */ LF_EXPORT cbool lf_lens_interpolate_crop (const lfLens *lens, float focal, lfLensCalibCrop *res); /** @sa lfLens::InterpolateFov */ DEPRECATED LF_EXPORT cbool lf_lens_interpolate_fov (const lfLens *lens, float focal, lfLensCalibFov *res); /** @sa lfLens::InterpolateRealFocal */ LF_EXPORT cbool lf_lens_interpolate_real_focal (const lfLens *lens, float focal, lfLensCalibRealFocal *res); /** @sa lfLens::AddCalibDistortion */ LF_EXPORT void lf_lens_add_calib_distortion (lfLens *lens, const lfLensCalibDistortion *dc); /** @sa lfLens::RemoveCalibDistortion */ LF_EXPORT cbool lf_lens_remove_calib_distortion (lfLens *lens, int idx); /** @sa lfLens::AddCalibTCA */ LF_EXPORT void lf_lens_add_calib_tca (lfLens *lens, const lfLensCalibTCA *tcac); /** @sa lfLens::RemoveCalibTCA */ LF_EXPORT cbool lf_lens_remove_calib_tca (lfLens *lens, int idx); /** @sa lfLens::AddCalibVignetting */ LF_EXPORT void lf_lens_add_calib_vignetting (lfLens *lens, const lfLensCalibVignetting *vc); /** @sa lfLens::RemoveCalibVignetting */ LF_EXPORT cbool lf_lens_remove_calib_vignetting (lfLens *lens, int idx); /** @sa lfLens::AddCalibCrop */ LF_EXPORT void lf_lens_add_calib_crop (lfLens *lens, const lfLensCalibCrop *cc); /** @sa lfLens::RemoveCalibCrop */ LF_EXPORT cbool lf_lens_remove_calib_crop (lfLens *lens, int idx); /** @sa lfLens::AddCalibFov */ DEPRECATED LF_EXPORT void lf_lens_add_calib_fov (lfLens *lens, const lfLensCalibFov *cf); /** @sa lfLens::RemoveCalibFov */ DEPRECATED LF_EXPORT cbool lf_lens_remove_calib_fov (lfLens *lens, int idx); /** @sa lfLens::AddCalibRealFocal */ LF_EXPORT void lf_lens_add_calib_real_focal (lfLens *lens, const lfLensCalibRealFocal *cf); /** @sa lfLens::RemoveCalibRealFocal */ LF_EXPORT cbool lf_lens_remove_calib_real_focal (lfLens *lens, int idx); /** @} */ /*----------------------------------------------------------------------------*/ /** * @defgroup Database Database functions * @brief Create, destroy and search database for objects. * @{ */ /** * @brief Flags controlling the behavior of database searches. */ enum { /** * @brief This flag selects a looser search algorithm resulting in * more results (still sorted by score). * * If it is not present, all results where at least one of the input * words is missing will be discarded. */ LF_SEARCH_LOOSE = 1, /** * @brief This flag makes Lensfun to sort the results by focal * length, and remove all double lens names. * * If a lens has entries for different crop factors/aspect ratios, * the only best match is included into the result. This is meant * to be used to create a list presented to the user to pick a lens. * Or, to lookup a lens for which you know maker and model exactly, * and to check whether the result list really contains only one * element. */ LF_SEARCH_SORT_AND_UNIQUIFY = 2 }; /** * @brief A lens database object. * * This object contains a list of mounts, cameras and lenses through * which you can search. The objects are loaded from XML files * located in (default configuration): * \verbatim /usr/share/lensfun/ /usr/local/share/lensfun/ ~/.local/share/lensfun/ \endverbatim * * Objects loaded later override objects loaded earlier. * Thus, if user modifies a object you must save it to its home directory * (see lfDatabase::HomeDataDir), where it will override any definitions * from the system-wide database. * */ struct LF_EXPORT lfDatabase { /** @brief Home lens database directory (something like "~/.local/share/lensfun") */ char *HomeDataDir; /** @brief Home lens database directory for automatic updates (something * like "~/.local/share/lensfun/updates") */ char *UserUpdatesDir; #ifdef __cplusplus lfDatabase (); ~lfDatabase (); /** * @brief Create a new empty database object. This function is deprecated and * will be removed in the future. Use the standard constructor instead. */ DEPRECATED static lfDatabase *Create (); /** * @brief Destroy the database object and free all loaded data. * * This function is deprecated and will be removed in the future. * Please use the standard destructor instead. */ DEPRECATED void Destroy (); /** * @brief Open and parse all XML files in a given directory. * * Returns true if valid Lensfun XML data was found and loaded * sucessfully. * @param dirname * The directory to be read. * @return * True if valid lensfun XML data was succesfully loaded. */ bool LoadDirectory (const char *dirname); /** * @brief Find and load the lens database. * * This function automatically tries to determine the location of the * lens database on the system. See @ref dbsearch for more information. * @return * LF_NO_ERROR or a error code. */ lfError Load (); /** * @brief Load just a specific XML file. * * If the loaded file contains the specification of a camera/lens that's * already in memory, it overrides that data. * @param filename * The name of a XML file to load. Note that Lensfun does not support * the full XML specification as it uses the glib's simple XML parser, * so advanced XML features are not available. * @return * LF_NO_ERROR or a error code. */ lfError Load (const char *filename); /** * @brief Load a set of camera/lenses from a memory array. * * This is the lowest-level loading function. * @param errcontext * The error context to be displayed in error messages * (usually this is the name of the file to which data belongs). * @param data * The XML data. * @param data_size * XML data size in bytes. * @return * LF_NO_ERROR or a error code. */ lfError Load (const char *errcontext, const char *data, size_t data_size); /** * @brief Save the whole database to a file. * @param filename * The file name to write the XML stream into. * @return * LF_NO_ERROR or a error code. */ lfError Save (const char *filename) const; /** * @brief Save a set of camera and lens descriptions to a file. * @param filename * The file name to write the XML stream into. * @param mounts * A list of mounts to be written to the file. Can be NULL. * @param cameras * A list of cameras to be written to the file. Can be NULL. * @param lenses * A list of lenses to be written to the file. Can be NULL. * @return * LF_NO_ERROR or a error code. */ lfError Save (const char *filename, const lfMount *const *mounts, const lfCamera *const *cameras, const lfLens *const *lenses) const; /** * @brief Save a set of camera and lens descriptions into a memory array. * @param mounts * A list of mounts to be written to the file. Can be NULL. * @param cameras * A list of cameras to be written to the file. Can be NULL. * @param lenses * A list of lenses to be written to the file. Can be NULL. * @return * A pointer to an allocated string with the output. * Free it with lf_free(). */ static char *Save (const lfMount *const *mounts, const lfCamera *const *cameras, const lfLens *const *lenses); /** * @brief Find a set of cameras that fit given criteria. * * The maker and model must be given (if possible) exactly as they are * spelled in database, except that the library will compare * case-insensitively and will compress spaces. This means that the * database must contain camera maker/lens *exactly* how it is given * in EXIF data, but you may add human-friendly translations of them * using the multi-language string feature (including a translation * to "en" to avoid displaying EXIF tags in user interface - they are * often upper-case which looks ugly). * @param maker * Camera maker (either from EXIF tags or from some other source). * The string is expected to be pure ASCII, since EXIF data does * not allow 8-bit data to be used. * @param model * Camera model (either from EXIF tags or from some other source). * The string is expected to be pure ASCII, since EXIF data does * not allow 8-bit data to be used. * @return * A NULL-terminated list of cameras matching the search criteria * or NULL if none. Release return value with lf_free() (only the list * of pointers, not the camera objects!). */ const lfCamera **FindCameras (const char *maker, const char *model) const; /** * @brief Searches all translations of camera maker and model. * * Thus, you may search for a user-entered camera even in a language * different from English. This function is somewhat similar to * FindCameras(), but uses a different search algorithm. * * This is a lot slower than FindCameras(). * @param maker * Camera maker. This can be any UTF-8 string. * @param model * Camera model. This can be any UTF-8 string. * @param sflags * Additional flags influencing the search algorithm. * This is a combination of LF_SEARCH_XXX flags. * @return * A NULL-terminated list of cameras matching the search criteria * or NULL if none. Release return value with lf_free() (only the list * of pointers, not the camera objects!). */ const lfCamera **FindCamerasExt (const char *maker, const char *model, int sflags = 0) const; /** * @brief Retrieve a full list of cameras. * @return * An NULL-terminated list containing all cameras loaded until now. * The list is valid only until the lens database is modified. * The returned pointer does not have to be freed. */ const lfCamera *const *GetCameras () const; /** * @brief Parse a human-friendly lens description (ex: "smc PENTAX-F 35-105mm F4-5.6" * or "SIGMA AF 28-300 F3.5-5.6 DL IF") and return a list of lfLens'es which * are matching this description. * * Multiple lenses may be returned if multiple lenses match (perhaps due to * non-unique lens description provided, e.g. "Pentax SMC"). * * The matching algorithm works as follows: first the user description * is tried to be interpreted according to several well-known lens naming * schemes, so additional data like focal and aperture ranges are extracted * if they are present. After that word matching is done; a lens matches * the description ONLY IF it contains all the words found in the description * (including buzzwords e.g. IF IZ AL LD DI USM SDM etc). Order of the words * does not matter. An additional check is done on the focal/aperture ranges, * they must exactly match if they are specified. * @param camera * The camera (can be NULL if camera is unknown, or just certain * fields in structure can be NULL). The algorithm will look for * a lens with crop factor not larger than of given camera, since * the mathematical models of the lens can be incorrect for sensor * sizes larger than the one used for calibration. Also camera * mount is taken into account, the lenses with incompatible * mounts will be filtered out. * @param maker * Lens maker or NULL if not known. * @param model * A human description of the lens model(-s). * @param sflags * Additional flags influencing the search algorithm. * This is a combination of LF_SEARCH_XXX flags. * @return * A list of lenses parsed from user description or NULL. * Release memory with lf_free(). The list is ordered in the * most-likely to least-likely order, e.g. the first returned * value is the most likely match. */ const lfLens **FindLenses (const lfCamera *camera, const char *maker, const char *model, int sflags = 0) const; /** * @brief Find a set of lenses that fit certain criteria. * @param lens * The approximative lense. Uncertain fields may be NULL. * The "CropFactor" field defines the minimal value for crop factor; * no lenses with crop factor larger than that will be returned. * The Mounts field will be scanned for allowed mounts, if NULL * any mounts are considered compatible. * @param sflags * Additional flags influencing the search algorithm. * This is a combination of LF_SEARCH_XXX flags. * @return * A NULL-terminated list of lenses matching the search criteria * or NULL if none. Release memory with lf_free(). The list is ordered * in the most-likely to least-likely order, e.g. the first returned * value is the most likely match. */ const lfLens **FindLenses (const lfLens *lens, int sflags = 0) const; /** * @brief Retrieve a full list of lenses. * @return * An NULL-terminated list containing all lenses loaded until now. * The list is valid only until the lens database is modified. * The returned pointer does not have to be freed. */ const lfLens *const *GetLenses () const; /** * @brief Return the lfMount structure given the (basic) mount name. * @param mount * The basic mount name. * @return * A pointer to lfMount structure or NULL. */ const lfMount *FindMount (const char *mount) const; /** * @brief Get the name of a mount in current locale. * @param mount * The basic mount name. * @return * The name of the mount in current locale (UTF-8 string). */ const char *MountName (const char *mount) const; /** * @brief Retrieve a full list of mounts. * @return * An array containing all mounts loaded until now. * The list is valid only until the mount database is modified. * The returned pointer does not have to be freed. */ const lfMount *const *GetMounts () const; /** * @brief Add a mount to the database. * @param mount * the mount to add */ void AddMount (lfMount *mount); /** * @brief Add a camera to the database. * @param camera * the camera to add */ void AddCamera (lfCamera *camera); /** * @brief Add a lens to the database. * @param lens * the lens to add */ void AddLens (lfLens *lens); private: #endif void *Mounts; void *Cameras; void *Lenses; }; C_TYPEDEF (struct, lfDatabase) /** * @brief Create a new empty database object. * * Usually the application will want to do this at startup, * after which it would be a good idea to call lf_db_load(). * @return * A new empty database object. * @sa * lfDatabase::lfDatabase */ LF_EXPORT lfDatabase *lf_db_new (void); /** * @brief Destroy the database object. * * This is the only way to correctly destroy the database object. * @param db * The database to destroy. * @sa * lfDatabase::~lfDatabase */ LF_EXPORT void lf_db_destroy (lfDatabase *db); /** @sa lfDatabase::Load() */ LF_EXPORT lfError lf_db_load (lfDatabase *db); /** @sa lfDatabase::Load(const char *) */ LF_EXPORT lfError lf_db_load_file (lfDatabase *db, const char *filename); /** @sa lfDatabase::LoadDirectory(const char *) */ LF_EXPORT cbool lf_db_load_directory (lfDatabase *db, const char *dirname); /** @sa lfDatabase::Load(const char *, const char *, size_t) */ LF_EXPORT lfError lf_db_load_data (lfDatabase *db, const char *errcontext, const char *data, size_t data_size); /** @sa lfDatabase::Save(const char *) */ LF_EXPORT lfError lf_db_save_all (const lfDatabase *db, const char *filename); /** @sa lfDatabase::Save(const char *, const lfMount *const *, const lfCamera *const *, const lfLens *const *) */ LF_EXPORT lfError lf_db_save_file (const lfDatabase *db, const char *filename, const lfMount *const *mounts, const lfCamera *const *cameras, const lfLens *const *lenses); /** @sa lfDatabase::Save(const lfMount *const *, const lfCamera *const *, const lfLens *const *) */ LF_EXPORT char *lf_db_save (const lfMount *const *mounts, const lfCamera *const *cameras, const lfLens *const *lenses); /** @sa lfDatabase::FindCameras */ LF_EXPORT const lfCamera **lf_db_find_cameras ( const lfDatabase *db, const char *maker, const char *model); /** @sa lfDatabase::FindCamerasExt */ LF_EXPORT const lfCamera **lf_db_find_cameras_ext ( const lfDatabase *db, const char *maker, const char *model, int sflags); /** @sa lfDatabase::GetCameras */ LF_EXPORT const lfCamera *const *lf_db_get_cameras (const lfDatabase *db); /** @sa lfDatabase::FindLenses(const lfCamera *, const char *, const char *) */ LF_EXPORT const lfLens **lf_db_find_lenses_hd ( const lfDatabase *db, const lfCamera *camera, const char *maker, const char *lens, int sflags); /** @sa lfDatabase::FindLenses(const lfCamera *, const lfLens *) */ LF_EXPORT const lfLens **lf_db_find_lenses ( const lfDatabase *db, const lfLens *lens, int sflags); /** @sa lfDatabase::GetLenses */ LF_EXPORT const lfLens *const *lf_db_get_lenses (const lfDatabase *db); /** @sa lfDatabase::FindMount */ LF_EXPORT const lfMount *lf_db_find_mount (const lfDatabase *db, const char *mount); /** @sa lfDatabase::MountName */ LF_EXPORT const char *lf_db_mount_name (const lfDatabase *db, const char *mount); /** @sa lfDatabase::GetMounts */ LF_EXPORT const lfMount *const *lf_db_get_mounts (const lfDatabase *db); /** @} */ /*----------------------------------------------------------------------------*/ /** * @defgroup Correction Image correction * @brief This group of functions will allow you to apply a image transform * that will correct some lens defects. * @{ */ /** @brief A list of bitmask flags used for ordering various image corrections */ enum { /** Correct (or apply) lens transversal chromatic aberrations */ LF_MODIFY_TCA = 0x00000001, /** Correct (or apply) lens vignetting */ LF_MODIFY_VIGNETTING = 0x00000002, /* Value 0x00000004 is deprecated. */ /** Correct (or apply) lens distortion */ LF_MODIFY_DISTORTION = 0x00000008, /** Convert image geometry */ LF_MODIFY_GEOMETRY = 0x00000010, /** Additional resize of image */ LF_MODIFY_SCALE = 0x00000020, /** Apply all possible corrections */ LF_MODIFY_ALL = ~0 }; /** @brief A list of pixel formats supported by internal colour callbacks */ enum lfPixelFormat { /** Unsigned 8-bit R,G,B */ LF_PF_U8, /** Unsigned 16-bit R,G,B */ LF_PF_U16, /** Unsigned 32-bit R,G,B */ LF_PF_U32, /** 32-bit floating-point R,G,B */ LF_PF_F32, /** 64-bit floating-point R,G,B */ LF_PF_F64 }; C_TYPEDEF (enum, lfPixelFormat) /** @brief These constants define the role of every pixel component, four bits * each. "pixel" refers here to a set of values which share the same (x, y) * coordinates. */ enum lfComponentRole { /** * This marks the end of the role list. It doesn't have to be specified * explicitly, since LF_CR_X macros always pad the value with zeros */ LF_CR_END = 0, /** * This value tells that what follows applies to next pixel. * This can be used to define Bayer images, e.g. use * LF_CR_3(LF_CR_RED, LF_CR_NEXT, LF_CR_GREEN) for even rows and * LF_CR_3(LF_CR_GREEN, LF_CR_NEXT, LF_CR_BLUE) for odd rows. */ LF_CR_NEXT, /** This component has an unknown/doesn't matter role */ LF_CR_UNKNOWN, /** This is the pixel intensity (grayscale) */ LF_CR_INTENSITY, /** This is the Red pixel component */ LF_CR_RED, /** This is the Green pixel component */ LF_CR_GREEN, /** This is the Blue pixel component */ LF_CR_BLUE }; C_TYPEDEF (enum, lfComponentRole) /** @brief This macro defines a pixel format consisting of one component */ #define LF_CR_1(a) (LF_CR_ ## a) /** @brief This macro defines a pixel format consisting of two components */ #define LF_CR_2(a,b) ((LF_CR_ ## a) | ((LF_CR_ ## b) << 4)) /** @brief This macro defines a pixel format consisting of three components */ #define LF_CR_3(a,b,c) ((LF_CR_ ## a) | ((LF_CR_ ## b) << 4) | \ ((LF_CR_ ## c) << 8)) /** @brief This macro defines a pixel format consisting of four components */ #define LF_CR_4(a,b,c,d) ((LF_CR_ ## a) | ((LF_CR_ ## b) << 4) | \ ((LF_CR_ ## c) << 8) | ((LF_CR_ ## d) << 12)) /** @brief This macro defines a pixel format consisting of five components */ #define LF_CR_5(a,b,c,d,e) ((LF_CR_ ## a) | ((LF_CR_ ## b) << 4) | \ ((LF_CR_ ## c) << 8) | ((LF_CR_ ## d) << 12) | \ ((LF_CR_ ## e) << 16)) /** @brief This macro defines a pixel format consisting of six components */ #define LF_CR_6(a,b,c,d,e,f) ((LF_CR_ ## a) | ((LF_CR_ ## b) << 4) | \ ((LF_CR_ ## c) << 8) | ((LF_CR_ ## d) << 12) | \ ((LF_CR_ ## e) << 16) | ((LF_CR_ ## f) << 20)) /** @brief This macro defines a pixel format consisting of seven components */ #define LF_CR_7(a,b,c,d,e,f,g) ((LF_CR_ ## a) | ((LF_CR_ ## b) << 4) | \ ((LF_CR_ ## c) << 8) | ((LF_CR_ ## d) << 12) | \ ((LF_CR_ ## e) << 16) | ((LF_CR_ ## f) << 20) | \ ((LF_CR_ ## g) << 24)) /** @brief This macro defines a pixel format consisting of eight components */ #define LF_CR_8(a,b,c,d,e,f,g,h) ((LF_CR_ ## a) | ((LF_CR_ ## b) << 4) | \ ((LF_CR_ ## c) << 8) | ((LF_CR_ ## d) << 12) | \ ((LF_CR_ ## e) << 16) | ((LF_CR_ ## f) << 20) | \ ((LF_CR_ ## g) << 24) | ((LF_CR_ ## h) << 28)) /** * @brief A callback function which modifies the separate coordinates for all color * components for every pixel in a strip. * * This kind of callbacks are used in the second stage of image modification. * @param data * A opaque pointer to some data. * @param iocoord * A pointer to an array of count*3 pixel coordinates (X,Y). * The first coordinate pair is for the R component, second for G * and third for B of same pixel. There are count*2*3 floats total * in this array. * @param count * Number of coordinate groups to handle. */ typedef void (*lfSubpixelCoordFunc) (void *data, float *iocoord, int count); /** * @brief A callback function which modifies the colors of a strip of pixels * * This kind of callbacks are used in the first stage of image modification. * @param data * A opaque pointer to some data. * @param x * The X coordinate of the beginning of the strip. For next pixels * the X coordinate increments sequentialy. * @param y * The Y coordinate of the pixel strip. This is a constant across * all pixels of the strip. * @param pixels * A pointer to pixel data. It is the responsability of the function * inserting the callback into the chain to provide a callback operating * with the correct pixel format. * @param comp_role * The role of every pixel component. This is a bitfield, made by one * of the LF_CR_X macros which defines the roles of every pixel field. * For example, LF_CR_4(RED,GREEN,BLUE,UNKNOWN) will define a RGBA * (or RGBX) pixel format, and the UNKNOWN field will not be modified. * @param count * Number of pixels to process. */ typedef void (*lfModifyColorFunc) (void *data, float x, float y, void *pixels, int comp_role, int count); /** * @brief A callback function which modifies the coordinates of a strip of pixels. * * This kind of callbacks are used in third stage of image modification. * @param data * A opaque pointer to some data. * @param iocoord * A pointer to an array @a count pixel coordinates (X,Y). * The function must replace the coordinates with their new values. * @param count * Number of coordinate groups to handle. */ typedef void (*lfModifyCoordFunc) (void *data, float *iocoord, int count); // @cond #ifdef __cplusplus /// Common ancestor for lfCoordCallbackData and lfColorCallbackData struct lfCallbackData { int priority; void *data; size_t data_size; virtual ~lfCallbackData() {}; }; // A test point in the autoscale algorithm typedef struct { float angle, dist; } lfPoint; #endif // @endcond /** * @brief A modifier object contains optimized data required to rectify a * image. * * You can either create an empty modifier object and then enable the * required modification functions individually, or you can take * a lens object, which contains a set of correction models, and * create a modifier object from it. * * Normally, you will create an instance of lfModifier and initialise * immediately it with lfModifier::Initialize, passing a valid lens object in * both cases. Users of the plain C interface will use lf_modifier_new() and * lf_modifier_initialize() instead. * * Every image modification has a corresponding inverse function, * e.g. the library allows both to correct lens distortions and to * simulate lens characteristics. * * The normal order of applying a lens correction on a image is: *
    *
  1. Fix lens vignetting *
  2. Fix chromatic aberrations (TCA) *
  3. Fix lens distortion *
  4. Fix lens geometry *
  5. Scale the image *
* * This is the theoretical order. But in reality, when using this library, the * order is reversed (see \ref corrections for an explanation): * *
    *
  1. Color
      *
    1. Fix lens vignetting *
    *
  2. Coordinates
      *
    1. Scale the image *
    2. Fix lens geometry *
    3. Fix lens distortion *
    *
  3. Subpixel coordinates
      *
    1. Fix chromatic aberrations (TCA) *
    *
* * This process is divided into three stages. * * In the first stage, the colors of the image pixels are fixed * (vignetting). You pass a pointer to your pixel data, and it will be modified * in place. * * Then, the distortions introduced by the lens are removed (distortion and * geometry), and an additional scaling factor is applied if required. This * operation requires building new image in a new allocated buffer: you cannot * modify the image in place, or bad things will happen. Note that Lensfun * does not provide pixel interpolation routines. You have to implement the * lookup in the original image yourself. * * And finally, in the subpixel distortion stage, application corrects * transversal chromatic aberrations. For every target pixel coordinate the * modifier will return you three new coordinates: the first will tell you the * coordinates of the red component, second of the green, and third of the blue * component. This again requires copying the image, but you can use the same * buffers as in stage two, just in reverse order. * * Of course, you can skip some stages of the process, e.g. if you, for * example, don't want to change a fisheye image to a rectilinear you * can omit that step. * * Obviously, when simulating lens distortions, the modification stages * must be applied in reverse order. While the library takes care to reverse * the steps which are grouped into a single stage, the application must * apply the stages themselves in reverse order. * * HOWEVER. Doing it in three stages is not memory efficient, and is prone to * error accumulation because you have to interpolate pixels twice - once * during stage 2 and once during stage 3. To avoid this, it is sensful to do * stages 2 & 3 in one step. In this case the output R,G,B coordinates from * stage 2, which treats the colour channels equally, are fed directly into * stage 3, which will correct the R,G,B coordinates further. * ApplySubpixelGeometryDistortion() does this in a convenient fashion. */ #ifdef __cplusplus } #endif struct LF_EXPORT lfModifier { #ifdef __cplusplus /** * @brief Create an empty image modifier object. * * Before using the returned object you must add the required * modifier callbacks (see methods AddXXXCallback below). * * You must provide the original image width/height even if you * plan to correct just a part of the image. * * @param lens * For all modifications, the crop factor, aspect ratio, and * center shift of this lens will be used. * @param crop * The crop factor for current camera. The distortion models will * take this into account if lens models were measured on a camera * with a different crop factor. * @param width * The width of the image you want to correct. * @param height * The height of the image you want to correct. */ lfModifier (const lfLens *lens, float crop, int width, int height); ~lfModifier (); /** * @brief Create an empty image modifier object. * * Before using the returned object you must add the required * modifier callbacks (see methods AddXXXCallback below). * * You must provide the original image width/height even if you * plan to correct just a part of the image. * * This function is deprecated and will be removed in the future. * Please use the standard constructor instead. * * @param lens * For all modifications, the crop factor, aspect ratio, and * center shift of this lens will be used. * @param crop * The crop factor for current camera. The distortion models will * take this into account if lens models were measured on a camera * with a different crop factor. * @param width * The width of the image you want to correct. * @param height * The height of the image you want to correct. * @return * A new empty image modifier object. */ DEPRECATED static lfModifier *Create (const lfLens *lens, float crop, int width, int height); /** * @brief Initialize the process of correcting aberrations in a image. * * The modifier object will be set up to rectify all aberrations * found in the lens description. Make sure the focal length, * aperture, and focus distance are correct in order to ensure * proper rectification. * * Aperture and focus distance are only used for vignetting * correction. Because the dependence of vignetting on focus * distance is very small, and it is usually not available in EXIF * data, you may give an approximative value here. If you really * do not know, as a last resort, use "1000" as a default value. * @param lens * The lens which aberrations you want to correct in a image. * It should be the same lens object as the one passed to * the lfModifier constructor. * @param format * Pixel format of your image (bits per pixel component) * @param focal * The focal length in mm at which the image was taken. * @param aperture * The aperture (f-number) at which the image was taken. * @param distance * The approximative focus distance in meters (distance > 0). * @param scale * An additional scale factor to be applied onto the image * (1.0 - no scaling; 0.0 - automatic scaling). * @param targeom * Target geometry. If LF_MODIFY_GEOMETRY is set in @a flags and * @a targeom is different from lens->Type, a geometry conversion * will be applied on the image. * @param flags * A set of flags (se LF_MODIFY_XXX) telling which distortions * you want corrected. A value of LF_MODIFY_ALL orders correction * of everything possible (will enable all correction models * present in lens description). * @param reverse * If this parameter is true, a reverse transform will be prepared. * That is, you take a undistorted image at input and convert it so * that it will look as if it would be a shot made with @a lens. * @return * A set of LF_MODIFY_XXX flags in effect. This is the @a flags argument * with dropped bits for operations which are actually no-ops. */ int Initialize ( const lfLens *lens, lfPixelFormat format, float focal, float aperture, float distance, float scale, lfLensType targeom, int flags, bool reverse); /** * @brief Destroy the modifier object. * * This function is deprecated and will be removed in the future. * Please use the standard destructor instead. */ DEPRECATED void Destroy (); /** * @brief Add a user-defined callback to the coordinate correction chain. * @param callback * The callback to be called for every strip of pixels. * @param priority * Callback priority (0-999). Callbacks are always called in * increasing priority order. * @param data * A pointer to additional user data. A copy of this data * is made internally, so client application may do whatever * it needs with this data after this call. * @param data_size * User data size in bytes. If data size is zero, the data is not * copied and instead a verbatim copy of the 'data' parameter * is passed to the callback. */ void AddCoordCallback (lfModifyCoordFunc callback, int priority, void *data, size_t data_size); /** * @brief Add a user-defined callback to the subpixel coordinate * rectification chain. * @param callback * The callback to be called for every strip of pixels. * @param priority * Callback priority (0-999). Callbacks are always called in * increasing priority order. * @param data * A pointer to additional user data. A copy of this data * is made internally, so client application may do whatever * it needs with this data after this call. * @param data_size * User data size in bytes. If data size is zero, the data is not * copied and instead a verbatim copy of the 'data' parameter * is passed to the callback. */ void AddSubpixelCallback (lfSubpixelCoordFunc callback, int priority, void *data, size_t data_size); /** * @brief Add a user-defined callback to the color modification chain. * @param callback * The callback to be called for every strip of pixels. * @param priority * Callback priority (0-999). Callbacks are always called in * increasing priority order. * @param data * A pointer to additional user data. A copy of this data * is made internally, so client application may do whatever * it needs with this data after this call. * @param data_size * User data size in bytes. If data size is zero, the data is not * copied and instead a verbatim copy of the 'data' parameter * is passed to the callback. */ void AddColorCallback (lfModifyColorFunc callback, int priority, void *data, size_t data_size); /** * @brief Add the stock TCA correcting callback into the chain. * * The TCA correction callback always has a fixed priority of 500. * The behaviour is undefined if you'll add more than one TCA * correction callback to a modifier. * @param model * Lens TCA model data. * @param reverse * If true, the reverse model will be applied, e.g. simulate * a lens' TCA on a clean image. * @return * True if TCA model is valid and the callback was added to chain. */ bool AddSubpixelCallbackTCA (lfLensCalibTCA &model, bool reverse = false); /** * @brief Add the stock lens vignetting correcting callback into the chain. * The vignetting correction callback always has a fixed priority of * 250 when rectifying a image or 750 when doing reverse transform. * @param model * Lens vignetting model data. * @param format * Pixel format of your image (bits per pixel component) * @param reverse * If true, the reverse model will be applied, e.g. simulate * a lens' vignetting on a clean image. * @return * True if vignetting model is valid and the callback was added to chain. */ bool AddColorCallbackVignetting (lfLensCalibVignetting &model, lfPixelFormat format, bool reverse = false); /** * @brief Add the stock lens distortion correcting callback into the chain. * * The distortion correction callback always has a fixed priority of 750 * when rectifying a image and 250 on reverse transform. * @param model * Lens distortion model data. * @param reverse * If true, the reverse model will be applied, e.g. simulate * a lens' distortion on a clean image. * @return * True if distortion model is valid and the callback was added to chain. */ bool AddCoordCallbackDistortion (lfLensCalibDistortion &model, bool reverse = false); /** * @brief Add the stock lens geometry rectification callback into the * chain. * * The geometry correction callback always has a fixed priority of 500. * @param from * The lens model for source image. * @param to * The lens model for target image. * @param focal * Lens focal length in mm. * @return * True if a library has a callback for given from->to conversion. */ bool AddCoordCallbackGeometry (lfLensType from, lfLensType to, float focal); /** * @brief Add the stock image scaling callback into the chain. * * The scaling callback always has a fixed priority of 100. * Note that scaling should be always the first operation to perform * no matter if we're doing a forward or reverse transform. * @param scale * Image scale. If equal to 0.0, the image is automatically scaled * so that there won't be any unfilled gaps in the resulting image. * Note that all coordinate distortion callbacks must be already * added to the stack for this to work correctly! * @param reverse * If true, the reverse model will be applied. * @return * True if the callback was added to chain. */ bool AddCoordCallbackScale (float scale, bool reverse = false); /** * @brief Compute the automatic scale factor for the image. * * This expects that all coordinate distortion callbacks are already * set up and working. The function will try at its best to find a * scale value that will ensure that no pixels with coordinates out * of range will get into the resulting image. But since this is * an approximative method, the returned scale sometimes is a little * less than the optimal scale (e.g. you can still get some black * corners with some high-distortion cases). * @param reverse * If true, the reverse scaling factor is computed. */ float GetAutoScale (bool reverse); /** * @brief Image correction step 1: fix image colors. * * This currently is only vignetting transform. * @param pixels * This points to image pixels. The actual pixel format depends on both * pixel_format and comp_role arguments. * The results are stored in place in the same format. * Warning: this array should be aligned at least on a 16-byte boundary. * @param x * The X coordinate of the corner of the block. * @param y * The Y coordinate of the corner of the block. * @param width * The width of the image block in pixels. * @param height * The height of the image block in pixels. * @param comp_role * The role of every pixel component. This is a bitfield, made by one * of the LF_CR_X macros which defines the roles of every pixel field. * For example, LF_CR_4(RED,GREEN,BLUE,UNKNOWN) will define a RGBA * (or RGBX) pixel format, and the UNKNOWN field will not be modified. * @param row_stride * The size of a image row in bytes. This can be actually different * from width * pixel_width as some image formats use funny things * like alignments, filler bytes etc. * @return * true if return buffer has been altered, false if nothing to do */ bool ApplyColorModification (void *pixels, float x, float y, int width, int height, int comp_role, int row_stride) const; /** * @brief Image correction step 2: apply the transforms on a block of pixel * coordinates. * * The undistorted coordinates are computed for every pixel in a * rectangular block: \f$(x_u, y_u), (x_u+1, y_u), \ldots, (x_u + * \mathrm{width} - 1, y_u), (x_u, y_u + 1), \ldots, (x_u + \mathrm{width} * - 1, y_u + \mathrm{height} - 1)\f$. * * The corrected coordinates are put into the output buffer * sequentially, X and Y values. * * This routine has been designed to be safe to use in parallel from * several threads. * @param xu * The undistorted X coordinate of the start of the block of pixels. * @param yu * The undistorted Y coordinate of the start of the block of pixels. * @param width * The width of the block in pixels. * @param height * The height of the block in pixels. * @param res * A pointer to an output array which receives the respective X and Y * distorted coordinates for every pixel of the block. The size of * this array must be at least width*height*2 elements. * Warning: this array should be aligned at least on a 16-byte boundary. * @return * true if return buffer has been filled, false if nothing to do */ bool ApplyGeometryDistortion (float xu, float yu, int width, int height, float *res) const; /** * @brief Image correction step 3: apply subpixel distortions. * * The undistorted R,G,B coordinates are computed for every pixel in a * square block: \f$(x_u, y_u), (x_u+1, y_u), \ldots, (x_u + * \mathrm{width} - 1, y_u), (x_u, y_u + 1), \ldots, (x_u + \mathrm{width} * - 1, y_u + \mathrm{height} - 1)\f$. * * Returns the corrected coordinates separately for R/G/B channels * The resulting coordinates are put into the output buffer * sequentially, X and Y values. * * This routine has been designed to be safe to use in parallel from * several threads. * @param xu * The undistorted X coordinate of the start of the block of pixels. * @param yu * The undistorted Y coordinate of the start of the block of pixels. * @param width * The width of the block in pixels. * @param height * The height of the block in pixels. * @param res * A pointer to an output array which receives the respective X and Y * distorted coordinates of the red, green and blue channels for * every pixel of the block. The size of this array must be * at least width*height*2*3 elements. * Warning: this array should be aligned at least on a 16-byte boundary. * @return * true if return buffer has been filled, false if nothing to do */ bool ApplySubpixelDistortion (float xu, float yu, int width, int height, float *res) const; /** * @brief Apply stage 2 & 3 in one step. * * See the main comment to the lfModifier class. The undistorted (R, G, B) * coordinates are computed for every pixel in a square block: \f$(x_u, * y_u), (x_u+1, y_u), \ldots, (x_u + \mathrm{width} - 1, y_u), (x_u, y_u + * 1), \ldots, (x_u + \mathrm{width} - 1, y_u + \mathrm{height} - 1)\f$. * * Returns the corrected coordinates separately for R/G/B channels * The resulting coordinates are put into the output buffer * sequentially, X and Y values. * * This routine has been designed to be safe to use in parallel from * several threads. * @param xu * The undistorted X coordinate of the start of the block of pixels. * @param yu * The undistorted Y coordinate of the start of the block of pixels. * @param width * The width of the block in pixels. * @param height * The height of the block in pixels. * @param res * A pointer to an output array which receives the respective X and Y * distorted coordinates for every pixel of the block. The size of * this array must be at least width*height*2*3 elements. * Warning: this array should be aligned at least on a 16-byte boundary. * @return * true if return buffer has been filled, false if nothing to do */ bool ApplySubpixelGeometryDistortion (float xu, float yu, int width, int height, float *res) const; private: /** * @brief Determine the real focal length. * * Returns the real focal length (in contrast to the nominal focal length * given in the "focal" attribute in the XML files). This is the textbook * focal length, derived from the magnification in paraxial approximation. * It is needed for accurate geometry transformations, e.g. from fisheye to * rectilinear. If there is neither real focal length nor FOV data * available, the nominal focal length is returned as a fallback. * * In practice, its effect is mostly negligible. When converting to * rectilinear, it merely results in a magnification (which probably is * reverted by autoscaling). When converting to a fisheye projection * besides stereographic, the degree of distortion is not detectable by the * human eye. Moreover, most non-fisheyes have quite accurate nominal * focal lengths printed on the lens. Thus, the only use case left is the * conversion from non-stereographic fisheye to stereographic. This maps * perfect circled to perfect circles, so it is noticeable if the nominal * focal length is rather off. * * @param lens * The lens for which the focal length should be returned. * @param focal * The nominal focal length for which the real focal length should be * returned. * @return * the real focal length, or, if no real focal length data and no FOV * data is included into the calibration, the given nominal focal * length */ float GetRealFocalLength (const lfLens *lens, float focal); void AddCallback (void *arr, lfCallbackData *d, int priority, void *data, size_t data_size); /** * @brief Calculate distance between point and image edge. * * This is an internal function used for autoscaling. It returns the * distance between the given point and the edge of the image. The * coordinate system used is the normalized system. Points inside the * image frame yield negative values, points outside positive values, and * on the frame zero. * @param coord * The x, y coordinates of the points, as a 2-component array. * @return * The distance of the point from the edge. */ double AutoscaleResidualDistance (float *coord) const; /** * @brief Calculate distance of the corrected edge point from the centre. * * This is an internal function used for autoscaling. It returns the * distance of the point on the edge of the corrected image which lies in * the direction of the given coordinates. "Distance" means "distance from * origin". This way, the necessary autoscaling value for this direction * can be calculated by the calling routine. * @param point * The polar coordinates of the point for which the distance of the * corrected counterpart should be calculated. * @return * The distance of the corrected image edge from the origin. */ float GetTransformedDistance (lfPoint point) const; static void ModifyCoord_UnTCA_Linear (void *data, float *iocoord, int count); static void ModifyCoord_TCA_Linear (void *data, float *iocoord, int count); static void ModifyCoord_UnTCA_Poly3 (void *data, float *iocoord, int count); static void ModifyCoord_TCA_Poly3 (void *data, float *iocoord, int count); static void ModifyCoord_UnDist_Poly3 (void *data, float *iocoord, int count); static void ModifyCoord_Dist_Poly3 (void *data, float *iocoord, int count); #ifdef VECTORIZATION_SSE static void ModifyCoord_Dist_Poly3_SSE (void *data, float *iocoord, int count); #endif static void ModifyCoord_UnDist_Poly5 (void *data, float *iocoord, int count); static void ModifyCoord_Dist_Poly5 (void *data, float *iocoord, int count); static void ModifyCoord_UnDist_PTLens (void *data, float *iocoord, int count); static void ModifyCoord_Dist_PTLens (void *data, float *iocoord, int count); #ifdef VECTORIZATION_SSE static void ModifyCoord_UnDist_PTLens_SSE (void *data, float *iocoord, int count); static void ModifyCoord_Dist_PTLens_SSE (void *data, float *iocoord, int count); #endif static void ModifyCoord_Geom_FishEye_Rect (void *data, float *iocoord, int count); static void ModifyCoord_Geom_Panoramic_Rect (void *data, float *iocoord, int count); static void ModifyCoord_Geom_ERect_Rect (void *data, float *iocoord, int count); static void ModifyCoord_Geom_Rect_FishEye (void *data, float *iocoord, int count); static void ModifyCoord_Geom_Panoramic_FishEye (void *data, float *iocoord, int count); static void ModifyCoord_Geom_ERect_FishEye (void *data, float *iocoord, int count); static void ModifyCoord_Geom_Rect_Panoramic (void *data, float *iocoord, int count); static void ModifyCoord_Geom_FishEye_Panoramic (void *data, float *iocoord, int count); static void ModifyCoord_Geom_ERect_Panoramic (void *data, float *iocoord, int count); static void ModifyCoord_Geom_Rect_ERect (void *data, float *iocoord, int count); static void ModifyCoord_Geom_FishEye_ERect (void *data, float *iocoord, int count); static void ModifyCoord_Geom_Panoramic_ERect (void *data, float *iocoord, int count); static void ModifyCoord_Geom_Orthographic_ERect (void *data, float *iocoord, int count); static void ModifyCoord_Geom_ERect_Orthographic (void *data, float *iocoord, int count); static void ModifyCoord_Geom_Stereographic_ERect (void *data, float *iocoord, int count); static void ModifyCoord_Geom_ERect_Stereographic (void *data, float *iocoord, int count); static void ModifyCoord_Geom_Equisolid_ERect (void *data, float *iocoord, int count); static void ModifyCoord_Geom_ERect_Equisolid (void *data, float *iocoord, int count); static void ModifyCoord_Geom_Thoby_ERect (void *data, float *iocoord, int count); static void ModifyCoord_Geom_ERect_Thoby (void *data, float *iocoord, int count); #ifdef VECTORIZATION_SSE static void ModifyColor_DeVignetting_PA_SSE ( void *data, float _x, float _y, lf_f32 *pixels, int comp_role, int count); #endif #ifdef VECTORIZATION_SSE2 static void ModifyColor_DeVignetting_PA_SSE2 ( void *data, float _x, float _y, lf_u16 *pixels, int comp_role, int count); #endif template static void ModifyColor_Vignetting_PA ( void *data, float x, float y, T *rgb, int comp_role, int count); template static void ModifyColor_DeVignetting_PA ( void *data, float x, float y, T *rgb, int comp_role, int count); static void ModifyCoord_Scale (void *data, float *iocoord, int count); #endif /// Image width and height int Width, Height; /// The center of distortions in normalized coordinates double CenterX, CenterY; /// The coefficients for conversion to and from normalized coords double NormScale, NormUnScale; /// Factor to transform from normalized into absolute coords (mm). Needed /// for geometry transformation. double NormalizedInMillimeters; /// Used for conversion from distortion to vignetting coordinate system of /// the calibration sensor double AspectRatioCorrection; /// A list of subpixel coordinate modifier callbacks. void *SubpixelCallbacks; /// A list of pixel color modifier callbacks. void *ColorCallbacks; /// A list of pixel coordinate modifier callbacks. void *CoordCallbacks; /// Maximal x and y value in normalized coordinates for the original image double MaxX, MaxY; }; #ifdef __cplusplus extern "C" { #endif C_TYPEDEF (struct, lfModifier) /** @sa lfModifier::Create */ LF_EXPORT lfModifier *lf_modifier_new ( const lfLens *lens, float crop, int width, int height); /** @sa lfModifier::Destroy */ LF_EXPORT void lf_modifier_destroy (lfModifier *modifier); /** @sa lfModifier::Initialize */ LF_EXPORT int lf_modifier_initialize ( lfModifier *modifier, const lfLens *lens, lfPixelFormat format, float focal, float aperture, float distance, float scale, lfLensType targeom, int flags, cbool reverse); /** @sa lfModifier::AddCoordCallback */ LF_EXPORT void lf_modifier_add_coord_callback ( lfModifier *modifier, lfModifyCoordFunc callback, int priority, void *data, size_t data_size); /** @sa lfModifier::AddSubpixelCallback */ LF_EXPORT void lf_modifier_add_subpixel_callback ( lfModifier *modifier, lfSubpixelCoordFunc callback, int priority, void *data, size_t data_size); /** @sa lfModifier::AddColorCallback */ LF_EXPORT void lf_modifier_add_color_callback ( lfModifier *modifier, lfModifyColorFunc callback, int priority, void *data, size_t data_size); /** @sa lfModifier::AddSubpixelCallbackTCA */ LF_EXPORT cbool lf_modifier_add_subpixel_callback_TCA ( lfModifier *modifier, lfLensCalibTCA *model, cbool reverse); /** @sa lfModifier::AddColorCallbackVignetting */ LF_EXPORT cbool lf_modifier_add_color_callback_vignetting ( lfModifier *modifier, lfLensCalibVignetting *model, lfPixelFormat format, cbool reverse); /** @sa lfModifier::AddCoordCallbackDistortion */ LF_EXPORT cbool lf_modifier_add_coord_callback_distortion ( lfModifier *modifier, lfLensCalibDistortion *model, cbool reverse); /** @sa lfModifier::AddCoordCallbackGeometry */ LF_EXPORT cbool lf_modifier_add_coord_callback_geometry ( lfModifier *modifier, lfLensType from, lfLensType to, float focal); /** @sa lfModifier::AddCoordCallbackScale */ LF_EXPORT cbool lf_modifier_add_coord_callback_scale ( lfModifier *modifier, float scale, cbool reverse); /** @sa lfModifier::GetAutoScale */ LF_EXPORT float lf_modifier_get_auto_scale ( lfModifier *modifier, cbool reverse); /** @sa lfModifier::ApplySubpixelDistortion */ LF_EXPORT cbool lf_modifier_apply_subpixel_distortion ( lfModifier *modifier, float xu, float yu, int width, int height, float *res); /** @sa lfModifier::ApplyColorModification */ LF_EXPORT cbool lf_modifier_apply_color_modification ( lfModifier *modifier, void *pixels, float x, float y, int width, int height, int comp_role, int row_stride); /** @sa lfModifier::ApplyGeometryDistortion */ LF_EXPORT cbool lf_modifier_apply_geometry_distortion ( lfModifier *modifier, float xu, float yu, int width, int height, float *res); /** @sa lfModifier::ApplySubpixelGeometryDistortion */ LF_EXPORT cbool lf_modifier_apply_subpixel_geometry_distortion ( lfModifier *modifier, float xu, float yu, int width, int height, float *res); /** @} */ #undef cbool #ifdef __cplusplus } #endif #endif /* __LENSFUN_H__ */ lensfun-0.3.4/include/regex/000077500000000000000000000000001445356770400157445ustar00rootroot00000000000000lensfun-0.3.4/include/regex/regex.h000066400000000000000000000201061445356770400172260ustar00rootroot00000000000000/* regex.h - POSIX.2 compatible regexp interface and TRE extensions Copyright (c) 2001-2006 Ville Laurikari . This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TRE_REGEX_H #define TRE_REGEX_H 1 #include "config.h" #ifdef HAVE_SYS_TYPES_H #include #endif /* HAVE_SYS_TYPES_H */ #ifdef HAVE_LIBUTF8_H #include #endif /* HAVE_LIBUTF8_H */ #ifdef TRE_USE_SYSTEM_REGEX_H /* Include the system regex.h to make TRE ABI compatible with the system regex. */ #include TRE_SYSTEM_REGEX_H_PATH #endif /* TRE_USE_SYSTEM_REGEX_H */ #ifdef __cplusplus extern "C" { #endif #ifdef TRE_USE_SYSTEM_REGEX_H #ifndef REG_OK #define REG_OK 0 #endif /* !REG_OK */ #ifndef HAVE_REG_ERRCODE_T typedef int reg_errcode_t; #endif /* !HAVE_REG_ERRCODE_T */ #if !defined(REG_NOSPEC) && !defined(REG_LITERAL) #define REG_LITERAL 0x1000 #endif /* Extra regcomp() flags. */ #ifndef REG_BASIC #define REG_BASIC 0 #endif /* !REG_BASIC */ #define REG_RIGHT_ASSOC (REG_LITERAL << 1) #define REG_UNGREEDY (REG_RIGHT_ASSOC << 1) /* Extra regexec() flags. */ #define REG_APPROX_MATCHER 0x1000 #define REG_BACKTRACKING_MATCHER (REG_APPROX_MATCHER << 1) #else /* !TRE_USE_SYSTEM_REGEX_H */ /* If the we're not using system regex.h, we need to define the structs and enums ourselves. */ typedef int regoff_t; typedef struct { size_t re_nsub; /* Number of parenthesized subexpressions. */ void *value; /* For internal use only. */ } regex_t; typedef struct { regoff_t rm_so; regoff_t rm_eo; } regmatch_t; typedef enum { REG_OK = 0, /* No error. */ /* POSIX regcomp() return error codes. (In the order listed in the standard.) */ REG_NOMATCH, /* No match. */ REG_BADPAT, /* Invalid regexp. */ REG_ECOLLATE, /* Unknown collating element. */ REG_ECTYPE, /* Unknown character class name. */ REG_EESCAPE, /* Trailing backslash. */ REG_ESUBREG, /* Invalid back reference. */ REG_EBRACK, /* "[]" imbalance */ REG_EPAREN, /* "\(\)" or "()" imbalance */ REG_EBRACE, /* "\{\}" or "{}" imbalance */ REG_BADBR, /* Invalid content of {} */ REG_ERANGE, /* Invalid use of range operator */ REG_ESPACE, /* Out of memory. */ REG_BADRPT /* Invalid use of repetition operators. */ } reg_errcode_t; /* POSIX regcomp() flags. */ #define REG_EXTENDED 1 #define REG_ICASE (REG_EXTENDED << 1) #define REG_NEWLINE (REG_ICASE << 1) #define REG_NOSUB (REG_NEWLINE << 1) /* Extra regcomp() flags. */ #define REG_BASIC 0 #define REG_LITERAL (REG_NOSUB << 1) #define REG_RIGHT_ASSOC (REG_LITERAL << 1) #define REG_UNGREEDY (REG_RIGHT_ASSOC << 1) /* POSIX regexec() flags. */ #define REG_NOTBOL 1 #define REG_NOTEOL (REG_NOTBOL << 1) /* Extra regexec() flags. */ #define REG_APPROX_MATCHER (REG_NOTEOL << 1) #define REG_BACKTRACKING_MATCHER (REG_APPROX_MATCHER << 1) #endif /* !TRE_USE_SYSTEM_REGEX_H */ /* REG_NOSPEC and REG_LITERAL mean the same thing. */ #if defined(REG_LITERAL) && !defined(REG_NOSPEC) #define REG_NOSPEC REG_LITERAL #elif defined(REG_NOSPEC) && !defined(REG_LITERAL) #define REG_LITERAL REG_NOSPEC #endif /* defined(REG_NOSPEC) */ /* The maximum number of iterations in a bound expression. */ #undef RE_DUP_MAX #define RE_DUP_MAX 255 /* The POSIX.2 regexp functions */ extern int regcomp(regex_t *preg, const char *regex, int cflags); extern int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); extern size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size); extern void regfree(regex_t *preg); #ifdef TRE_WCHAR #ifdef HAVE_WCHAR_H #include #endif /* HAVE_WCHAR_H */ /* Wide character versions (not in POSIX.2). */ extern int regwcomp(regex_t *preg, const wchar_t *regex, int cflags); extern int regwexec(const regex_t *preg, const wchar_t *string, size_t nmatch, regmatch_t pmatch[], int eflags); #endif /* TRE_WCHAR */ /* Versions with a maximum length argument and therefore the capability to handle null characters in the middle of the strings (not in POSIX.2). */ extern int regncomp(regex_t *preg, const char *regex, size_t len, int cflags); extern int regnexec(const regex_t *preg, const char *string, size_t len, size_t nmatch, regmatch_t pmatch[], int eflags); #ifdef TRE_WCHAR extern int regwncomp(regex_t *preg, const wchar_t *regex, size_t len, int cflags); extern int regwnexec(const regex_t *preg, const wchar_t *string, size_t len, size_t nmatch, regmatch_t pmatch[], int eflags); #endif /* TRE_WCHAR */ #ifdef TRE_APPROX /* Approximate matching parameter struct. */ typedef struct { int cost_ins; /* Default cost of an inserted character. */ int cost_del; /* Default cost of a deleted character. */ int cost_subst; /* Default cost of a substituted character. */ int max_cost; /* Maximum allowed cost of a match. */ int max_ins; /* Maximum allowed number of inserts. */ int max_del; /* Maximum allowed number of deletes. */ int max_subst; /* Maximum allowed number of substitutes. */ int max_err; /* Maximum allowed number of errors total. */ } regaparams_t; /* Approximate matching result struct. */ typedef struct { size_t nmatch; /* Length of pmatch[] array. */ regmatch_t *pmatch; /* Submatch data. */ int cost; /* Cost of the match. */ int num_ins; /* Number of inserts in the match. */ int num_del; /* Number of deletes in the match. */ int num_subst; /* Number of substitutes in the match. */ } regamatch_t; /* Approximate matching functions. */ extern int regaexec(const regex_t *preg, const char *string, regamatch_t *match, regaparams_t params, int eflags); extern int reganexec(const regex_t *preg, const char *string, size_t len, regamatch_t *match, regaparams_t params, int eflags); #ifdef TRE_WCHAR /* Wide character approximate matching. */ extern int regawexec(const regex_t *preg, const wchar_t *string, regamatch_t *match, regaparams_t params, int eflags); extern int regawnexec(const regex_t *preg, const wchar_t *string, size_t len, regamatch_t *match, regaparams_t params, int eflags); #endif /* TRE_WCHAR */ /* Sets the parameters to default values. */ extern void regaparams_default(regaparams_t *params); #endif /* TRE_APPROX */ #ifdef TRE_WCHAR typedef wchar_t tre_char_t; #else /* !TRE_WCHAR */ typedef unsigned char tre_char_t; #endif /* !TRE_WCHAR */ typedef struct { int (*get_next_char)(tre_char_t *c, unsigned int *pos_add, void *context); void (*rewind)(size_t pos, void *context); int (*compare)(size_t pos1, size_t pos2, size_t len, void *context); void *context; } tre_str_source; extern int reguexec(const regex_t *preg, const tre_str_source *string, size_t nmatch, regmatch_t pmatch[], int eflags); /* Returns the version string. The returned string is static. */ extern char * tre_version(void); /* Returns the value for a config parameter. The type to which `result' must point to depends of the value of `query', see documentation for more details. */ extern int tre_config(int query, void *result); enum { TRE_CONFIG_APPROX, TRE_CONFIG_WCHAR, TRE_CONFIG_MULTIBYTE, TRE_CONFIG_SYSTEM_ABI, TRE_CONFIG_VERSION }; /* Returns 1 if the compiled pattern has back references, 0 if not. */ extern int tre_have_backrefs(const regex_t *preg); /* Returns 1 if the compiled pattern uses approximate matching features, 0 if not. */ extern int tre_have_approx(const regex_t *preg); #ifdef __cplusplus } #endif #endif /* TRE_REGEX_H */ /* EOF */ lensfun-0.3.4/libs/000077500000000000000000000000001445356770400141405ustar00rootroot00000000000000lensfun-0.3.4/libs/CMakeLists.txt000066400000000000000000000002571445356770400167040ustar00rootroot00000000000000IF(NOT HAVE_REGEX_H) ADD_SUBDIRECTORY(regex) ENDIF() ADD_SUBDIRECTORY(lensfun) # also build getopt on windows IF(WIN32 AND BUILD_TESTS) ADD_SUBDIRECTORY(getopt) ENDIF() lensfun-0.3.4/libs/getopt/000077500000000000000000000000001445356770400154425ustar00rootroot00000000000000lensfun-0.3.4/libs/getopt/CMakeLists.txt000066400000000000000000000000551445356770400202020ustar00rootroot00000000000000ADD_LIBRARY(getopt STATIC getopt.c getopt.h) lensfun-0.3.4/libs/getopt/LICENSE000066400000000000000000000461061445356770400164560ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (c) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software - to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The ``Program'', below, refers to any such program or work, and a ``work based on the Program'' means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term ``modification''.) Each licensee is addressed as ``you''. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a. You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b. You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c. If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a. Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b. Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c. Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and ``any later version'', you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found. One line to give the program's name and a brief idea of what it does. Copyright (C) 19yy Name of author This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy Name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands show w and show c should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than show w and show c; they could even be mouse-clicks or menu items - whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a ``copyright disclaimer'' for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. Signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. lensfun-0.3.4/libs/getopt/getopt.c000066400000000000000000000527411445356770400171210ustar00rootroot00000000000000/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* NOTE!!! AIX requires this to be the first thing in the file. Do not put ANYTHING before it! */ #if !defined (__GNUC__) && defined (_AIX) #pragma alloca #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef __GNUC__ #define alloca __builtin_alloca #else /* not __GNUC__ */ #if defined (HAVE_ALLOCA_H) || (defined(sparc) && (defined(sun) || (!defined(USG) && !defined(SVR4) && !defined(__svr4__)))) #include #else #ifndef _AIX char *alloca (); #endif #endif /* alloca.h */ #endif /* not __GNUC__ */ #if !__STDC__ && !defined(const) && IN_GCC #define const #endif /* This tells Alpha OSF/1 not to define a getopt prototype in . */ #ifndef _NO_PROTO #define _NO_PROTO #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #if defined (_LIBC) || !defined (__GNU_LIBRARY__) /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ #undef alloca /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ #include #else /* Not GNU C library. */ #if defined(__IBMC__) || defined(__IBMCPP__) || defined(_MSC_VER) #include #ifdef _MSC_VER #include #undef __alloca #define __alloca _alloca #else #undef alloca #define alloca _alloca #endif #else #define __alloca alloca #endif /* IBMCSet */ #endif /* GNU C library. */ /* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a long-named option. Because this is not POSIX.2 compliant, it is being phased out. */ /* #define GETOPT_COMPAT */ /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = 0; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* XXX 1003.2 says this must be 1 before any call. */ int optind = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return EOF with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; #if defined(__GNU_LIBRARY__) || defined(__IBMC__) || defined(__IBMCPP__) || defined(_MSC_VER) /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ #include #define my_index strchr #define my_bcopy(src, dst, n) memcpy ((dst), (src), (n)) #else /* Avoid depending on library functions or files whose names are inconsistent. */ char *getenv (); static char * #if __STDC__ || _MSC_VER my_index (const char *str, int chr) #else my_index (str, chr) const char *str; int chr; #endif { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } static void #if __STDC__ || _MSC_VER my_bcopy (const char *from, char *to, int size) #else my_bcopy (from, to, size) const char *from; char *to; int size; #endif { int i; for (i = 0; i < size; i++) to[i] = from[i]; } #endif /* GNU C library. */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ static void #if __STDC__ || _MSC_VER exchange (char **argv) #else exchange (argv) char **argv; #endif { int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *); char **temp = (char **) __alloca (nonopts_size); /* Interchange the two blocks of data in ARGV. */ my_bcopy ((char *) &argv[first_nonopt], (char *) temp, nonopts_size); my_bcopy ((char *) &argv[last_nonopt], (char *) &argv[first_nonopt], (optind - last_nonopt) * sizeof (char *)); my_bcopy ((char *) temp, (char *) &argv[first_nonopt + optind - last_nonopt], nonopts_size); /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns `EOF'. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int #if __STDC__ || _MSC_VER _getopt_internal (int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind, int long_only) #else _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int argc; char *const *argv; const char *optstring; const struct option *longopts; int *longind; int long_only; #endif { int option_index; optarg = 0; /* Initialize the internal data when the first call is made. Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ if (optind == 0) { first_nonopt = last_nonopt = optind = 1; nextchar = NULL; /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (getenv ("POSIXLY_CORRECT") != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; } if (nextchar == NULL || *nextchar == '\0') { if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Now skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && (argv[optind][0] != '-' || argv[optind][1] == '\0') #ifdef GETOPT_COMPAT && (longopts == NULL || argv[optind][0] != '+' || argv[optind][1] == '\0') #endif /* GETOPT_COMPAT */ ) optind++; last_nonopt = optind; } /* Special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return EOF; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if ((argv[optind][0] != '-' || argv[optind][1] == '\0') #ifdef GETOPT_COMPAT && (longopts == NULL || argv[optind][0] != '+' || argv[optind][1] == '\0') #endif /* GETOPT_COMPAT */ ) { if (ordering == REQUIRE_ORDER) return EOF; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Start decoding its characters. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } if (longopts != NULL && ((argv[optind][0] == '-' && (argv[optind][1] == '-' || long_only)) #ifdef GETOPT_COMPAT || argv[optind][0] == '+' #endif /* GETOPT_COMPAT */ )) { const struct option *p; char *s = nextchar; int exact = 0; int ambig = 0; const struct option *pfound = NULL; int indfound = 0; while (*s && *s != '=') s++; /* Test all options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, s - nextchar)) { if ((size_t) (s - nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, "%s: option `%s' is ambiguous\n", argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*s) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = s + 1; else { if (opterr) { if (argv[optind - 1][1] == '-') /* --option */ fprintf (stderr, "%s: option `--%s' doesn't allow an argument\n", argv[0], pfound->name); else /* +option or -option */ fprintf (stderr, "%s: option `%c%s' doesn't allow an argument\n", argv[0], argv[optind - 1][0], pfound->name); } nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, "%s: option `%s' requires an argument\n", argv[0], argv[optind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' #ifdef GETOPT_COMPAT || argv[optind][0] == '+' #endif /* GETOPT_COMPAT */ || my_index (optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ fprintf (stderr, "%s: unrecognized option `--%s'\n", argv[0], nextchar); else /* +option or -option */ fprintf (stderr, "%s: unrecognized option `%c%s'\n", argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; return '?'; } } /* Look at and handle the next option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (opterr) { #if 0 if (c < 040 || c >= 0177) fprintf (stderr, "%s: unrecognized option, character code 0%o\n", argv[0], c); else fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); #else /* 1003.2 specifies the format of this message. */ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); #endif } optopt = c; return '?'; } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = 0; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { #if 0 fprintf (stderr, "%s: option `-%c' requires an argument\n", argv[0], c); #else /* 1003.2 specifies the format of this message. */ fprintf (stderr, "%s: option requires an argument -- %c\n", argv[0], c); #endif } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int #if __STDC__ || _MSC_VER getopt (int argc, char *const *argv, const char *optstring) #else getopt (argc, argv, optstring) int argc; char *const *argv; const char *optstring; #endif { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind) { return _getopt_internal(argc, argv, shortopts, longopts, longind, 0); } #endif /* _LIBC or not __GNU_LIBRARY__. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int #if __STDC__ || _MSC_VER main (int argc, char **argv) #else main (argc, argv) int argc; char **argv; #endif { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == EOF) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ lensfun-0.3.4/libs/getopt/getopt.h000066400000000000000000000106701445356770400171210ustar00rootroot00000000000000/* Declarations for getopt. Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _GETOPT_H #define _GETOPT_H 1 #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { #if __STDC__ || _MSC_VER || defined(XP_OS2_VACPP) const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #if __STDC__ || _MSC_VER || defined( XP_OS2_VACPP ) #if defined(__GNU_LIBRARY__) || defined( XP_OS2_VACPP ) || defined(_MSC_VER) /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int argc, char *const *argv, const char *shortopts); #else /* not __GNU_LIBRARY__ */ extern int getopt (); #endif /* not __GNU_LIBRARY__ */ extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind, int long_only); #else /* not __STDC__ */ extern int getopt (); extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); #endif /* not __STDC__ */ #ifdef __cplusplus } #endif #endif /* _GETOPT_H */ lensfun-0.3.4/libs/lensfun/000077500000000000000000000000001445356770400156125ustar00rootroot00000000000000lensfun-0.3.4/libs/lensfun/CMakeLists.txt000066400000000000000000000027451445356770400203620ustar00rootroot00000000000000# build Lensfun library SET(LENSFUN_SRC camera.cpp database.cpp lens.cpp mount.cpp lensfunprv.h cpuid.cpp mod-color-sse.cpp mod-color-sse2.cpp mod-color.cpp mod-coord-sse.cpp mod-coord.cpp mod-subpix.cpp modifier.cpp auxfun.cpp ../../include/lensfun/lensfun.h.in) IF(WIN32) LIST(APPEND LENSFUN_SRC windows/auxfun.cpp) ENDIF() SET_SOURCE_FILES_PROPERTIES(mod-color-sse.cpp mod-coord-sse.cpp PROPERTIES COMPILE_FLAGS "${VECTORIZATION_SSE_FLAGS}") SET_SOURCE_FILES_PROPERTIES(mod-color-sse2.cpp PROPERTIES COMPILE_FLAGS "${VECTORIZATION_SSE2_FLAGS}") IF(BUILD_STATIC) ADD_LIBRARY(lensfun STATIC ${LENSFUN_SRC}) ELSE() ADD_LIBRARY(lensfun SHARED ${LENSFUN_SRC}) SET_TARGET_PROPERTIES(lensfun PROPERTIES COMPILE_FLAGS -DCONF_SYMBOL_VISIBILITY) ENDIF() SET_TARGET_PROPERTIES(lensfun PROPERTIES SOVERSION "${VERSION_API}" VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO}") IF(NOT HAVE_REGEX_H) TARGET_LINK_LIBRARIES(lensfun tre_regex) ENDIF() TARGET_LINK_LIBRARIES(lensfun ${GLIB2_LIBRARIES}) INSTALL(TARGETS lensfun RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) # pkgconfig support CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/lensfun.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/lensfun.pc @ONLY) INSTALL( FILES ${CMAKE_CURRENT_BINARY_DIR}/lensfun.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) lensfun-0.3.4/libs/lensfun/auxfun.cpp000066400000000000000000000353601445356770400176330ustar00rootroot00000000000000/* Auxiliary helper functions for Lensfun Copyright (C) 2007 by Andrew Zabolotny */ #include "config.h" #include "lensfun.h" #include "lensfunprv.h" #include #include #include #include static const char *_lf_get_lang () { #ifndef LC_MESSAGES /* Windows badly sucks, like always */ # define LC_MESSAGES LC_ALL #endif static char lang [16]; static const char *last_locale = NULL; const char *lc_msg = setlocale (LC_MESSAGES, NULL); if (!lc_msg) return strcpy (lang, "en"); if (lc_msg == last_locale) return lang; const char *u = strchr (lc_msg, '_'); if (!u || (size_t (u - lc_msg) >= sizeof (lang))) return strcpy (lang, "en"); memcpy (lang, lc_msg, u - lc_msg); lang [u - lc_msg] = 0; /* On Windows we have "Russian" instead of "ru" and so on... :-( * Microsoft, like always, invents his own stuff, never heard of ISO 639-1 */ if (u - lc_msg > 2) { /* For now, just take the first two letters of language name. */ lang [0] = tolower (lang [0]); lang [1] = tolower (lang [1]); lang [2] = 0; } return lang; } LF_EXPORT void lf_free (void *data) { g_free (data); } LF_EXPORT const char *lf_mlstr_get (const lfMLstr str) { if (!str) return str; /* Get the current locale for messages */ const char *lang = _lf_get_lang (); /* Default value if no language matches */ const char *def = str; /* Find the corresponding string in the lot */ const char *cur = strchr (str, 0) + 1; while (*cur) { const char *next = strchr (cur, 0) + 1; if (!strcmp (cur, lang)) return next; if (!strcmp (cur, "en")) def = next; if (*(cur = next)) cur = strchr (cur, 0) + 1; } return def; } LF_EXPORT lfMLstr lf_mlstr_add (lfMLstr str, const char *lang, const char *trstr) { if (!trstr) return str; size_t trstr_len = strlen (trstr) + 1; /* Find the length of multi-language string */ size_t str_len = 0; if (str) { str_len = strlen (str) + 1; while (str [str_len]) str_len += 1 + strlen (str + str_len); } if (!lang) { /* Replace the default string */ size_t def_str_len = str ? strlen (str) + 1 : 0; memcpy (str + trstr_len, str + def_str_len, str_len - def_str_len); str = (char *)g_realloc (str, str_len - def_str_len + trstr_len + 1); memcpy (str, trstr, trstr_len); str_len = str_len - def_str_len + trstr_len; str [str_len] = 0; return str; } size_t lang_len = lang ? strlen (lang) + 1 : 0; str = (char *)g_realloc (str, str_len + lang_len + trstr_len + 1); memcpy (str + str_len, lang, lang_len); memcpy (str + str_len + lang_len, trstr, trstr_len); str [str_len + lang_len + trstr_len] = 0; return str; } LF_EXPORT lfMLstr lf_mlstr_dup (const lfMLstr str) { /* Find the length of multi-language string */ size_t str_len = 0; if (str) { str_len = strlen (str) + 1; while (str [str_len]) str_len += 2 + strlen (str + str_len + 1); /* Reserve space for the last - closing - zero */ str_len++; } gchar *ret = (char *)g_malloc (str_len); memcpy (ret, str, str_len); return ret; } void _lf_list_free (void **list) { int i; if (!list) return; for (i = 0; list [i]; i++) g_free (list [i]); g_free (list); } void _lf_setstr (gchar **var, const gchar *val) { if (*var) g_free (*var); *var = g_strdup (val); } void _lf_addstr (gchar ***var, const gchar *val) { _lf_addobj ((void ***)var, val, strlen (val) + 1, NULL); } void _lf_addobj (void ***var, const void *val, size_t val_size, bool (*cmpf) (const void *, const void *)) { int n = 0; if (*var) for (n = 0; (*var) [n]; n++) if (cmpf && cmpf (val, (*var) [n])) { g_free ((*var) [n]); goto alloc_copy; return; } n++; (*var) = (void **)g_realloc (*var, (n + 1) * sizeof (void *)); (*var) [n--] = NULL; alloc_copy: (*var) [n] = g_malloc (val_size); memcpy ((*var) [n], val, val_size); } bool _lf_delobj (void ***var, int idx) { if (!(*var)) return false; int len; for (len = 0; (*var) [len]; len++) ; if (idx < 0 || idx >= len) return false; g_free ((*var) [idx]); memmove (&(*var) [idx], &(*var) [idx + 1], (len - idx) * sizeof (void *)); (*var) = (void **)g_realloc (*var, len * sizeof (void *)); return true; } void _lf_xml_printf (GString *output, const char *format, ...) { va_list args; va_start (args, format); gchar *s = g_markup_vprintf_escaped (format, args); va_end (args); g_string_append (output, s); g_free (s); } void _lf_xml_printf_mlstr (GString *output, const char *prefix, const char *element, const lfMLstr val) { if (!val) return; _lf_xml_printf (output, "%s<%s>%s\n", prefix, element, val, element); for (const char *cur = val;;) { cur = strchr (cur, 0) + 1; if (!*cur) break; const char *lang = cur; cur = strchr (cur, 0) + 1; _lf_xml_printf (output, "%s<%s lang=\"%s\">%s\n", prefix, element, lang, cur, element); } } int _lf_ptr_array_insert_sorted ( GPtrArray *array, void *item, GCompareFunc compare) { int length = array->len; g_ptr_array_set_size (array, length + 1); void **root = array->pdata; int m = 0, l = 0, r = length - 1; // Skip trailing NULL, if any if (l <= r && !root [r]) r--; while (l <= r) { m = (l + r) / 2; int cmp = compare (root [m], item); if (cmp == 0) { ++m; goto done; } else if (cmp < 0) l = m + 1; else r = m - 1; } if (r == m) m++; done: memmove (root + m + 1, root + m, (length - m) * sizeof (void *)); root [m] = item; return m; } int _lf_ptr_array_insert_unique ( GPtrArray *array, void *item, GCompareFunc compare, GDestroyNotify dest) { int idx1, idx2; int idx = _lf_ptr_array_insert_sorted (array, item, compare); void **root = array->pdata; int length = array->len; for (idx1 = idx - 1; idx1 >= 0 && compare (root [idx1], item) == 0; idx1--) ; for (idx2 = idx + 1; idx2 < length && compare (root [idx2], item) == 0; idx2++) ; if (dest) for (int i = idx1 + 1; i < idx2; i++) if (i != idx) dest (g_ptr_array_index (array, i)); if (idx2 - idx - 1) g_ptr_array_remove_range (array, idx + 1, idx2 - idx - 1); if (idx - idx1 - 1) g_ptr_array_remove_range (array, idx1 + 1, idx - idx1 - 1); return idx1 + 1; } int _lf_ptr_array_find_sorted ( const GPtrArray *array, void *item, GCompareFunc compare) { int length = array->len; if (!length) return -1; void **root = array->pdata; int l = 0, r = length - 1; int m = 0, cmp = 0; // Skip trailing NULL, if any if (!root [r]) r--; while (l <= r) { m = (l + r) / 2; cmp = compare (root [m], item); if (cmp == 0) return m; else if (cmp < 0) l = m + 1; else r = m - 1; } return -1; } int _lf_strcmp (const char *s1, const char *s2) { if (s1 && !*s1) s1 = NULL; if (s2 && !*s2) s2 = NULL; if (!s1) { if (!s2) return 0; else return -1; } if (!s2) return +1; bool begin = true; for (;;) { skip_start_spaces_s1: gunichar c1 = g_utf8_get_char (s1); s1 = g_utf8_next_char (s1); if (g_unichar_isspace (c1)) { c1 = L' '; while (g_unichar_isspace (g_utf8_get_char (s1))) s1 = g_utf8_next_char (s1); } if (begin && c1 == L' ') goto skip_start_spaces_s1; c1 = g_unichar_tolower (c1); skip_start_spaces_s2: gunichar c2 = g_utf8_get_char (s2); s2 = g_utf8_next_char (s2); if (g_unichar_isspace (c2)) { c2 = L' '; while (g_unichar_isspace (g_utf8_get_char (s2))) s2 = g_utf8_next_char (s2); } if (begin && c2 == L' ') goto skip_start_spaces_s2; c2 = g_unichar_tolower (c2); begin = false; if (c1 == c2) { if (!c1) return 0; continue; } if (!c2 && c1 == L' ') { // Check if first string contains spaces up to the end while (g_unichar_isspace (g_utf8_get_char (s1))) s1 = g_utf8_next_char (s1); return *s1 ? +1 : 0; } if (!c1 && c2 == L' ') { // Check if second string contains spaces up to the end while (g_unichar_isspace (g_utf8_get_char (s2))) s2 = g_utf8_next_char (s2); return *s2 ? -1 : 0; } return c1 - c2; } } int _lf_mlstrcmp (const char *s1, const lfMLstr s2) { if (!s1) { if (!s2) return 0; else return -1; } if (!s2) return +1; const char *s2c = s2; int ret = 0; while (*s2c) { int res = _lf_strcmp (s1, s2c); if (!res) return 0; if (s2c == s2) ret = res; // Skip the string s2c = strchr (s2c, 0) + 1; if (!*s2c) break; // Ignore the language descriptor s2c = strchr (s2c, 0) + 1; } return ret; } float _lf_interpolate (float y1, float y2, float y3, float y4, float t) { float tg2, tg3; float t2 = t * t; float t3 = t2 * t; if (y1 == FLT_MAX) tg2 = y3 - y2; else tg2 = (y3 - y1) * 0.5; if (y4 == FLT_MAX) tg3 = y3 - y2; else tg3 = (y4 - y2) * 0.5; // Hermite polynomial return (2 * t3 - 3 * t2 + 1) * y2 + (t3 - 2 * t2 + t) * tg2 + (-2 * t3 + 3 * t2) * y3 + (t3 - t2) * tg3; } long int _lf_read_database_timestamp (const gchar *dirname) { long int timestamp = -1; GDir *dir = g_dir_open (dirname, 0, NULL); if (dir) { if (g_dir_read_name (dir)) { gchar *filename = g_build_filename (dirname, "timestamp.txt", NULL); std::ifstream timestamp_file (filename); g_free (filename); if (!timestamp_file.fail ()) timestamp_file >> timestamp; else timestamp = 0; } g_dir_close (dir); } return timestamp; } //------------------------// Fuzzy string matching //------------------------// lfFuzzyStrCmp::lfFuzzyStrCmp (const char *pattern, bool allwords) { pattern_words = g_ptr_array_new (); match_words = g_ptr_array_new (); Split (pattern, pattern_words); match_all_words = allwords; } lfFuzzyStrCmp::~lfFuzzyStrCmp () { Free (pattern_words); g_ptr_array_free (pattern_words, TRUE); g_ptr_array_free (match_words, TRUE); } void lfFuzzyStrCmp::Free (GPtrArray *dest) { for (size_t i = 0; i < dest->len; i++) g_free (g_ptr_array_index (dest, i)); g_ptr_array_set_size (dest, 0); } void lfFuzzyStrCmp::Split (const char *str, GPtrArray *dest) { if (!str) return; while (*str) { while (*str && isspace (*str)) str++; if (!*str) break; const char *word = str++; // Split into words based on character class if (isdigit (*word)) while (*str && (isdigit (*str) || *str == '.')) str++; else if (ispunct (*word)) while (*str && ispunct (*str)) str++; else while (*str && !isspace (*str) && !isdigit (*str) && !ispunct (*str)) str++; // Skip solitary symbols, including a single letter "f", except for "+" // and "*", which sometimes occur in lens model names as important // characters if (str - word == 1 && (ispunct (*word) || tolower (*word) == 'f') && *word != '*' && *word != '+') continue; gchar *item = g_utf8_casefold (word, str - word); _lf_ptr_array_insert_sorted (dest, item, (GCompareFunc)strcmp); } } int lfFuzzyStrCmp::Compare (const char *match) { Split (match, match_words); if (!match_words->len || !pattern_words->len) return 0; size_t mi = 0; int score = 0; for (size_t pi = 0; pi < pattern_words->len; pi++) { const char *pattern_str = (char *)g_ptr_array_index (pattern_words, pi); int old_mi = mi; for (; mi < match_words->len; mi++) { // Since we casefolded our strings at init time, we can // use now a regular strcmp, which is way faster... int r = strcmp (pattern_str, (char *)g_ptr_array_index (match_words, mi)); if (r == 0) { score++; break; } if (r < 0) { // Since our arrays are sorted, if pattern word becomes // "smaller" than next word from the match, this means // there's no chance anymore to find it. if (match_all_words) { Free (match_words); return 0; } else { mi = old_mi - 1; break; } } } if (match_all_words) { if (mi >= match_words->len) { // Found a word not present in match Free (match_words); return 0; } mi++; } else { if (mi >= match_words->len) // Found a word not present in match mi = old_mi; else mi++; } } score = (score * 200) / (pattern_words->len + match_words->len); Free (match_words); return score; } int lfFuzzyStrCmp::Compare (const lfMLstr match) { if (!match) return 0; const char *mc = match; int ret = 0; while (*mc) { int res = Compare (mc); if (res > ret) { ret = res; if (ret >= 100) break; } // Skip the string mc = strchr (mc, 0) + 1; if (!*mc) break; // Ignore the language descriptor mc = strchr (mc, 0) + 1; } return ret; } lensfun-0.3.4/libs/lensfun/camera.cpp000066400000000000000000000046111445356770400175500ustar00rootroot00000000000000/* Private constructors and destructors Copyright (C) 2007 by Andrew Zabolotny */ #include "config.h" #include "lensfun.h" #include "lensfunprv.h" lfCamera::lfCamera () { // Defaults for attributes are "unknown" (mostly 0). Otherwise, ad hoc // lfLens instances used for searches could not be matched against database // lenses easily. If you need defaults for database tags, set them when // reading the database. memset (this, 0, sizeof (*this)); } lfCamera::~lfCamera () { lf_free (Maker); lf_free (Model); lf_free (Variant); lf_free (Mount); } lfCamera::lfCamera (const lfCamera &other) { Maker = lf_mlstr_dup (other.Maker); Model = lf_mlstr_dup (other.Model); Variant = lf_mlstr_dup (other.Variant); Mount = g_strdup (other.Mount); CropFactor = other.CropFactor; } lfCamera &lfCamera::operator = (const lfCamera &other) { lf_free (Maker); Maker = lf_mlstr_dup (other.Maker); lf_free (Model); Model = lf_mlstr_dup (other.Model); lf_free (Variant); Variant = lf_mlstr_dup (other.Variant); _lf_setstr (&Mount, other.Mount); CropFactor = other.CropFactor; return *this; } void lfCamera::SetMaker (const char *val, const char *lang) { Maker = lf_mlstr_add (Maker, lang, val); } void lfCamera::SetModel (const char *val, const char *lang) { Model = lf_mlstr_add (Model, lang, val); } void lfCamera::SetVariant (const char *val, const char *lang) { Variant = lf_mlstr_add (Variant, lang, val); } void lfCamera::SetMount (const char *val) { _lf_setstr (&Mount, val); } bool lfCamera::Check () { if (!Maker || !Model || !Mount || CropFactor <= 0) return false; return true; } //---------------------------// The C interface //---------------------------// lfCamera *lf_camera_new () { return new lfCamera (); } void lf_camera_destroy (lfCamera *camera) { delete camera; } void lf_camera_copy (lfCamera *dest, const lfCamera *source) { *dest = *source; } cbool lf_camera_check (lfCamera *camera) { return camera->Check (); } gint _lf_camera_compare (gconstpointer a, gconstpointer b) { lfCamera *i1 = (lfCamera *)a; lfCamera *i2 = (lfCamera *)b; int cmp = _lf_strcmp (i1->Maker, i2->Maker); if (cmp != 0) return cmp; cmp = _lf_strcmp (i1->Model, i2->Model); if (cmp != 0) return cmp; return _lf_strcmp (i1->Variant, i2->Variant); } lensfun-0.3.4/libs/lensfun/cpuid.cpp000066400000000000000000000117751445356770400174350ustar00rootroot00000000000000/* CPU features detection Copyright (C) 2010 by Andrew Zabolotny */ #include "config.h" #include "lensfun.h" #include "lensfunprv.h" #if defined (_MSC_VER) #include guint _lf_detect_cpu_features () { static guint cpuflags = -1; #if defined(GLIB_CHECK_VERSION) && GLIB_CHECK_VERSION(2,32,0) static GMutex lock; g_mutex_lock (&lock); #else static GStaticMutex lock = G_STATIC_MUTEX_INIT; g_static_mutex_lock (&lock); #endif if (cpuflags == (guint)-1) { cpuflags = 0; int CPUInfo [4] = {-1}; __cpuid (CPUInfo, 0); /* Are there are standard features? */ if (CPUInfo [0] >= 1) { /* Get the standard level */ __cpuid (CPUInfo, 1); if (CPUInfo [3] & 0x800000) cpuflags |= LF_CPU_FLAG_MMX; if (CPUInfo [3] & 0x2000000) cpuflags |= LF_CPU_FLAG_SSE; if (CPUInfo [3] & 0x4000000) cpuflags |= LF_CPU_FLAG_SSE2; if (CPUInfo [3] & 0x8000) cpuflags |= LF_CPU_FLAG_CMOV; if (CPUInfo [2] & 0x1) cpuflags |= LF_CPU_FLAG_SSE3; if (CPUInfo [2] & 0x200) cpuflags |= LF_CPU_FLAG_SSSE3; if (CPUInfo [2] & 0x80000) cpuflags |= LF_CPU_FLAG_SSE4_1; if (CPUInfo [2] & 0x100000) cpuflags |= LF_CPU_FLAG_SSE4_2; /* Are there extensions? */ __cpuid (CPUInfo, 0x80000000); if (CPUInfo [0] >= 1) { /* ask extensions */ __cpuid (CPUInfo, 0x80000001); if (CPUInfo [3] & 0x80000000) cpuflags |= LF_CPU_FLAG_3DNOW; if (CPUInfo [3] & 0x40000000) cpuflags |= LF_CPU_FLAG_3DNOW_EXT; if (CPUInfo [3] & 0x00400000) cpuflags |= LF_CPU_FLAG_AMD_ISSE; }; }; }; #if defined(GLIB_CHECK_VERSION) && GLIB_CHECK_VERSION(2,32,0) g_mutex_unlock (&lock); #else g_static_mutex_unlock (&lock); #endif return cpuflags; }; #else #if defined (__i386__) || defined (__x86_64__) #ifdef __x86_64__ # define R_AX "rax" # define R_BX "rbx" # define R_CX "rcx" # define R_DX "rdx" #else # define R_AX "eax" # define R_BX "ebx" # define R_CX "ecx" # define R_DX "edx" #endif // Borrowed from RawStudio guint _lf_detect_cpu_features () { #define cpuid(cmd) \ __asm volatile ( \ "push %%" R_BX "\n" \ "cpuid\n" \ "pop %%" R_BX "\n" \ : "=a" (ax), "=c" (cx), "=d" (dx) \ : "0" (cmd)) #ifdef __x86_64__ guint64 ax, cx, dx, tmp; #else guint32 ax, cx, dx, tmp; #endif static guint cpuflags = -1; #if defined(GLIB_CHECK_VERSION) && GLIB_CHECK_VERSION(2,32,0) static GMutex lock; g_mutex_lock (&lock); #else static GStaticMutex lock = G_STATIC_MUTEX_INIT; g_static_mutex_lock (&lock); #endif if (cpuflags == (guint)-1) { cpuflags = 0; /* Test cpuid presence by checking bit 21 of eflags */ __asm volatile ( "pushf\n" "pop %0\n" "mov %0, %1\n" "xor $0x00200000, %0\n" "push %0\n" "popf\n" "pushf\n" "pop %0\n" "cmp %0, %1\n" "setne %%al\n" "movzb %%al, %0\n" : "=r" (ax), "=r" (tmp)); if (ax) { /* Get the standard level */ cpuid (0x00000000); if (ax) { /* Request for standard features */ cpuid (0x00000001); if (dx & 0x00800000) cpuflags |= LF_CPU_FLAG_MMX; if (dx & 0x02000000) cpuflags |= LF_CPU_FLAG_SSE; if (dx & 0x04000000) cpuflags |= LF_CPU_FLAG_SSE2; if (dx & 0x00008000) cpuflags |= LF_CPU_FLAG_CMOV; if (cx & 0x00000001) cpuflags |= LF_CPU_FLAG_SSE3; if (cx & 0x00000200) cpuflags |= LF_CPU_FLAG_SSSE3; if (cx & 0x00040000) cpuflags |= LF_CPU_FLAG_SSE4_1; if (cx & 0x00080000) cpuflags |= LF_CPU_FLAG_SSE4_2; } /* Are there extensions? */ cpuid (0x80000000); if (ax) { /* Ask extensions */ cpuid (0x80000001); if (dx & 0x80000000) cpuflags |= LF_CPU_FLAG_3DNOW; if (dx & 0x40000000) cpuflags |= LF_CPU_FLAG_3DNOW_EXT; if (dx & 0x00400000) cpuflags |= LF_CPU_FLAG_AMD_ISSE; } } } #if defined(GLIB_CHECK_VERSION) && GLIB_CHECK_VERSION(2,32,0) g_mutex_unlock (&lock); #else g_static_mutex_unlock (&lock); #endif return cpuflags; #undef cpuid } #endif /* __i386__ || __x86_64__ */ #endif lensfun-0.3.4/libs/lensfun/database.cpp000066400000000000000000001414521445356770400200710ustar00rootroot00000000000000/* Lens database methods implementation Copyright (C) 2007 by Andrew Zabolotny */ #include "config.h" #include "lensfun.h" #include "lensfunprv.h" #include #include #include #include #include #ifdef PLATFORM_WINDOWS # include #else # include #endif lfDatabase::lfDatabase () { HomeDataDir = g_build_filename (g_get_user_data_dir (), CONF_PACKAGE, NULL); UserUpdatesDir = g_build_filename (HomeDataDir, "updates", DATABASE_SUBDIR, NULL); Mounts = g_ptr_array_new (); g_ptr_array_add ((GPtrArray *)Mounts, NULL); Cameras = g_ptr_array_new (); g_ptr_array_add ((GPtrArray *)Cameras, NULL); Lenses = g_ptr_array_new (); g_ptr_array_add ((GPtrArray *)Lenses, NULL); } lfDatabase::~lfDatabase () { size_t i; for (i = 0; i < ((GPtrArray *)Mounts)->len - 1; i++) delete static_cast (g_ptr_array_index ((GPtrArray *)Mounts, i)); g_ptr_array_free ((GPtrArray *)Mounts, TRUE); for (i = 0; i < ((GPtrArray *)Cameras)->len - 1; i++) delete static_cast (g_ptr_array_index ((GPtrArray *)Cameras, i)); g_ptr_array_free ((GPtrArray *)Cameras, TRUE); for (i = 0; i < ((GPtrArray *)Lenses)->len - 1; i++) delete static_cast (g_ptr_array_index ((GPtrArray *)Lenses, i)); g_ptr_array_free ((GPtrArray *)Lenses, TRUE); g_free (HomeDataDir); g_free (UserUpdatesDir); } lfDatabase *lfDatabase::Create () { return new lfDatabase (); } void lfDatabase::Destroy () { delete this; } bool lfDatabase::LoadDirectory (const gchar *dirname) { bool database_found = false; GDir *dir = g_dir_open (dirname, 0, NULL); if (dir) { GPatternSpec *ps = g_pattern_spec_new ("*.xml"); if (ps) { const gchar *fn; while ((fn = g_dir_read_name (dir))) { size_t sl = strlen (fn); if (g_pattern_match (ps, sl, fn, NULL)) { gchar *ffn = g_build_filename (dirname, fn, NULL); /* Ignore errors */ if (Load (ffn) == LF_NO_ERROR) database_found = true; g_free (ffn); } } g_pattern_spec_free (ps); } g_dir_close (dir); } return database_found; } lfError lfDatabase::Load () { bool database_found = false; #ifndef PLATFORM_WINDOWS gchar *main_dirname = g_build_filename (CONF_DATADIR, DATABASE_SUBDIR, NULL); #else /* windows based OS */ extern gchar *_lf_get_database_dir (); gchar *main_dirname = _lf_get_database_dir (); #endif const gchar *system_updates_dirname = g_build_filename (SYSTEM_DB_UPDATE_PATH, DATABASE_SUBDIR, NULL); const int timestamp_main = _lf_read_database_timestamp (main_dirname); const int timestamp_system_updates = _lf_read_database_timestamp (system_updates_dirname); const int timestamp_user_updates = _lf_read_database_timestamp (UserUpdatesDir); if (timestamp_main > timestamp_system_updates) if (timestamp_user_updates > timestamp_main) database_found |= LoadDirectory (UserUpdatesDir); else database_found |= LoadDirectory (main_dirname); else if (timestamp_user_updates > timestamp_system_updates) database_found |= LoadDirectory (UserUpdatesDir); else database_found |= LoadDirectory (system_updates_dirname); g_free (main_dirname); database_found |= LoadDirectory (HomeDataDir); return database_found ? LF_NO_ERROR : LF_NO_DATABASE; } lfError lfDatabase::Load (const char *filename) { gchar *contents; gsize length; GError *err = NULL; if (!g_file_get_contents (filename, &contents, &length, &err)) return lfError (err->code == G_FILE_ERROR_ACCES ? -EACCES : -ENOENT); lfError e = Load (filename, contents, length); g_free (contents); return e; } //-----------------------------// XML parser //-----------------------------// /* Private structure used by XML parse */ typedef struct { lfDatabase *db; lfMount *mount; lfCamera *camera; lfLens *lens; gchar *lang; const gchar *stack [16]; size_t stack_depth; const char *errcontext; } lfParserData; static bool __chk_no_attrs(const gchar *element_name, const gchar **attribute_names, GError **error) { if (attribute_names [0]) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, "The <%s> element cannot have any attributes!\n", element_name); return false; } return true; } static void _xml_start_element (GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer user_data, GError **error) { int i; lfParserData *pd = (lfParserData *)user_data; if (pd->stack_depth >= sizeof (pd->stack) / sizeof (pd->stack [0])) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "<%s>: very deeply nested element!\n", element_name); return; } const gchar *ctx = NULL; if (pd->stack_depth) ctx = pd->stack [pd->stack_depth - 1]; pd->stack [pd->stack_depth++] = element_name; if (!strcmp (element_name, "lensdatabase")) { if (ctx) { bad_ctx: g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Inappropiate context for <%s>!\n", element_name); return; } int version = 0; for (i = 0; attribute_names [i]; i++) if (!strcmp (attribute_names [i], "version")) version = atoi (attribute_values [i]); else goto bad_attr; if (version < LF_MIN_DATABASE_VERSION) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Database version is %d, but oldest supported is only %d!\n", version, LF_MIN_DATABASE_VERSION); return; } if (version > LF_MAX_DATABASE_VERSION) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Database version is %d, but newest supported is only %d!\n", version, LF_MAX_DATABASE_VERSION); return; } } else if (!strcmp (element_name, "mount")) { if (ctx && !strcmp (ctx, "lensdatabase")) { pd->mount = new lfMount (); if (!__chk_no_attrs(element_name, attribute_names, error)) return; } else if (ctx && (!strcmp (ctx, "camera") || !strcmp (ctx, "lens"))) { if (!__chk_no_attrs(element_name, attribute_names, error)) return; } else goto bad_ctx; } else if (!strcmp (element_name, "camera")) { if (!ctx || strcmp (ctx, "lensdatabase")) goto bad_ctx; pd->camera = new lfCamera (); if (!__chk_no_attrs(element_name, attribute_names, error)) return; } else if (!strcmp (element_name, "lens")) { if (!ctx || strcmp (ctx, "lensdatabase")) goto bad_ctx; pd->lens = new lfLens (); // Set default values for lens database entries. This way, they are // still 0 (aka "unknown") for dummy lfLens instances created ad hoc // for search matching. pd->lens->Type = LF_RECTILINEAR; pd->lens->AspectRatio = 1.5; if (!__chk_no_attrs(element_name, attribute_names, error)) return; } else if (!strcmp (element_name, "focal")) { if (!ctx || strcmp (ctx, "lens") || !pd->lens) goto bad_ctx; for (i = 0; attribute_names [i]; i++) if (!strcmp (attribute_names [i], "min")) pd->lens->MinFocal = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "max")) pd->lens->MaxFocal = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "value")) pd->lens->MinFocal = pd->lens->MaxFocal = atof (attribute_values [i]); else goto bad_attr; } else if (!strcmp (element_name, "aperture")) { if (!ctx || strcmp (ctx, "lens") || !pd->lens) goto bad_ctx; for (i = 0; attribute_names [i]; i++) if (!strcmp (attribute_names [i], "min")) pd->lens->MinAperture = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "max")) pd->lens->MaxAperture = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "value")) pd->lens->MinAperture = pd->lens->MaxAperture = atof (attribute_values [i]); else goto bad_attr; } else if (!strcmp (element_name, "center")) { if (!ctx || strcmp (ctx, "lens") || !pd->lens) goto bad_ctx; for (i = 0; attribute_names [i]; i++) if (!strcmp (attribute_names [i], "x")) pd->lens->CenterX = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "y")) pd->lens->CenterY = atof (attribute_values [i]); else goto bad_attr; } else if (!strcmp (element_name, "type")) { if (!ctx || strcmp (ctx, "lens") || !pd->lens) goto bad_ctx; if (!__chk_no_attrs(element_name, attribute_names, error)) return; } else if (!strcmp (element_name, "calibration")) { if (!ctx || strcmp (ctx, "lens")) goto bad_ctx; if (!__chk_no_attrs(element_name, attribute_names, error)) return; } else if (!strcmp (element_name, "distortion")) { if (!ctx || strcmp (ctx, "calibration")) goto bad_ctx; lfLensCalibDistortion dc; memset (&dc, 0, sizeof (dc)); for (i = 0; attribute_names [i]; i++) if (!strcmp (attribute_names [i], "model")) { if (!strcmp (attribute_values [i], "none")) dc.Model = LF_DIST_MODEL_NONE; else if (!strcmp (attribute_values [i], "poly3")) dc.Model = LF_DIST_MODEL_POLY3; else if (!strcmp (attribute_values [i], "poly5")) dc.Model = LF_DIST_MODEL_POLY5; else if (!strcmp (attribute_values [i], "ptlens")) dc.Model = LF_DIST_MODEL_PTLENS; else { bad_attr: g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Bad attribute value `%s=%s' for element <%s>!\n", attribute_names [i], attribute_values [i], element_name); return; } } else if (!strcmp (attribute_names [i], "focal")) dc.Focal = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "a") || !strcmp (attribute_names [i], "k1")) dc.Terms [0] = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "b") || !strcmp (attribute_names [i], "k2")) dc.Terms [1] = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "c")) dc.Terms [2] = atof (attribute_values [i]); else { unk_attr: g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Unknown attribute `%s' for element <%s>!\n", attribute_names [i], element_name); return; } pd->lens->AddCalibDistortion (&dc); } else if (!strcmp (element_name, "tca")) { if (!ctx || strcmp (ctx, "calibration")) goto bad_ctx; lfLensCalibTCA tcac; memset (&tcac, 0, sizeof (tcac)); tcac.Terms [0] = tcac.Terms [1] = 1.0; for (i = 0; attribute_names [i]; i++) if (!strcmp (attribute_names [i], "model")) { if (!strcmp (attribute_values [i], "none")) tcac.Model = LF_TCA_MODEL_NONE; else if (!strcmp (attribute_values [i], "linear")) tcac.Model = LF_TCA_MODEL_LINEAR; else if (!strcmp (attribute_values [i], "poly3")) tcac.Model = LF_TCA_MODEL_POLY3; else goto bad_attr; } else if (!strcmp (attribute_names [i], "focal")) tcac.Focal = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "kr") || !strcmp (attribute_names [i], "vr")) tcac.Terms [0] = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "kb") || !strcmp (attribute_names [i], "vb")) tcac.Terms [1] = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "cr")) tcac.Terms [2] = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "cb")) tcac.Terms [3] = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "br")) tcac.Terms [4] = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "bb")) tcac.Terms [5] = atof (attribute_values [i]); else goto unk_attr; pd->lens->AddCalibTCA (&tcac); } else if (!strcmp (element_name, "vignetting")) { if (!ctx || strcmp (ctx, "calibration")) goto bad_ctx; lfLensCalibVignetting vc; memset (&vc, 0, sizeof (vc)); for (i = 0; attribute_names [i]; i++) if (!strcmp (attribute_names [i], "model")) { if (!strcmp (attribute_values [i], "none")) vc.Model = LF_VIGNETTING_MODEL_NONE; else if (!strcmp (attribute_values [i], "pa")) vc.Model = LF_VIGNETTING_MODEL_PA; else goto bad_attr; } else if (!strcmp (attribute_names [i], "focal")) vc.Focal = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "aperture")) vc.Aperture = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "distance")) vc.Distance = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "k1")) vc.Terms [0] = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "k2")) vc.Terms [1] = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "k3")) vc.Terms [2] = atof (attribute_values [i]); else goto unk_attr; pd->lens->AddCalibVignetting (&vc); } else if (!strcmp (element_name, "crop")) { if (!ctx || strcmp (ctx, "calibration")) goto bad_ctx; lfLensCalibCrop lcc; memset (&lcc, 0, sizeof (lcc)); for (i = 0; attribute_names [i]; i++) if (!strcmp (attribute_names [i], "focal")) lcc.Focal = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "mode")) { if (!strcmp (attribute_values [i], "no_crop")) lcc.CropMode = LF_NO_CROP; else if (!strcmp (attribute_values [i], "crop_rectangle")) lcc.CropMode = LF_CROP_RECTANGLE; else if (!strcmp (attribute_values [i], "crop_circle")) lcc.CropMode = LF_CROP_CIRCLE; else { goto bad_attr; } } else if (!strcmp (attribute_names [i], "left")) lcc.Crop [0] = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "right")) lcc.Crop [1] = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "top")) lcc.Crop [2] = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "bottom")) lcc.Crop [3] = atof (attribute_values [i]); else { goto unk_attr; } pd->lens->AddCalibCrop (&lcc); } else if (!strcmp (element_name, "field_of_view")) { if (!ctx || strcmp (ctx, "calibration")) goto bad_ctx; gint line, col; g_markup_parse_context_get_position (context, &line, &col); g_warning ("[Lensfun] %s:%d:%d: tag is deprecated. Use instead", pd->errcontext, line, col); lfLensCalibFov lcf; memset (&lcf, 0, sizeof (lcf)); for (i = 0; attribute_names [i]; i++) if (!strcmp (attribute_names [i], "focal")) lcf.Focal = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "fov")) lcf.FieldOfView = atof (attribute_values [i]); else { goto unk_attr; } pd->lens->AddCalibFov (&lcf); } else if (!strcmp (element_name, "real-focal-length")) { if (!ctx || strcmp (ctx, "calibration")) goto bad_ctx; lfLensCalibRealFocal lcf; memset (&lcf, 0, sizeof (lcf)); for (i = 0; attribute_names [i]; i++) if (!strcmp (attribute_names [i], "focal")) lcf.Focal = atof (attribute_values [i]); else if (!strcmp (attribute_names [i], "real-focal")) lcf.RealFocal = atof (attribute_values [i]); else { goto unk_attr; } pd->lens->AddCalibRealFocal (&lcf); } /* Handle multi-language strings */ else if (!strcmp (element_name, "maker") || !strcmp (element_name, "model") || !strcmp (element_name, "variant") || !strcmp (element_name, "name")) { for (i = 0; attribute_names [i]; i++) if (!strcmp (attribute_names [i], "lang")) _lf_setstr (&pd->lang, attribute_values [i]); else goto unk_attr; } else if (!strcmp (element_name, "compat") || !strcmp (element_name, "cropfactor") || !strcmp (element_name, "aspect-ratio")) { if (!__chk_no_attrs(element_name, attribute_names, error)) return; } else g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Unknown element <%s>!\n", element_name); } static void _xml_end_element (GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **error) { lfParserData *pd = (lfParserData *)user_data; g_assert (pd->stack_depth); pd->stack_depth--; if (!strcmp (element_name, "lensdatabase")) { /* nothing to do for now */ } else if (!strcmp (element_name, "mount") && pd->mount) { /* Sanity check */ if (!pd->mount->Check ()) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Invalid mount definition (%s)\n", pd->mount ? pd->mount->Name : "???"); return; } pd->db->AddMount(pd->mount); pd->mount = NULL; } else if (!strcmp (element_name, "camera")) { /* Sanity check */ if (!pd->camera || !pd->camera->Check ()) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Invalid camera definition (%s/%s)\n", pd->camera ? pd->camera->Maker : "???", pd->camera ? pd->camera->Model : "???"); return; } pd->db->AddCamera(pd->camera); pd->camera = NULL; } else if (!strcmp (element_name, "lens")) { /* Sanity check */ if (!pd->lens || !pd->lens->Check ()) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Invalid lens definition (%s/%s)\n", pd->lens ? pd->lens->Maker : "???", pd->lens ? pd->lens->Model : "???"); return; } pd->db->AddLens(pd->lens); pd->lens = NULL; } } static void _xml_text (GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **error) { lfParserData *pd = (lfParserData *)user_data; const gchar *ctx = g_markup_parse_context_get_element (context); while (*text && strchr (" \t\n\r", *text)) text++; if (!*text) goto leave; if (!strcmp (ctx, "name")) { if (pd->mount) pd->mount->SetName (text, pd->lang); else { bad_ctx: g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Wrong context for element <%.*s>\n", int (text_len), text); goto leave; } } else if (!strcmp (ctx, "maker")) { if (pd->camera) pd->camera->SetMaker (text, pd->lang); else if (pd->lens) pd->lens->SetMaker (text, pd->lang); else goto bad_ctx; } else if (!strcmp (ctx, "model")) { if (pd->camera) pd->camera->SetModel (text, pd->lang); else if (pd->lens) pd->lens->SetModel (text, pd->lang); else goto bad_ctx; } else if (!strcmp (ctx, "variant")) { if (pd->camera) pd->camera->SetVariant (text, pd->lang); else goto bad_ctx; } else if (!strcmp (ctx, "mount")) { if (pd->camera) pd->camera->SetMount (text); else if (pd->lens) pd->lens->AddMount (text); else goto bad_ctx; } else if (!strcmp (ctx, "compat")) { if (pd->mount) pd->mount->AddCompat (text); else goto bad_ctx; } else if (!strcmp (ctx, "cropfactor")) { if (pd->camera) pd->camera->CropFactor = atof (text); else if (pd->lens) pd->lens->CropFactor = atof (text); else goto bad_ctx; } else if (!strcmp (ctx, "aspect-ratio")) { if (pd->lens) { const char *colon = strpbrk (text, ":"); if (colon) pd->lens->AspectRatio = atof (text) / atof (colon + 1); else pd->lens->AspectRatio = atof (text); } else goto bad_ctx; } else if (!strcmp (ctx, "type")) { if (pd->lens) { if (!_lf_strcmp (text, "rectilinear")) pd->lens->Type = LF_RECTILINEAR; else if (!_lf_strcmp (text, "fisheye")) pd->lens->Type = LF_FISHEYE; else if (!_lf_strcmp (text, "panoramic")) pd->lens->Type = LF_PANORAMIC; else if (!_lf_strcmp (text, "equirectangular")) pd->lens->Type = LF_EQUIRECTANGULAR; else if (!_lf_strcmp (text, "orthographic")) pd->lens->Type = LF_FISHEYE_ORTHOGRAPHIC; else if (!_lf_strcmp (text, "stereographic")) pd->lens->Type = LF_FISHEYE_STEREOGRAPHIC; else if (!_lf_strcmp (text, "equisolid")) pd->lens->Type = LF_FISHEYE_EQUISOLID; else if (!_lf_strcmp (text, "fisheye_thoby")) pd->lens->Type = LF_FISHEYE_THOBY; else { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Invalid lens type `%s' (%s/%s)\n", text, pd->camera ? pd->camera->Maker : "???", pd->camera ? pd->camera->Model : "???"); return; } } else goto bad_ctx; } leave: lf_free (pd->lang); pd->lang = NULL; } lfError lfDatabase::Load (const char *errcontext, const char *data, size_t data_size) { static GMarkupParser gmp = { _xml_start_element, _xml_end_element, _xml_text, NULL, NULL }; /* Temporarily drop numeric format to "C" */ char *old_numeric = setlocale (LC_NUMERIC, NULL); old_numeric = strdup(old_numeric); setlocale(LC_NUMERIC,"C"); /* eek! GPtrArray does not have a method to insert a pointer into middle of the array... We have to remove the trailing NULL and re-append it after loading ... */ g_ptr_array_remove_index_fast ((GPtrArray *)Mounts, ((GPtrArray *)Mounts)->len - 1); g_ptr_array_remove_index_fast ((GPtrArray *)Cameras, ((GPtrArray *)Cameras)->len - 1); g_ptr_array_remove_index_fast ((GPtrArray *)Lenses, ((GPtrArray *)Lenses)->len - 1); lfParserData pd; memset (&pd, 0, sizeof (pd)); pd.db = this; pd.errcontext = errcontext; GMarkupParseContext *mpc = g_markup_parse_context_new ( &gmp, (GMarkupParseFlags)0, &pd, NULL); GError *err = NULL; lfError e = g_markup_parse_context_parse (mpc, data, data_size, &err) ? LF_NO_ERROR : LF_WRONG_FORMAT; /* Display the parsing error as a warning */ if (e != LF_NO_ERROR) { gint line, col; g_markup_parse_context_get_position (mpc, &line, &col); g_warning ("[Lensfun] %s:%d:%d: %s", errcontext, line, col, err->message); } g_markup_parse_context_free (mpc); /* Re-add the trailing NULL */ g_ptr_array_add ((GPtrArray *)Mounts, NULL); g_ptr_array_add ((GPtrArray *)Cameras, NULL); g_ptr_array_add ((GPtrArray *)Lenses, NULL); /* Restore numeric format */ setlocale (LC_NUMERIC, old_numeric); free(old_numeric); return e; } lfError lfDatabase::Save (const char *filename) const { return Save (filename, (lfMount **)((GPtrArray *)Mounts)->pdata, (lfCamera **)((GPtrArray *)Cameras)->pdata, (lfLens **)((GPtrArray *)Lenses)->pdata); } lfError lfDatabase::Save (const char *filename, const lfMount *const *mounts, const lfCamera *const *cameras, const lfLens *const *lenses) const { /* Special case: if filename begins with HomeDataDir and HomeDataDir * does not exist, try to create it (since we're in charge for this dir). */ if (g_str_has_prefix (filename, HomeDataDir) && g_file_test (HomeDataDir, G_FILE_TEST_IS_DIR)) g_mkdir (HomeDataDir, 0777); char *output = Save (mounts, cameras, lenses); if (!output) return lfError (-ENOMEM); int fh = g_open (filename, O_CREAT | O_WRONLY | O_TRUNC, 0666); if (fh < 0) { g_free (output); return lfError (-errno); } int ol = strlen (output); ol = (write (fh, output, ol) == ol); close (fh); g_free (output); return ol ? LF_NO_ERROR : lfError (-ENOSPC); } char *lfDatabase::Save (const lfMount *const *mounts, const lfCamera *const *cameras, const lfLens *const *lenses) { /* Temporarily drop numeric format to "C" */ char *old_numeric = setlocale (LC_NUMERIC, NULL); old_numeric = strdup(old_numeric); setlocale(LC_NUMERIC,"C"); int i, j; GString *output = g_string_sized_new (1024); g_string_append (output, "\n\n"); if (mounts) for (i = 0; mounts [i]; i++) { g_string_append (output, "\t\n"); _lf_xml_printf_mlstr (output, "\t\t", "name", mounts [i]->Name); if (mounts [i]->Compat) for (j = 0; mounts [i]->Compat [j]; j++) _lf_xml_printf (output, "\t\t%s\n", mounts [i]->Compat [j]); g_string_append (output, "\t\n\n"); } if (cameras) for (i = 0; cameras [i]; i++) { g_string_append (output, "\t\n"); _lf_xml_printf_mlstr (output, "\t\t", "maker", cameras [i]->Maker); _lf_xml_printf_mlstr (output, "\t\t", "model", cameras [i]->Model); _lf_xml_printf_mlstr (output, "\t\t", "variant", cameras [i]->Variant); _lf_xml_printf (output, "\t\t%s\n", cameras [i]->Mount); _lf_xml_printf (output, "\t\t%g\n", cameras [i]->CropFactor); g_string_append (output, "\t\n\n"); } if (lenses) for (i = 0; lenses [i]; i++) { g_string_append (output, "\t\n"); _lf_xml_printf_mlstr (output, "\t\t", "maker", lenses [i]->Maker); _lf_xml_printf_mlstr (output, "\t\t", "model", lenses [i]->Model); if (lenses [i]->MinFocal) { if (lenses [i]->MinFocal == lenses [i]->MaxFocal) _lf_xml_printf (output, "\t\t\n", lenses [i]->MinFocal); else _lf_xml_printf (output, "\t\t\n", lenses [i]->MinFocal, lenses [i]->MaxFocal); } if (lenses [i]->MinAperture) { if (lenses [i]->MinAperture == lenses [i]->MaxAperture) _lf_xml_printf (output, "\t\t\n", lenses [i]->MinAperture); else _lf_xml_printf (output, "\t\t\n", lenses [i]->MinAperture, lenses [i]->MaxAperture); } if (lenses [i]->Mounts) for (j = 0; lenses [i]->Mounts [j]; j++) _lf_xml_printf (output, "\t\t%s\n", lenses [i]->Mounts [j]); if (lenses [i]->Type != LF_RECTILINEAR) _lf_xml_printf (output, "\t\t%s\n", lenses [i]->Type == LF_FISHEYE ? "fisheye" : lenses [i]->Type == LF_PANORAMIC ? "panoramic" : lenses [i]->Type == LF_EQUIRECTANGULAR ? "equirectangular" : lenses [i]->Type == LF_FISHEYE_ORTHOGRAPHIC ? "orthographic" : lenses [i]->Type == LF_FISHEYE_STEREOGRAPHIC ? "stereographic" : lenses [i]->Type == LF_FISHEYE_EQUISOLID ? "equisolid" : lenses [i]->Type == LF_FISHEYE_THOBY ? "fisheye_thoby" : "rectilinear"); if (lenses [i]->CenterX || lenses [i]->CenterY) _lf_xml_printf (output, "\t\t
\n", lenses [i]->CenterX, lenses [i]->CenterY); _lf_xml_printf (output, "\t\t%g\n", lenses [i]->CropFactor); _lf_xml_printf (output, "\t\t%g\n", lenses [i]->AspectRatio); if (lenses [i]->CalibDistortion || lenses [i]->CalibTCA || lenses [i]->CalibVignetting || lenses [i]->CalibCrop || lenses [i]->CalibFov || lenses [i]->CalibRealFocal) g_string_append (output, "\t\t\n"); if (lenses [i]->CalibDistortion) { for (j = 0; lenses [i]->CalibDistortion [j]; j++) { lfLensCalibDistortion *cd = lenses [i]->CalibDistortion [j]; _lf_xml_printf (output, "\t\t\tFocal); switch (cd->Model) { case LF_DIST_MODEL_POLY3: _lf_xml_printf ( output, "model=\"poly3\" k1=\"%g\" />\n", cd->Terms [0]); break; case LF_DIST_MODEL_POLY5: _lf_xml_printf ( output, "model=\"poly5\" k1=\"%g\" k2=\"%g\" />\n", cd->Terms [0], cd->Terms [1]); break; case LF_DIST_MODEL_PTLENS: _lf_xml_printf ( output, "model=\"ptlens\" a=\"%g\" b=\"%g\" c=\"%g\" />\n", cd->Terms [0], cd->Terms [1], cd->Terms [2]); break; default: _lf_xml_printf (output, "model=\"none\" />\n"); break; } } } if (lenses [i]->CalibTCA) { for (j = 0; lenses [i]->CalibTCA [j]; j++) { lfLensCalibTCA *ctca = lenses [i]->CalibTCA [j]; _lf_xml_printf (output, "\t\t\tFocal); switch (ctca->Model) { case LF_TCA_MODEL_LINEAR: _lf_xml_printf (output, "model=\"linear\" kr=\"%g\" kb=\"%g\" />\n", ctca->Terms [0], ctca->Terms [1]); break; case LF_TCA_MODEL_POLY3: _lf_xml_printf (output, "model=\"poly3\" vr=\"%g\" vb=\"%g\" " "cr=\"%g\" cb=\"%g\" br=\"%g\" bb=\"%g\" />\n", ctca->Terms [0], ctca->Terms [1], ctca->Terms [2], ctca->Terms [3], ctca->Terms [4], ctca->Terms [5]); break; default: _lf_xml_printf (output, "model=\"none\" />\n"); break; } } } if (lenses [i]->CalibVignetting) { for (j = 0; lenses [i]->CalibVignetting [j]; j++) { lfLensCalibVignetting *cv = lenses [i]->CalibVignetting [j]; _lf_xml_printf (output, "\t\t\tFocal, cv->Aperture, cv->Distance); switch (cv->Model) { case LF_VIGNETTING_MODEL_PA: _lf_xml_printf (output, "model=\"pa\" k1=\"%g\" k2=\"%g\" k3=\"%g\" />\n", cv->Terms [0], cv->Terms [1], cv->Terms [2]); break; default: _lf_xml_printf (output, "model=\"none\" />\n"); break; } } } if (lenses [i]->CalibCrop) { for (j = 0; lenses [i]->CalibCrop [j]; j++) { lfLensCalibCrop *lcc = lenses [i]->CalibCrop [j]; _lf_xml_printf (output, "\t\t\tFocal); switch (lcc->CropMode) { case LF_CROP_RECTANGLE: _lf_xml_printf ( output, "mode=\"crop_rectangle\" left=\"%g\" right=\"%g\" top=\"%g\" bottom=\"%g\" />\n", lcc->Crop [0], lcc->Crop [1], lcc->Crop [2], lcc->Crop [3]); break; case LF_CROP_CIRCLE: _lf_xml_printf ( output, "mode=\"crop_circle\" left=\"%g\" right=\"%g\" top=\"%g\" bottom=\"%g\" />\n", lcc->Crop [0], lcc->Crop [1], lcc->Crop [2], lcc->Crop [3]); break; case LF_NO_CROP: default: _lf_xml_printf (output, "mode=\"no_crop\" />\n"); break; } } } if (lenses [i]->CalibFov) { for (j = 0; lenses [i]->CalibFov [j]; j++) { lfLensCalibFov *lcf = lenses [i]->CalibFov [j]; if (lcf->FieldOfView>0) { _lf_xml_printf (output, "\t\t\t\n", lcf->Focal, lcf->FieldOfView); }; } } if (lenses [i]->CalibRealFocal) { for (j = 0; lenses [i]->CalibRealFocal [j]; j++) { lfLensCalibRealFocal *lcf = lenses [i]->CalibRealFocal [j]; if (lcf->RealFocal>0) { _lf_xml_printf (output, "\t\t\t\n", lcf->Focal, lcf->RealFocal); }; } } if (lenses [i]->CalibDistortion || lenses [i]->CalibTCA || lenses [i]->CalibVignetting || lenses [i]->CalibCrop || lenses [i]->CalibFov || lenses [i]->CalibRealFocal) g_string_append (output, "\t\t\n"); g_string_append (output, "\t\n\n"); } g_string_append (output, "\n"); /* Restore numeric format */ setlocale (LC_NUMERIC, old_numeric); free(old_numeric); return g_string_free (output, FALSE); } static gint __find_camera_compare (gconstpointer a, gconstpointer b) { lfCamera *i1 = (lfCamera *)a; lfCamera *i2 = (lfCamera *)b; if (i1->Maker && i2->Maker) { int cmp = _lf_strcmp (i1->Maker, i2->Maker); if (cmp != 0) return cmp; } if (i1->Model && i2->Model) return _lf_strcmp (i1->Model, i2->Model); return 0; } const lfCamera **lfDatabase::FindCameras (const char *maker, const char *model) const { if (maker && !*maker) maker = NULL; if (model && !*model) model = NULL; lfCamera tc; tc.SetMaker (maker); tc.SetModel (model); int idx = _lf_ptr_array_find_sorted ((GPtrArray *)Cameras, &tc, __find_camera_compare); if (idx < 0) return NULL; guint idx1 = idx; while (idx1 > 0 && __find_camera_compare (g_ptr_array_index ((GPtrArray *)Cameras, idx1 - 1), &tc) == 0) idx1--; guint idx2 = idx; while (++idx2 < ((GPtrArray *)Cameras)->len - 1 && __find_camera_compare (g_ptr_array_index ((GPtrArray *)Cameras, idx2), &tc) == 0) ; const lfCamera **ret = g_new (const lfCamera *, idx2 - idx1 + 1); for (guint i = idx1; i < idx2; i++) ret [i - idx1] = (lfCamera *)g_ptr_array_index ((GPtrArray *)Cameras, i); ret [idx2 - idx1] = NULL; return ret; } static gint _lf_compare_camera_score (gconstpointer a, gconstpointer b) { lfCamera *i1 = (lfCamera *)a; lfCamera *i2 = (lfCamera *)b; return i2->Score - i1->Score; } const lfCamera **lfDatabase::FindCamerasExt (const char *maker, const char *model, int sflags) const { if (maker && !*maker) maker = NULL; if (model && !*model) model = NULL; GPtrArray *ret = g_ptr_array_new (); lfFuzzyStrCmp fcmaker (maker, (sflags & LF_SEARCH_LOOSE) == 0); lfFuzzyStrCmp fcmodel (model, (sflags & LF_SEARCH_LOOSE) == 0); for (size_t i = 0; i < ((GPtrArray *)Cameras)->len - 1; i++) { lfCamera *dbcam = static_cast (g_ptr_array_index ((GPtrArray *)Cameras, i)); int score1 = 0, score2 = 0; if ((!maker || (score1 = fcmaker.Compare (dbcam->Maker))) && (!model || (score2 = fcmodel.Compare (dbcam->Model)))) { dbcam->Score = score1 + score2; _lf_ptr_array_insert_sorted (ret, dbcam, _lf_compare_camera_score); } } // Add a NULL to mark termination of the array if (ret->len) g_ptr_array_add (ret, NULL); // Free the GPtrArray but not the actual list. return (const lfCamera **) (g_ptr_array_free (ret, FALSE)); } const lfCamera *const *lfDatabase::GetCameras () const { return (lfCamera **)((GPtrArray *)Cameras)->pdata; } const lfLens **lfDatabase::FindLenses (const lfCamera *camera, const char *maker, const char *model, int sflags) const { if (maker && !*maker) maker = NULL; if (model && !*model) model = NULL; lfLens lens; lens.SetMaker (maker); lens.SetModel (model); if (camera) lens.AddMount (camera->Mount); // Guess lens parameters from lens model name lens.GuessParameters (); lens.CropFactor = camera ? camera->CropFactor : 0.0; return FindLenses (&lens, sflags); } static gint _lf_compare_lens_score (gconstpointer a, gconstpointer b) { lfLens *i1 = (lfLens *)a; lfLens *i2 = (lfLens *)b; return i2->Score - i1->Score; } static gint _lf_compare_lens_details (gconstpointer a, gconstpointer b) { // Actually, we not only sort by focal length, but by MinFocal, MaxFocal, // MinAperature, Maker, and Model -- in this order of priorities. lfLens *i1 = (lfLens *)a; lfLens *i2 = (lfLens *)b; int cmp = _lf_lens_parameters_compare (i1, i2); if (cmp != 0) return cmp; return _lf_lens_name_compare (i1, i2); } static void _lf_add_compat_mounts ( const lfDatabase *This, const lfLens *lens, GPtrArray *mounts, char *mount) { const lfMount *m = This->FindMount (mount); if (m && m->Compat) for (int i = 0; m->Compat [i]; i++) { mount = m->Compat [i]; int idx = _lf_ptr_array_find_sorted (mounts, mount, (GCompareFunc)_lf_strcmp); if (idx >= 0) continue; // mount already in the list // Check if the mount is not already in the main list bool already = false; for (int j = 0; lens->Mounts [j]; j++) if (!_lf_strcmp (mount, lens->Mounts [j])) { already = true; break; } if (!already) _lf_ptr_array_insert_sorted (mounts, mount, (GCompareFunc)_lf_strcmp); } } const lfLens **lfDatabase::FindLenses (const lfLens *lens, int sflags) const { GPtrArray *ret = g_ptr_array_new (); GPtrArray *mounts = g_ptr_array_new (); lfFuzzyStrCmp fc (lens->Model, (sflags & LF_SEARCH_LOOSE) == 0); // Create a list of compatible mounts if (lens->Mounts) for (int i = 0; lens->Mounts [i]; i++) _lf_add_compat_mounts (this, lens, mounts, lens->Mounts [i]); g_ptr_array_add (mounts, NULL); int score; const bool sort_and_uniquify = (sflags & LF_SEARCH_SORT_AND_UNIQUIFY) != 0; for (size_t i = 0; i < ((GPtrArray *)Lenses)->len - 1; i++) { lfLens *dblens = static_cast (g_ptr_array_index ((GPtrArray *)Lenses, i)); if ((score = _lf_lens_compare_score ( lens, dblens, &fc, (const char **)mounts->pdata)) > 0) { dblens->Score = score; if (sort_and_uniquify) { bool already = false; for (size_t i = 0; i < ret->len; i++) { const lfLens *previous_lens = static_cast (g_ptr_array_index (ret, i)); if (!_lf_lens_name_compare (previous_lens, dblens)) { if (dblens->Score > previous_lens->Score) ret->pdata[i] = dblens; already = true; break; } } if (!already) _lf_ptr_array_insert_sorted (ret, dblens, _lf_compare_lens_details); } else _lf_ptr_array_insert_sorted (ret, dblens, _lf_compare_lens_score); } } // Add a NULL to mark termination of the array if (ret->len) g_ptr_array_add (ret, NULL); g_ptr_array_free (mounts, TRUE); // Free the GPtrArray but not the actual list. return (const lfLens **) (g_ptr_array_free (ret, FALSE)); } const lfLens *const *lfDatabase::GetLenses () const { return (lfLens **)((GPtrArray *)Lenses)->pdata; } const lfMount *lfDatabase::FindMount (const char *mount) const { lfMount tm; tm.SetName (mount); int idx = _lf_ptr_array_find_sorted ((GPtrArray *)Mounts, &tm, _lf_mount_compare); if (idx < 0) return NULL; return (const lfMount *)g_ptr_array_index ((GPtrArray *)Mounts, idx); } const char *lfDatabase::MountName (const char *mount) const { const lfMount *m = FindMount (mount); if (!m) return mount; return lf_mlstr_get (m->Name); } const lfMount * const *lfDatabase::GetMounts () const { return (lfMount **)((GPtrArray *)Mounts)->pdata; } void lfDatabase::AddMount (lfMount *mount) { _lf_ptr_array_insert_unique ( (GPtrArray *)Mounts, mount, _lf_mount_compare, (GDestroyNotify)lf_mount_destroy); } void lfDatabase::AddCamera (lfCamera *camera) { _lf_ptr_array_insert_unique ( (GPtrArray *)Cameras, camera, _lf_camera_compare, (GDestroyNotify)lf_camera_destroy); } void lfDatabase::AddLens (lfLens *lens) { _lf_ptr_array_insert_unique ( (GPtrArray *)Lenses, lens, _lf_lens_compare, (GDestroyNotify)lf_lens_destroy); } //---------------------------// The C interface //---------------------------// lfDatabase *lf_db_new () { return new lfDatabase (); } void lf_db_destroy (lfDatabase *db) { db->Destroy (); } lfError lf_db_load (lfDatabase *db) { return db->Load (); } cbool lf_db_load_directory (lfDatabase *db, const char *dirname) { return db->LoadDirectory (dirname); } lfError lf_db_load_file (lfDatabase *db, const char *filename) { return db->Load (filename); } lfError lf_db_load_data (lfDatabase *db, const char *errcontext, const char *data, size_t data_size) { return db->Load (errcontext, data, data_size); } lfError lf_db_save_all (const lfDatabase *db, const char *filename) { return db->Save (filename); } lfError lf_db_save_file (const lfDatabase *db, const char *filename, const lfMount *const *mounts, const lfCamera *const *cameras, const lfLens *const *lenses) { return db->Save (filename, mounts, cameras, lenses); } char *lf_db_save (const lfMount *const *mounts, const lfCamera *const *cameras, const lfLens *const *lenses) { return lfDatabase::Save (mounts, cameras, lenses); } const lfCamera **lf_db_find_cameras (const lfDatabase *db, const char *maker, const char *model) { return db->FindCameras (maker, model); } const lfCamera **lf_db_find_cameras_ext ( const lfDatabase *db, const char *maker, const char *model, int sflags) { return db->FindCamerasExt (maker, model, sflags); } const lfCamera *const *lf_db_get_cameras (const lfDatabase *db) { return db->GetCameras (); } const lfLens **lf_db_find_lenses_hd (const lfDatabase *db, const lfCamera *camera, const char *maker, const char *lens, int sflags) { return db->FindLenses (camera, maker, lens, sflags); } const lfLens **lf_db_find_lenses (const lfDatabase *db, const lfLens *lens, int sflags) { return db->FindLenses (lens, sflags); } const lfLens *const *lf_db_get_lenses (const lfDatabase *db) { return db->GetLenses (); } const lfMount *lf_db_find_mount (const lfDatabase *db, const char *mount) { return db->FindMount (mount); } const char *lf_db_mount_name (const lfDatabase *db, const char *mount) { return db->MountName (mount); } const lfMount * const *lf_db_get_mounts (const lfDatabase *db) { return db->GetMounts (); } lensfun-0.3.4/libs/lensfun/lens.cpp000066400000000000000000001316071445356770400172670ustar00rootroot00000000000000/* Private constructors and destructors Copyright (C) 2007 by Andrew Zabolotny */ #include "config.h" #include "lensfun.h" #include "lensfunprv.h" #include #include #include #include #include #include #include "windows/mathconstants.h" #include static struct { const char *regex; guchar matchidx [3]; bool compiled; regex_t rex; } lens_name_regex [] = { { // [min focal]-[max focal]mm f/[min aperture]-[max aperture] "([[:space:]]+|^)([0-9]+[0-9.]*)(-[0-9]+[0-9.]*)?(mm)?[[:space:]]+(f/|f|1/|1:)?([0-9.]+)(-[0-9.]+)?", { 2, 3, 6 }, false }, { // 1:[min aperture]-[max aperture] [min focal]-[max focal]mm "[[:space:]]+1:([0-9.]+)(-[0-9.]+)?[[:space:]]+([0-9.]+)(-[0-9.]+)?(mm)?", { 3, 4, 1 }, false }, { // [min aperture]-[max aperture]/[min focal]-[max focal] "([0-9.]+)(-[0-9.]+)?[[:space:]]*/[[:space:]]*([0-9.]+)(-[0-9.]+)?", { 3, 4, 1 }, false }, }; static float _lf_parse_float (const char *model, const regmatch_t &match) { char tmp [100]; const char *src = model + match.rm_so; int len = match.rm_eo - match.rm_so; // Skip '-' since it's not a minus sign but rather the separator if (*src == '-') src++, len--; strncpy (tmp, src, len); tmp [len] = 0; return atof (tmp); } static bool _lf_parse_lens_name (const char *model, float &minf, float &maxf, float &mina) { if (!model) return false; for (size_t i = 0; i < ARRAY_LEN (lens_name_regex); i++) { if (!lens_name_regex [i].compiled) { regcomp (&lens_name_regex [i].rex, lens_name_regex [i].regex, REG_EXTENDED | REG_ICASE); lens_name_regex [i].compiled = true; } regmatch_t matches [10]; if (regexec (&lens_name_regex [i].rex, model, 10, matches, 0)) continue; guchar *matchidx = lens_name_regex [i].matchidx; if (matches [matchidx [0]].rm_so != -1) minf = _lf_parse_float (model, matches [matchidx [0]]); if (matches [matchidx [1]].rm_so != -1) maxf = _lf_parse_float (model, matches [matchidx [1]]); if (matches [matchidx [2]].rm_so != -1) mina = _lf_parse_float (model, matches [matchidx [2]]); return true; } return false; } static void _lf_free_lens_regex () { for (size_t i = 0; i < ARRAY_LEN (lens_name_regex); i++) if (lens_name_regex [i].compiled) { regfree (&lens_name_regex [i].rex); lens_name_regex [i].compiled = false; } } //------------------------------------------------------------------------// static int _lf_lens_regex_refs = 0; lfLens::lfLens () { // Defaults for attributes are "unknown" (mostly 0). Otherwise, ad hoc // lfLens instances used for searches could not be matched against database // lenses easily. If you need defaults for database tags, set them when // reading the database. memset (this, 0, sizeof (*this)); Type = LF_UNKNOWN; _lf_lens_regex_refs++; } lfLens::~lfLens () { lf_free (Maker); lf_free (Model); _lf_list_free ((void **)Mounts); _lf_list_free ((void **)CalibDistortion); _lf_list_free ((void **)CalibTCA); _lf_list_free ((void **)CalibVignetting); _lf_list_free ((void **)CalibCrop); _lf_list_free ((void **)CalibFov); _lf_list_free ((void **)CalibRealFocal); if (!--_lf_lens_regex_refs) _lf_free_lens_regex (); } lfLens::lfLens (const lfLens &other) { Maker = lf_mlstr_dup (other.Maker); Model = lf_mlstr_dup (other.Model); MinFocal = other.MinFocal; MaxFocal = other.MaxFocal; MinAperture = other.MinAperture; MaxAperture = other.MaxAperture; Mounts = NULL; if (other.Mounts) for (int i = 0; other.Mounts [i]; i++) AddMount (other.Mounts [i]); CenterX = other.CenterX; CenterY = other.CenterY; CropFactor = other.CropFactor; AspectRatio = other.AspectRatio; Type = other.Type; CalibDistortion = NULL; if (other.CalibDistortion) for (int i = 0; other.CalibDistortion [i]; i++) AddCalibDistortion (other.CalibDistortion [i]); CalibTCA = NULL; if (other.CalibTCA) for (int i = 0; other.CalibTCA [i]; i++) AddCalibTCA (other.CalibTCA [i]); CalibVignetting = NULL; if (other.CalibVignetting) for (int i = 0; other.CalibVignetting [i]; i++) AddCalibVignetting (other.CalibVignetting [i]); CalibCrop = NULL; if (other.CalibCrop) for (int i = 0; other.CalibCrop [i]; i++) AddCalibCrop (other.CalibCrop [i]); CalibFov = NULL; if (other.CalibFov) for (int i = 0; other.CalibFov [i]; i++) AddCalibFov (other.CalibFov [i]); CalibRealFocal = NULL; if (other.CalibRealFocal) for (int i = 0; other.CalibRealFocal [i]; i++) AddCalibRealFocal (other.CalibRealFocal [i]); } lfLens &lfLens::operator = (const lfLens &other) { lf_free (Maker); Maker = lf_mlstr_dup (other.Maker); lf_free (Model); Model = lf_mlstr_dup (other.Model); MinFocal = other.MinFocal; MaxFocal = other.MaxFocal; MinAperture = other.MinAperture; MaxAperture = other.MaxAperture; lf_free (Mounts); Mounts = NULL; if (other.Mounts) for (int i = 0; other.Mounts [i]; i++) AddMount (other.Mounts [i]); CenterX = other.CenterX; CenterY = other.CenterY; CropFactor = other.CropFactor; AspectRatio = other.AspectRatio; Type = other.Type; lf_free (CalibDistortion); CalibDistortion = NULL; if (other.CalibDistortion) for (int i = 0; other.CalibDistortion [i]; i++) AddCalibDistortion (other.CalibDistortion [i]); lf_free (CalibTCA); CalibTCA = NULL; if (other.CalibTCA) for (int i = 0; other.CalibTCA [i]; i++) AddCalibTCA (other.CalibTCA [i]); lf_free (CalibVignetting); CalibVignetting = NULL; if (other.CalibVignetting) for (int i = 0; other.CalibVignetting [i]; i++) AddCalibVignetting (other.CalibVignetting [i]); lf_free (CalibCrop); CalibCrop = NULL; if (other.CalibCrop) for (int i = 0; other.CalibCrop [i]; i++) AddCalibCrop (other.CalibCrop [i]); lf_free (CalibFov); CalibFov = NULL; if (other.CalibFov) for (int i = 0; other.CalibFov [i]; i++) AddCalibFov (other.CalibFov [i]); lf_free (CalibRealFocal); CalibRealFocal = NULL; if (other.CalibRealFocal) for (int i = 0; other.CalibRealFocal [i]; i++) AddCalibRealFocal (other.CalibRealFocal [i]); return *this; } void lfLens::SetMaker (const char *val, const char *lang) { Maker = lf_mlstr_add (Maker, lang, val); } void lfLens::SetModel (const char *val, const char *lang) { Model = lf_mlstr_add (Model, lang, val); } void lfLens::AddMount (const char *val) { if (val) _lf_addstr (&Mounts, val); } void lfLens::GuessParameters () { float minf = float (INT_MAX), maxf = float (INT_MIN); float mina = float (INT_MAX), maxa = float (INT_MIN); char *old_numeric = setlocale (LC_NUMERIC, NULL); old_numeric = strdup (old_numeric); setlocale (LC_NUMERIC, "C"); if (Model && (!MinAperture || !MinFocal) && !strstr (Model, "adapter") && !strstr (Model, "reducer") && !strstr (Model, "booster") && !strstr (Model, "extender") && !strstr (Model, "converter")) _lf_parse_lens_name (Model, minf, maxf, mina); if (!MinAperture || !MinFocal) { // Try to find out the range of focal lengths using calibration data if (CalibDistortion) for (int i = 0; CalibDistortion [i]; i++) { float f = CalibDistortion [i]->Focal; if (f < minf) minf = f; if (f > maxf) maxf = f; } if (CalibTCA) for (int i = 0; CalibTCA [i]; i++) { float f = CalibTCA [i]->Focal; if (f < minf) minf = f; if (f > maxf) maxf = f; } if (CalibVignetting) for (int i = 0; CalibVignetting [i]; i++) { float f = CalibVignetting [i]->Focal; float a = CalibVignetting [i]->Aperture; if (f < minf) minf = f; if (f > maxf) maxf = f; if (a < mina) mina = a; if (a > maxa) maxa = a; } if (CalibCrop) for (int i=0; CalibCrop [i]; i++) { float f = CalibCrop [i]->Focal; if (f < minf) minf = f; if (f > maxf) maxf = f; } if (CalibFov) for (int i=0; CalibFov [i]; i++) { float f = CalibFov [i]->Focal; if (f < minf) minf = f; if (f > maxf) maxf = f; } if (CalibRealFocal) for (int i=0; CalibRealFocal [i]; i++) { float f = CalibRealFocal [i]->Focal; if (f < minf) minf = f; if (f > maxf) maxf = f; } } if (minf != INT_MAX && !MinFocal) MinFocal = minf; if (maxf != INT_MIN && !MaxFocal) MaxFocal = maxf; if (mina != INT_MAX && !MinAperture) MinAperture = mina; if (maxa != INT_MIN && !MaxAperture) MaxAperture = maxa; if (!MaxFocal) MaxFocal = MinFocal; setlocale (LC_NUMERIC, old_numeric); free (old_numeric); } bool lfLens::Check () { GuessParameters (); if (!Model || !Mounts || CropFactor <= 0 || MinFocal > MaxFocal || (MaxAperture && MinAperture > MaxAperture) || AspectRatio < 1) return false; return true; } const char *lfLens::GetDistortionModelDesc ( lfDistortionModel model, const char **details, const lfParameter ***params) { static const lfParameter *param_none [] = { NULL }; static const lfParameter param_poly3_k1 = { "k1", -0.2F, 0.2F, 0.0F }; static const lfParameter *param_poly3 [] = { ¶m_poly3_k1, NULL }; static const lfParameter param_poly5_k2 = { "k2", -0.2F, 0.2F, 0.0F }; static const lfParameter *param_poly5 [] = { ¶m_poly3_k1, ¶m_poly5_k2, NULL }; static const lfParameter param_ptlens_a = { "a", -0.2F, 0.2F, 0.0F }; static const lfParameter param_ptlens_b = { "b", -0.2F, 0.2F, 0.0F }; static const lfParameter param_ptlens_c = { "c", -0.2F, 0.2F, 0.0F }; static const lfParameter *param_ptlens [] = { ¶m_ptlens_a, ¶m_ptlens_b, ¶m_ptlens_c, NULL }; switch (model) { case LF_DIST_MODEL_NONE: if (details) *details = "No distortion model"; if (params) *params = param_none; return "None"; case LF_DIST_MODEL_POLY3: if (details) *details = "Rd = Ru * (1 - k1 + k1 * Ru^2)\n" "Ref: http://www.imatest.com/docs/distortion.html"; if (params) *params = param_poly3; return "3rd order polynomial"; case LF_DIST_MODEL_POLY5: if (details) *details = "Rd = Ru * (1 + k1 * Ru^2 + k2 * Ru^4)\n" "Ref: http://www.imatest.com/docs/distortion.html"; if (params) *params = param_poly5; return "5th order polynomial"; case LF_DIST_MODEL_PTLENS: if (details) *details = "Rd = Ru * (a * Ru^3 + b * Ru^2 + c * Ru + 1 - (a + b + c))\n" "Ref: http://wiki.panotools.org/Lens_correction_model"; if (params) *params = param_ptlens; return "PanoTools lens model"; default: // keep gcc 4.4 happy break; } if (details) *details = NULL; if (params) *params = NULL; return NULL; } const char *lfLens::GetTCAModelDesc ( lfTCAModel model, const char **details, const lfParameter ***params) { static const lfParameter *param_none [] = { NULL }; static const lfParameter param_linear_kr = { "kr", 0.99F, 1.01F, 1.0F }; static const lfParameter param_linear_kb = { "kb", 0.99F, 1.01F, 1.0F }; static const lfParameter *param_linear [] = { ¶m_linear_kr, ¶m_linear_kb, NULL }; static const lfParameter param_poly3_br = { "br", -0.01F, 0.01F, 0.0F }; static const lfParameter param_poly3_cr = { "cr", -0.01F, 0.01F, 0.0F }; static const lfParameter param_poly3_vr = { "vr", 0.99F, 1.01F, 1.0F }; static const lfParameter param_poly3_bb = { "bb", -0.01F, 0.01F, 0.0F }; static const lfParameter param_poly3_cb = { "cb", -0.01F, 0.01F, 0.0F }; static const lfParameter param_poly3_vb = { "vb", 0.99F, 1.01F, 1.0F }; static const lfParameter *param_poly3 [] = { ¶m_poly3_vr, ¶m_poly3_vb, ¶m_poly3_cr, ¶m_poly3_cb, ¶m_poly3_br, ¶m_poly3_bb, NULL }; switch (model) { case LF_TCA_MODEL_NONE: if (details) *details = "No transversal chromatic aberration model"; if (params) *params = param_none; return "None"; case LF_TCA_MODEL_LINEAR: if (details) *details = "Cd = Cs * k\n" "Ref: http://cipa.icomos.org/fileadmin/papers/Torino2005/403.pdf"; if (params) *params = param_linear; return "Linear"; case LF_TCA_MODEL_POLY3: if (details) *details = "Cd = Cs^3 * b + Cs^2 * c + Cs * v\n" "Ref: http://wiki.panotools.org/Tca_correct"; if (params) *params = param_poly3; return "3rd order polynomial"; default: // keep gcc 4.4 happy break; } if (details) *details = NULL; if (params) *params = NULL; return NULL; } const char *lfLens::GetVignettingModelDesc ( lfVignettingModel model, const char **details, const lfParameter ***params) { static const lfParameter *param_none [] = { NULL }; static const lfParameter param_pa_k1 = { "k1", -1.0, 2.0, 0.0 }; static const lfParameter param_pa_k2 = { "k2", -1.0, 2.0, 0.0 }; static const lfParameter param_pa_k3 = { "k3", -1.0, 2.0, 0.0 }; static const lfParameter *param_pa [] = { ¶m_pa_k1, ¶m_pa_k2, ¶m_pa_k3, NULL }; switch (model) { case LF_VIGNETTING_MODEL_NONE: if (details) *details = "No vignetting model"; if (params) *params = param_none; return "None"; case LF_VIGNETTING_MODEL_PA: if (details) *details = "Pablo D'Angelo vignetting model\n" "(which is a more general variant of the cos^4 law):\n" "Cd = Cs * (1 + k1 * R^2 + k2 * R^4 + k3 * R^6)\n" "Ref: http://hugin.sourceforge.net/tech/"; if (params) *params = param_pa; return "6th order polynomial"; default: // keep gcc 4.4 happy break; } if (details) *details = ""; if (params) *params = NULL; return NULL; } const char *lfLens::GetCropDesc ( lfCropMode mode , const char **details, const lfParameter ***params) { static const lfParameter *param_none [] = { NULL }; static const lfParameter param_crop_left = { "left", -1.0F, 1.0F, 0.0F }; static const lfParameter param_crop_right = { "right", 0.0F, 2.0F, 0.0F }; static const lfParameter param_crop_top = { "top", -1.0F, 1.0F, 0.0F }; static const lfParameter param_crop_bottom = { "bottom", 0.0F, 2.0F, 0.0F }; static const lfParameter *param_crop [] = { ¶m_crop_left, ¶m_crop_right, ¶m_crop_top, ¶m_crop_bottom, NULL }; switch (mode) { case LF_NO_CROP: if (details) *details = "No crop"; if (params) *params = param_none; return "No crop"; case LF_CROP_RECTANGLE: if (details) *details = "Rectangular crop area"; if (params) *params = param_crop; return "rectangular crop"; case LF_CROP_CIRCLE: if (details) *details = "Circular crop area"; if (params) *params = param_crop; return "circular crop"; default: // keep gcc 4.4 happy break; } if (details) *details = NULL; if (params) *params = NULL; return NULL; } const char *lfLens::GetLensTypeDesc (lfLensType type, const char **details) { switch (type) { case LF_UNKNOWN: if (details) *details = ""; return "Unknown"; case LF_RECTILINEAR: if (details) *details = "Ref: http://wiki.panotools.org/Rectilinear_Projection"; return "Rectilinear"; case LF_FISHEYE: if (details) *details = "Ref: http://wiki.panotools.org/Fisheye_Projection"; return "Fish-Eye"; case LF_PANORAMIC: if (details) *details = "Ref: http://wiki.panotools.org/Cylindrical_Projection"; return "Panoramic"; case LF_EQUIRECTANGULAR: if (details) *details = "Ref: http://wiki.panotools.org/Equirectangular_Projection"; return "Equirectangular"; case LF_FISHEYE_ORTHOGRAPHIC: if (details) *details = "Ref: http://wiki.panotools.org/Fisheye_Projection"; return "Fisheye, orthographic"; case LF_FISHEYE_STEREOGRAPHIC: if (details) *details = "Ref: http://wiki.panotools.org/Stereographic_Projection"; return "Fisheye, stereographic"; case LF_FISHEYE_EQUISOLID: if (details) *details = "Ref: http://wiki.panotools.org/Fisheye_Projection"; return "Fisheye, equisolid"; case LF_FISHEYE_THOBY: if (details) *details = "Ref: http://groups.google.com/group/hugin-ptx/browse_thread/thread/bd822d178e3e239d"; return "Thoby-Fisheye"; default: // keep gcc 4.4 happy break; } if (details) *details = ""; return NULL; } static bool cmp_distortion (const void *x1, const void *x2) { const lfLensCalibDistortion *d1 = static_cast (x1); const lfLensCalibDistortion *d2 = static_cast (x2); return (d1->Focal == d2->Focal); } void lfLens::AddCalibDistortion (const lfLensCalibDistortion *dc) { // Avoid "dereferencing type-punned pointer will break strict-aliasing rules" warning union { lfLensCalibDistortion ***cd; void ***arr; } x = { &CalibDistortion }; _lf_addobj (x.arr, dc, sizeof (*dc), cmp_distortion); } bool lfLens::RemoveCalibDistortion (int idx) { // Avoid "dereferencing type-punned pointer will break strict-aliasing rules" warning union { lfLensCalibDistortion ***cd; void ***arr; } x = { &CalibDistortion }; return _lf_delobj (x.arr, idx); } static bool cmp_tca (const void *x1, const void *x2) { const lfLensCalibTCA *t1 = static_cast (x1); const lfLensCalibTCA *t2 = static_cast (x2); return (t1->Focal == t2->Focal); } void lfLens::AddCalibTCA (const lfLensCalibTCA *tcac) { // Avoid "dereferencing type-punned pointer will break strict-aliasing rules" warning union { lfLensCalibTCA ***ctca; void ***arr; } x = { &CalibTCA }; _lf_addobj (x.arr, tcac, sizeof (*tcac), cmp_tca); } bool lfLens::RemoveCalibTCA (int idx) { // Avoid "dereferencing type-punned pointer will break strict-aliasing rules" warning union { lfLensCalibTCA ***ctca; void ***arr; } x = { &CalibTCA }; return _lf_delobj (x.arr, idx); } static bool cmp_vignetting (const void *x1, const void *x2) { const lfLensCalibVignetting *v1 = static_cast (x1); const lfLensCalibVignetting *v2 = static_cast (x2); return (v1->Focal == v2->Focal) && (v1->Distance == v2->Distance) && (v1->Aperture == v2->Aperture); } void lfLens::AddCalibVignetting (const lfLensCalibVignetting *vc) { // Avoid "dereferencing type-punned pointer will break strict-aliasing rules" warning union { lfLensCalibVignetting ***cv; void ***arr; } x = { &CalibVignetting }; _lf_addobj (x.arr, vc, sizeof (*vc), cmp_vignetting); } bool lfLens::RemoveCalibVignetting (int idx) { // Avoid "dereferencing type-punned pointer will break strict-aliasing rules" warning union { lfLensCalibVignetting ***cv; void ***arr; } x = { &CalibVignetting }; return _lf_delobj (x.arr, idx); } static bool cmp_lenscrop (const void *x1, const void *x2) { const lfLensCalibCrop *d1 = static_cast (x1); const lfLensCalibCrop *d2 = static_cast (x2); return (d1->Focal == d2->Focal); } void lfLens::AddCalibCrop (const lfLensCalibCrop *lcc) { // Avoid "dereferencing type-punned pointer will break strict-aliasing rules" warning union { lfLensCalibCrop ***cd; void ***arr; } x = { &CalibCrop }; _lf_addobj (x.arr, lcc, sizeof (*lcc), cmp_lenscrop); } bool lfLens::RemoveCalibCrop (int idx) { // Avoid "dereferencing type-punned pointer will break strict-aliasing rules" warning union { lfLensCalibCrop ***cd; void ***arr; } x = { &CalibCrop }; return _lf_delobj (x.arr, idx); } static bool cmp_lensfov (const void *x1, const void *x2) { const lfLensCalibFov *d1 = static_cast (x1); const lfLensCalibFov *d2 = static_cast (x2); return (d1->Focal == d2->Focal); } void lfLens::AddCalibFov (const lfLensCalibFov *lcf) { // Avoid "dereferencing type-punned pointer will break strict-aliasing rules" warning union { lfLensCalibFov ***cd; void ***arr; } x = { &CalibFov }; _lf_addobj (x.arr, lcf, sizeof (*lcf), cmp_lensfov); } bool lfLens::RemoveCalibFov (int idx) { // Avoid "dereferencing type-punned pointer will break strict-aliasing rules" warning union { lfLensCalibFov ***cd; void ***arr; } x = { &CalibFov }; return _lf_delobj (x.arr, idx); } static bool cmp_real_focal (const void *x1, const void *x2) { const lfLensCalibRealFocal *d1 = static_cast (x1); const lfLensCalibRealFocal *d2 = static_cast (x2); return (d1->Focal == d2->Focal); } void lfLens::AddCalibRealFocal (const lfLensCalibRealFocal *lcf) { // Avoid "dereferencing type-punned pointer will break strict-aliasing rules" warning union { lfLensCalibRealFocal ***cd; void ***arr; } x = { &CalibRealFocal }; _lf_addobj (x.arr, lcf, sizeof (*lcf), cmp_real_focal); } bool lfLens::RemoveCalibRealFocal (int idx) { // Avoid "dereferencing type-punned pointer will break strict-aliasing rules" warning union { lfLensCalibRealFocal ***cd; void ***arr; } x = { &CalibRealFocal }; return _lf_delobj (x.arr, idx); } static int __insert_spline (void **spline, float *spline_dist, float dist, void *val) { if (dist < 0) { if (dist > spline_dist [1]) { spline_dist [0] = spline_dist [1]; spline_dist [1] = dist; spline [0] = spline [1]; spline [1] = val; return 1; } else if (dist > spline_dist [0]) { spline_dist [0] = dist; spline [0] = val; return 0; } } else { if (dist < spline_dist [2]) { spline_dist [3] = spline_dist [2]; spline_dist [2] = dist; spline [3] = spline [2]; spline [2] = val; return 2; } else if (dist < spline_dist [3]) { spline_dist [3] = dist; spline [3] = val; return 3; } } return -1; } static void __parameter_scales (float values [], int number_of_values, int type, int model, int index) { switch (type) { case LF_MODIFY_DISTORTION: switch (model) { case LF_DIST_MODEL_POLY3: case LF_DIST_MODEL_POLY5: case LF_DIST_MODEL_PTLENS: break; } break; case LF_MODIFY_TCA: switch (model) { case LF_TCA_MODEL_LINEAR: case LF_TCA_MODEL_POLY3: if (index < 2) for (int i=0; i < number_of_values; i++) values [i] = 1.0; break; } break; } } bool lfLens::InterpolateDistortion (float focal, lfLensCalibDistortion &res) const { if (!CalibDistortion) return false; union { lfLensCalibDistortion *spline [4]; void *spline_ptr [4]; }; float spline_dist [4] = { -FLT_MAX, -FLT_MAX, FLT_MAX, FLT_MAX }; lfDistortionModel dm = LF_DIST_MODEL_NONE; memset (spline, 0, sizeof (spline)); for (int i = 0; CalibDistortion [i]; i++) { lfLensCalibDistortion *c = CalibDistortion [i]; if (c->Model == LF_DIST_MODEL_NONE) continue; // Take into account just the first encountered lens model if (dm == LF_DIST_MODEL_NONE) dm = c->Model; else if (dm != c->Model) { g_warning ("[Lensfun] lens %s/%s has multiple distortion models defined\n", Maker, Model); continue; } float df = focal - c->Focal; if (df == 0.0) { // Exact match found, don't care to interpolate res = *c; return true; } __insert_spline (spline_ptr, spline_dist, df, c); } if (!spline [1] || !spline [2]) { if (spline [1]) res = *spline [1]; else if (spline [2]) res = *spline [2]; else return false; return true; } // No exact match found, interpolate the model parameters res.Model = dm; res.Focal = focal; float t = (focal - spline [1]->Focal) / (spline [2]->Focal - spline [1]->Focal); for (size_t i = 0; i < ARRAY_LEN (res.Terms); i++) { float values [5] = {spline [0] ? spline [0]->Focal : NAN, spline [1]->Focal, spline [2]->Focal, spline [3] ? spline [3]->Focal : NAN, focal}; __parameter_scales (values, 5, LF_MODIFY_DISTORTION, dm, i); res.Terms [i] = _lf_interpolate ( spline [0] ? spline [0]->Terms [i] * values [0] : FLT_MAX, spline [1]->Terms [i] * values [1], spline [2]->Terms [i] * values [2], spline [3] ? spline [3]->Terms [i] * values [3] : FLT_MAX, t) / values [4]; } return true; } bool lfLens::InterpolateTCA (float focal, lfLensCalibTCA &res) const { if (!CalibTCA) return false; union { lfLensCalibTCA *spline [4]; void *spline_ptr [4]; }; float spline_dist [4] = { -FLT_MAX, -FLT_MAX, FLT_MAX, FLT_MAX }; lfTCAModel tcam = LF_TCA_MODEL_NONE; memset (&spline, 0, sizeof (spline)); for (int i = 0; CalibTCA [i]; i++) { lfLensCalibTCA *c = CalibTCA [i]; if (c->Model == LF_TCA_MODEL_NONE) continue; // Take into account just the first encountered lens model if (tcam == LF_TCA_MODEL_NONE) tcam = c->Model; else if (tcam != c->Model) { g_warning ("[Lensfun] lens %s/%s has multiple TCA models defined\n", Maker, Model); continue; } float df = focal - c->Focal; if (df == 0.0) { // Exact match found, don't care to interpolate res = *c; return true; } __insert_spline (spline_ptr, spline_dist, df, c); } if (!spline [1] || !spline [2]) { if (spline [1]) res = *spline [1]; else if (spline [2]) res = *spline [2]; else return false; return true; } // No exact match found, interpolate the model parameters res.Model = tcam; res.Focal = focal; float t = (focal - spline [1]->Focal) / (spline [2]->Focal - spline [1]->Focal); for (size_t i = 0; i < ARRAY_LEN (res.Terms); i++) { float values [5] = {spline [0] ? spline [0]->Focal : NAN, spline [1]->Focal, spline [2]->Focal, spline [3] ? spline [3]->Focal : NAN, focal}; __parameter_scales (values, 5, LF_MODIFY_TCA, tcam, i); res.Terms [i] = _lf_interpolate ( spline [0] ? spline [0]->Terms [i] * values [0] : FLT_MAX, spline [1]->Terms [i] * values [1], spline [2]->Terms [i] * values [2], spline [3] ? spline [3]->Terms [i] * values [3] : FLT_MAX, t) / values [4]; } return true; } static float __vignetting_dist ( const lfLens *l, const lfLensCalibVignetting &x, float focal, float aperture, float distance) { // translate every value to linear scale and normalize // approximatively to range 0..1 float f1 = focal - l->MinFocal; float f2 = x.Focal - l->MinFocal; float df = l->MaxFocal - l->MinFocal; if (df != 0) { f1 /= df; f2 /= df; } float a1 = 4.0 / aperture; float a2 = 4.0 / x.Aperture; float d1 = 0.1 / distance; float d2 = 0.1 / x.Distance; return sqrt (square (f2 - f1) + square (a2 - a1) + square (d2 - d1)); } bool lfLens::InterpolateVignetting ( float focal, float aperture, float distance, lfLensCalibVignetting &res) const { if (!CalibVignetting) return false; lfVignettingModel vm = LF_VIGNETTING_MODEL_NONE; res.Focal = focal; res.Aperture = aperture; res.Distance = distance; for (size_t i = 0; i < ARRAY_LEN (res.Terms); i++) res.Terms [i] = 0; // Use http://en.wikipedia.org/wiki/Inverse_distance_weighting with // p = 3.5. float total_weighting = 0; const float power = 3.5; float smallest_interpolation_distance = FLT_MAX; for (int i = 0; CalibVignetting [i]; i++) { const lfLensCalibVignetting* c = CalibVignetting [i]; // Take into account just the first encountered lens model if (vm == LF_VIGNETTING_MODEL_NONE) { vm = c->Model; res.Model = vm; } else if (vm != c->Model) { g_warning ("[Lensfun] lens %s/%s has multiple vignetting models defined\n", Maker, Model); continue; } float interpolation_distance = __vignetting_dist (this, *c, focal, aperture, distance); if (interpolation_distance < 0.0001) { res = *c; return true; } smallest_interpolation_distance = std::min(smallest_interpolation_distance, interpolation_distance); float weighting = fabs (1.0 / pow (interpolation_distance, power)); for (size_t i = 0; i < ARRAY_LEN (res.Terms); i++) res.Terms [i] += weighting * c->Terms [i]; total_weighting += weighting; } if (smallest_interpolation_distance > 1) return false; if (total_weighting > 0 && smallest_interpolation_distance < FLT_MAX) { for (size_t i = 0; i < ARRAY_LEN (res.Terms); i++) res.Terms [i] /= total_weighting; return true; } else return false; } bool lfLens::InterpolateCrop (float focal, lfLensCalibCrop &res) const { if (!CalibCrop) return false; union { lfLensCalibCrop *spline [4]; void *spline_ptr [4]; }; float spline_dist [4] = { -FLT_MAX, -FLT_MAX, FLT_MAX, FLT_MAX }; lfCropMode cm = LF_NO_CROP; memset (spline, 0, sizeof (spline)); for (int i = 0; CalibCrop [i]; i++) { lfLensCalibCrop *c = CalibCrop [i]; if (c->CropMode == LF_NO_CROP) continue; // Take into account just the first encountered crop mode if (cm == LF_NO_CROP) cm = c->CropMode; else if (cm != c->CropMode) { g_warning ("[Lensfun] lens %s/%s has multiple crop modes defined\n", Maker, Model); continue; } float df = focal - c->Focal; if (df == 0.0) { // Exact match found, don't care to interpolate res = *c; return true; } __insert_spline (spline_ptr, spline_dist, df, c); } if (!spline [1] || !spline [2]) { if (spline [1]) res = *spline [1]; else if (spline [2]) res = *spline [2]; else return false; return true; } // No exact match found, interpolate the model parameters res.CropMode = cm; res.Focal = focal; float t = (focal - spline [1]->Focal) / (spline [2]->Focal - spline [1]->Focal); for (size_t i = 0; i < ARRAY_LEN (res.Crop); i++) res.Crop [i] = _lf_interpolate ( spline [0] ? spline [0]->Crop [i] : FLT_MAX, spline [1]->Crop [i], spline [2]->Crop [i], spline [3] ? spline [3]->Crop [i] : FLT_MAX, t); return true; } bool lfLens::InterpolateFov (float focal, lfLensCalibFov &res) const { if (!CalibFov) return false; union { lfLensCalibFov *spline [4]; void *spline_ptr [4]; }; float spline_dist [4] = { -FLT_MAX, -FLT_MAX, FLT_MAX, FLT_MAX }; memset (spline, 0, sizeof (spline)); int counter=0; for (int i = 0; CalibFov [i]; i++) { lfLensCalibFov *c = CalibFov [i]; if (c->FieldOfView == 0) continue; counter++; float df = focal - c->Focal; if (df == 0.0) { // Exact match found, don't care to interpolate res = *c; return true; } __insert_spline (spline_ptr, spline_dist, df, c); } //no valid data found if (counter==0) return false; if (!spline [1] || !spline [2]) { if (spline [1]) res = *spline [1]; else if (spline [2]) res = *spline [2]; else return false; return true; } // No exact match found, interpolate the model parameters res.Focal = focal; float t = (focal - spline [1]->Focal) / (spline [2]->Focal - spline [1]->Focal); res.FieldOfView = _lf_interpolate ( spline [0] ? spline [0]->FieldOfView : FLT_MAX, spline [1]->FieldOfView, spline [2]->FieldOfView, spline [3] ? spline [3]->FieldOfView : FLT_MAX, t); return true; } bool lfLens::InterpolateRealFocal (float focal, lfLensCalibRealFocal &res) const { if (!CalibRealFocal) return false; union { lfLensCalibRealFocal *spline [4]; void *spline_ptr [4]; }; float spline_dist [4] = { -FLT_MAX, -FLT_MAX, FLT_MAX, FLT_MAX }; memset (spline, 0, sizeof (spline)); int counter=0; for (int i = 0; CalibRealFocal [i]; i++) { lfLensCalibRealFocal *c = CalibRealFocal [i]; if (c->RealFocal == 0) continue; counter++; float df = focal - c->Focal; if (df == 0.0) { // Exact match found, don't care to interpolate res = *c; return true; } __insert_spline (spline_ptr, spline_dist, df, c); } //no valid data found if (counter==0) return false; if (!spline [1] || !spline [2]) { if (spline [1]) res = *spline [1]; else if (spline [2]) res = *spline [2]; else return false; return true; } // No exact match found, interpolate the model parameters res.Focal = focal; float t = (focal - spline [1]->Focal) / (spline [2]->Focal - spline [1]->Focal); res.RealFocal = _lf_interpolate ( spline [0] ? spline [0]->RealFocal : FLT_MAX, spline [1]->RealFocal, spline [2]->RealFocal, spline [3] ? spline [3]->RealFocal : FLT_MAX, t); return true; } gint _lf_lens_parameters_compare (const lfLens *i1, const lfLens *i2) { int cmp = int ((i1->MinFocal - i2->MinFocal) * 100); if (cmp != 0) return cmp; cmp = int ((i1->MaxFocal - i2->MaxFocal) * 100); if (cmp != 0) return cmp; return int ((i1->MinAperture - i2->MinAperture) * 100); // MaxAperture is usually not given in database... // so it's a guessed value, often incorrect. } gint _lf_lens_name_compare (const lfLens *i1, const lfLens *i2) { int cmp = _lf_strcmp (i1->Maker, i2->Maker); if (cmp != 0) return cmp; return _lf_strcmp (i1->Model, i2->Model); } gint _lf_lens_compare (gconstpointer a, gconstpointer b) { lfLens *i1 = (lfLens *)a; lfLens *i2 = (lfLens *)b; int cmp = _lf_lens_name_compare (i1, i2); if (cmp != 0) return cmp; return int ((i1->CropFactor - i2->CropFactor) * 100); } static int _lf_compare_num (float a, float b) { if (!a || !b) return 0; // neutral float r = a / b; if (r <= 0.99 || r >= 1.01) return -1; // strong no return +1; // strong yes } int _lf_lens_compare_score (const lfLens *pattern, const lfLens *match, lfFuzzyStrCmp *fuzzycmp, const char **compat_mounts) { int score = 0; // Compare numeric fields first since that's easy. if (pattern->Type != LF_UNKNOWN) if (pattern->Type != match->Type) return 0; if (pattern->CropFactor > 0.01 && pattern->CropFactor < match->CropFactor * 0.96) return 0; if (pattern->CropFactor >= match->CropFactor * 1.41) score += 2; else if (pattern->CropFactor >= match->CropFactor * 1.31) score += 4; else if (pattern->CropFactor >= match->CropFactor * 1.21) score += 6; else if (pattern->CropFactor >= match->CropFactor * 1.11) score += 8; else if (pattern->CropFactor >= match->CropFactor * 1.01) score += 10; else if (pattern->CropFactor >= match->CropFactor) score += 5; else if (pattern->CropFactor >= match->CropFactor * 0.96) score += 3; switch (_lf_compare_num (pattern->MinFocal, match->MinFocal)) { case -1: return 0; case +1: score += 10; break; } switch (_lf_compare_num (pattern->MaxFocal, match->MaxFocal)) { case -1: return 0; case +1: score += 10; break; } switch (_lf_compare_num (pattern->MinAperture, match->MinAperture)) { case -1: return 0; case +1: score += 10; break; } switch (_lf_compare_num (pattern->MaxAperture, match->MaxAperture)) { case -1: return 0; case +1: score += 10; break; } switch (_lf_compare_num (pattern->AspectRatio, match->AspectRatio)) { case -1: return 0; case +1: score += 10; break; } if (compat_mounts && !compat_mounts [0]) compat_mounts = NULL; // Check the lens mount, if specified if (match->Mounts && (pattern->Mounts || compat_mounts)) { bool matching_mount_found = false; if (pattern->Mounts) for (int i = 0; pattern->Mounts [i]; i++) for (int j = 0; match->Mounts [j]; j++) if (!_lf_strcmp (pattern->Mounts [i], match->Mounts [j])) { matching_mount_found = true; score += 10; goto exit_mount_search; } if (compat_mounts) for (int i = 0; compat_mounts [i]; i++) for (int j = 0; match->Mounts [j]; j++) if (!_lf_strcmp (compat_mounts [i], match->Mounts [j])) { matching_mount_found = true; score += 9; goto exit_mount_search; } exit_mount_search: if (!matching_mount_found) return 0; } // If maker is specified, check it using our patented _lf_strcmp(tm) technology if (pattern->Maker && match->Maker) { if (_lf_mlstrcmp (pattern->Maker, match->Maker) != 0) return 0; // Bah! different maker. else score += 10; // Good doggy, here's a cookie } // And now the most complex part - compare models if (pattern->Model && match->Model) { int _score = fuzzycmp->Compare (match->Model); if (!_score) return 0; // Model does not match _score = (_score * 4) / 10; if (!_score) _score = 1; score += _score; } return score; } //---------------------------// The C interface //---------------------------// lfLens *lf_lens_new () { return new lfLens (); } void lf_lens_destroy (lfLens *lens) { delete lens; } void lf_lens_copy (lfLens *dest, const lfLens *source) { *dest = *source; } void lf_lens_guess_parameters (lfLens *lens) { lens->GuessParameters (); } cbool lf_lens_check (lfLens *lens) { return lens->Check (); } const char *lf_get_distortion_model_desc ( enum lfDistortionModel model, const char **details, const lfParameter ***params) { return lfLens::GetDistortionModelDesc (model, details, params); } const char *lf_get_tca_model_desc ( enum lfTCAModel model, const char **details, const lfParameter ***params) { return lfLens::GetTCAModelDesc (model, details, params); } const char *lf_get_vignetting_model_desc ( enum lfVignettingModel model, const char **details, const lfParameter ***params) { return lfLens::GetVignettingModelDesc (model, details, params); } const char *lf_get_crop_desc ( enum lfCropMode mode, const char **details, const lfParameter ***params) { return lfLens::GetCropDesc (mode, details, params); } const char *lf_get_lens_type_desc (enum lfLensType type, const char **details) { return lfLens::GetLensTypeDesc (type, details); } cbool lf_lens_interpolate_distortion (const lfLens *lens, float focal, lfLensCalibDistortion *res) { return lens->InterpolateDistortion (focal, *res); } cbool lf_lens_interpolate_tca (const lfLens *lens, float focal, lfLensCalibTCA *res) { return lens->InterpolateTCA (focal, *res); } cbool lf_lens_interpolate_vignetting (const lfLens *lens, float focal, float aperture, float distance, lfLensCalibVignetting *res) { return lens->InterpolateVignetting (focal, aperture, distance, *res); } cbool lf_lens_interpolate_crop (const lfLens *lens, float focal, lfLensCalibCrop *res) { return lens->InterpolateCrop (focal, *res); } cbool lf_lens_interpolate_fov (const lfLens *lens, float focal, lfLensCalibFov *res) { return lens->InterpolateFov (focal, *res); } cbool lf_lens_interpolate_real_focal (const lfLens *lens, float focal, lfLensCalibRealFocal *res) { return lens->InterpolateRealFocal (focal, *res); } void lf_lens_add_calib_distortion (lfLens *lens, const lfLensCalibDistortion *dc) { lens->AddCalibDistortion (dc); } cbool lf_lens_remove_calib_distortion (lfLens *lens, int idx) { return lens->RemoveCalibDistortion (idx); } void lf_lens_add_calib_tca (lfLens *lens, const lfLensCalibTCA *tcac) { lens->AddCalibTCA (tcac); } cbool lf_lens_remove_calib_tca (lfLens *lens, int idx) { return lens->RemoveCalibTCA (idx); } void lf_lens_add_calib_vignetting (lfLens *lens, const lfLensCalibVignetting *vc) { lens->AddCalibVignetting (vc); } cbool lf_lens_remove_calib_vignetting (lfLens *lens, int idx) { return lens->RemoveCalibVignetting (idx); } void lf_lens_add_calib_crop (lfLens *lens, const lfLensCalibCrop *lcc) { lens->AddCalibCrop (lcc); } cbool lf_lens_remove_calib_crop (lfLens *lens, int idx) { return lens->RemoveCalibCrop (idx); } void lf_lens_add_calib_fov (lfLens *lens, const lfLensCalibFov *lcf) { lens->AddCalibFov (lcf); } cbool lf_lens_remove_calib_fov (lfLens *lens, int idx) { return lens->RemoveCalibFov (idx); } void lf_lens_add_calib_real_focal (lfLens *lens, const lfLensCalibRealFocal *lcf) { lens->AddCalibRealFocal (lcf); } cbool lf_lens_remove_calib_real_focal (lfLens *lens, int idx) { return lens->RemoveCalibRealFocal (idx); } lensfun-0.3.4/libs/lensfun/lensfun.pc.cmake000066400000000000000000000007241445356770400206720ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ bindir=@CMAKE_INSTALL_FULL_BINDIR@ libdir=@CMAKE_INSTALL_FULL_LIBDIR@ includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ datadir=@CMAKE_INSTALL_FULL_DATADIR@ docdir=@CMAKE_INSTALL_FULL_DOCDIR@ Name: lensfun Description: A photographic lens database and access library Version: @VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_MICRO@.@VERSION_BUGFIX@ Requires.private: glib-2.0 Libs: -L${libdir} -llensfun Cflags: -I${includedir} -I${includedir}/lensfun lensfun-0.3.4/libs/lensfun/lensfunprv.h000066400000000000000000000367321445356770400202000ustar00rootroot00000000000000/* Internal library functions and definitions Copyright (C) 2007 by Andrew Zabolotny */ #ifndef __LENSFUNPRV_H__ #define __LENSFUNPRV_H__ #include #include #define MEMBER_OFFSET(s,f) ((unsigned int)(char *)&((s *)0)->f) #define ARRAY_LEN(a) (sizeof (a) / sizeof (a [0])) #define cbool int // This epsilon is in image coordinate space, where 1.0 is // half of the smallest image dimension (width or height) // adjusted for the lens calibration data/camera crop factors. #define NEWTON_EPS 0.00001 class lfFuzzyStrCmp; /** * @brief Return the absolute value of a number. * @param x * A number * @return * The absolute value of x */ template static inline T absolute (T x) { return (x < 0) ? -x : x; } /** * @brief Return the square of the argument. * @param x * A floating-point number. */ template static inline T square (T x) { return x * x; } /** * @brief Clamp a double value between 0 and max, then convert to given type. * @param x * The number to clamp. * @param min * The minimal value. * @param max * The maximal value. If equal to 0, no clamping by upper boundary is done. * @return * The clamped value. */ template static inline T clampd (double x, double min, double max) { if (x < min) return static_cast (min); else if (max != 0.0 && x > max) return static_cast (max); return static_cast (x); } /** * @brief Free a list of pointers. * @param list * A NULL-terminated list of pointers */ extern void _lf_list_free (void **list); /** * @brief Make a copy of given value into given variable using g_strdup, * freeing the old value if defined. * @param var * The variable to copy value into * @param val * The value to assign to the variable */ extern void _lf_setstr (gchar **var, const gchar *val); /** * @brief Add a string to the end of a string list. * @param var * A pointer to an array of strings. * @param val * The value to be added to the array. */ extern void _lf_addstr (gchar ***var, const gchar *val); /** * @brief Insert a item into a GPtrArray, keeping the array sorted. * * This method assumes that the array is already sorted, so * function uses a binary search algorithm. * Returns the index at which the item as inserted. * @param array * The array of pointers to similar items. * @param item * The item to insert into the array. * @param compare * The function to compare two items. * @return * The index at which the item was inserted. */ extern int _lf_ptr_array_insert_sorted ( GPtrArray *array, void *item, GCompareFunc compare); /** * @brief Insert a item into a GPtrArray, keeping the array sorted. If array * contains a item equal to the inserted one, the new item overrides the old. * @param array * The array of pointers to similar items. * @param item * The item to insert into the array. * @param compare * The function to compare two items. * @param dest * The function to destroy old duplicate item (if found). * @return * The index at which the item was inserted. */ extern int _lf_ptr_array_insert_unique ( GPtrArray *array, void *item, GCompareFunc compare, GDestroyNotify dest); /** * @brief Find a item in a sorted array. * * The function uses a binary search algorithm. * @param array * The array of pointers to similar items. * @param item * The item to search for. * @return * The index where the item was found or -1 if not found. */ extern int _lf_ptr_array_find_sorted ( const GPtrArray *array, void *item, GCompareFunc compare); /** * @brief Add a object to a list of objects. * * Accepts an optional pointer to * a function that compares two values from the list, if function * returns true the existing object is replaced with the new one. * @param var * A pointer to an array of objects. * @param val * The value to be added to the array. * @param val_size * The size of the value in bytes. * @param cmpf * An auxiliary function which, if not NULL, should return * true if two objects are similar or false if not. */ extern void _lf_addobj (void ***var, const void *val, size_t val_size, bool (*cmpf) (const void *, const void *)); /** * @brief Remove an object from a list of objects, freeing memory which was * allocated by _lf_addobj(). * @param var * A pointer to an array of objects. * @param idx * The index of the object to remove (zero-based). * @return * false if idx is out of range. */ extern bool _lf_delobj (void ***var, int idx); /** * @brief Appends a formatted string to a dynamically-growing string * using g_markup_printf_escaped() internally. * @param output * The output array. * @param format * The format string. */ extern void _lf_xml_printf (GString *output, const char *format, ...); /** * @brief Output a multi-language value to output string. * * Outputs a number of lines which looks like: * * \Verbatim * ${prefix}<${element}>${val} * ${prefix}<${element} lang="xxx">${val[xxx]} * ... * \EndVerbatim * @param output * The output array. * @param prefix * The prefix at the start of every line of output. * @param element * The name of the element to output. * @param val * The value of the multi-language string. */ extern void _lf_xml_printf_mlstr (GString *output, const char *prefix, const char *element, const lfMLstr val); /** * @brief Get the XML id of the given distortion model * @param model * The model. */ extern const char *_lf_get_distortion_model_id (lfDistortionModel model); /** * @brief Something like a very advanced strcmp(). * * It doesn't segfault if one or both strings are NULL: * NULL is considered to be less than any string. * Actually this function does a fuzzy comparison of the strings, * ignoring spaces at both ends of the string, compressing multiple * spaces into one and ignoring character case. */ extern int _lf_strcmp (const char *s1, const char *s2); /** * @brief Same as _lf_strcmp(), but compares a string with a multi-language * string. * * If it equals any of the translations, 0 is returned, otherwise * the result of strcmp() with the first (default) string is returned. */ extern int _lf_mlstrcmp (const char *s1, const lfMLstr s2); /** * @brief Comparison function for mount sorting and finding. * * Since this function is used when reading the database, it effectively * enforces the primary key for mounts, which is their Name. * @param a * A pointer to first lfMount object. * @param b * A pointer to second lfMount object. * @return * Positive if a > b, negative if a < b, zero if they are equal. */ extern gint _lf_mount_compare (gconstpointer a, gconstpointer b); /** * @brief Comparison function for camera sorting and finding. * * Since this function is used when reading the database, it effectively * enforces the primary key for cameras, which is the combination of the * attributes Maker, Model, and Variant. * @param a * A pointer to first lfCamera object. * @param b * A pointer to second lfCamera object. * @return * Positive if a > b, negative if a < b, zero if they are equal. */ extern gint _lf_camera_compare (gconstpointer a, gconstpointer b); /** * @brief Comparison helper function for lens sorting and finding. * * This function compares the numerical parameters of the lenses: MinFocal, * MaxFocal, and MinAperture, in this order. Since it is not meant to be used * as a sorting key function directly, it doesn't take generic pointers as * parameters. Instead, it is supposed to be used by such sorting key * functions like _lf_lens_compare. * @param i1 * A pointer to first lfLens object. * @param i2 * A pointer to second lfLens object. * @return * Positive if i1 > i2, negative if i1 < i2, zero if they are equal. */ extern gint _lf_lens_parameters_compare (const lfLens *i1, const lfLens *i2); /** * @brief Comparison helper function for lens sorting and finding. * * This function compares the names of the lenses: Maker and Model, in this * order. Since it is not meant to be used as a sorting key function directly, * it doesn't take generic pointers as parameters. Instead, it is supposed to * be used by such sorting key functions like _lf_lens_compare. * @param i1 * A pointer to first lfLens object. * @param i2 * A pointer to second lfLens object. * @return * Positive if i1 > i2, negative if i1 < i2, zero if they are equal. */ extern gint _lf_lens_name_compare (const lfLens *i1, const lfLens *i2); /** * @brief Comparison function for lens sorting and finding. * * Since this function is used when reading the database, it effectively * enforces the primary key for lenses, which is the combination of the * attributes Maker, Model, and CropFactor. * @param a * A pointer to first lfLens object. * @param b * A pointer to second lfLens object. * @return * Positive if a > b, negative if a < b, zero if they are equal. */ extern gint _lf_lens_compare (gconstpointer a, gconstpointer b); /** * @brief Get an interpolated value. * * Currently this uses a kind of Catmull-Rom splines with linear * interpolation at the ends, allowing for non-evenly spaced values * and handling the extreme cases correctly (the one at the start * of spline and at the end of spline). The region of interest is * from y2 to y3, selected by values of t from 0.0 to 1.0. * @param y1 * The Y coordinate of the first spline point. * If equal to FLT_MAX, the first point is considered non-existent. * @param y2 * The Y coordinate of the second spline point. * @param y3 * The Y coordinate of the third spline point. * @param y4 * The Y coordinate of the fourth spline point. * If equal to FLT_MAX, the fourth point is considered non-existent. * @param t * Value from 0.0 to 1.0 selects a point on spline on the interval * between points 2 and 3. */ extern float _lf_interpolate (float y1, float y2, float y3, float y4, float t); /** * @brief Scans for the timestamp of a Lensfun database. * * "database" means here a directory containing XML files. If it also contains * a file timestamp.txt, its content is interpreted as a string-encoded * floating point value, representing the timestamp in seconds since the Epoch * (UNIX time). If it is not present, 0 is returned. If the directory is not * found or empty, a negative value is returned. * @param dirname * the name of the directory containing a Lensfun database; the "version_x" * suffix is implicitly appended * @return * the number of seconds since the Epoch when this database was last * updated. */ extern long int _lf_read_database_timestamp(const gchar *dirname); /** * @brief Compare a lens with a pattern and return a matching score. * * The comparison is quasi-intelligent: the order of words in a name * does not matter; the more words from match are present in the pattern, * the higher is score. Numeric parameters have to coincide or not be specified * at all, otherwise the score drops to zero (well, a 1% tolerance is allowed * for rounding errors etc). * @param pattern * A pattern to compare against. Unsure fields should be set to NULL. * It is generally a good idea to call GuessParameters() first since * that may give additional info for quicker comparison. * @param match * The object to match against. * @param fuzzycmp * A fuzzy comparator initialized with pattern->Model * @param compat_mounts * An additional list of compatible mounts, can be NULL. * This does not include the mounts from pattern->Mounts. * @return * A numeric score in the range 0 to 100, where 100 means that * every field matches and 0 means that at least one field is * fundamentally different. */ extern int _lf_lens_compare_score (const lfLens *pattern, const lfLens *match, lfFuzzyStrCmp *fuzzycmp, const char **compat_mounts); enum { LF_CPU_FLAG_MMX = 0x00000001, LF_CPU_FLAG_SSE = 0x00000002, LF_CPU_FLAG_CMOV = 0x00000004, LF_CPU_FLAG_3DNOW = 0x00000008, LF_CPU_FLAG_3DNOW_EXT = 0x00000010, LF_CPU_FLAG_AMD_ISSE = 0x00000020, LF_CPU_FLAG_SSE2 = 0x00000040, LF_CPU_FLAG_SSE3 = 0x00000080, LF_CPU_FLAG_SSSE3 = 0x00000100, LF_CPU_FLAG_SSE4_1 = 0x00000200, LF_CPU_FLAG_SSE4_2 = 0x00000400 }; /** * @brief Detect supported CPU features (used for runtime selection of accelerated * functions for specific architecture extensions). */ extern guint _lf_detect_cpu_features (); /** * @brief Google-in-your-pocket: a fuzzy string comparator. * * This has been designed for comparing lens and camera model names. * At construction the pattern is split into words and then the component * words from target are matched against them. */ class lfFuzzyStrCmp { GPtrArray *pattern_words; GPtrArray *match_words; bool match_all_words; void Split (const char *str, GPtrArray *dest); void Free (GPtrArray *dest); public: /** * @param pattern * The pattern which will be compared against a number of strings. * This is typically what was found in the EXIF data. * @param allwords * If true, all words of the pattern must be present in the * target string. If not, a looser result will be accepted, * although this will be reflected in the match score. */ lfFuzzyStrCmp (const char *pattern, bool allwords); ~lfFuzzyStrCmp (); /** * @brief Fuzzy compare the pattern with a string. * @param match * The string to match against. This is typically taken from the * Lensfun database. * @return * Returns a score in range 0-100. If the match succedes, this score * is the number of matched words divided by the mean word count of * pattern and string, given as a percentage. If it fails, it is 0. * It fails if no words could be matched, of if allwords was set to * true and one word in pattern could not be found in match. */ int Compare (const char *match); /** * @brief Compares the pattern with a multi-language string. * * This function returns the largest score as compared against * every of the translated strings. * @param match * The multi-language string to match against. This is typically taken * from the Lensfun database. * @return * Returns the maximal score in range 0-100. For every component of * the multi-language string, a score is computed: If the match * succedes, the score is the number of matched words divided by the * mean word count of pattern and string, given as a percentage. If it * fails, it is 0. It fails if no words could be matched, of if * allwords was set to true and one word in pattern could not be found * in match. */ int Compare (const lfMLstr match); }; /// Subpixel distortion callback struct lfSubpixelCallbackData : public lfCallbackData { lfSubpixelCoordFunc callback; }; /// A single pixel coordinate modifier callback. struct lfCoordCallbackData : public lfCallbackData { lfModifyCoordFunc callback; }; /// A single pixel color modifier callback. struct lfColorCallbackData : public lfCallbackData { lfModifyColorFunc callback; }; #endif /* __LENSFUNPRV_H__ */ lensfun-0.3.4/libs/lensfun/mod-color-sse.cpp000066400000000000000000000041071445356770400210030ustar00rootroot00000000000000/* Image modifier implementation Copyright (C) 2014 by Roman Lebedev */ #include "config.h" #ifdef VECTORIZATION_SSE #include "lensfun.h" #include "lensfunprv.h" #include #if defined (_MSC_VER) typedef size_t uintptr_t; #else typedef __SIZE_TYPE__ uintptr_t; #endif void lfModifier::ModifyColor_DeVignetting_PA_SSE ( void *data, float _x, float _y, lf_f32 *pixels, int comp_role, int count) { int cr = comp_role; /* * If there are not four components per pixel, or buffer is not aligned, * fall back to plain code */ if (!(((cr & 15) > LF_CR_NEXT) && (((cr >> 4) & 15) > LF_CR_NEXT) && (((cr >> 8) & 15) > LF_CR_NEXT) && (((cr >> 12) & 15) > LF_CR_NEXT) && (((cr >> 16) & 15) == LF_CR_END)) || ((uintptr_t)(pixels) & 0xf)) { return ModifyColor_DeVignetting_PA(data, _x, _y, pixels, comp_role, count); } float *param = (float *)data; float x = _x * param [4]; float y = _y * param [4]; __m128 x2 = _mm_set_ps1 (x); __m128 r2 = _mm_set_ps1 (x * x + y * y); __m128 d1 = _mm_set_ps1 (2.0 * param [3]); __m128 p0 = _mm_set_ps1 (param [0]); __m128 p1 = _mm_set_ps1 (param [1]); __m128 p2 = _mm_set_ps1 (param [2]); __m128 p3 = _mm_set_ps1 (param [3]); __m128 one = _mm_set_ps1 (1.0f); __m128 d2 = _mm_set_ps1 (param [3] * param [3]); // SSE Loop processes 1 pixel/loop for (int i = 0; i < count; i++) { __m128 pix = _mm_load_ps (&pixels [i * 4]); __m128 r4 = _mm_mul_ps (r2, r2); __m128 r6 = _mm_mul_ps (r4, r2); // c = 1.0 + param [0] * r2 + param [1] * r4 + param [2] * r6; __m128 c = _mm_add_ps (_mm_add_ps (_mm_add_ps ( one, _mm_mul_ps (p0, r2)), _mm_mul_ps (r4, p1)), _mm_mul_ps (r6, p2)); pix = _mm_div_ps(pix, c); pix = _mm_max_ps(pix, _mm_setzero_ps()); _mm_store_ps (&pixels [i * 4], pix); // Prepare for next iteration r2 = _mm_add_ps (_mm_add_ps (d2, r2), _mm_mul_ps (d1, x2)); x2 = _mm_add_ps (x2, p3); } } #endif lensfun-0.3.4/libs/lensfun/mod-color-sse2.cpp000066400000000000000000000126151445356770400210700ustar00rootroot00000000000000/* Image modifier implementation Copyright (C) 2007 by Andrew Zabolotny Copyright (C) 2014 by Roman Lebedev */ #include "config.h" #ifdef VECTORIZATION_SSE2 #include "lensfun.h" #include "lensfunprv.h" #include #if defined (_MSC_VER) #define PREFIX_ALIGN __declspec(align(16)) #define SUFFIX_ALIGN #else #define PREFIX_ALIGN #define SUFFIX_ALIGN __attribute__ ((aligned (16))) #endif static PREFIX_ALIGN gint _15_bit_epi32[4] SUFFIX_ALIGN = { 32768, 32768, 32768, 32768 }; static PREFIX_ALIGN guint _16_bit_sign[4] SUFFIX_ALIGN = { 0x80008000, 0x80008000, 0x80008000, 0x80008000 }; #if defined (_MSC_VER) typedef size_t uintptr_t; #else typedef __SIZE_TYPE__ uintptr_t; #endif void lfModifier::ModifyColor_DeVignetting_PA_SSE2 ( void *data, float _x, float _y, lf_u16 *pixels, int comp_role, int count) { int cr = comp_role; /* * If there are not four components per pixel, or buffer is not aligned, * fall back to plain code */ if (!(((cr & 15) > LF_CR_NEXT) && (((cr >> 4) & 15) > LF_CR_NEXT) && (((cr >> 8) & 15) > LF_CR_NEXT) && (((cr >> 12) & 15) > LF_CR_NEXT) && (((cr >> 16) & 15) == LF_CR_END)) || ((uintptr_t)(pixels) & 0xf)) { return ModifyColor_DeVignetting_PA(data, _x, _y, pixels, comp_role, count); } float *param = (float *)data; float p4 = param [4]; float p3 = param [3]; float x = _x * p4; float y = _y * p4; __m128 x2 = _mm_set_ps1 (x); float t0 = x * x + y * y; x += p3; float t1 = x * x + y * y; x += p3; float t2 = x * x + y * y; x += p3; float t3 = x * x + y * y; x += p3; __m128 r2 = _mm_set_ps (t3, t2, t1, t0); __m128 d1_4 = _mm_set_ps1 (4.0f * 2.0 * p3); __m128 p0 = _mm_set_ps1 (param [0]); __m128 p1 = _mm_set_ps1 (param [1]); __m128 p2 = _mm_set_ps1 (param [2]); __m128 p3_4 = _mm_set_ps1 (p3 * 4.0f); __m128 one = _mm_set_ps1 (1.0f); __m128 frac = _mm_set_ps1 (1024.0f); __m128i rounder = _mm_set1_epi32 (512); // add_four = 4 * d2 + 6 * d1 * p3 __m128 add_four = _mm_set_ps1 (16.0f * p3 * p3); // SSE Loop processes 4 pixels/loop int loop_count = count / 4; for (int i = 0; i < loop_count ; i++) { // First two pixels __m128i pix0 = _mm_load_si128 ((__m128i*)&pixels [i * 16]); // Second pair __m128i pix1 = _mm_load_si128 ((__m128i*)&pixels [i * 16 + 8]); __m128 r4 = _mm_mul_ps (r2, r2); __m128 r6 = _mm_mul_ps (r4, r2); // c = 1.0 + param [0] * r2 + param [1] * r4 + param [2] * r6; __m128 c = _mm_add_ps (_mm_add_ps (_mm_add_ps (one, _mm_mul_ps (p0, r2)), _mm_mul_ps (r4, p1)), _mm_mul_ps (r6, p2)); // Calculate 5.10 fixed point coefficients. __m128i fraction = _mm_cvttps_epi32 (_mm_mul_ps (_mm_rcp_ps (c), frac)); // Pack to 16 bit signed fraction = _mm_packs_epi32 (fraction, fraction); __m128i pix_frac0 = _mm_shufflelo_epi16 (fraction, _MM_SHUFFLE (0, 0, 0, 0)); pix_frac0 = _mm_shufflehi_epi16 (pix_frac0, _MM_SHUFFLE (1, 1, 1, 1)); __m128i pix_frac1 = _mm_shufflelo_epi16 (fraction, _MM_SHUFFLE (2, 2, 2, 2)); pix_frac1 = _mm_shufflehi_epi16 (pix_frac1, _MM_SHUFFLE (3, 3, 3, 3)); __m128i pix0_lo = _mm_mullo_epi16 (pix0, pix_frac0); __m128i pix0_hi = _mm_mulhi_epu16 (pix0, pix_frac0); __m128i pix1_lo = _mm_mullo_epi16 (pix1, pix_frac1); __m128i pix1_hi = _mm_mulhi_epu16 (pix1, pix_frac1); __m128i sub_32 = _mm_load_si128 ((__m128i*)_15_bit_epi32); __m128i signxor = _mm_load_si128 ((__m128i*)_16_bit_sign); // Recombine multiplied values and shift down by fraction pix0 = _mm_srai_epi32 (_mm_add_epi32 ( _mm_unpacklo_epi16 (pix0_lo, pix0_hi), rounder), 10); pix1 = _mm_srai_epi32 (_mm_add_epi32 ( _mm_unpackhi_epi16 (pix0_lo, pix0_hi), rounder), 10); __m128i pix2 = _mm_srai_epi32 (_mm_add_epi32 ( _mm_unpacklo_epi16 (pix1_lo, pix1_hi), rounder), 10); __m128i pix3 = _mm_srai_epi32 (_mm_add_epi32 ( _mm_unpackhi_epi16 (pix1_lo, pix1_hi), rounder), 10); // Subtract 32768 to avoid saturation pix0 = _mm_sub_epi32 (pix0, sub_32); pix1 = _mm_sub_epi32 (pix1, sub_32); pix2 = _mm_sub_epi32 (pix2, sub_32); pix3 = _mm_sub_epi32 (pix3, sub_32); // 32 bit signed -> 16 bit signed conversion, including saturation pix0 = _mm_packs_epi32 (pix0, pix1); pix1 = _mm_packs_epi32 (pix2, pix3); // Convert sign back pix0 = _mm_xor_si128 (pix0, signxor); pix1 = _mm_xor_si128 (pix1, signxor); // First two pixels _mm_store_si128 ((__m128i*)&pixels [i * 16], pix0); // Second pair _mm_store_si128 ((__m128i*)&pixels [i * 16 + 8], pix1); // r2_new = ((((r2) + d1 * (x + (p3*0)) + d2) + d1 * (x + (p3*1)) + d2) + d1 * (x + (p3*2)) + d2) + d1 * (x + (p3*3)) + d2 // r2_new = 4 * d2 + 6 * d1 * p3 + r2 + 4*d1*x // r2_new = add_four + r2 + 4*d1*x // Prepare for next iteration r2 = _mm_add_ps (_mm_add_ps (add_four, r2), _mm_mul_ps (d1_4, x2)); x2 = _mm_add_ps (x2, p3_4); } loop_count *= 4; count -= loop_count; if (count) ModifyColor_DeVignetting_PA (data, _x + loop_count, _y + loop_count, &pixels [loop_count * 4], comp_role, count); } #endif lensfun-0.3.4/libs/lensfun/mod-color.cpp000066400000000000000000000236401445356770400202160ustar00rootroot00000000000000/* Image modifier implementation Copyright (C) 2007 by Andrew Zabolotny */ #include "config.h" #include "lensfun.h" #include "lensfunprv.h" #include void lfModifier::AddColorCallback ( lfModifyColorFunc callback, int priority, void *data, size_t data_size) { lfColorCallbackData *d = new lfColorCallbackData (); d->callback = callback; AddCallback (ColorCallbacks, d, priority, data, data_size); } bool lfModifier::AddColorCallbackVignetting ( lfLensCalibVignetting &model, lfPixelFormat format, bool reverse) { float tmp [5]; #define ADD_CALLBACK(func, type, prio) \ AddColorCallback ( \ (lfModifyColorFunc)(void (*)(void *, float, float, type *, int, int)) \ lfModifier::func, prio, tmp, 5 * sizeof (float)) \ memcpy (tmp, model.Terms, 3 * sizeof (float)); // Damn! Hugin uses two different "normalized" coordinate systems: // for distortions it uses 1.0 = min(half width, half height) and // for vignetting it uses 1.0 = half diagonal length. We have // to compute a transition coefficient as lfModifier works in // the first coordinate system. tmp [3] = NormScale / AspectRatioCorrection; tmp [4] = 1.0 / AspectRatioCorrection; if (reverse) switch (model.Model) { case LF_VIGNETTING_MODEL_PA: switch (format) { case LF_PF_U8: ADD_CALLBACK (ModifyColor_Vignetting_PA, lf_u8, 250); break; case LF_PF_U16: ADD_CALLBACK (ModifyColor_Vignetting_PA, lf_u16, 250); break; case LF_PF_U32: ADD_CALLBACK (ModifyColor_Vignetting_PA, lf_u32, 250); break; case LF_PF_F32: ADD_CALLBACK (ModifyColor_Vignetting_PA, lf_f32, 250); break; case LF_PF_F64: ADD_CALLBACK (ModifyColor_Vignetting_PA, lf_f64, 250); break; default: return false; } break; default: return false; } else switch (model.Model) { case LF_VIGNETTING_MODEL_PA: switch (format) { case LF_PF_U8: ADD_CALLBACK (ModifyColor_DeVignetting_PA, lf_u8, 750); break; case LF_PF_U16: #ifdef VECTORIZATION_SSE2 if (_lf_detect_cpu_features () & LF_CPU_FLAG_SSE2) ADD_CALLBACK (ModifyColor_DeVignetting_PA_SSE2, lf_u16, 750); else #endif ADD_CALLBACK (ModifyColor_DeVignetting_PA, lf_u16, 750); break; case LF_PF_U32: ADD_CALLBACK (ModifyColor_DeVignetting_PA, lf_u32, 750); break; case LF_PF_F32: #ifdef VECTORIZATION_SSE if (_lf_detect_cpu_features () & LF_CPU_FLAG_SSE) ADD_CALLBACK (ModifyColor_DeVignetting_PA_SSE, lf_f32, 750); else #endif ADD_CALLBACK (ModifyColor_DeVignetting_PA, lf_f32, 750); break; case LF_PF_F64: ADD_CALLBACK (ModifyColor_DeVignetting_PA, lf_f64, 750); break; default: return false; } break; default: return false; } #undef ADD_CALLBACK return true; } bool lfModifier::ApplyColorModification ( void *pixels, float x, float y, int width, int height, int comp_role, int row_stride) const { if (((GPtrArray *)ColorCallbacks)->len <= 0 || height <= 0) return false; // nothing to do x = x * NormScale - CenterX; y = y * NormScale - CenterY; for (; height; y += NormScale, height--) { for (int i = 0; i < (int)((GPtrArray *)ColorCallbacks)->len; i++) { lfColorCallbackData *cd = (lfColorCallbackData *)g_ptr_array_index ((GPtrArray *)ColorCallbacks, i); cd->callback (cd->data, x, y, pixels, comp_role, width); } pixels = ((char *)pixels) + row_stride; } return true; } // Helper template to return the maximal value for a type. // By default returns 0.0, which means to not clamp by upper boundary. templateinline double type_max (T x) { return 0.0; } template<>inline double type_max (lf_u16 x) { return 65535.0; } template<>inline double type_max (lf_u32 x) { return 4294967295.0; } templatestatic inline T *apply_multiplier (T *pixels, double c, int &cr) { for (;;) { switch (cr & 15) { case LF_CR_END: return pixels; case LF_CR_NEXT: cr >>= 4; return pixels; case LF_CR_UNKNOWN: break; default: *pixels = clampd (*pixels * c, 0.0, type_max (T (0))); break; } pixels++; cr >>= 4; } return pixels; } inline guint clampbits (gint x, guint n) { guint32 _y_temp; if ((_y_temp = x >> n)) x = ~_y_temp >> (32 - n); return x; } // For lf_u8 pixel type do a more efficient arithmetic using fixed point template<>inline lf_u8 *apply_multiplier (lf_u8 *pixels, double c, int &cr) { // Use 20.12 fixed-point math. That leaves 11 bits (factor 2048) as max multiplication int c12 = int (c * 4096.0); if (c12 > (2047 << 12)) c12 = 2047 << 12; for (;;) { switch (cr & 15) { case LF_CR_END: return pixels; case LF_CR_NEXT: cr >>= 4; return pixels; case LF_CR_UNKNOWN: break; default: if ((cr & 15) > LF_CR_UNKNOWN) { int r = (int (*pixels) * c12 + 2048) >> 12; *pixels = clampbits (r, 8); } break; } pixels++; cr >>= 4; } return pixels; } // For lf_u16 pixel type do a more efficient arithmetic using fixed point template<>inline lf_u16 *apply_multiplier (lf_u16 *pixels, double c, int &cr) { // Use 22.10 fixed-point math. That leaves 6 bits (factor 32) as max multiplication int c10 = int (c * 1024.0); if (c10 > (31 << 10)) c10 = 31 << 10; for (;;) { switch (cr & 15) { case LF_CR_END: return pixels; case LF_CR_NEXT: cr >>= 4; return pixels; case LF_CR_UNKNOWN: break; default: if ((cr & 15) > LF_CR_UNKNOWN) { int r = (int (*pixels) * c10 + 512) >> 10; *pixels = clampbits (r, 16); } break; } pixels++; cr >>= 4; } return pixels; } template void lfModifier::ModifyColor_Vignetting_PA ( void *data, float x, float y, T *pixels, int comp_role, int count) { float *param = (float *)data; x *= param [4]; y *= param [4]; // For faster computation we will compute r^2 here, and // further compute just the delta: // ((x+1)*(x+1)+y*y) - (x*x + y*y) = 2 * x + 1 // But since we work in a normalized coordinate system, a step of // 1.0 pixels should be multiplied by NormScale, so it's really: // ((x+ns)*(x+ns)+y*y) - (x*x + y*y) = 2 * ns * x + ns^2 float r2 = x * x + y * y; float d1 = 2.0 * param [3]; float d2 = param [3] * param [3]; int cr = 0; while (count--) { float r4 = r2 * r2; float r6 = r4 * r2; float c = 1.0 + param [0] * r2 + param [1] * r4 + param [2] * r6; if (!cr) cr = comp_role; pixels = apply_multiplier (pixels, c, cr); r2 += d1 * x + d2; x += param [3]; } } template void lfModifier::ModifyColor_DeVignetting_PA ( void *data, float x, float y, T *pixels, int comp_role, int count) { float *param = (float *)data; x *= param [4]; y *= param [4]; // For faster computation we will compute r^2 here, and // further compute just the delta: // ((x+1)*(x+1)+y*y) - (x*x + y*y) = 2 * x + 1 // But since we work in a normalized coordinate system, a step of // 1.0 pixels should be multiplied by NormScale, so it's really: // ((x+ns)*(x+ns)+y*y) - (x*x + y*y) = 2 * ns * x + ns^2 float r2 = x * x + y * y; float d1 = 2.0 * param [3]; float d2 = param [3] * param [3]; int cr = 0; while (count--) { float r4 = r2 * r2; float r6 = r4 * r2; float c = 1.0 + param [0] * r2 + param [1] * r4 + param [2] * r6; if (!cr) cr = comp_role; pixels = apply_multiplier (pixels, 1.0f / c, cr); r2 += d1 * x + d2; x += param [3]; } } //---------------------------// The C interface //---------------------------// void lf_modifier_add_color_callback ( lfModifier *modifier, lfModifyColorFunc callback, int priority, void *data, size_t data_size) { modifier->AddColorCallback (callback, priority, data, data_size); } cbool lf_modifier_add_color_callback_vignetting ( lfModifier *modifier, lfLensCalibVignetting *model, lfPixelFormat format, cbool reverse) { return modifier->AddColorCallbackVignetting (*model, format, reverse); } cbool lf_modifier_apply_color_modification ( lfModifier *modifier, void *pixels, float x, float y, int width, int height, int comp_role, int row_stride) { return modifier->ApplyColorModification ( pixels, x, y, width, height, comp_role, row_stride); } lensfun-0.3.4/libs/lensfun/mod-coord-sse.cpp000066400000000000000000000132771445356770400210030ustar00rootroot00000000000000/* Image modifier implementation: (un)distortion functions Copyright (C) 2007 by Andrew Zabolotny Copyright (C) 2014 by Roman Lebedev Most of the math in this file has been borrowed from PanoTools. Thanks to the PanoTools team for their pioneering work. */ #include "config.h" #ifdef VECTORIZATION_SSE #include "lensfun.h" #include "lensfunprv.h" #include #if defined (_MSC_VER) typedef size_t uintptr_t; #else typedef __SIZE_TYPE__ uintptr_t; #endif void lfModifier::ModifyCoord_UnDist_PTLens_SSE (void *data, float *iocoord, int count) { /* * If buffer is not aligned, fall back to plain code */ if((uintptr_t)(iocoord) & 0xf) { return ModifyCoord_UnDist_PTLens(data, iocoord, count); } float *param = (float *)data; __m128 a = _mm_set_ps1 (param [0]); __m128 b = _mm_set_ps1 (param [1]); __m128 c = _mm_set_ps1 (param [2]); __m128 very_small = _mm_set_ps1 (1e-15); __m128 one = _mm_set_ps1 (1.0f); __m128 d = _mm_sub_ps (one, _mm_add_ps (a, _mm_add_ps (b, c))); // SSE Loop processes 4 pixels/loop int loop_count = count / 4; for (int i = 0; i < loop_count ; i++) { // Load 4 sets of coordinates __m128 c0 = _mm_load_ps (&iocoord[8*i]); __m128 c1 = _mm_load_ps (&iocoord[8*i+4]); __m128 x = _mm_shuffle_ps (c0, c1, _MM_SHUFFLE (2, 0, 2, 0)); __m128 y = _mm_shuffle_ps (c0, c1, _MM_SHUFFLE (3, 1, 3, 1)); __m128 rd = _mm_add_ps (_mm_mul_ps (x, x), _mm_mul_ps (y, y)); // We don't check for zero, but set it to a very small value instead rd = _mm_max_ps (rd, very_small); rd = _mm_rcp_ps (_mm_rsqrt_ps (rd)); __m128 ru = rd; for (int step = 0; step < 4; step++) { // fru = ru * (a * ru^2 * ru + b * ru^2 + c * ru + d) - rd __m128 ru_sq = _mm_mul_ps (ru, ru); __m128 fru = _mm_mul_ps (_mm_mul_ps (a, ru), ru_sq); __m128 t = _mm_add_ps (_mm_mul_ps (b, ru_sq), _mm_add_ps (d, _mm_mul_ps (c, ru))); fru = _mm_sub_ps (_mm_mul_ps (_mm_add_ps (t, fru), ru), rd); // This is most likely faster than loading form L1 cache __m128 two = _mm_add_ps (one, one); __m128 three = _mm_add_ps (one, two); __m128 four = _mm_add_ps (two, two); // corr = 4 * a * ru * ru^2 + 3 * b * ru^2 + 2 * c * ru + d __m128 corr = _mm_mul_ps (c, ru); corr = _mm_add_ps (d, _mm_add_ps (corr, corr)); t = _mm_mul_ps (ru_sq, _mm_mul_ps (three, b)); corr = _mm_add_ps (corr, _mm_mul_ps (_mm_mul_ps (ru, ru_sq), _mm_mul_ps (four, a))); corr = _mm_rcp_ps (_mm_add_ps (corr, t)); // ru -= fru * corr ru = _mm_sub_ps (ru, _mm_mul_ps (fru, corr)); } // We don't check for zero, but set it to a very small value instead ru = _mm_max_ps (ru, very_small); // ru /= rd ru = _mm_mul_ps (ru, _mm_rcp_ps(rd)); c0 = _mm_mul_ps (c0, ru); c1 = _mm_mul_ps (c1, ru); _mm_store_ps (&iocoord [8 * i], c0); _mm_store_ps (&iocoord [8 * i + 4], c1); } loop_count *= 4; int remain = count - loop_count; if (remain) ModifyCoord_UnDist_PTLens (data, &iocoord [loop_count * 2], remain); } void lfModifier::ModifyCoord_Dist_PTLens_SSE (void *data, float *iocoord, int count) { /* * If buffer is not aligned, fall back to plain code */ if((uintptr_t)(iocoord) & 0xf) { return ModifyCoord_Dist_PTLens(data, iocoord, count); } float *param = (float *)data; // Rd = Ru * (a * Ru^3 + b * Ru^2 + c * Ru + d) __m128 a = _mm_set_ps1 (param [0]); __m128 b = _mm_set_ps1 (param [1]); __m128 c = _mm_set_ps1 (param [2]); __m128 d = _mm_sub_ps (_mm_set_ps1 (1.0f), _mm_add_ps (a, _mm_add_ps (b, c))); // SSE Loop processes 4 pixels/loop int loop_count = count / 4; for (int i = 0; i < loop_count ; i++) { __m128 c0 = _mm_load_ps (&iocoord [8 * i]); __m128 c1 = _mm_load_ps (&iocoord [8 * i + 4]); __m128 x = _mm_shuffle_ps (c0, c1, _MM_SHUFFLE (2, 0, 2, 0)); __m128 y = _mm_shuffle_ps (c0, c1, _MM_SHUFFLE (3, 1, 3, 1)); __m128 ru2 = _mm_add_ps (_mm_mul_ps (x, x), _mm_mul_ps (y, y)); __m128 ru = _mm_rcp_ps (_mm_rsqrt_ps (ru2)); // Calculate poly3 = a * ru2 * ru + b * ru2 + c * ru + d; __m128 t = _mm_mul_ps (ru2, b); __m128 poly3 = _mm_mul_ps (_mm_mul_ps (a, ru2), ru); t = _mm_add_ps (t, _mm_mul_ps (ru, c)); poly3 = _mm_add_ps (t, _mm_add_ps (poly3, d)); _mm_store_ps (&iocoord [8 * i], _mm_mul_ps (poly3, c0)); _mm_store_ps (&iocoord [8 * i + 4], _mm_mul_ps (poly3, c1)); } loop_count *= 4; int remain = count - loop_count; if (remain) ModifyCoord_Dist_PTLens (data, &iocoord [loop_count * 2], remain); } void lfModifier::ModifyCoord_Dist_Poly3_SSE (void *data, float *iocoord, int count) { /* * If buffer is not aligned, fall back to plain code */ if((uintptr_t)(iocoord) & 0xf) { return ModifyCoord_Dist_Poly3(data, iocoord, count); } float *param = (float *)data; // Rd = Ru * (d + k1 * Ru^2), d = 1 - k1 __m128 k1 = _mm_set_ps1 (param [0]); __m128 d = _mm_sub_ps (_mm_set_ps1 (1.0f), k1); // SSE Loop processes 4 pixels/loop int loop_count = count / 4; for (int i = 0; i < loop_count ; i++) { __m128 c0 = _mm_load_ps (&iocoord [8 * i]); __m128 c1 = _mm_load_ps (&iocoord [8 * i + 4]); __m128 x = _mm_shuffle_ps (c0, c1, _MM_SHUFFLE (2, 0, 2, 0)); __m128 y = _mm_shuffle_ps (c0, c1, _MM_SHUFFLE (3, 1, 3, 1)); // Calculate poly3 = k1 * ru * ru + d; __m128 poly3 = _mm_add_ps (_mm_mul_ps (_mm_add_ps (_mm_mul_ps (x, x), _mm_mul_ps (y, y)), k1), d); _mm_store_ps (&iocoord [8 * i], _mm_mul_ps (poly3, c0)); _mm_store_ps (&iocoord [8 * i + 4], _mm_mul_ps (poly3, c1)); } loop_count *= 4; int remain = count - loop_count; if (remain) ModifyCoord_Dist_Poly3 (data, &iocoord [loop_count * 2], remain); } #endif lensfun-0.3.4/libs/lensfun/mod-coord.cpp000066400000000000000000001057101445356770400202050ustar00rootroot00000000000000/* Image modifier implementation: (un)distortion functions Copyright (C) 2007 by Andrew Zabolotny Most of the math in this file has been borrowed from PanoTools. Thanks to the PanoTools team for their pioneering work. */ #include "config.h" #include "lensfun.h" #include "lensfunprv.h" #include #include "windows/mathconstants.h" void lfModifier::AddCoordCallback ( lfModifyCoordFunc callback, int priority, void *data, size_t data_size) { lfCoordCallbackData *d = new lfCoordCallbackData (); d->callback = callback; AddCallback (CoordCallbacks, d, priority, data, data_size); } bool lfModifier::AddCoordCallbackDistortion (lfLensCalibDistortion &model, bool reverse) { float tmp [3]; if (reverse) switch (model.Model) { case LF_DIST_MODEL_POLY3: if (!model.Terms [0]) return false; tmp [0] = 1.0 / model.Terms [0]; AddCoordCallback (ModifyCoord_UnDist_Poly3, 250, tmp, sizeof (float)); break; case LF_DIST_MODEL_POLY5: AddCoordCallback (ModifyCoord_UnDist_Poly5, 250, model.Terms, sizeof (float) * 2); break; case LF_DIST_MODEL_PTLENS: #ifdef VECTORIZATION_SSE if (_lf_detect_cpu_features () & LF_CPU_FLAG_SSE) AddCoordCallback (ModifyCoord_UnDist_PTLens_SSE, 250, model.Terms, sizeof (float) * 3); else #endif AddCoordCallback (ModifyCoord_UnDist_PTLens, 250, model.Terms, sizeof (float) * 3); break; default: return false; } else switch (model.Model) { case LF_DIST_MODEL_POLY3: #ifdef VECTORIZATION_SSE if (_lf_detect_cpu_features () & LF_CPU_FLAG_SSE) AddCoordCallback (ModifyCoord_Dist_Poly3_SSE, 750, model.Terms, sizeof (float)); else #endif AddCoordCallback (ModifyCoord_Dist_Poly3, 750, model.Terms, sizeof (float)); break; case LF_DIST_MODEL_POLY5: AddCoordCallback (ModifyCoord_Dist_Poly5, 750, model.Terms, sizeof (float) * 2); break; case LF_DIST_MODEL_PTLENS: #ifdef VECTORIZATION_SSE if (_lf_detect_cpu_features () & LF_CPU_FLAG_SSE) AddCoordCallback (ModifyCoord_Dist_PTLens_SSE, 750, model.Terms, sizeof (float) * 3); else #endif AddCoordCallback (ModifyCoord_Dist_PTLens, 750, model.Terms, sizeof (float) * 3); break; default: return false; } return true; } double lfModifier::AutoscaleResidualDistance (float *coord) const { double result = coord [0] - MaxX; double intermediate = -MaxX - coord [0]; if (intermediate > result) result = intermediate; intermediate = coord [1] - MaxY; if (intermediate > result) result = intermediate; intermediate = -MaxY - coord [1]; return intermediate > result ? intermediate : result; } float lfModifier::GetTransformedDistance (lfPoint point) const { double dist = point.dist; double sa = sin (point.angle); double ca = cos (point.angle); // We have to find the radius ru in the direction of the given point which // distorts to the original (distorted) image edge. We will use Newton's // method for minimizing the distance between the distorted point at ru and // the original edge. float ru = dist; // Initial approximation float dx = 0.0001F; for (int countdown = 50; ; countdown--) { float res [2]; res [0] = ca * ru; res [1] = sa * ru; for (int j = 0; j < (int)((GPtrArray *)CoordCallbacks)->len; j++) { lfCoordCallbackData *cd = (lfCoordCallbackData *)g_ptr_array_index ((GPtrArray *)CoordCallbacks, j); cd->callback (cd->data, res, 1); } double rd = AutoscaleResidualDistance (res); if (rd > -NEWTON_EPS * 100 && rd < NEWTON_EPS * 100) break; if (!countdown) // e.g. for some ultrawide fisheyes corners extend to infinity // so function never converge ... return -1; // Compute approximative function prime in (x,y) res [0] = ca * (ru + dx); res [1] = sa * (ru + dx); for (int j = 0; j < (int)((GPtrArray *)CoordCallbacks)->len; j++) { lfCoordCallbackData *cd = (lfCoordCallbackData *)g_ptr_array_index ((GPtrArray *)CoordCallbacks, j); cd->callback (cd->data, res, 1); } double rd1 = AutoscaleResidualDistance (res); // If rd1 is very close to rd, this means our delta is too small // and we can hit the precision limit of the float format... if (absolute (rd1 - rd) < 0.00001) { dx *= 2; continue; } // dy/dx; double prime = (rd1 - rd) / dx; ru -= rd / prime; } return ru; } float lfModifier::GetAutoScale (bool reverse) { // Compute the scale factor automatically const float subpixel_scale = ((GPtrArray *)SubpixelCallbacks)->len == 0 ? 1.0 : 1.001; if (((GPtrArray *)CoordCallbacks)->len == 0) return subpixel_scale; // 3 2 1 // 4 0 // 5 6 7 lfPoint point [8]; point [1].angle = atan2 (float (Height), float (Width)); point [3].angle = M_PI - point [1].angle; point [5].angle = M_PI + point [1].angle; point [7].angle = 2 * M_PI - point [1].angle; point [0].angle = 0.0F; point [2].angle = float (M_PI / 2.0); point [4].angle = float (M_PI); point [6].angle = float (M_PI * 3.0 / 2.0); point [1].dist = point [3].dist = point [5].dist = point [7].dist = sqrt (float (square (Width) + square (Height))) * 0.5 * NormScale; point [0].dist = point [4].dist = Width * 0.5 * NormScale; point [2].dist = point [6].dist = Height * 0.5 * NormScale; float scale = 0.01F; for (int i = 0; i < 8; i++) { float transformed_distance = GetTransformedDistance (point [i]); float point_scale = point [i].dist / transformed_distance; if (point_scale > scale) scale = point_scale; } // 1 permille is our limit of accuracy (in rare cases, we may be even // worse, depending on what happens between the test points), so assure // that we really have no black borders left. scale *= 1.001; scale *= subpixel_scale; return reverse ? 1.0 / scale : scale; } bool lfModifier::AddCoordCallbackScale (float scale, bool reverse) { float tmp [1]; // Inverse scale factor if (scale == 0.0) { scale = GetAutoScale (reverse); if (scale == 0.0) return false; } tmp [0] = reverse ? scale : 1.0 / scale; int priority = reverse ? 900 : 100; AddCoordCallback (ModifyCoord_Scale, priority, tmp, sizeof (tmp)); return true; } bool lfModifier::AddCoordCallbackGeometry (lfLensType from, lfLensType to, float focal) { float tmp [2]; tmp [0] = focal / NormalizedInMillimeters; tmp [1] = 1.0 / tmp [0]; if(from == to) return false; if(from == LF_UNKNOWN) return false; if(to == LF_UNKNOWN) return false; // handle special cases switch (from) { case LF_RECTILINEAR: switch (to) { case LF_FISHEYE: AddCoordCallback (ModifyCoord_Geom_FishEye_Rect, 500, tmp, sizeof (tmp)); return true; case LF_PANORAMIC: AddCoordCallback (ModifyCoord_Geom_Panoramic_Rect, 500, tmp, sizeof (tmp)); return true; case LF_EQUIRECTANGULAR: AddCoordCallback (ModifyCoord_Geom_ERect_Rect, 500, tmp, sizeof (tmp)); return true; default: // keep gcc 4.4+ happy break; } break; case LF_FISHEYE: switch (to) { case LF_RECTILINEAR: AddCoordCallback (ModifyCoord_Geom_Rect_FishEye, 500, tmp, sizeof (tmp)); return true; case LF_PANORAMIC: AddCoordCallback (ModifyCoord_Geom_Panoramic_FishEye, 500, tmp, sizeof (tmp)); return true; case LF_EQUIRECTANGULAR: AddCoordCallback (ModifyCoord_Geom_ERect_FishEye, 500, tmp, sizeof (tmp)); return true; default: // keep gcc 4.4+ happy break; } break; case LF_PANORAMIC: switch (to) { case LF_RECTILINEAR: AddCoordCallback (ModifyCoord_Geom_Rect_Panoramic, 500, tmp, sizeof (tmp)); return true; case LF_FISHEYE: AddCoordCallback (ModifyCoord_Geom_FishEye_Panoramic, 500, tmp, sizeof (tmp)); return true; case LF_EQUIRECTANGULAR: AddCoordCallback (ModifyCoord_Geom_ERect_Panoramic, 500, tmp, sizeof (tmp)); return true; default: // keep gcc 4.4+ happy break; } break; case LF_EQUIRECTANGULAR: switch (to) { case LF_RECTILINEAR: AddCoordCallback (ModifyCoord_Geom_Rect_ERect, 500, tmp, sizeof (tmp)); return true; case LF_FISHEYE: AddCoordCallback (ModifyCoord_Geom_FishEye_ERect, 500, tmp, sizeof (tmp)); return true; case LF_PANORAMIC: AddCoordCallback (ModifyCoord_Geom_Panoramic_ERect, 500, tmp, sizeof (tmp)); return true; default: // keep gcc 4.4+ happy break; } case LF_FISHEYE_ORTHOGRAPHIC: case LF_FISHEYE_STEREOGRAPHIC: case LF_FISHEYE_EQUISOLID: case LF_FISHEYE_THOBY: case LF_UNKNOWN: default: break; }; //convert from input projection to target projection via equirectangular projection switch(to) { case LF_RECTILINEAR: AddCoordCallback (ModifyCoord_Geom_Rect_ERect, 500, tmp, sizeof (tmp)); break; case LF_FISHEYE: AddCoordCallback (ModifyCoord_Geom_FishEye_ERect, 500, tmp, sizeof (tmp)); break; case LF_PANORAMIC: AddCoordCallback (ModifyCoord_Geom_Panoramic_ERect, 500, tmp, sizeof (tmp)); break; case LF_FISHEYE_ORTHOGRAPHIC: AddCoordCallback (ModifyCoord_Geom_Orthographic_ERect, 500, tmp, sizeof (tmp)); break; case LF_FISHEYE_STEREOGRAPHIC: AddCoordCallback (ModifyCoord_Geom_Stereographic_ERect, 500, tmp, sizeof (tmp)); break; case LF_FISHEYE_EQUISOLID: AddCoordCallback (ModifyCoord_Geom_Equisolid_ERect, 500, tmp, sizeof (tmp)); break; case LF_FISHEYE_THOBY: AddCoordCallback (ModifyCoord_Geom_Thoby_ERect, 500, tmp, sizeof (tmp)); break; case LF_EQUIRECTANGULAR: default: //nothing to do break; }; switch(from) { case LF_RECTILINEAR: AddCoordCallback (ModifyCoord_Geom_ERect_Rect, 500, tmp, sizeof (tmp)); break; case LF_FISHEYE: AddCoordCallback (ModifyCoord_Geom_ERect_FishEye, 500, tmp, sizeof (tmp)); break; case LF_PANORAMIC: AddCoordCallback (ModifyCoord_Geom_ERect_Panoramic, 500, tmp, sizeof (tmp)); break; case LF_FISHEYE_ORTHOGRAPHIC: AddCoordCallback (ModifyCoord_Geom_ERect_Orthographic, 500, tmp, sizeof (tmp)); break; case LF_FISHEYE_STEREOGRAPHIC: AddCoordCallback (ModifyCoord_Geom_ERect_Stereographic, 500, tmp, sizeof (tmp)); break; case LF_FISHEYE_EQUISOLID: AddCoordCallback (ModifyCoord_Geom_ERect_Equisolid, 500, tmp, sizeof (tmp)); break; case LF_FISHEYE_THOBY: AddCoordCallback (ModifyCoord_Geom_ERect_Thoby, 500, tmp, sizeof (tmp)); break; case LF_EQUIRECTANGULAR: default: //nothing to do break; }; return true; } bool lfModifier::ApplyGeometryDistortion ( float xu, float yu, int width, int height, float *res) const { if (((GPtrArray *)CoordCallbacks)->len <= 0 || height <= 0) return false; // nothing to do // All callbacks work with normalized coordinates xu = xu * NormScale - CenterX; yu = yu * NormScale - CenterY; for (float y = yu; height; y += NormScale, height--) { int i; float x = xu; for (i = 0; i < width; i++, x += NormScale) { res [i * 2] = x; res [i * 2 + 1] = y; } for (i = 0; i < (int)((GPtrArray *)CoordCallbacks)->len; i++) { lfCoordCallbackData *cd = (lfCoordCallbackData *)g_ptr_array_index ((GPtrArray *)CoordCallbacks, i); cd->callback (cd->data, res, width); } // Convert normalized coordinates back into natural coordiates for (i = 0; i < width; i++) { res [0] = (res [0] + CenterX) * NormUnScale; res [1] = (res [1] + CenterY) * NormUnScale; res += 2; } } return true; } void lfModifier::ModifyCoord_Scale (void *data, float *iocoord, int count) { float scale = *(float *)data; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { iocoord [0] *= scale; iocoord [1] *= scale; } } void lfModifier::ModifyCoord_UnDist_Poly3 (void *data, float *iocoord, int count) { const float inv_k1 = *(float *)data; const float one_minus_k1_div_k1 = (1 - 1.0 / inv_k1) * inv_k1; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; double rd = sqrt (x * x + y * y); if (rd == 0.0) continue; float rd_div_k1 = rd * inv_k1; // Use Newton's method to avoid dealing with complex numbers // When carefully tuned this works almost as fast as Cardano's // method (and we don't use complex numbers in it, which is // required for a full solution!) // // Original function: Rd = k1 * Ru^3 + (1 - k1) * Ru // Target function: k1 * Ru^3 + (1 - k1) * Ru - Rd = 0 // Divide by k1: Ru^3 + Ru * (1 - k1)/k1 - Rd/k1 = 0 // Derivative: 3 * Ru^2 + (1 - k1)/k1 double ru = rd; for (int step = 0; ; step++) { double fru = ru * ru * ru + ru * one_minus_k1_div_k1 - rd_div_k1; if (fru >= -NEWTON_EPS && fru < NEWTON_EPS) break; if (step > 5) // Does not converge, no real solution in this area? goto next_pixel; ru -= fru / (3 * ru * ru + one_minus_k1_div_k1); } if (ru < 0.0) continue; // Negative radius does not make sense at all ru /= rd; iocoord [0] = x * ru; iocoord [1] = y * ru; next_pixel: ; } } void lfModifier::ModifyCoord_Dist_Poly3 (void *data, float *iocoord, int count) { // Rd = Ru * (1 - k1 + k1 * Ru^2) const float k1 = *(float *)data; const float one_minus_k1 = 1.0 - k1; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { const float x = iocoord [0]; const float y = iocoord [1]; const float poly2 = one_minus_k1 + k1 * (x * x + y * y); iocoord [0] = x * poly2; iocoord [1] = y * poly2; } } void lfModifier::ModifyCoord_UnDist_Poly5 (void *data, float *iocoord, int count) { float *param = (float *)data; float k1 = param [0]; float k2 = param [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; double rd = sqrt (x * x + y * y); if (rd == 0.0) continue; // Use Newton's method double ru = rd; for (int step = 0; ; step++) { double ru2 = ru * ru; double fru = ru * (1.0 + k1 * ru2 + k2 * ru2 * ru2) - rd; if (fru >= -NEWTON_EPS && fru < NEWTON_EPS) break; if (step > 5) // Does not converge, no real solution in this area? goto next_pixel; ru -= fru / (1.0 + 3 * k1 * ru2 + 5 * k2 * ru2 * ru2); } if (ru < 0.0) continue; // Negative radius does not make sense at all ru /= rd; iocoord [0] = x * ru; iocoord [1] = y * ru; next_pixel: ; } } void lfModifier::ModifyCoord_Dist_Poly5 (void *data, float *iocoord, int count) { float *param = (float *)data; // Rd = Ru * (1 + k1 * Ru^2 + k2 * Ru^4) const float k1 = param [0]; const float k2 = param [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { const float x = iocoord [0]; const float y = iocoord [1]; const float ru2 = x * x + y * y; const float poly4 = (1.0 + k1 * ru2 + k2 * ru2 * ru2); iocoord [0] = x * poly4; iocoord [1] = y * poly4; } } void lfModifier::ModifyCoord_UnDist_PTLens (void *data, float *iocoord, int count) { float *param = (float *)data; float a = param [0]; float b = param [1]; float c = param [2]; float d = 1.0 - a - b - c; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; double rd = sqrt (x * x + y * y); if (rd == 0.0) continue; // Use Newton's method double ru = rd; for (int step = 0; ; step++) { double fru = ru * (a * ru * ru * ru + b * ru * ru + c * ru + d) - rd; if (fru >= -NEWTON_EPS && fru < NEWTON_EPS) break; if (step > 5) // Does not converge, no real solution in this area? goto next_pixel; ru -= fru / (4 * a * ru * ru * ru + 3 * b * ru * ru + 2 * c * ru + d); } if (ru < 0.0) continue; // Negative radius does not make sense at all ru /= rd; iocoord [0] = x * ru; iocoord [1] = y * ru; next_pixel: ; } } void lfModifier::ModifyCoord_Dist_PTLens (void *data, float *iocoord, int count) { float *param = (float *)data; // Rd = Ru * (a * Ru^3 + b * Ru^2 + c * Ru + d) const float a = param [0]; const float b = param [1]; const float c = param [2]; const float d = 1.0 - a - b - c; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { const float x = iocoord [0]; const float y = iocoord [1]; const float ru2 = x * x + y * y; const float r = sqrtf (ru2); const float poly3 = a * ru2 * r + b * ru2 + c * r + d; iocoord [0] = x * poly3; iocoord [1] = y * poly3; } } void lfModifier::ModifyCoord_Geom_FishEye_Rect (void *data, float *iocoord, int count) { const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; float r = sqrt (x * x + y * y); float rho, theta = r * inv_dist; if (theta >= M_PI / 2.0) rho = 1.6e16F; else if (theta == 0.0) rho = 1.0; else rho = tan (theta) / theta; iocoord [0] = rho * x; iocoord [1] = rho * y; } } void lfModifier::ModifyCoord_Geom_Rect_FishEye (void *data, float *iocoord, int count) { const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; float theta, r = sqrt (x * x + y * y) * inv_dist; if (r == 0.0) theta = 1.0; else theta = atan (r) / r; iocoord [0] = theta * x; iocoord [1] = theta * y; } } void lfModifier::ModifyCoord_Geom_Panoramic_Rect ( void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0] * inv_dist; float y = iocoord [1]; iocoord [0] = dist * tan (x); iocoord [1] = y / cos (x); } } void lfModifier::ModifyCoord_Geom_Rect_Panoramic ( void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; iocoord [0] = dist * atan (x * inv_dist); iocoord [1] = y * cos (iocoord [0] * inv_dist); } } void lfModifier::ModifyCoord_Geom_FishEye_Panoramic ( void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; double r = sqrt (x * x + y * y); double theta = r * inv_dist; double s = (theta == 0.0) ? inv_dist : (sin (theta) / r); double vx = cos (theta); // z' -> x double vy = s * x; // x' -> y iocoord [0] = dist * atan2 (vy, vx); iocoord [1] = dist * s * y / sqrt (vx * vx + vy * vy); } } void lfModifier::ModifyCoord_Geom_Panoramic_FishEye ( void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; double phi = x * inv_dist; double s = dist * sin (phi); // y' -> x double r = sqrt (s * s + y * y); double theta = 0.0; if (r==0.0) theta = 0.0; else theta = dist * atan2 (r, dist * cos (phi)) / r; iocoord [0] = theta * s; iocoord [1] = theta * y; } } void lfModifier::ModifyCoord_Geom_ERect_Rect (void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; double phi = x * inv_dist; double theta = -y * inv_dist + M_PI / 2.0; if (theta < 0) { theta = -theta; phi += M_PI; } if (theta > M_PI) { theta = 2 * M_PI - theta; phi += M_PI; } iocoord [0] = dist * tan (phi); iocoord [1] = dist / (tan (theta) * cos (phi)); } } void lfModifier::ModifyCoord_Geom_Rect_ERect (void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; iocoord [0] = dist * atan2 (x, dist); iocoord [1] = dist * atan2 (y, sqrt (dist * dist + x * x)); } } void lfModifier::ModifyCoord_Geom_ERect_FishEye (void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; double phi = x * inv_dist; double theta = -y * inv_dist + M_PI / 2; if (theta < 0) { theta = -theta; phi += M_PI; } if (theta > M_PI) { theta = 2 * M_PI - theta; phi += M_PI; } double s = sin (theta); double vx = s * sin (phi); // y' -> x double vy = cos (theta); // z' -> y double r = sqrt (vx * vx + vy * vy); theta = dist * atan2 (r, s * cos (phi)); r = 1.0 / r; iocoord [0] = theta * vx * r; iocoord [1] = theta * vy * r; } } void lfModifier::ModifyCoord_Geom_FishEye_ERect (void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; double r = sqrt (x * x + y * y); double theta = r * inv_dist; double s = (theta == 0.0) ? inv_dist : (sin (theta) / r); double vx = cos (theta); double vy = s * x; iocoord [0] = dist * atan2 (vy, vx); iocoord [1] = dist * atan (s * y / sqrt (vx * vx + vy * vy)); } } void lfModifier::ModifyCoord_Geom_ERect_Panoramic (void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float y = iocoord [1]; iocoord [1] = dist * tan (y * inv_dist); } } void lfModifier::ModifyCoord_Geom_Panoramic_ERect (void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float y = iocoord [1]; iocoord [1] = dist * atan (y * inv_dist); } } void lfModifier::ModifyCoord_Geom_Orthographic_ERect (void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; double r = sqrt(x * x + y * y); double theta = 0.0; if (r < dist) theta = asin (r * inv_dist); else theta = M_PI / 2.0; double phi = atan2 (y, x); double s = (theta == 0.0) ? inv_dist : (sin (theta) / (theta * dist) ); double vx = cos (theta); double vy = s * dist * theta * cos (phi); iocoord [0] = dist * atan2 (vy, vx); iocoord [1] = dist * atan (s * dist * theta * sin (phi) / sqrt (vx * vx + vy * vy)); } }; void lfModifier::ModifyCoord_Geom_ERect_Orthographic (void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; double phi = x * inv_dist; double theta = -y * inv_dist + M_PI / 2; if (theta < 0) { theta = -theta; phi += M_PI; } if (theta > M_PI) { theta = 2 * M_PI - theta; phi += M_PI; } double s = sin (theta); double vx = s * sin (phi); // y' -> x double vy = cos (theta); // z' -> y theta = atan2 (sqrt (vx * vx + vy * vy), s * cos (phi)); phi = atan2 (vy, vx); double rho = dist * sin (theta); iocoord [0] = rho * cos (phi); iocoord [1] = rho * sin (phi); } }; #define EPSLN 1.0e-10 void lfModifier::ModifyCoord_Geom_Stereographic_ERect (void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0] * inv_dist; float y = iocoord [1] * inv_dist; double rh = sqrt (x * x + y * y); double c = 2.0 * atan (rh / 2.0); double sinc = sin (c); double cosc = cos (c); iocoord [0] = 0; if(fabs (rh) <= EPSLN) { iocoord [1] = 1.6e16F; } else { iocoord [1] = asin (y * sinc / rh) * dist; if((fabs (cosc) >= EPSLN) || (fabs (x) >= EPSLN)) { iocoord [0] = atan2 (x * sinc, cosc * rh) * dist; } else { iocoord [0] = 1.6e16F; }; }; }; }; void lfModifier::ModifyCoord_Geom_ERect_Stereographic (void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float lon = iocoord [0] * inv_dist; float lat = iocoord [1] * inv_dist; double cosphi = cos (lat); double ksp = dist * 2.0 / (1.0 + cosphi * cos (lon)); iocoord [0] = ksp * cosphi * sin (lon); iocoord [1] = ksp * sin (lat); } }; void lfModifier::ModifyCoord_Geom_Equisolid_ERect (void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; double r = sqrt (x * x + y * y); double theta = 0.0; if (r < dist*2.0) theta = 2.0 * asin (r * inv_dist / 2.0); else theta = M_PI / 2.0; double phi = atan2 (y, x); double s = (theta == 0.0) ? inv_dist : (sin (theta) / (dist * theta)); double vx = cos (theta); double vy = s * dist * theta * cos (phi); iocoord [0] = dist * atan2 (vy, vx); iocoord [1] = dist * atan (s * dist * theta * sin (phi) / sqrt (vx * vx + vy * vy)); }; }; void lfModifier::ModifyCoord_Geom_ERect_Equisolid (void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { double lambda = iocoord [0] / dist; double phi = iocoord [1] / dist; if (fabs (cos(phi) * cos(lambda) + 1.0) <= EPSLN) { iocoord [0] = 1.6e16F; iocoord [1] = 1.6e16F; } else { double k1 = sqrt (2.0 / (1 + cos(phi) * cos(lambda))); iocoord [0] = dist * k1 * cos (phi) * sin (lambda); iocoord [1] = dist * k1 * sin (phi); }; }; }; #define THOBY_K1_PARM 1.47F #define THOBY_K2_PARM 0.713F void lfModifier::ModifyCoord_Geom_Thoby_ERect (void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; double rho = sqrt (x * x + y * y) * inv_dist; if(rho<-THOBY_K1_PARM || rho > THOBY_K1_PARM) { iocoord [0] = 1.6e16F; iocoord [1] = 1.6e16F; } else { double theta = asin (rho / THOBY_K1_PARM) / THOBY_K2_PARM; double phi = atan2 (y, x); double s = (theta == 0.0) ? inv_dist : (sin (theta) / (dist * theta) ); double vx = cos (theta); double vy = s * dist * theta * cos (phi); iocoord [0] = dist * atan2 (vy, vx); iocoord [1] = dist * atan (s * dist * theta * sin (phi) / sqrt (vx * vx + vy * vy)); }; }; }; void lfModifier::ModifyCoord_Geom_ERect_Thoby (void *data, float *iocoord, int count) { const float dist = ((float *)data) [0]; const float inv_dist = ((float *)data) [1]; for (float *end = iocoord + count * 2; iocoord < end; iocoord += 2) { float x = iocoord [0]; float y = iocoord [1]; double phi = x * inv_dist; double theta = -y * inv_dist + M_PI / 2; if (theta < 0) { theta = -theta; phi += M_PI; } if (theta > M_PI) { theta = 2 * M_PI - theta; phi += M_PI; } double s = sin (theta); double vx = s * sin (phi); // y' -> x double vy = cos (theta); // z' -> y theta = atan2 (sqrt (vx * vx + vy * vy), s * cos (phi)); phi = atan2 (vy, vx); double rho = THOBY_K1_PARM * dist * sin (theta * THOBY_K2_PARM); iocoord [0] = rho * cos (phi); iocoord [1] = rho * sin (phi); }; }; //---------------------------// The C interface //---------------------------// void lf_modifier_add_coord_callback ( lfModifier *modifier, lfModifyCoordFunc callback, int priority, void *data, size_t data_size) { modifier->AddCoordCallback (callback, priority, data, data_size); } cbool lf_modifier_add_coord_callback_distortion ( lfModifier *modifier, lfLensCalibDistortion *model, cbool reverse) { return modifier->AddCoordCallbackDistortion (*model, reverse); } cbool lf_modifier_add_coord_callback_geometry ( lfModifier *modifier, lfLensType from, lfLensType to, float focal) { return modifier->AddCoordCallbackGeometry (from, to, focal); } cbool lf_modifier_add_coord_callback_scale ( lfModifier *modifier, float scale, cbool reverse) { return modifier->AddCoordCallbackScale (scale, reverse); } float lf_modifier_get_auto_scale (lfModifier *modifier, cbool reverse) { return modifier->GetAutoScale (reverse); } cbool lf_modifier_apply_geometry_distortion ( lfModifier *modifier, float xu, float yu, int width, int height, float *res) { return modifier->ApplyGeometryDistortion (xu, yu, width, height, res); } lensfun-0.3.4/libs/lensfun/mod-subpix.cpp000066400000000000000000000241751445356770400204160ustar00rootroot00000000000000/* Image modifier implementation: (un)distortion functions Copyright (C) 2007 by Andrew Zabolotny */ #include "config.h" #include "lensfun.h" #include "lensfunprv.h" #include void lfModifier::AddSubpixelCallback ( lfSubpixelCoordFunc callback, int priority, void *data, size_t data_size) { lfSubpixelCallbackData *d = new lfSubpixelCallbackData (); d->callback = callback; AddCallback (SubpixelCallbacks, d, priority, data, data_size); } bool lfModifier::AddSubpixelCallbackTCA (lfLensCalibTCA &model, bool reverse) { float tmp [2]; if (reverse) switch (model.Model) { case LF_TCA_MODEL_NONE: break; case LF_TCA_MODEL_LINEAR: for (int i = 0; i < 2; i++) { if (!model.Terms [i]) return false; tmp [i] = 1.0 / model.Terms [i]; } AddSubpixelCallback (ModifyCoord_UnTCA_Linear, 500, tmp, 2 * sizeof (float)); return true; case LF_TCA_MODEL_POLY3: AddSubpixelCallback (ModifyCoord_UnTCA_Poly3, 500, model.Terms, 6 * sizeof (float)); return true; default: // keep gcc 4.4+ happy break; } else switch (model.Model) { case LF_TCA_MODEL_NONE: break; case LF_TCA_MODEL_LINEAR: AddSubpixelCallback (ModifyCoord_TCA_Linear, 500, model.Terms, 2 * sizeof (float)); return true; case LF_TCA_MODEL_POLY3: AddSubpixelCallback (ModifyCoord_TCA_Poly3, 500, model.Terms, 6 * sizeof (float)); return true; default: // keep gcc 4.4+ happy break; } return false; } bool lfModifier::ApplySubpixelDistortion ( float xu, float yu, int width, int height, float *res) const { if (((GPtrArray *)SubpixelCallbacks)->len <= 0 || height <= 0) return false; // nothing to do // All callbacks work with normalized coordinates xu = xu * NormScale - CenterX; yu = yu * NormScale - CenterY; for (float y = yu; height; y += NormScale, height--) { int i; float x = xu; float *out = res; for (i = 0; i < width; i++, x += NormScale) { out [0] = out [2] = out [4] = x; out [1] = out [3] = out [5] = y; out += 6; } for (i = 0; i < (int)((GPtrArray *)SubpixelCallbacks)->len; i++) { lfSubpixelCallbackData *cd = (lfSubpixelCallbackData *)g_ptr_array_index ((GPtrArray *)SubpixelCallbacks, i); cd->callback (cd->data, res, width); } // Convert normalized coordinates back into natural coordiates for (i = width * 3; i > 0; i--) { res [0] = (res [0] + CenterX) * NormUnScale; res [1] = (res [1] + CenterY) * NormUnScale; res += 2; } } return true; } bool lfModifier::ApplySubpixelGeometryDistortion ( float xu, float yu, int width, int height, float *res) const { if ((((GPtrArray *)SubpixelCallbacks)->len <= 0 && ((GPtrArray *)CoordCallbacks)->len <= 0) || height <= 0) return false; // nothing to do // All callbacks work with normalized coordinates xu = xu * NormScale - CenterX; yu = yu * NormScale - CenterY; for (float y = yu; height; y += NormScale, height--) { int i; float x = xu; float *out = res; for (i = 0; i < width; i++, x += NormScale) { out [0] = out [2] = out [4] = x; out [1] = out [3] = out [5] = y; out += 6; } for (i = 0; i < (int)((GPtrArray *)CoordCallbacks)->len; i++) { lfCoordCallbackData *cd = (lfCoordCallbackData *)g_ptr_array_index ((GPtrArray *)CoordCallbacks, i); cd->callback (cd->data, res, width * 3); } for (i = 0; i < (int)((GPtrArray *)SubpixelCallbacks)->len; i++) { lfSubpixelCallbackData *cd = (lfSubpixelCallbackData *)g_ptr_array_index ((GPtrArray *)SubpixelCallbacks, i); cd->callback (cd->data, res, width); } // Convert normalized coordinates back into natural coordiates for (i = width * 3; i > 0; i--) { res [0] = (res [0] + CenterX) * NormUnScale; res [1] = (res [1] + CenterY) * NormUnScale; res += 2; } } return true; } void lfModifier::ModifyCoord_UnTCA_Linear (void *data, float *iocoord, int count) { float *param = (float *)data; float k_r = param [0]; float k_b = param [1]; for (float *end = iocoord + count * 2 * 3; iocoord < end; iocoord += 6) { iocoord [0] *= k_r; iocoord [1] *= k_r; iocoord [4] *= k_b; iocoord [5] *= k_b; } } void lfModifier::ModifyCoord_TCA_Linear (void *data, float *iocoord, int count) { float *param = (float *)data; float k_r = param [0]; float k_b = param [1]; for (float *end = iocoord + count * 2 * 3; iocoord < end; iocoord += 6) { iocoord [0] *= k_r; iocoord [1] *= k_r; iocoord [4] *= k_b; iocoord [5] *= k_b; } } void lfModifier::ModifyCoord_UnTCA_Poly3 (void *data, float *iocoord, int count) { const float *param = (float *)data; const float vr = param [0]; const float vb = param [1]; const float cr = param [2]; const float cb = param [3]; const float br = param [4]; const float bb = param [5]; for (float *end = iocoord + count * 2 * 3; iocoord < end; iocoord += 6) { float x, y; double rd, ru, ru2; x = iocoord [0]; y = iocoord [1]; rd = sqrt (x * x + y * y); if (rd == 0.0) goto next_subpixel_r; // Original equation: Rd = b * Ru^3 + c * Ru^2 + v * Ru // We have Rd, need to find Ru. We will use Newton's method // for finding the root of the equation: // // Target function: b * Ru^3 + c * Ru^2 + v * Ru - Rd = 0 // Derivative: 3 * b * Ru^2 + 2 * c * Ru + v ru = rd; for (int step = 0; ; step++) { ru2 = ru * ru; double fru = br * ru2 * ru + cr * ru2 + vr * ru - rd; if (fru >= -NEWTON_EPS && fru < NEWTON_EPS) break; if (step > 5) // Does not converge, no real solution in this area? goto next_subpixel_r; ru -= fru / (3 * br * ru2 + 2 * cr * ru + vr); } // Negative radius does not make sense at all if (ru > 0.0) { ru /= rd; iocoord [0] = x * ru; iocoord [1] = y * ru; } next_subpixel_r: x = iocoord [4]; y = iocoord [5]; rd = sqrt (x * x + y * y); if (rd == 0.0) goto next_subpixel_b; ru = rd; for (int step = 0; ; step++) { ru2 = ru * ru; double fru = bb * ru2 * ru + cb * ru2 + vb * ru - rd; if (fru >= -NEWTON_EPS && fru < NEWTON_EPS) break; if (step > 5) // Does not converge, no real solution in this area? goto next_subpixel_b; ru -= fru / (3 * bb * ru2 + 2 * cb * ru + vb); } // Negative radius does not make sense at all if (ru > 0.0) { ru /= rd; iocoord [4] = x * ru; iocoord [5] = y * ru; } next_subpixel_b:; } } void lfModifier::ModifyCoord_TCA_Poly3 (void *data, float *iocoord, int count) { // Rd = Ru * (b * Ru^2 + c * Ru + v) const float *param = (float *)data; const float vr = param [0]; const float vb = param [1]; const float cr = param [2]; const float cb = param [3]; const float br = param [4]; const float bb = param [5]; float x, y, ru2, poly2; // Optimize for the case when c == 0 (avoid two square roots per pixel) if (cr == 0.0 && cb == 0.0) for (float *end = iocoord + count * 2 * 3; iocoord < end; iocoord += 6) { x = iocoord [0]; y = iocoord [1]; ru2 = x * x + y * y; poly2 = br * ru2 + vr; iocoord [0] = x * poly2; iocoord [1] = y * poly2; x = iocoord [4]; y = iocoord [5]; ru2 = x * x + y * y; poly2 = bb * ru2 + vb; iocoord [4] = x * poly2; iocoord [5] = y * poly2; } else for (float *end = iocoord + count * 2 * 3; iocoord < end; iocoord += 6) { x = iocoord [0]; y = iocoord [1]; ru2 = x * x + y * y; poly2 = br * ru2 + cr * sqrt (ru2) + vr; iocoord [0] = x * poly2; iocoord [1] = y * poly2; x = iocoord [4]; y = iocoord [5]; ru2 = x * x + y * y; poly2 = bb * ru2 + cb * sqrt (ru2) + vb; iocoord [4] = x * poly2; iocoord [5] = y * poly2; } } //---------------------------// The C interface //---------------------------// void lf_modifier_add_subpixel_callback ( lfModifier *modifier, lfSubpixelCoordFunc callback, int priority, void *data, size_t data_size) { modifier->AddSubpixelCallback (callback, priority, data, data_size); } cbool lf_modifier_add_subpixel_callback_TCA ( lfModifier *modifier, lfLensCalibTCA *model, cbool reverse) { return modifier->AddSubpixelCallbackTCA (*model, reverse); } cbool lf_modifier_apply_subpixel_distortion ( lfModifier *modifier, float xu, float yu, int width, int height, float *res) { return modifier->ApplySubpixelDistortion (xu, yu, width, height, res); } cbool lf_modifier_apply_subpixel_geometry_distortion ( lfModifier *modifier, float xu, float yu, int width, int height, float *res) { return modifier->ApplySubpixelGeometryDistortion (xu, yu, width, height, res); } lensfun-0.3.4/libs/lensfun/modifier.cpp000066400000000000000000000267601445356770400201270ustar00rootroot00000000000000/* Image modifier implementation Copyright (C) 2007 by Andrew Zabolotny */ #include "config.h" #include "lensfun.h" #include "lensfunprv.h" #include #include "windows/mathconstants.h" /* Takes into account that the Hugin models (Poly3, PTLens), use a wrong focal * length (see the thread http://thread.gmane.org/gmane.comp.misc.ptx/34865). */ float get_hugin_focal_correction (const lfLens *lens, float focal) { lfLensCalibDistortion res; if (lens->InterpolateDistortion(focal, res)) { if (res.Model == LF_DIST_MODEL_POLY3) return 1 - res.Terms[0]; else if (res.Model == LF_DIST_MODEL_PTLENS) return 1 - res.Terms[0] - res.Terms[1] - res.Terms[2]; } return 1; } lfModifier *lfModifier::Create (const lfLens *lens, float crop, int width, int height) { return new lfModifier (lens, crop, width, height); } int lfModifier::Initialize ( const lfLens *lens, lfPixelFormat format, float focal, float aperture, float distance, float scale, lfLensType targeom, int flags, bool reverse) { int oflags = 0; if (flags & LF_MODIFY_TCA) { lfLensCalibTCA lctca; if (lens->InterpolateTCA (focal, lctca)) if (AddSubpixelCallbackTCA (lctca, reverse)) oflags |= LF_MODIFY_TCA; } if (flags & LF_MODIFY_VIGNETTING) { lfLensCalibVignetting lcv; if (lens->InterpolateVignetting (focal, aperture, distance, lcv)) if (AddColorCallbackVignetting (lcv, format, reverse)) oflags |= LF_MODIFY_VIGNETTING; } if (flags & LF_MODIFY_DISTORTION) { lfLensCalibDistortion lcd; if (lens->InterpolateDistortion (focal, lcd)) if (AddCoordCallbackDistortion (lcd, reverse)) oflags |= LF_MODIFY_DISTORTION; } if (flags & LF_MODIFY_GEOMETRY && lens->Type != targeom) { float real_focal_length = GetRealFocalLength (lens, focal); real_focal_length /= get_hugin_focal_correction (lens, focal); if (reverse ? AddCoordCallbackGeometry (targeom, lens->Type, real_focal_length) : AddCoordCallbackGeometry (lens->Type, targeom, real_focal_length)) oflags |= LF_MODIFY_GEOMETRY; } if (flags & LF_MODIFY_SCALE && scale != 1.0) if (AddCoordCallbackScale (scale, reverse)) oflags |= LF_MODIFY_SCALE; return oflags; } float lfModifier::GetRealFocalLength (const lfLens *lens, float focal) { lfLensCalibRealFocal real_focal; if (lens && lens->InterpolateRealFocal (focal, real_focal)) return real_focal.RealFocal; float result = focal; lfLensCalibFov fov_raw; if (lens && lens->InterpolateFov (focal, fov_raw)) { float fov = fov_raw.FieldOfView * M_PI / 180.0; float half_width_in_millimeters = NormalizedInMillimeters * lens->AspectRatio; // See also SrcPanoImage::calcFocalLength in Hugin. switch (lens->Type) { case LF_UNKNOWN: break; case LF_RECTILINEAR: result = half_width_in_millimeters / tan (fov / 2.0); break; case LF_FISHEYE: case LF_PANORAMIC: case LF_EQUIRECTANGULAR: result = half_width_in_millimeters / (fov / 2.0); break; case LF_FISHEYE_ORTHOGRAPHIC: result = half_width_in_millimeters / sin (fov / 2.0); break; case LF_FISHEYE_STEREOGRAPHIC: result = half_width_in_millimeters / (2 * tan (fov / 4.0)); break; case LF_FISHEYE_EQUISOLID: result = half_width_in_millimeters / (2 * sin (fov / 4.0)); break; case LF_FISHEYE_THOBY: result = half_width_in_millimeters / (1.47 * sin (0.713 * fov / 2.0)); break; default: // This should never happen result = NAN; } } /* It may be surprising that get_hugin_focal_correction is applied even if * only the nominal focal length is found and used. The reason is twofold: * First, many lens manufacturers seem to use a focal length closer to * Hugin's quirky definition. And secondly, we have better * backwards-compatibility this way. In particular, one can use Hugin * results (using the nominal focal length) out-of-the-box. If the nominal * focal length is used, it is guesswork anyway, so this compromise is * acceptable. */ return result * get_hugin_focal_correction (lens, focal); } void lfModifier::Destroy () { delete this; } //---------------------------------------------------------------------------// /* About coordinate systems in Lensfun Lensfun uses three coordinate systems. In all of them, the centre of the image is the origin. There is a single coordinate "r" which is the distance from the origin. (1) For scaling, distortion, and TCA correction, the so-called "normalised" coordinate system is used. r = 1 is the middle of the long edge, in other words, the half height of the image (in landscape mode). (2) For vignetting, r = 1 is the corner of the image. (3) For geometry transformation, the unit length is the focal length. The constructor lfModifier::lfModifier is the central method that handles the coordinate systems. It does so by providing the scaling factors between them: NormScale (and NormUnScale = 1/NormScale), NormalizedInMillimeters, and AspectRatioCorrection. Have a look at lfModifier::ApplySubpixelGeometryDistortion to see the coordinate systems (1) and (3) in action. First, the original pixel coordinates are converted into (1) by multiplying by NormScale. Then, scaling, geometry transformation, un-distortion, and un-TCA are performed, in this order. Remember that this means that the coordinates are *distorted*, to make a proper lookup in the uncorrected, original bitmap. For this to work, the coordinates are finally divided by NormScale again. Done. But the devil is in the details. Geometry transformation has to happen in (3), so for only this step, all coordinates are scaled by focal / NormalizedInMillimeters in lfModifier::AddCoordCallbackGeometry. Moreover, it is important to see that the conversion into (1) is pretty irrelevant. (It is performed for that the resulting image is not ridiculously small; but this could also be achieved with proper auto-scaling.) Instead, really critical is only the *back-transformation* from (1) into the pixel coordinate system of the uncorrected, original bitmap. This must be exactly correct. Otherwise, the strength of correction does not match with the position in the picture, and the correction cannot work. And then there is vignetting. All callbacks work in (1), and vignetting, being the only colour modification so far, also gets its coordinates in (1). Thus, lfModifier::AddColorCallbackVignetting appends two more floats to the array of vignetting parameters for conversion into (2). Sometimes, a calibration is used that was made with another sensor size, i.e. different crop factor and/or aspect ratio. Then, coordinate_correction in the following routine is different from 1. It maps coordinates from (1) of the image sensor to (1) of the calibration sensor. It is a product of three components: Converting to (2) of the image sensor, scaling by the ratio of the cropfactors to (2) of the calibration sensor, and finally converting to (1) of the calibration sensor. The detour via (2) is necessary because crop factors are defined by the sensor diagonal, as is (2). */ lfModifier::lfModifier (const lfLens *lens, float crop, int width, int height) { SubpixelCallbacks = g_ptr_array_new (); ColorCallbacks = g_ptr_array_new (); CoordCallbacks = g_ptr_array_new (); // Avoid divide overflows on singular cases. The "- 1" is due to the fact // that `Width` and `Height` are measured at the pixel centres (they are // actually transformed) instead at their outer rims. Width = (width >= 2 ? width - 1 : 1); Height = (height >= 2 ? height - 1 : 1); // Image "size" float size = float ((Width < Height) ? Width : Height); float image_aspect_ratio = (Width < Height) ? float (Height) / float (Width) : float (Width) / float (Height); float calibration_cropfactor; if (lens) { calibration_cropfactor = lens->CropFactor; AspectRatioCorrection = sqrt (lens->AspectRatio * lens->AspectRatio + 1); } else AspectRatioCorrection = calibration_cropfactor = NAN; float coordinate_correction = 1.0 / sqrt (image_aspect_ratio * image_aspect_ratio + 1) * calibration_cropfactor / crop * AspectRatioCorrection; // In NormalizedInMillimeters, we un-do all factors of // coordinate_correction that refer to the calibration sensor because // NormalizedInMillimeters is supposed to transform to image coordinates. NormalizedInMillimeters = sqrt (36.0*36.0 + 24.0*24.0) / 2.0 / AspectRatioCorrection / calibration_cropfactor; // The scale to transform {-size/2 .. 0 .. size/2-1} to {-1 .. 0 .. +1} NormScale = 2.0 / size * coordinate_correction; // The scale to transform {-1 .. 0 .. +1} to {-size/2 .. 0 .. size/2-1} NormUnScale = size * 0.5 / coordinate_correction; // Geometric lens center in normalized coordinates CenterX = (Width / size + (lens ? lens->CenterX : 0.0)) * coordinate_correction; CenterY = (Height / size + (lens ? lens->CenterY : 0.0)) * coordinate_correction; // Used for autoscaling MaxX = double (Width) / 2.0 * NormScale; MaxY = double (Height) / 2.0 * NormScale; } static void free_callback_list (void *arr) { for (unsigned i = 0; i < ((GPtrArray *)arr)->len; i++) { lfCallbackData *d = (lfCallbackData *)g_ptr_array_index ((GPtrArray *)arr, i); if (d) { if (d->data_size) g_free (d->data); delete d; } } g_ptr_array_free ((GPtrArray *)arr, TRUE); } lfModifier::~lfModifier () { free_callback_list (SubpixelCallbacks); free_callback_list (ColorCallbacks); free_callback_list (CoordCallbacks); } static gint _lf_coordcb_compare (gconstpointer a, gconstpointer b) { lfCallbackData *d1 = (lfCallbackData *)a; lfCallbackData *d2 = (lfCallbackData *)b; return d1->priority < d2->priority ? -1 : d1->priority > d2->priority ? +1 : 0; } void lfModifier::AddCallback (void *arr, lfCallbackData *d, int priority, void *data, size_t data_size) { d->priority = priority; d->data_size = data_size; if (data_size) { d->data = g_malloc (data_size); memcpy (d->data, data, data_size); } else d->data = data; _lf_ptr_array_insert_sorted ((GPtrArray *)arr, d, _lf_coordcb_compare); } //---------------------------// The C interface //---------------------------// lfModifier *lf_modifier_new ( const lfLens *lens, float crop, int width, int height) { return new lfModifier (lens, crop, width, height); } void lf_modifier_destroy (lfModifier *modifier) { modifier->Destroy (); } int lf_modifier_initialize ( lfModifier *modifier, const lfLens *lens, lfPixelFormat format, float focal, float aperture, float distance, float scale, lfLensType targeom, int flags, cbool reverse) { return modifier->Initialize (lens, format, focal, aperture, distance, scale, targeom, flags, reverse); } lensfun-0.3.4/libs/lensfun/mount.cpp000066400000000000000000000033611445356770400174630ustar00rootroot00000000000000/* Private constructors and destructors Copyright (C) 2007 by Andrew Zabolotny */ #include "config.h" #include "lensfun.h" #include "lensfunprv.h" lfMount::lfMount () { // Defaults for attributes are "unknown" (mostly 0). Otherwise, ad hoc // lfLens instances used for searches could not be matched against database // lenses easily. If you need defaults for database tags, set them when // reading the database. memset (this, 0, sizeof (*this)); } lfMount::~lfMount () { lf_free (Name); _lf_list_free ((void **)Compat); } lfMount::lfMount (const lfMount &other) { Name = lf_mlstr_dup (other.Name); Compat = NULL; if (other.Compat) for (int i = 0; other.Compat [i]; i++) AddCompat (other.Compat [i]); } lfMount &lfMount::operator = (const lfMount &other) { lf_free (Name); Name = lf_mlstr_dup (other.Name); lf_free (Compat); Compat = NULL; if (other.Compat) for (int i = 0; other.Compat [i]; i++) AddCompat (other.Compat [i]); return *this; } void lfMount::SetName (const char *val, const char *lang) { Name = lf_mlstr_add (Name, lang, val); } void lfMount::AddCompat (const char *val) { _lf_addstr (&Compat, val); } bool lfMount::Check () { if (!Name) return false; return true; } gint _lf_mount_compare (gconstpointer a, gconstpointer b) { lfMount *i1 = (lfMount *)a; lfMount *i2 = (lfMount *)b; return _lf_strcmp (i1->Name, i2->Name); } //---------------------------// The C interface //---------------------------// lfMount *lf_mount_new () { return new lfMount (); } void lf_mount_destroy (lfMount *mount) { delete mount; } cbool lf_mount_check (lfMount *mount) { return mount->Check (); } lensfun-0.3.4/libs/lensfun/windows/000077500000000000000000000000001445356770400173045ustar00rootroot00000000000000lensfun-0.3.4/libs/lensfun/windows/auxfun.cpp000066400000000000000000000012171445356770400213170ustar00rootroot00000000000000/* Windows-specific stuff Copyright (C) 2008 by Andrew Zabolotny */ #include "config.h" #include #include char *_lf_get_database_dir () { static gchar *dir = NULL; HMODULE h = GetModuleHandle ("liblensfun.dll"); if (!h) return g_strdup (""); char buff [FILENAME_MAX]; if (GetModuleFileName (h, buff, sizeof (buff)) <= 0) return g_strdup (""); char *eos = strchr (buff, 0); while (eos > buff && eos [-1] != '/' && eos [-1] != ':' && eos [-1] != '\\') eos--; *eos = 0; dir = g_build_filename (buff, CONF_DATADIR, DATABASE_SUBDIR, NULL); return dir; }lensfun-0.3.4/libs/lensfun/windows/mathconstants.h000066400000000000000000000010261445356770400223420ustar00rootroot00000000000000/* Math constants definitions for non-POSIX or old compilers. Should be included if necessary after . Copyright (C) 2014 by Torsten Bronger */ #ifndef __MATHCONSTANTS_H__ #define __MATHCONSTANTS_H__ #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #ifndef M_PI_2 #define M_PI_2 1.57079632679489661923 #endif #ifndef NAN #define NAN std::numeric_limits::quiet_NaN() #endif #ifndef INF #define INF std::numeric_limits::infinity() #endif #endif /* __MATHCONSTANTS_H__ */ lensfun-0.3.4/libs/regex/000077500000000000000000000000001445356770400152525ustar00rootroot00000000000000lensfun-0.3.4/libs/regex/CMakeLists.txt000066400000000000000000000007671445356770400200240ustar00rootroot00000000000000# build regex library IF(NOT HAVE_REGEX_H) FILE(GLOB REGEX_SRC *.c *.h) LIST(APPEND REGEX_SRC ../../include/regex/regex.h) ADD_LIBRARY(tre_regex STATIC ${REGEX_SRC}) SET_TARGET_PROPERTIES(tre_regex PROPERTIES COMPILE_FLAGS "-DHAVE_SYS_TYPES_H -DTRE_REGEX_T_FIELD=value -DTRE_VERSION=\\\"0.8.0\\\" -Dinline=_inline") SET_TARGET_PROPERTIES(tre_regex PROPERTIES VERSION "${VERSION_MAJOR}.${VERSION_MINOR}).${VERSION_MICRO}") INSTALL(TARGETS tre_regex ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) ENDIF() lensfun-0.3.4/libs/regex/README000066400000000000000000000005421445356770400161330ustar00rootroot00000000000000This is a subset of the TRE regular expression library: Home page: http://www.laurikari.net/tre/index.html This library is used on platforms without a built-in regular expression library (e.g. windoz). On most Unices this library is not needed. The library is licensed under same terms as Lensfun library, so there's no problem linking them together. lensfun-0.3.4/libs/regex/regcomp.c000066400000000000000000000065531445356770400170630ustar00rootroot00000000000000/* regcomp.c - TRE POSIX compatible regex compilation functions. Copyright (c) 2001-2006 Ville Laurikari This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #include #include #include #include "regex.h" #include "tre-internal.h" #include "xmalloc.h" int regncomp(regex_t *preg, const char *regex, size_t n, int cflags) { int ret; #if TRE_WCHAR tre_char_t *wregex; int wlen; wregex = xmalloc(sizeof(tre_char_t) * (n + 1)); if (wregex == NULL) return REG_ESPACE; /* If the current locale uses the standard single byte encoding of characters, we don't do a multibyte string conversion. If we did, many applications which use the default locale would break since the default "C" locale uses the 7-bit ASCII character set, and all characters with the eighth bit set would be considered invalid. */ #if TRE_MULTIBYTE if (TRE_MB_CUR_MAX == 1) #endif /* TRE_MULTIBYTE */ { unsigned int i; const unsigned char *str = (unsigned char *)regex; tre_char_t *wstr = wregex; for (i = 0; i < n; i++) *(wstr++) = *(str++); wlen = n; } #if TRE_MULTIBYTE else { int consumed; tre_char_t *wcptr = wregex; #ifdef HAVE_MBSTATE_T mbstate_t state; memset(&state, '\0', sizeof(state)); #endif /* HAVE_MBSTATE_T */ while (n > 0) { consumed = tre_mbrtowc(wcptr, regex, n, &state); switch (consumed) { case 0: if (*regex == '\0') consumed = 1; else { xfree(wregex); return REG_BADPAT; } break; case -1: DPRINT(("mbrtowc: error %d: %s.\n", errno, strerror(errno))); xfree(wregex); return REG_BADPAT; case -2: /* The last character wasn't complete. Let's not call it a fatal error. */ consumed = n; break; } regex += consumed; n -= consumed; wcptr++; } wlen = wcptr - wregex; } #endif /* TRE_MULTIBYTE */ wregex[wlen] = L'\0'; ret = tre_compile(preg, wregex, wlen, cflags); xfree(wregex); #else /* !TRE_WCHAR */ ret = tre_compile(preg, (const tre_char_t *)regex, n, cflags); #endif /* !TRE_WCHAR */ return ret; } int regcomp(regex_t *preg, const char *regex, int cflags) { return regncomp(preg, regex, regex ? strlen(regex) : 0, cflags); } #ifdef TRE_WCHAR int regwncomp(regex_t *preg, const wchar_t *regex, size_t n, int cflags) { return tre_compile(preg, regex, n, cflags); } int regwcomp(regex_t *preg, const wchar_t *regex, int cflags) { return tre_compile(preg, regex, regex ? wcslen(regex) : 0, cflags); } #endif /* TRE_WCHAR */ void regfree(regex_t *preg) { tre_free(preg); } /* EOF */ lensfun-0.3.4/libs/regex/regerror.c000066400000000000000000000055761445356770400172620ustar00rootroot00000000000000/* regerror.c - POSIX regerror() implementation for TRE. Copyright (c) 2001-2006 Ville Laurikari . This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #include #ifdef HAVE_WCHAR_H #include #endif /* HAVE_WCHAR_H */ #ifdef HAVE_WCTYPE_H #include #endif /* HAVE_WCTYPE_H */ #include "tre-internal.h" #include "regex.h" #ifdef HAVE_GETTEXT_H #include "gettext.h" #define _(String) dgettext(PACKAGE, String) #define gettext_noop(String) String #else #define _(String) String #define gettext_noop(String) String #define gettext(String) String #endif /* Error message strings for error codes listed in `regex.h'. This list needs to be in sync with the codes listed there, naturally. */ static const char *tre_error_messages[] = { gettext_noop("No error"), /* REG_OK */ gettext_noop("No match"), /* REG_NOMATCH */ gettext_noop("Invalid regexp"), /* REG_BADPAT */ gettext_noop("Unknown collating element"), /* REG_ECOLLATE */ gettext_noop("Unknown character class name"), /* REG_ECTYPE */ gettext_noop("Trailing backslash"), /* REG_EESCAPE */ gettext_noop("Invalid back reference"), /* REG_ESUBREG */ gettext_noop("Missing ']'"), /* REG_EBRACK */ gettext_noop("Missing ')'"), /* REG_EPAREN */ gettext_noop("Missing '}'"), /* REG_EBRACE */ gettext_noop("Invalid contents of {}"), /* REG_BADBR */ gettext_noop("Invalid character range"), /* REG_ERANGE */ gettext_noop("Out of memory"), /* REG_ESPACE */ gettext_noop("Invalid use of repetition operators") /* REG_BADRPT */ }; size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) { const char *err; size_t err_len; if (errcode >= 0 && errcode < (sizeof(tre_error_messages) / sizeof(*tre_error_messages))) err = gettext(tre_error_messages[errcode]); else err = gettext("Unknown error"); err_len = strlen(err) + 1; if (errbuf_size > 0 && errbuf != NULL) { if (err_len > errbuf_size) { strncpy(errbuf, err, errbuf_size - 1); errbuf[errbuf_size - 1] = '\0'; } else { strcpy(errbuf, err); } } return err_len; } /* EOF */ lensfun-0.3.4/libs/regex/regexec.c000066400000000000000000000227101445356770400170420ustar00rootroot00000000000000/* regexec.c - TRE POSIX compatible matching functions (and more). Copyright (c) 2001-2006 Ville Laurikari . This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #ifdef TRE_USE_ALLOCA /* AIX requires this to be the first thing in the file. */ #ifndef __GNUC__ # if HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif #endif #endif /* TRE_USE_ALLOCA */ #include #include #include #ifdef HAVE_WCHAR_H #include #endif /* HAVE_WCHAR_H */ #ifdef HAVE_WCTYPE_H #include #endif /* HAVE_WCTYPE_H */ #ifndef TRE_WCHAR #include #endif /* !TRE_WCHAR */ #ifdef HAVE_MALLOC_H #include #endif /* HAVE_MALLOC_H */ #include #include "tre-internal.h" #include "regex.h" #include "xmalloc.h" /* Fills the POSIX.2 regmatch_t array according to the TNFA tag and match endpoint values. */ void tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags, const tre_tnfa_t *tnfa, int *tags, int match_eo) { tre_submatch_data_t *submatch_data; unsigned int i, j; int *parents; i = 0; if (match_eo >= 0 && !(cflags & REG_NOSUB)) { /* Construct submatch offsets from the tags. */ DPRINT(("end tag = t%d = %d\n", tnfa->end_tag, match_eo)); submatch_data = tnfa->submatch_data; while (i < tnfa->num_submatches && i < nmatch) { if (submatch_data[i].so_tag == tnfa->end_tag) pmatch[i].rm_so = match_eo; else pmatch[i].rm_so = tags[submatch_data[i].so_tag]; if (submatch_data[i].eo_tag == tnfa->end_tag) pmatch[i].rm_eo = match_eo; else pmatch[i].rm_eo = tags[submatch_data[i].eo_tag]; /* If either of the endpoints were not used, this submatch was not part of the match. */ if (pmatch[i].rm_so == -1 || pmatch[i].rm_eo == -1) pmatch[i].rm_so = pmatch[i].rm_eo = -1; DPRINT(("pmatch[%d] = {t%d = %d, t%d = %d}\n", i, submatch_data[i].so_tag, pmatch[i].rm_so, submatch_data[i].eo_tag, pmatch[i].rm_eo)); i++; } /* Reset all submatches that are not within all of their parent submatches. */ i = 0; while (i < tnfa->num_submatches && i < nmatch) { if (pmatch[i].rm_eo == -1) assert(pmatch[i].rm_so == -1); assert(pmatch[i].rm_so <= pmatch[i].rm_eo); parents = submatch_data[i].parents; if (parents != NULL) for (j = 0; parents[j] >= 0; j++) { DPRINT(("pmatch[%d] parent %d\n", i, parents[j])); if (pmatch[i].rm_so < pmatch[parents[j]].rm_so || pmatch[i].rm_eo > pmatch[parents[j]].rm_eo) pmatch[i].rm_so = pmatch[i].rm_eo = -1; } i++; } } while (i < nmatch) { pmatch[i].rm_so = -1; pmatch[i].rm_eo = -1; i++; } } /* Wrapper functions for POSIX compatible regexp matching. */ int tre_have_backrefs(const regex_t *preg) { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; return tnfa->have_backrefs; } int tre_have_approx(const regex_t *preg) { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; return tnfa->have_approx; } static int tre_match(const tre_tnfa_t *tnfa, const void *string, size_t len, tre_str_type_t type, size_t nmatch, regmatch_t pmatch[], int eflags) { reg_errcode_t status; int *tags = NULL, eo; if (tnfa->num_tags > 0 && nmatch > 0) { #ifdef TRE_USE_ALLOCA tags = alloca(sizeof(*tags) * tnfa->num_tags); #else /* !TRE_USE_ALLOCA */ tags = xmalloc(sizeof(*tags) * tnfa->num_tags); #endif /* !TRE_USE_ALLOCA */ if (tags == NULL) return REG_ESPACE; } /* Dispatch to the appropriate matcher. */ if (tnfa->have_backrefs || eflags & REG_BACKTRACKING_MATCHER) { /* The regex has back references, use the backtracking matcher. */ if (type == STR_USER) { const tre_str_source *source = string; if (source->rewind == NULL || source->compare == NULL) /* The backtracking matcher requires rewind and compare capabilities from the input stream. */ return REG_BADPAT; } status = tre_tnfa_run_backtrack(tnfa, string, len, type, tags, eflags, &eo); } #ifdef TRE_APPROX else if (tnfa->have_approx || eflags & REG_APPROX_MATCHER) { /* The regex uses approximate matching, use the approximate matcher. */ regamatch_t match; regaparams_t params; regaparams_default(¶ms); params.max_err = 0; params.max_cost = 0; status = tre_tnfa_run_approx(tnfa, string, len, type, tags, &match, params, eflags, &eo); } #endif /* TRE_APPROX */ else { /* Exact matching, no back references, use the parallel matcher. */ status = tre_tnfa_run_parallel(tnfa, string, len, type, tags, eflags, &eo); } if (status == REG_OK) /* A match was found, so fill the submatch registers. */ tre_fill_pmatch(nmatch, pmatch, tnfa->cflags, tnfa, tags, eo); #ifndef TRE_USE_ALLOCA if (tags) xfree(tags); #endif /* !TRE_USE_ALLOCA */ return status; } int regnexec(const regex_t *preg, const char *str, size_t len, size_t nmatch, regmatch_t pmatch[], int eflags) { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; tre_str_type_t type = (TRE_MB_CUR_MAX == 1) ? STR_BYTE : STR_MBS; return tre_match(tnfa, str, len, type, nmatch, pmatch, eflags); } int regexec(const regex_t *preg, const char *str, size_t nmatch, regmatch_t pmatch[], int eflags) { return regnexec(preg, str, -1, nmatch, pmatch, eflags); } #ifdef TRE_WCHAR int regwnexec(const regex_t *preg, const wchar_t *str, size_t len, size_t nmatch, regmatch_t pmatch[], int eflags) { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; return tre_match(tnfa, str, len, STR_WIDE, nmatch, pmatch, eflags); } int regwexec(const regex_t *preg, const wchar_t *str, size_t nmatch, regmatch_t pmatch[], int eflags) { return regwnexec(preg, str, -1, nmatch, pmatch, eflags); } #endif /* TRE_WCHAR */ int reguexec(const regex_t *preg, const tre_str_source *str, size_t nmatch, regmatch_t pmatch[], int eflags) { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; return tre_match(tnfa, str, -1, STR_USER, nmatch, pmatch, eflags); } #ifdef TRE_APPROX /* Wrapper functions for approximate regexp matching. */ static int tre_match_approx(const tre_tnfa_t *tnfa, const void *string, size_t len, tre_str_type_t type, regamatch_t *match, regaparams_t params, int eflags) { reg_errcode_t status; int *tags = NULL, eo; /* If the regexp does not use approximate matching features, the maximum cost is zero, and the approximate matcher isn't forced, use the exact matcher instead. */ if (params.max_cost == 0 && !tnfa->have_approx && !(eflags & REG_APPROX_MATCHER)) return tre_match(tnfa, string, len, type, match->nmatch, match->pmatch, eflags); /* Back references are not supported by the approximate matcher. */ if (tnfa->have_backrefs) return REG_BADPAT; if (tnfa->num_tags > 0 && match->nmatch > 0) { #if TRE_USE_ALLOCA tags = alloca(sizeof(*tags) * tnfa->num_tags); #else /* !TRE_USE_ALLOCA */ tags = xmalloc(sizeof(*tags) * tnfa->num_tags); #endif /* !TRE_USE_ALLOCA */ if (tags == NULL) return REG_ESPACE; } status = tre_tnfa_run_approx(tnfa, string, len, type, tags, match, params, eflags, &eo); if (status == REG_OK) tre_fill_pmatch(match->nmatch, match->pmatch, tnfa->cflags, tnfa, tags, eo); #ifndef TRE_USE_ALLOCA if (tags) xfree(tags); #endif /* !TRE_USE_ALLOCA */ return status; } int reganexec(const regex_t *preg, const char *str, size_t len, regamatch_t *match, regaparams_t params, int eflags) { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; tre_str_type_t type = (TRE_MB_CUR_MAX == 1) ? STR_BYTE : STR_MBS; return tre_match_approx(tnfa, str, len, type, match, params, eflags); } int regaexec(const regex_t *preg, const char *str, regamatch_t *match, regaparams_t params, int eflags) { return reganexec(preg, str, -1, match, params, eflags); } #ifdef TRE_WCHAR int regawnexec(const regex_t *preg, const wchar_t *str, size_t len, regamatch_t *match, regaparams_t params, int eflags) { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; return tre_match_approx(tnfa, str, len, STR_WIDE, match, params, eflags); } int regawexec(const regex_t *preg, const wchar_t *str, regamatch_t *match, regaparams_t params, int eflags) { return regawnexec(preg, str, -1, match, params, eflags); } #endif /* TRE_WCHAR */ void regaparams_default(regaparams_t *params) { memset(params, 0, sizeof(*params)); params->cost_ins = 1; params->cost_del = 1; params->cost_subst = 1; params->max_cost = INT_MAX; params->max_ins = INT_MAX; params->max_del = INT_MAX; params->max_subst = INT_MAX; params->max_err = INT_MAX; } #endif /* TRE_APPROX */ /* EOF */ lensfun-0.3.4/libs/regex/tre-ast.c000066400000000000000000000132731445356770400170030ustar00rootroot00000000000000/* tre-ast.c - Abstract syntax tree (AST) routines Copyright (c) 2001-2006 Ville Laurikari This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #include #include "tre-ast.h" #include "tre-mem.h" tre_ast_node_t * tre_ast_new_node(tre_mem_t mem, tre_ast_type_t type, size_t size) { tre_ast_node_t *node; node = tre_mem_calloc(mem, sizeof(*node)); if (!node) return NULL; node->obj = tre_mem_calloc(mem, size); if (!node->obj) return NULL; node->type = type; node->nullable = -1; node->submatch_id = -1; return node; } tre_ast_node_t * tre_ast_new_literal(tre_mem_t mem, int code_min, int code_max, int position) { tre_ast_node_t *node; tre_literal_t *lit; node = tre_ast_new_node(mem, LITERAL, sizeof(tre_literal_t)); if (!node) return NULL; lit = node->obj; lit->code_min = code_min; lit->code_max = code_max; lit->position = position; return node; } tre_ast_node_t * tre_ast_new_iter(tre_mem_t mem, tre_ast_node_t *arg, int min, int max, int minimal) { tre_ast_node_t *node; tre_iteration_t *iter; node = tre_ast_new_node(mem, ITERATION, sizeof(tre_iteration_t)); if (!node) return NULL; iter = node->obj; iter->arg = arg; iter->min = min; iter->max = max; iter->minimal = minimal; node->num_submatches = arg->num_submatches; return node; } tre_ast_node_t * tre_ast_new_union(tre_mem_t mem, tre_ast_node_t *left, tre_ast_node_t *right) { tre_ast_node_t *node; node = tre_ast_new_node(mem, UNION, sizeof(tre_union_t)); if (node == NULL) return NULL; ((tre_union_t *)node->obj)->left = left; ((tre_union_t *)node->obj)->right = right; node->num_submatches = left->num_submatches + right->num_submatches; return node; } tre_ast_node_t * tre_ast_new_catenation(tre_mem_t mem, tre_ast_node_t *left, tre_ast_node_t *right) { tre_ast_node_t *node; node = tre_ast_new_node(mem, CATENATION, sizeof(tre_catenation_t)); if (node == NULL) return NULL; ((tre_catenation_t *)node->obj)->left = left; ((tre_catenation_t *)node->obj)->right = right; node->num_submatches = left->num_submatches + right->num_submatches; return node; } #ifdef TRE_DEBUG static void tre_findent(FILE *stream, int i) { while (i-- > 0) fputc(' ', stream); } void tre_print_params(int *params) { int i; if (params) { DPRINT(("params [")); for (i = 0; i < TRE_PARAM_LAST; i++) { if (params[i] == TRE_PARAM_UNSET) DPRINT(("unset")); else if (params[i] == TRE_PARAM_DEFAULT) DPRINT(("default")); else DPRINT(("%d", params[i])); if (i < TRE_PARAM_LAST - 1) DPRINT((", ")); } DPRINT(("]")); } } static void tre_do_print(FILE *stream, tre_ast_node_t *ast, int indent) { int code_min, code_max, pos; int num_tags = ast->num_tags; tre_literal_t *lit; tre_iteration_t *iter; tre_findent(stream, indent); switch (ast->type) { case LITERAL: lit = ast->obj; code_min = lit->code_min; code_max = lit->code_max; pos = lit->position; if (IS_EMPTY(lit)) { fprintf(stream, "literal empty\n"); } else if (IS_ASSERTION(lit)) { int i; char *assertions[] = { "bol", "eol", "ctype", "!ctype", "bow", "eow", "wb", "!wb" }; if (code_max >= ASSERT_LAST << 1) assert(0); fprintf(stream, "assertions: "); for (i = 0; (1 << i) <= ASSERT_LAST; i++) if (code_max & (1 << i)) fprintf(stream, "%s ", assertions[i]); fprintf(stream, "\n"); } else if (IS_TAG(lit)) { fprintf(stream, "tag %d\n", code_max); } else if (IS_BACKREF(lit)) { fprintf(stream, "backref %d, pos %d\n", code_max, pos); } else if (IS_PARAMETER(lit)) { tre_print_params(lit->u.params); fprintf(stream, "\n"); } else { fprintf(stream, "literal (%c, %c) (%d, %d), pos %d, sub %d, " "%d tags\n", code_min, code_max, code_min, code_max, pos, ast->submatch_id, num_tags); } break; case ITERATION: iter = ast->obj; fprintf(stream, "iteration {%d, %d}, sub %d, %d tags, %s\n", iter->min, iter->max, ast->submatch_id, num_tags, iter->minimal ? "minimal" : "greedy"); tre_do_print(stream, iter->arg, indent + 2); break; case UNION: fprintf(stream, "union, sub %d, %d tags\n", ast->submatch_id, num_tags); tre_do_print(stream, ((tre_union_t *)ast->obj)->left, indent + 2); tre_do_print(stream, ((tre_union_t *)ast->obj)->right, indent + 2); break; case CATENATION: fprintf(stream, "catenation, sub %d, %d tags\n", ast->submatch_id, num_tags); tre_do_print(stream, ((tre_catenation_t *)ast->obj)->left, indent + 2); tre_do_print(stream, ((tre_catenation_t *)ast->obj)->right, indent + 2); break; default: assert(0); break; } } static void tre_ast_fprint(FILE *stream, tre_ast_node_t *ast) { tre_do_print(stream, ast, 0); } void tre_ast_print(tre_ast_node_t *tree) { printf("AST:\n"); tre_ast_fprint(stdout, tree); } #endif /* TRE_DEBUG */ /* EOF */ lensfun-0.3.4/libs/regex/tre-ast.h000066400000000000000000000100441445356770400170010ustar00rootroot00000000000000/* tre-ast.h - Abstract syntax tree (AST) definitions Copyright (c) 2001-2006 Ville Laurikari This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TRE_AST_H #define TRE_AST_H 1 #include "tre-mem.h" #include "tre-internal.h" #include "tre-compile.h" /* The different AST node types. */ typedef enum { LITERAL, CATENATION, ITERATION, UNION } tre_ast_type_t; /* Special subtypes of TRE_LITERAL. */ #define EMPTY -1 /* Empty leaf (denotes empty string). */ #define ASSERTION -2 /* Assertion leaf. */ #define TAG -3 /* Tag leaf. */ #define BACKREF -4 /* Back reference leaf. */ #define PARAMETER -5 /* Parameter. */ #define IS_SPECIAL(x) ((x)->code_min < 0) #define IS_EMPTY(x) ((x)->code_min == EMPTY) #define IS_ASSERTION(x) ((x)->code_min == ASSERTION) #define IS_TAG(x) ((x)->code_min == TAG) #define IS_BACKREF(x) ((x)->code_min == BACKREF) #define IS_PARAMETER(x) ((x)->code_min == PARAMETER) /* A generic AST node. All AST nodes consist of this node on the top level with `obj' pointing to the actual content. */ typedef struct { tre_ast_type_t type; /* Type of the node. */ void *obj; /* Pointer to actual node. */ int nullable; int submatch_id; int num_submatches; int num_tags; tre_pos_and_tags_t *firstpos; tre_pos_and_tags_t *lastpos; } tre_ast_node_t; /* A "literal" node. These are created for assertions, back references, tags, matching parameter settings, and all expressions that match one character. */ typedef struct { long code_min; long code_max; int position; union { tre_ctype_t class; int *params; } u; tre_ctype_t *neg_classes; } tre_literal_t; /* A "catenation" node. These are created when two regexps are concatenated. If there are more than one subexpressions in sequence, the `left' part holds all but the last, and `right' part holds the last subexpression (catenation is left associative). */ typedef struct { tre_ast_node_t *left; tre_ast_node_t *right; } tre_catenation_t; /* An "iteration" node. These are created for the "*", "+", "?", and "{m,n}" operators. */ typedef struct { /* Subexpression to match. */ tre_ast_node_t *arg; /* Minimum number of consecutive matches. */ int min; /* Maximum number of consecutive matches. */ int max; /* If 0, match as many characters as possible, if 1 match as few as possible. Note that this does not always mean the same thing as matching as many/few repetitions as possible. */ unsigned int minimal:1; /* Approximate matching parameters (or NULL). */ int *params; } tre_iteration_t; /* An "union" node. These are created for the "|" operator. */ typedef struct { tre_ast_node_t *left; tre_ast_node_t *right; } tre_union_t; tre_ast_node_t * tre_ast_new_node(tre_mem_t mem, tre_ast_type_t type, size_t size); tre_ast_node_t * tre_ast_new_literal(tre_mem_t mem, int code_min, int code_max, int position); tre_ast_node_t * tre_ast_new_iter(tre_mem_t mem, tre_ast_node_t *arg, int min, int max, int minimal); tre_ast_node_t * tre_ast_new_union(tre_mem_t mem, tre_ast_node_t *left, tre_ast_node_t *right); tre_ast_node_t * tre_ast_new_catenation(tre_mem_t mem, tre_ast_node_t *left, tre_ast_node_t *right); #ifdef TRE_DEBUG void tre_ast_print(tre_ast_node_t *tree); /* XXX - rethink AST printing API */ void tre_print_params(int *params); #endif /* TRE_DEBUG */ #endif /* TRE_AST_H */ /* EOF */ lensfun-0.3.4/libs/regex/tre-compile.c000066400000000000000000001701171445356770400176450ustar00rootroot00000000000000/* tre-compile.c - TRE regex compiler Copyright (c) 2001-2006 Ville Laurikari This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* TODO: - Fix tre_ast_to_tnfa() to recurse using a stack instead of recursive function calls. */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #include #include #include #include "tre-internal.h" #include "tre-mem.h" #include "tre-stack.h" #include "tre-ast.h" #include "tre-parse.h" #include "tre-compile.h" #include "regex.h" #include "xmalloc.h" /* Algorithms to setup tags so that submatch addressing can be done. */ /* Inserts a catenation node to the root of the tree given in `node'. As the left child a new tag with number `tag_id' to `node' is added, and the right child is the old root. */ static reg_errcode_t tre_add_tag_left(tre_mem_t mem, tre_ast_node_t *node, int tag_id) { tre_catenation_t *c; DPRINT(("add_tag_left: tag %d\n", tag_id)); c = tre_mem_alloc(mem, sizeof(*c)); if (c == NULL) return REG_ESPACE; c->left = tre_ast_new_literal(mem, TAG, tag_id, -1); if (c->left == NULL) return REG_ESPACE; c->right = tre_mem_alloc(mem, sizeof(tre_ast_node_t)); if (c->right == NULL) return REG_ESPACE; c->right->obj = node->obj; c->right->type = node->type; c->right->nullable = -1; c->right->submatch_id = -1; c->right->firstpos = NULL; c->right->lastpos = NULL; c->right->num_tags = 0; node->obj = c; node->type = CATENATION; return REG_OK; } /* Inserts a catenation node to the root of the tree given in `node'. As the right child a new tag with number `tag_id' to `node' is added, and the left child is the old root. */ static reg_errcode_t tre_add_tag_right(tre_mem_t mem, tre_ast_node_t *node, int tag_id) { tre_catenation_t *c; DPRINT(("tre_add_tag_right: tag %d\n", tag_id)); c = tre_mem_alloc(mem, sizeof(*c)); if (c == NULL) return REG_ESPACE; c->right = tre_ast_new_literal(mem, TAG, tag_id, -1); if (c->right == NULL) return REG_ESPACE; c->left = tre_mem_alloc(mem, sizeof(tre_ast_node_t)); if (c->left == NULL) return REG_ESPACE; c->left->obj = node->obj; c->left->type = node->type; c->left->nullable = -1; c->left->submatch_id = -1; c->left->firstpos = NULL; c->left->lastpos = NULL; c->left->num_tags = 0; node->obj = c; node->type = CATENATION; return REG_OK; } typedef enum { ADDTAGS_RECURSE, ADDTAGS_AFTER_ITERATION, ADDTAGS_AFTER_UNION_LEFT, ADDTAGS_AFTER_UNION_RIGHT, ADDTAGS_AFTER_CAT_LEFT, ADDTAGS_AFTER_CAT_RIGHT, ADDTAGS_SET_SUBMATCH_END } tre_addtags_symbol_t; typedef struct { int tag; int next_tag; } tre_tag_states_t; /* Adds tags to appropriate locations in the parse tree in `tree', so that subexpressions marked for submatch addressing can be traced. */ static reg_errcode_t tre_add_tags(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *tree, tre_tnfa_t *tnfa) { reg_errcode_t status = REG_OK; tre_addtags_symbol_t symbol; tre_ast_node_t *node = tree; /* Tree node we are currently looking at. */ int bottom = tre_stack_num_objects(stack); /* True for first pass (counting number of needed tags) */ int first_pass = (mem == NULL || tnfa == NULL); int *regset, *orig_regset; int num_tags = 0; /* Total number of tags. */ int num_minimals = 0; /* Number of special minimal tags. */ int tag = 0; /* The tag that is to be added next. */ int next_tag = 1; /* Next tag to use after this one. */ int *parents; /* Stack of submatches the current submatch is contained in. */ int minimal_tag = -1; /* Tag that marks the beginning of a minimal match. */ tre_tag_states_t *saved_states; tre_tag_direction_t direction = TRE_TAG_MINIMIZE; if (!first_pass) { tnfa->end_tag = 0; tnfa->minimal_tags[0] = -1; } regset = xmalloc(sizeof(*regset) * ((tnfa->num_submatches + 1) * 2)); if (regset == NULL) return REG_ESPACE; regset[0] = -1; orig_regset = regset; parents = xmalloc(sizeof(*parents) * (tnfa->num_submatches + 1)); if (parents == NULL) { xfree(regset); return REG_ESPACE; } parents[0] = -1; saved_states = xmalloc(sizeof(*saved_states) * (tnfa->num_submatches + 1)); if (saved_states == NULL) { xfree(regset); xfree(parents); return REG_ESPACE; } else { unsigned int i; for (i = 0; i <= tnfa->num_submatches; i++) saved_states[i].tag = -1; } STACK_PUSH(stack, voidptr, node); STACK_PUSH(stack, int, ADDTAGS_RECURSE); while (tre_stack_num_objects(stack) > bottom) { if (status != REG_OK) break; symbol = (tre_addtags_symbol_t)tre_stack_pop_int(stack); switch (symbol) { case ADDTAGS_SET_SUBMATCH_END: { int id = tre_stack_pop_int(stack); int i; /* Add end of this submatch to regset. */ for (i = 0; regset[i] >= 0; i++); regset[i] = id * 2 + 1; regset[i + 1] = -1; /* Pop this submatch from the parents stack. */ for (i = 0; parents[i] >= 0; i++); parents[i - 1] = -1; break; } case ADDTAGS_RECURSE: node = tre_stack_pop_voidptr(stack); if (node->submatch_id >= 0) { int id = node->submatch_id; int i; /* Add start of this submatch to regset. */ for (i = 0; regset[i] >= 0; i++); regset[i] = id * 2; regset[i + 1] = -1; if (!first_pass) { for (i = 0; parents[i] >= 0; i++); tnfa->submatch_data[id].parents = NULL; if (i > 0) { int *p = xmalloc(sizeof(*p) * (i + 1)); if (p == NULL) { status = REG_ESPACE; break; } assert(tnfa->submatch_data[id].parents == NULL); tnfa->submatch_data[id].parents = p; for (i = 0; parents[i] >= 0; i++) p[i] = parents[i]; p[i] = -1; } } /* Add end of this submatch to regset after processing this node. */ STACK_PUSHX(stack, int, node->submatch_id); STACK_PUSHX(stack, int, ADDTAGS_SET_SUBMATCH_END); } switch (node->type) { case LITERAL: { tre_literal_t *lit = node->obj; if (!IS_SPECIAL(lit) || IS_BACKREF(lit)) { int i; DPRINT(("Literal %d-%d\n", (int)lit->code_min, (int)lit->code_max)); if (regset[0] >= 0) { /* Regset is not empty, so add a tag before the literal or backref. */ if (!first_pass) { status = tre_add_tag_left(mem, node, tag); tnfa->tag_directions[tag] = direction; if (minimal_tag >= 0) { DPRINT(("Minimal %d, %d\n", minimal_tag, tag)); for (i = 0; tnfa->minimal_tags[i] >= 0; i++); tnfa->minimal_tags[i] = tag; tnfa->minimal_tags[i + 1] = minimal_tag; tnfa->minimal_tags[i + 2] = -1; minimal_tag = -1; num_minimals++; } /* Go through the regset and set submatch data for submatches that are using this tag. */ for (i = 0; regset[i] >= 0; i++) { int id = regset[i] / 2; int start = !(regset[i] % 2); DPRINT((" Using tag %d for %s offset of " "submatch %d\n", tag, start ? "start" : "end", id)); if (start) tnfa->submatch_data[id].so_tag = tag; else tnfa->submatch_data[id].eo_tag = tag; } } else { DPRINT((" num_tags = 1\n")); node->num_tags = 1; } DPRINT((" num_tags++\n")); regset[0] = -1; tag = next_tag; num_tags++; next_tag++; } } else { assert(!IS_TAG(lit)); } break; } case CATENATION: { tre_catenation_t *cat = node->obj; tre_ast_node_t *left = cat->left; tre_ast_node_t *right = cat->right; int reserved_tag = -1; DPRINT(("Catenation, next_tag = %d\n", next_tag)); /* After processing right child. */ STACK_PUSHX(stack, voidptr, node); STACK_PUSHX(stack, int, ADDTAGS_AFTER_CAT_RIGHT); /* Process right child. */ STACK_PUSHX(stack, voidptr, right); STACK_PUSHX(stack, int, ADDTAGS_RECURSE); /* After processing left child. */ STACK_PUSHX(stack, int, next_tag + left->num_tags); DPRINT((" Pushing %d for after left\n", next_tag + left->num_tags)); if (left->num_tags > 0 && right->num_tags > 0) { /* Reserve the next tag to the right child. */ DPRINT((" Reserving next_tag %d to right child\n", next_tag)); reserved_tag = next_tag; next_tag++; } STACK_PUSHX(stack, int, reserved_tag); STACK_PUSHX(stack, int, ADDTAGS_AFTER_CAT_LEFT); /* Process left child. */ STACK_PUSHX(stack, voidptr, left); STACK_PUSHX(stack, int, ADDTAGS_RECURSE); } break; case ITERATION: { tre_iteration_t *iter = node->obj; DPRINT(("Iteration\n")); if (first_pass) { STACK_PUSHX(stack, int, regset[0] >= 0 || iter->minimal); } else { STACK_PUSHX(stack, int, tag); STACK_PUSHX(stack, int, iter->minimal); } STACK_PUSHX(stack, voidptr, node); STACK_PUSHX(stack, int, ADDTAGS_AFTER_ITERATION); STACK_PUSHX(stack, voidptr, iter->arg); STACK_PUSHX(stack, int, ADDTAGS_RECURSE); /* Regset is not empty, so add a tag here. */ if (regset[0] >= 0 || iter->minimal) { if (!first_pass) { int i; status = tre_add_tag_left(mem, node, tag); if (iter->minimal) tnfa->tag_directions[tag] = TRE_TAG_MAXIMIZE; else tnfa->tag_directions[tag] = direction; if (minimal_tag >= 0) { DPRINT(("Minimal %d, %d\n", minimal_tag, tag)); for (i = 0; tnfa->minimal_tags[i] >= 0; i++); tnfa->minimal_tags[i] = tag; tnfa->minimal_tags[i + 1] = minimal_tag; tnfa->minimal_tags[i + 2] = -1; minimal_tag = -1; num_minimals++; } /* Go through the regset and set submatch data for submatches that are using this tag. */ for (i = 0; regset[i] >= 0; i++) { int id = regset[i] / 2; int start = !(regset[i] % 2); DPRINT((" Using tag %d for %s offset of " "submatch %d\n", tag, start ? "start" : "end", id)); if (start) tnfa->submatch_data[id].so_tag = tag; else tnfa->submatch_data[id].eo_tag = tag; } } DPRINT((" num_tags++\n")); regset[0] = -1; tag = next_tag; num_tags++; next_tag++; } direction = TRE_TAG_MINIMIZE; } break; case UNION: { tre_union_t *uni = node->obj; tre_ast_node_t *left = uni->left; tre_ast_node_t *right = uni->right; int left_tag; int right_tag; if (regset[0] >= 0) { left_tag = next_tag; right_tag = next_tag + 1; } else { left_tag = tag; right_tag = next_tag; } DPRINT(("Union\n")); /* After processing right child. */ STACK_PUSHX(stack, int, right_tag); STACK_PUSHX(stack, int, left_tag); STACK_PUSHX(stack, voidptr, regset); STACK_PUSHX(stack, int, regset[0] >= 0); STACK_PUSHX(stack, voidptr, node); STACK_PUSHX(stack, voidptr, right); STACK_PUSHX(stack, voidptr, left); STACK_PUSHX(stack, int, ADDTAGS_AFTER_UNION_RIGHT); /* Process right child. */ STACK_PUSHX(stack, voidptr, right); STACK_PUSHX(stack, int, ADDTAGS_RECURSE); /* After processing left child. */ STACK_PUSHX(stack, int, ADDTAGS_AFTER_UNION_LEFT); /* Process left child. */ STACK_PUSHX(stack, voidptr, left); STACK_PUSHX(stack, int, ADDTAGS_RECURSE); /* Regset is not empty, so add a tag here. */ if (regset[0] >= 0) { if (!first_pass) { int i; status = tre_add_tag_left(mem, node, tag); tnfa->tag_directions[tag] = direction; if (minimal_tag >= 0) { DPRINT(("Minimal %d, %d\n", minimal_tag, tag)); for (i = 0; tnfa->minimal_tags[i] >= 0; i++); tnfa->minimal_tags[i] = tag; tnfa->minimal_tags[i + 1] = minimal_tag; tnfa->minimal_tags[i + 2] = -1; minimal_tag = -1; num_minimals++; } /* Go through the regset and set submatch data for submatches that are using this tag. */ for (i = 0; regset[i] >= 0; i++) { int id = regset[i] / 2; int start = !(regset[i] % 2); DPRINT((" Using tag %d for %s offset of " "submatch %d\n", tag, start ? "start" : "end", id)); if (start) tnfa->submatch_data[id].so_tag = tag; else tnfa->submatch_data[id].eo_tag = tag; } } DPRINT((" num_tags++\n")); regset[0] = -1; tag = next_tag; num_tags++; next_tag++; } if (node->num_submatches > 0) { /* The next two tags are reserved for markers. */ next_tag++; tag = next_tag; next_tag++; } break; } } if (node->submatch_id >= 0) { int i; /* Push this submatch on the parents stack. */ for (i = 0; parents[i] >= 0; i++); parents[i] = node->submatch_id; parents[i + 1] = -1; } break; /* end case: ADDTAGS_RECURSE */ case ADDTAGS_AFTER_ITERATION: { int minimal = 0; int enter_tag; node = tre_stack_pop_voidptr(stack); if (first_pass) { node->num_tags = ((tre_iteration_t *)node->obj)->arg->num_tags + tre_stack_pop_int(stack); minimal_tag = -1; } else { minimal = tre_stack_pop_int(stack); enter_tag = tre_stack_pop_int(stack); if (minimal) minimal_tag = enter_tag; } DPRINT(("After iteration\n")); if (!first_pass) { DPRINT((" Setting direction to %s\n", minimal ? "minimize" : "maximize")); if (minimal) direction = TRE_TAG_MINIMIZE; else direction = TRE_TAG_MAXIMIZE; } break; } case ADDTAGS_AFTER_CAT_LEFT: { int new_tag = tre_stack_pop_int(stack); next_tag = tre_stack_pop_int(stack); DPRINT(("After cat left, tag = %d, next_tag = %d\n", tag, next_tag)); if (new_tag >= 0) { DPRINT((" Setting tag to %d\n", new_tag)); tag = new_tag; } break; } case ADDTAGS_AFTER_CAT_RIGHT: DPRINT(("After cat right\n")); node = tre_stack_pop_voidptr(stack); if (first_pass) node->num_tags = ((tre_catenation_t *)node->obj)->left->num_tags + ((tre_catenation_t *)node->obj)->right->num_tags; break; case ADDTAGS_AFTER_UNION_LEFT: DPRINT(("After union left\n")); /* Lift the bottom of the `regset' array so that when processing the right operand the items currently in the array are invisible. The original bottom was saved at ADDTAGS_UNION and will be restored at ADDTAGS_AFTER_UNION_RIGHT below. */ while (*regset >= 0) regset++; break; case ADDTAGS_AFTER_UNION_RIGHT: { int added_tags, tag_left, tag_right; tre_ast_node_t *left = tre_stack_pop_voidptr(stack); tre_ast_node_t *right = tre_stack_pop_voidptr(stack); DPRINT(("After union right\n")); node = tre_stack_pop_voidptr(stack); added_tags = tre_stack_pop_int(stack); if (first_pass) { node->num_tags = ((tre_union_t *)node->obj)->left->num_tags + ((tre_union_t *)node->obj)->right->num_tags + added_tags + ((node->num_submatches > 0) ? 2 : 0); } regset = tre_stack_pop_voidptr(stack); tag_left = tre_stack_pop_int(stack); tag_right = tre_stack_pop_int(stack); /* Add tags after both children, the left child gets a smaller tag than the right child. This guarantees that we prefer the left child over the right child. */ /* XXX - This is not always necessary (if the children have tags which must be seen for every match of that child). */ /* XXX - Check if this is the only place where tre_add_tag_right is used. If so, use tre_add_tag_left (putting the tag before the child as opposed after the child) and throw away tre_add_tag_right. */ if (node->num_submatches > 0) { if (!first_pass) { status = tre_add_tag_right(mem, left, tag_left); tnfa->tag_directions[tag_left] = TRE_TAG_MAXIMIZE; status = tre_add_tag_right(mem, right, tag_right); tnfa->tag_directions[tag_right] = TRE_TAG_MAXIMIZE; } DPRINT((" num_tags += 2\n")); num_tags += 2; } direction = TRE_TAG_MAXIMIZE; break; } default: assert(0); break; } /* end switch(symbol) */ } /* end while(tre_stack_num_objects(stack) > bottom) */ if (!first_pass) { int i; /* Go through the regset and set submatch data for submatches that are using this tag. */ for (i = 0; regset[i] >= 0; i++) { int id = regset[i] / 2; int start = !(regset[i] % 2); DPRINT((" Using tag %d for %s offset of " "submatch %d\n", num_tags, start ? "start" : "end", id)); if (start) tnfa->submatch_data[id].so_tag = num_tags; else tnfa->submatch_data[id].eo_tag = num_tags; } } if (!first_pass && minimal_tag >= 0) { int i; DPRINT(("Minimal %d, %d\n", minimal_tag, tag)); for (i = 0; tnfa->minimal_tags[i] >= 0; i++); tnfa->minimal_tags[i] = tag; tnfa->minimal_tags[i + 1] = minimal_tag; tnfa->minimal_tags[i + 2] = -1; minimal_tag = -1; num_minimals++; } DPRINT(("tre_add_tags: %s complete. Number of tags %d.\n", first_pass? "First pass" : "Second pass", num_tags)); assert(tree->num_tags == num_tags); tnfa->end_tag = num_tags; tnfa->num_tags = num_tags; tnfa->num_minimals = num_minimals; xfree(orig_regset); xfree(parents); xfree(saved_states); return status; } /* AST to TNFA compilation routines. */ typedef enum { COPY_RECURSE, COPY_SET_RESULT_PTR } tre_copyast_symbol_t; /* Flags for tre_copy_ast(). */ #define COPY_REMOVE_TAGS 1 #define COPY_MAXIMIZE_FIRST_TAG 2 static reg_errcode_t tre_copy_ast(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *ast, int flags, int *pos_add, tre_tag_direction_t *tag_directions, tre_ast_node_t **copy, int *max_pos) { reg_errcode_t status = REG_OK; int bottom = tre_stack_num_objects(stack); int num_copied = 0; int first_tag = 1; tre_ast_node_t **result = copy; tre_copyast_symbol_t symbol; STACK_PUSH(stack, voidptr, ast); STACK_PUSH(stack, int, COPY_RECURSE); while (status == REG_OK && tre_stack_num_objects(stack) > bottom) { tre_ast_node_t *node; if (status != REG_OK) break; symbol = (tre_copyast_symbol_t)tre_stack_pop_int(stack); switch (symbol) { case COPY_SET_RESULT_PTR: result = tre_stack_pop_voidptr(stack); break; case COPY_RECURSE: node = tre_stack_pop_voidptr(stack); switch (node->type) { case LITERAL: { tre_literal_t *lit = node->obj; int pos = lit->position; int min = lit->code_min; int max = lit->code_max; if (!IS_SPECIAL(lit) || IS_BACKREF(lit)) { /* XXX - e.g. [ab] has only one position but two nodes, so we are creating holes in the state space here. Not fatal, just wastes memory. */ pos += *pos_add; num_copied++; } else if (IS_TAG(lit) && (flags & COPY_REMOVE_TAGS)) { /* Change this tag to empty. */ min = EMPTY; max = pos = -1; } else if (IS_TAG(lit) && (flags & COPY_MAXIMIZE_FIRST_TAG) && first_tag) { /* Maximize the first tag. */ tag_directions[max] = TRE_TAG_MAXIMIZE; first_tag = 0; } *result = tre_ast_new_literal(mem, min, max, pos); if (*result == NULL) status = REG_ESPACE; if (pos > *max_pos) *max_pos = pos; break; } case UNION: { tre_union_t *uni = node->obj; tre_union_t *tmp; *result = tre_ast_new_union(mem, uni->left, uni->right); if (*result == NULL) { status = REG_ESPACE; break; } tmp = (*result)->obj; result = &tmp->left; STACK_PUSHX(stack, voidptr, uni->right); STACK_PUSHX(stack, int, COPY_RECURSE); STACK_PUSHX(stack, voidptr, &tmp->right); STACK_PUSHX(stack, int, COPY_SET_RESULT_PTR); STACK_PUSHX(stack, voidptr, uni->left); STACK_PUSHX(stack, int, COPY_RECURSE); break; } case CATENATION: { tre_catenation_t *cat = node->obj; tre_catenation_t *tmp; *result = tre_ast_new_catenation(mem, cat->left, cat->right); if (*result == NULL) { status = REG_ESPACE; break; } tmp = (*result)->obj; tmp->left = NULL; tmp->right = NULL; result = &tmp->left; STACK_PUSHX(stack, voidptr, cat->right); STACK_PUSHX(stack, int, COPY_RECURSE); STACK_PUSHX(stack, voidptr, &tmp->right); STACK_PUSHX(stack, int, COPY_SET_RESULT_PTR); STACK_PUSHX(stack, voidptr, cat->left); STACK_PUSHX(stack, int, COPY_RECURSE); break; } case ITERATION: { tre_iteration_t *iter = node->obj; STACK_PUSHX(stack, voidptr, iter->arg); STACK_PUSHX(stack, int, COPY_RECURSE); *result = tre_ast_new_iter(mem, iter->arg, iter->min, iter->max, iter->minimal); if (*result == NULL) { status = REG_ESPACE; break; } iter = (*result)->obj; result = &iter->arg; break; } default: assert(0); break; } break; } } *pos_add += num_copied; return status; } typedef enum { EXPAND_RECURSE, EXPAND_AFTER_ITER } tre_expand_ast_symbol_t; /* Expands each iteration node that has a finite nonzero minimum or maximum iteration count to a catenated sequence of copies of the node. */ static reg_errcode_t tre_expand_ast(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *ast, int *position, tre_tag_direction_t *tag_directions, int *max_depth) { reg_errcode_t status = REG_OK; int bottom = tre_stack_num_objects(stack); int pos_add = 0; int pos_add_total = 0; int max_pos = 0; /* Current approximate matching parameters. */ int params[TRE_PARAM_LAST]; /* Approximate parameter nesting level. */ int params_depth = 0; int iter_depth = 0; int i; for (i = 0; i < TRE_PARAM_LAST; i++) params[i] = TRE_PARAM_DEFAULT; STACK_PUSHR(stack, voidptr, ast); STACK_PUSHR(stack, int, EXPAND_RECURSE); while (status == REG_OK && tre_stack_num_objects(stack) > bottom) { tre_ast_node_t *node; tre_expand_ast_symbol_t symbol; if (status != REG_OK) break; DPRINT(("pos_add %d\n", pos_add)); symbol = (tre_expand_ast_symbol_t)tre_stack_pop_int(stack); node = tre_stack_pop_voidptr(stack); switch (symbol) { case EXPAND_RECURSE: switch (node->type) { case LITERAL: { tre_literal_t *lit= node->obj; if (!IS_SPECIAL(lit) || IS_BACKREF(lit)) { lit->position += pos_add; if (lit->position > max_pos) max_pos = lit->position; } break; } case UNION: { tre_union_t *uni = node->obj; STACK_PUSHX(stack, voidptr, uni->right); STACK_PUSHX(stack, int, EXPAND_RECURSE); STACK_PUSHX(stack, voidptr, uni->left); STACK_PUSHX(stack, int, EXPAND_RECURSE); break; } case CATENATION: { tre_catenation_t *cat = node->obj; STACK_PUSHX(stack, voidptr, cat->right); STACK_PUSHX(stack, int, EXPAND_RECURSE); STACK_PUSHX(stack, voidptr, cat->left); STACK_PUSHX(stack, int, EXPAND_RECURSE); break; } case ITERATION: { tre_iteration_t *iter = node->obj; STACK_PUSHX(stack, int, pos_add); STACK_PUSHX(stack, voidptr, node); STACK_PUSHX(stack, int, EXPAND_AFTER_ITER); STACK_PUSHX(stack, voidptr, iter->arg); STACK_PUSHX(stack, int, EXPAND_RECURSE); /* If we are going to expand this node at EXPAND_AFTER_ITER then don't increase the `pos' fields of the nodes now, it will get done when expanding. */ if (iter->min > 1 || iter->max > 1) pos_add = 0; iter_depth++; DPRINT(("iter\n")); break; } default: assert(0); break; } break; case EXPAND_AFTER_ITER: { tre_iteration_t *iter = node->obj; int pos_add_last; pos_add = tre_stack_pop_int(stack); pos_add_last = pos_add; if (iter->min > 1 || iter->max > 1) { tre_ast_node_t *seq1 = NULL, *seq2 = NULL; int i; int pos_add_save = pos_add; /* Create a catenated sequence of copies of the node. */ for (i = 0; i < iter->min; i++) { tre_ast_node_t *copy; /* Remove tags from all but the last copy. */ int flags = ((i + 1 < iter->min) ? COPY_REMOVE_TAGS : COPY_MAXIMIZE_FIRST_TAG); DPRINT((" pos_add %d\n", pos_add)); pos_add_save = pos_add; status = tre_copy_ast(mem, stack, iter->arg, flags, &pos_add, tag_directions, ©, &max_pos); if (status != REG_OK) return status; if (seq1 != NULL) seq1 = tre_ast_new_catenation(mem, seq1, copy); else seq1 = copy; if (seq1 == NULL) return REG_ESPACE; } if (iter->max == -1) { /* No upper limit. */ pos_add_save = pos_add; status = tre_copy_ast(mem, stack, iter->arg, 0, &pos_add, NULL, &seq2, &max_pos); if (status != REG_OK) return status; seq2 = tre_ast_new_iter(mem, seq2, 0, -1, 0); if (seq2 == NULL) return REG_ESPACE; } else { for (i = iter->min; i < iter->max; i++) { tre_ast_node_t *tmp, *copy; pos_add_save = pos_add; status = tre_copy_ast(mem, stack, iter->arg, 0, &pos_add, NULL, ©, &max_pos); if (status != REG_OK) return status; if (seq2 != NULL) seq2 = tre_ast_new_catenation(mem, copy, seq2); else seq2 = copy; if (seq2 == NULL) return REG_ESPACE; tmp = tre_ast_new_literal(mem, EMPTY, -1, -1); if (tmp == NULL) return REG_ESPACE; seq2 = tre_ast_new_union(mem, tmp, seq2); if (seq2 == NULL) return REG_ESPACE; } } pos_add = pos_add_save; if (seq1 == NULL) seq1 = seq2; else if (seq2 != NULL) seq1 = tre_ast_new_catenation(mem, seq1, seq2); if (seq1 == NULL) return REG_ESPACE; node->obj = seq1->obj; node->type = seq1->type; } iter_depth--; pos_add_total += pos_add - pos_add_last; if (iter_depth == 0) pos_add = pos_add_total; /* If approximate parameters are specified, surround the result with two parameter setting nodes. The one on the left sets the specified parameters, and the one on the right restores the old parameters. */ if (iter->params) { tre_ast_node_t *tmp_l, *tmp_r, *tmp_node, *node_copy; int *old_params; tmp_l = tre_ast_new_literal(mem, PARAMETER, 0, -1); if (!tmp_l) return REG_ESPACE; ((tre_literal_t *)tmp_l->obj)->u.params = iter->params; iter->params[TRE_PARAM_DEPTH] = params_depth + 1; tmp_r = tre_ast_new_literal(mem, PARAMETER, 0, -1); if (!tmp_r) return REG_ESPACE; old_params = tre_mem_alloc(mem, sizeof(*old_params) * TRE_PARAM_LAST); if (!old_params) return REG_ESPACE; for (i = 0; i < TRE_PARAM_LAST; i++) old_params[i] = params[i]; ((tre_literal_t *)tmp_r->obj)->u.params = old_params; old_params[TRE_PARAM_DEPTH] = params_depth; /* XXX - this is the only place where ast_new_node is needed -- should be moved inside AST module. */ node_copy = tre_ast_new_node(mem, ITERATION, sizeof(tre_iteration_t)); if (!node_copy) return REG_ESPACE; node_copy->obj = node->obj; tmp_node = tre_ast_new_catenation(mem, tmp_l, node_copy); if (!tmp_node) return REG_ESPACE; tmp_node = tre_ast_new_catenation(mem, tmp_node, tmp_r); if (!tmp_node) return REG_ESPACE; /* Replace the contents of `node' with `tmp_node'. */ memcpy(node, tmp_node, sizeof(*node)); node->obj = tmp_node->obj; node->type = tmp_node->type; params_depth++; if (params_depth > *max_depth) *max_depth = params_depth; } break; } default: assert(0); break; } } *position += pos_add_total; /* `max_pos' should never be larger than `*position' if the above code works, but just an extra safeguard let's make sure `*position' is set large enough so enough memory will be allocated for the transition table. */ if (max_pos > *position) *position = max_pos; #ifdef TRE_DEBUG DPRINT(("Expanded AST:\n")); tre_ast_print(ast); DPRINT(("*position %d, max_pos %d\n", *position, max_pos)); #endif return status; } static tre_pos_and_tags_t * tre_set_empty(tre_mem_t mem) { tre_pos_and_tags_t *new_set; new_set = tre_mem_calloc(mem, sizeof(*new_set)); if (new_set == NULL) return NULL; new_set[0].position = -1; new_set[0].code_min = -1; new_set[0].code_max = -1; return new_set; } static tre_pos_and_tags_t * tre_set_one(tre_mem_t mem, int position, int code_min, int code_max, tre_ctype_t class, tre_ctype_t *neg_classes, int backref) { tre_pos_and_tags_t *new_set; new_set = tre_mem_calloc(mem, sizeof(*new_set) * 2); if (new_set == NULL) return NULL; new_set[0].position = position; new_set[0].code_min = code_min; new_set[0].code_max = code_max; new_set[0].class = class; new_set[0].neg_classes = neg_classes; new_set[0].backref = backref; new_set[1].position = -1; new_set[1].code_min = -1; new_set[1].code_max = -1; return new_set; } static tre_pos_and_tags_t * tre_set_union(tre_mem_t mem, tre_pos_and_tags_t *set1, tre_pos_and_tags_t *set2, int *tags, int assertions, int *params) { int s1, s2, i, j; tre_pos_and_tags_t *new_set; int *new_tags; int num_tags; for (num_tags = 0; tags != NULL && tags[num_tags] >= 0; num_tags++); for (s1 = 0; set1[s1].position >= 0; s1++); for (s2 = 0; set2[s2].position >= 0; s2++); new_set = tre_mem_calloc(mem, sizeof(*new_set) * (s1 + s2 + 1)); if (!new_set ) return NULL; for (s1 = 0; set1[s1].position >= 0; s1++) { new_set[s1].position = set1[s1].position; new_set[s1].code_min = set1[s1].code_min; new_set[s1].code_max = set1[s1].code_max; new_set[s1].assertions = set1[s1].assertions | assertions; new_set[s1].class = set1[s1].class; new_set[s1].neg_classes = set1[s1].neg_classes; new_set[s1].backref = set1[s1].backref; if (set1[s1].tags == NULL && tags == NULL) new_set[s1].tags = NULL; else { for (i = 0; set1[s1].tags != NULL && set1[s1].tags[i] >= 0; i++); new_tags = tre_mem_alloc(mem, (sizeof(*new_tags) * (i + num_tags + 1))); if (new_tags == NULL) return NULL; for (j = 0; j < i; j++) new_tags[j] = set1[s1].tags[j]; for (i = 0; i < num_tags; i++) new_tags[j + i] = tags[i]; new_tags[j + i] = -1; new_set[s1].tags = new_tags; } if (set1[s1].params) new_set[s1].params = set1[s1].params; if (params) { if (!new_set[s1].params) new_set[s1].params = params; else { new_set[s1].params = tre_mem_alloc(mem, sizeof(*params) * TRE_PARAM_LAST); if (!new_set[s1].params) return NULL; for (i = 0; i < TRE_PARAM_LAST; i++) if (params[i] != TRE_PARAM_UNSET) new_set[s1].params[i] = params[i]; } } } for (s2 = 0; set2[s2].position >= 0; s2++) { new_set[s1 + s2].position = set2[s2].position; new_set[s1 + s2].code_min = set2[s2].code_min; new_set[s1 + s2].code_max = set2[s2].code_max; /* XXX - why not | assertions here as well? */ new_set[s1 + s2].assertions = set2[s2].assertions; new_set[s1 + s2].class = set2[s2].class; new_set[s1 + s2].neg_classes = set2[s2].neg_classes; new_set[s1 + s2].backref = set2[s2].backref; if (set2[s2].tags == NULL) new_set[s1 + s2].tags = NULL; else { for (i = 0; set2[s2].tags[i] >= 0; i++); new_tags = tre_mem_alloc(mem, sizeof(*new_tags) * (i + 1)); if (new_tags == NULL) return NULL; for (j = 0; j < i; j++) new_tags[j] = set2[s2].tags[j]; new_tags[j] = -1; new_set[s1 + s2].tags = new_tags; } if (set2[s2].params) new_set[s1 + s2].params = set2[s2].params; if (params) { if (!new_set[s1 + s2].params) new_set[s1 + s2].params = params; else { new_set[s1 + s2].params = tre_mem_alloc(mem, sizeof(*params) * TRE_PARAM_LAST); if (!new_set[s1 + s2].params) return NULL; for (i = 0; i < TRE_PARAM_LAST; i++) if (params[i] != TRE_PARAM_UNSET) new_set[s1 + s2].params[i] = params[i]; } } } new_set[s1 + s2].position = -1; return new_set; } /* Finds the empty path through `node' which is the one that should be taken according to POSIX.2 rules, and adds the tags on that path to `tags'. `tags' may be NULL. If `num_tags_seen' is not NULL, it is set to the number of tags seen on the path. */ static reg_errcode_t tre_match_empty(tre_stack_t *stack, tre_ast_node_t *node, int *tags, int *assertions, int *params, int *num_tags_seen, int *params_seen) { tre_literal_t *lit; tre_union_t *uni; tre_catenation_t *cat; tre_iteration_t *iter; int i; int bottom = tre_stack_num_objects(stack); reg_errcode_t status = REG_OK; if (num_tags_seen) *num_tags_seen = 0; if (params_seen) *params_seen = 0; status = tre_stack_push_voidptr(stack, node); /* Walk through the tree recursively. */ while (status == REG_OK && tre_stack_num_objects(stack) > bottom) { node = tre_stack_pop_voidptr(stack); switch (node->type) { case LITERAL: lit = (tre_literal_t *)node->obj; switch (lit->code_min) { case TAG: if (lit->code_max >= 0) { if (tags != NULL) { /* Add the tag to `tags'. */ for (i = 0; tags[i] >= 0; i++) if (tags[i] == lit->code_max) break; if (tags[i] < 0) { tags[i] = lit->code_max; tags[i + 1] = -1; } } if (num_tags_seen) (*num_tags_seen)++; } break; case ASSERTION: assert(lit->code_max >= 1 || lit->code_max <= ASSERT_LAST); if (assertions != NULL) *assertions |= lit->code_max; break; case PARAMETER: if (params != NULL) for (i = 0; i < TRE_PARAM_LAST; i++) params[i] = lit->u.params[i]; if (params_seen != NULL) *params_seen = 1; break; case EMPTY: break; default: assert(0); break; } break; case UNION: /* Subexpressions starting earlier take priority over ones starting later, so we prefer the left subexpression over the right subexpression. */ uni = (tre_union_t *)node->obj; if (uni->left->nullable) STACK_PUSHX(stack, voidptr, uni->left) else if (uni->right->nullable) STACK_PUSHX(stack, voidptr, uni->right) else assert(0); break; case CATENATION: /* The path must go through both children. */ cat = (tre_catenation_t *)node->obj; assert(cat->left->nullable); assert(cat->right->nullable); STACK_PUSHX(stack, voidptr, cat->left); STACK_PUSHX(stack, voidptr, cat->right); break; case ITERATION: /* A match with an empty string is preferred over no match at all, so we go through the argument if possible. */ iter = (tre_iteration_t *)node->obj; if (iter->arg->nullable) STACK_PUSHX(stack, voidptr, iter->arg); break; default: assert(0); break; } } return status; } typedef enum { NFL_RECURSE, NFL_POST_UNION, NFL_POST_CATENATION, NFL_POST_ITERATION } tre_nfl_stack_symbol_t; /* Computes and fills in the fields `nullable', `firstpos', and `lastpos' for the nodes of the AST `tree'. */ static reg_errcode_t tre_compute_nfl(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *tree) { int bottom = tre_stack_num_objects(stack); STACK_PUSHR(stack, voidptr, tree); STACK_PUSHR(stack, int, NFL_RECURSE); while (tre_stack_num_objects(stack) > bottom) { tre_nfl_stack_symbol_t symbol; tre_ast_node_t *node; symbol = (tre_nfl_stack_symbol_t)tre_stack_pop_int(stack); node = tre_stack_pop_voidptr(stack); switch (symbol) { case NFL_RECURSE: switch (node->type) { case LITERAL: { tre_literal_t *lit = (tre_literal_t *)node->obj; if (IS_BACKREF(lit)) { /* Back references: nullable = false, firstpos = {i}, lastpos = {i}. */ node->nullable = 0; node->firstpos = tre_set_one(mem, lit->position, 0, TRE_CHAR_MAX, 0, NULL, -1); if (!node->firstpos) return REG_ESPACE; node->lastpos = tre_set_one(mem, lit->position, 0, TRE_CHAR_MAX, 0, NULL, lit->code_max); if (!node->lastpos) return REG_ESPACE; } else if (lit->code_min < 0) { /* Tags, empty strings, params, and zero width assertions: nullable = true, firstpos = {}, and lastpos = {}. */ node->nullable = 1; node->firstpos = tre_set_empty(mem); if (!node->firstpos) return REG_ESPACE; node->lastpos = tre_set_empty(mem); if (!node->lastpos) return REG_ESPACE; } else { /* Literal at position i: nullable = false, firstpos = {i}, lastpos = {i}. */ node->nullable = 0; node->firstpos = tre_set_one(mem, lit->position, lit->code_min, lit->code_max, 0, NULL, -1); if (!node->firstpos) return REG_ESPACE; node->lastpos = tre_set_one(mem, lit->position, lit->code_min, lit->code_max, lit->u.class, lit->neg_classes, -1); if (!node->lastpos) return REG_ESPACE; } break; } case UNION: /* Compute the attributes for the two subtrees, and after that for this node. */ STACK_PUSHR(stack, voidptr, node); STACK_PUSHR(stack, int, NFL_POST_UNION); STACK_PUSHR(stack, voidptr, ((tre_union_t *)node->obj)->right); STACK_PUSHR(stack, int, NFL_RECURSE); STACK_PUSHR(stack, voidptr, ((tre_union_t *)node->obj)->left); STACK_PUSHR(stack, int, NFL_RECURSE); break; case CATENATION: /* Compute the attributes for the two subtrees, and after that for this node. */ STACK_PUSHR(stack, voidptr, node); STACK_PUSHR(stack, int, NFL_POST_CATENATION); STACK_PUSHR(stack, voidptr, ((tre_catenation_t *)node->obj)->right); STACK_PUSHR(stack, int, NFL_RECURSE); STACK_PUSHR(stack, voidptr, ((tre_catenation_t *)node->obj)->left); STACK_PUSHR(stack, int, NFL_RECURSE); break; case ITERATION: /* Compute the attributes for the subtree, and after that for this node. */ STACK_PUSHR(stack, voidptr, node); STACK_PUSHR(stack, int, NFL_POST_ITERATION); STACK_PUSHR(stack, voidptr, ((tre_iteration_t *)node->obj)->arg); STACK_PUSHR(stack, int, NFL_RECURSE); break; } break; /* end case: NFL_RECURSE */ case NFL_POST_UNION: { tre_union_t *uni = (tre_union_t *)node->obj; node->nullable = uni->left->nullable || uni->right->nullable; node->firstpos = tre_set_union(mem, uni->left->firstpos, uni->right->firstpos, NULL, 0, NULL); if (!node->firstpos) return REG_ESPACE; node->lastpos = tre_set_union(mem, uni->left->lastpos, uni->right->lastpos, NULL, 0, NULL); if (!node->lastpos) return REG_ESPACE; break; } case NFL_POST_ITERATION: { tre_iteration_t *iter = (tre_iteration_t *)node->obj; if (iter->min == 0 || iter->arg->nullable) node->nullable = 1; else node->nullable = 0; node->firstpos = iter->arg->firstpos; node->lastpos = iter->arg->lastpos; break; } case NFL_POST_CATENATION: { int num_tags, *tags, assertions, params_seen; int *params; reg_errcode_t status; tre_catenation_t *cat = node->obj; node->nullable = cat->left->nullable && cat->right->nullable; /* Compute firstpos. */ if (cat->left->nullable) { /* The left side matches the empty string. Make a first pass with tre_match_empty() to get the number of tags and parameters. */ status = tre_match_empty(stack, cat->left, NULL, NULL, NULL, &num_tags, ¶ms_seen); if (status != REG_OK) return status; /* Allocate arrays for the tags and parameters. */ tags = xmalloc(sizeof(*tags) * (num_tags + 1)); if (!tags) return REG_ESPACE; tags[0] = -1; assertions = 0; params = NULL; if (params_seen) { params = tre_mem_alloc(mem, sizeof(*params) * TRE_PARAM_LAST); if (!params) { xfree(tags); return REG_ESPACE; } } /* Second pass with tre_mach_empty() to get the list of tags and parameters. */ status = tre_match_empty(stack, cat->left, tags, &assertions, params, NULL, NULL); if (status != REG_OK) { xfree(tags); return status; } node->firstpos = tre_set_union(mem, cat->right->firstpos, cat->left->firstpos, tags, assertions, params); xfree(tags); if (!node->firstpos) return REG_ESPACE; } else { node->firstpos = cat->left->firstpos; } /* Compute lastpos. */ if (cat->right->nullable) { /* The right side matches the empty string. Make a first pass with tre_match_empty() to get the number of tags and parameters. */ status = tre_match_empty(stack, cat->right, NULL, NULL, NULL, &num_tags, ¶ms_seen); if (status != REG_OK) return status; /* Allocate arrays for the tags and parameters. */ tags = xmalloc(sizeof(int) * (num_tags + 1)); if (!tags) return REG_ESPACE; tags[0] = -1; assertions = 0; params = NULL; if (params_seen) { params = tre_mem_alloc(mem, sizeof(*params) * TRE_PARAM_LAST); if (!params) { xfree(tags); return REG_ESPACE; } } /* Second pass with tre_mach_empty() to get the list of tags and parameters. */ status = tre_match_empty(stack, cat->right, tags, &assertions, params, NULL, NULL); if (status != REG_OK) { xfree(tags); return status; } node->lastpos = tre_set_union(mem, cat->left->lastpos, cat->right->lastpos, tags, assertions, params); xfree(tags); if (!node->lastpos) return REG_ESPACE; } else { node->lastpos = cat->right->lastpos; } break; } default: assert(0); break; } } return REG_OK; } /* Adds a transition from each position in `p1' to each position in `p2'. */ static reg_errcode_t tre_make_trans(tre_pos_and_tags_t *p1, tre_pos_and_tags_t *p2, tre_tnfa_transition_t *transitions, int *counts, int *offs) { tre_pos_and_tags_t *orig_p2 = p2; tre_tnfa_transition_t *trans; int i, j, k, l, dup, prev_p2_pos; if (transitions != NULL) while (p1->position >= 0) { p2 = orig_p2; prev_p2_pos = -1; while (p2->position >= 0) { /* Optimization: if this position was already handled, skip it. */ if (p2->position == prev_p2_pos) { p2++; continue; } prev_p2_pos = p2->position; /* Set `trans' to point to the next unused transition from position `p1->position'. */ trans = transitions + offs[p1->position]; while (trans->state != NULL) { #if 0 /* If we find a previous transition from `p1->position' to `p2->position', it is overwritten. This can happen only if there are nested loops in the regexp, like in "((a)*)*". In POSIX.2 repetition using the outer loop is always preferred over using the inner loop. Therefore the transition for the inner loop is useless and can be thrown away. */ /* XXX - The same position is used for all nodes in a bracket expression, so this optimization cannot be used (it will break bracket expressions) unless I figure out a way to detect it here. */ if (trans->state_id == p2->position) { DPRINT(("*")); break; } #endif trans++; } if (trans->state == NULL) (trans + 1)->state = NULL; /* Use the character ranges, assertions, etc. from `p1' for the transition from `p1' to `p2'. */ trans->code_min = p1->code_min; trans->code_max = p1->code_max; trans->state = transitions + offs[p2->position]; trans->state_id = p2->position; trans->assertions = p1->assertions | p2->assertions | (p1->class ? ASSERT_CHAR_CLASS : 0) | (p1->neg_classes != NULL ? ASSERT_CHAR_CLASS_NEG : 0); if (p1->backref >= 0) { assert((trans->assertions & ASSERT_CHAR_CLASS) == 0); assert(p2->backref < 0); trans->u.backref = p1->backref; trans->assertions |= ASSERT_BACKREF; } else trans->u.class = p1->class; if (p1->neg_classes != NULL) { for (i = 0; p1->neg_classes[i] != (tre_ctype_t)0; i++); trans->neg_classes = xmalloc(sizeof(*trans->neg_classes) * (i + 1)); if (trans->neg_classes == NULL) return REG_ESPACE; for (i = 0; p1->neg_classes[i] != (tre_ctype_t)0; i++) trans->neg_classes[i] = p1->neg_classes[i]; trans->neg_classes[i] = (tre_ctype_t)0; } else trans->neg_classes = NULL; /* Find out how many tags this transition has. */ i = 0; if (p1->tags != NULL) while(p1->tags[i] >= 0) i++; j = 0; if (p2->tags != NULL) while(p2->tags[j] >= 0) j++; /* If we are overwriting a transition, free the old tag array. */ if (trans->tags != NULL) xfree(trans->tags); trans->tags = NULL; /* If there were any tags, allocate an array and fill it. */ if (i + j > 0) { trans->tags = xmalloc(sizeof(*trans->tags) * (i + j + 1)); if (!trans->tags) return REG_ESPACE; i = 0; if (p1->tags != NULL) while(p1->tags[i] >= 0) { trans->tags[i] = p1->tags[i]; i++; } l = i; j = 0; if (p2->tags != NULL) while (p2->tags[j] >= 0) { /* Don't add duplicates. */ dup = 0; for (k = 0; k < i; k++) if (trans->tags[k] == p2->tags[j]) { dup = 1; break; } if (!dup) trans->tags[l++] = p2->tags[j]; j++; } trans->tags[l] = -1; } /* Set the parameter array. If both `p2' and `p1' have same parameters, the values in `p2' override those in `p1'. */ if (p1->params || p2->params) { if (!trans->params) trans->params = xmalloc(sizeof(*trans->params) * TRE_PARAM_LAST); if (!trans->params) return REG_ESPACE; for (i = 0; i < TRE_PARAM_LAST; i++) { trans->params[i] = TRE_PARAM_UNSET; if (p1->params && p1->params[i] != TRE_PARAM_UNSET) trans->params[i] = p1->params[i]; if (p2->params && p2->params[i] != TRE_PARAM_UNSET) trans->params[i] = p2->params[i]; } } else { if (trans->params) xfree(trans->params); trans->params = NULL; } #ifdef TRE_DEBUG { int *tags; DPRINT((" %2d -> %2d on %3d", p1->position, p2->position, p1->code_min)); if (p1->code_max != p1->code_min) DPRINT(("-%3d", p1->code_max)); tags = trans->tags; if (tags) { DPRINT((", tags [")); while (*tags >= 0) { DPRINT(("%d", *tags)); tags++; if (*tags >= 0) DPRINT((",")); } DPRINT(("]")); } if (trans->assertions) DPRINT((", assert %d", trans->assertions)); if (trans->assertions & ASSERT_BACKREF) DPRINT((", backref %d", trans->u.backref)); else if (trans->u.class) DPRINT((", class %ld", (long)trans->u.class)); if (trans->neg_classes) DPRINT((", neg_classes %p", trans->neg_classes)); if (trans->params) { DPRINT((", ")); tre_print_params(trans->params); } DPRINT(("\n")); } #endif /* TRE_DEBUG */ p2++; } p1++; } else /* Compute a maximum limit for the number of transitions leaving from each state. */ while (p1->position >= 0) { p2 = orig_p2; while (p2->position >= 0) { counts[p1->position]++; p2++; } p1++; } return REG_OK; } /* Converts the syntax tree to a TNFA. All the transitions in the TNFA are labelled with one character range (there are no transitions on empty strings). The TNFA takes O(n^2) space in the worst case, `n' is size of the regexp. */ static reg_errcode_t tre_ast_to_tnfa(tre_ast_node_t *node, tre_tnfa_transition_t *transitions, int *counts, int *offs) { tre_union_t *uni; tre_catenation_t *cat; tre_iteration_t *iter; reg_errcode_t errcode = REG_OK; /* XXX - recurse using a stack!. */ switch (node->type) { case LITERAL: break; case UNION: uni = (tre_union_t *)node->obj; errcode = tre_ast_to_tnfa(uni->left, transitions, counts, offs); if (errcode != REG_OK) return errcode; errcode = tre_ast_to_tnfa(uni->right, transitions, counts, offs); break; case CATENATION: cat = (tre_catenation_t *)node->obj; /* Add a transition from each position in cat->left->lastpos to each position in cat->right->firstpos. */ errcode = tre_make_trans(cat->left->lastpos, cat->right->firstpos, transitions, counts, offs); if (errcode != REG_OK) return errcode; errcode = tre_ast_to_tnfa(cat->left, transitions, counts, offs); if (errcode != REG_OK) return errcode; errcode = tre_ast_to_tnfa(cat->right, transitions, counts, offs); break; case ITERATION: iter = (tre_iteration_t *)node->obj; assert(iter->max == -1 || iter->max == 1); if (iter->max == -1) { assert(iter->min == 0 || iter->min == 1); /* Add a transition from each last position in the iterated expression to each first position. */ errcode = tre_make_trans(iter->arg->lastpos, iter->arg->firstpos, transitions, counts, offs); if (errcode != REG_OK) return errcode; } errcode = tre_ast_to_tnfa(iter->arg, transitions, counts, offs); break; } return errcode; } #define ERROR_EXIT(err) \ do \ { \ errcode = err; \ if (1) goto error_exit; \ } \ while (0) int tre_compile(regex_t *preg, const tre_char_t *regex, size_t n, int cflags) { tre_stack_t *stack; tre_ast_node_t *tree, *tmp_ast_l, *tmp_ast_r; tre_pos_and_tags_t *p; int *counts = NULL, *offs = NULL; int i, add = 0; tre_tnfa_transition_t *transitions, *initial; tre_tnfa_t *tnfa = NULL; tre_submatch_data_t *submatch_data; tre_tag_direction_t *tag_directions = NULL; reg_errcode_t errcode; tre_mem_t mem; /* Parse context. */ tre_parse_ctx_t parse_ctx; /* Allocate a stack used throughout the compilation process for various purposes. */ stack = tre_stack_new(512, 10240, 128); if (!stack) return REG_ESPACE; /* Allocate a fast memory allocator. */ mem = tre_mem_new(); if (!mem) { tre_stack_destroy(stack); return REG_ESPACE; } /* Parse the regexp. */ memset(&parse_ctx, 0, sizeof(parse_ctx)); parse_ctx.mem = mem; parse_ctx.stack = stack; parse_ctx.re = regex; parse_ctx.len = n; parse_ctx.cflags = cflags; parse_ctx.max_backref = -1; DPRINT(("tre_compile: parsing '%.*" STRF "'\n", (int)n, regex)); errcode = tre_parse(&parse_ctx); if (errcode != REG_OK) ERROR_EXIT(errcode); preg->re_nsub = parse_ctx.submatch_id - 1; tree = parse_ctx.result; /* Back references and approximate matching cannot currently be used in the same regexp. */ if (parse_ctx.max_backref >= 0 && parse_ctx.have_approx) ERROR_EXIT(REG_BADPAT); #ifdef TRE_DEBUG tre_ast_print(tree); #endif /* TRE_DEBUG */ /* Referring to nonexistent subexpressions is illegal. */ if (parse_ctx.max_backref > (int)preg->re_nsub) ERROR_EXIT(REG_ESUBREG); /* Allocate the TNFA struct. */ tnfa = xcalloc(1, sizeof(tre_tnfa_t)); if (tnfa == NULL) ERROR_EXIT(REG_ESPACE); tnfa->have_backrefs = parse_ctx.max_backref >= 0; tnfa->have_approx = parse_ctx.have_approx; tnfa->num_submatches = parse_ctx.submatch_id; /* Set up tags for submatch addressing. If REG_NOSUB is set and the regexp does not have back references, this can be skipped. */ if (tnfa->have_backrefs || !(cflags & REG_NOSUB)) { DPRINT(("tre_compile: setting up tags\n")); /* Figure out how many tags we will need. */ errcode = tre_add_tags(NULL, stack, tree, tnfa); if (errcode != REG_OK) ERROR_EXIT(errcode); #ifdef TRE_DEBUG tre_ast_print(tree); #endif /* TRE_DEBUG */ if (tnfa->num_tags > 0) { tag_directions = xmalloc(sizeof(*tag_directions) * (tnfa->num_tags + 1)); if (tag_directions == NULL) ERROR_EXIT(REG_ESPACE); tnfa->tag_directions = tag_directions; memset(tag_directions, -1, sizeof(*tag_directions) * (tnfa->num_tags + 1)); } tnfa->minimal_tags = xcalloc(tnfa->num_tags * 2 + 1, sizeof(tnfa->minimal_tags)); if (tnfa->minimal_tags == NULL) ERROR_EXIT(REG_ESPACE); submatch_data = xcalloc(parse_ctx.submatch_id, sizeof(*submatch_data)); if (submatch_data == NULL) ERROR_EXIT(REG_ESPACE); tnfa->submatch_data = submatch_data; errcode = tre_add_tags(mem, stack, tree, tnfa); if (errcode != REG_OK) ERROR_EXIT(errcode); #ifdef TRE_DEBUG for (i = 0; i < parse_ctx.submatch_id; i++) DPRINT(("pmatch[%d] = {t%d, t%d}\n", i, submatch_data[i].so_tag, submatch_data[i].eo_tag)); for (i = 0; i < tnfa->num_tags; i++) DPRINT(("t%d is %s\n", i, tag_directions[i] == TRE_TAG_MINIMIZE ? "minimized" : "maximized")); #endif /* TRE_DEBUG */ } /* Expand iteration nodes. */ errcode = tre_expand_ast(mem, stack, tree, &parse_ctx.position, tag_directions, &tnfa->params_depth); if (errcode != REG_OK) ERROR_EXIT(errcode); /* Add a dummy node for the final state. XXX - For certain patterns this dummy node can be optimized away, for example "a*" or "ab*". Figure out a simple way to detect this possibility. */ tmp_ast_l = tree; tmp_ast_r = tre_ast_new_literal(mem, 0, 0, parse_ctx.position++); if (tmp_ast_r == NULL) ERROR_EXIT(REG_ESPACE); tree = tre_ast_new_catenation(mem, tmp_ast_l, tmp_ast_r); if (tree == NULL) ERROR_EXIT(REG_ESPACE); #ifdef TRE_DEBUG tre_ast_print(tree); DPRINT(("Number of states: %d\n", parse_ctx.position)); #endif /* TRE_DEBUG */ errcode = tre_compute_nfl(mem, stack, tree); if (errcode != REG_OK) ERROR_EXIT(errcode); counts = xmalloc(sizeof(int) * parse_ctx.position); if (counts == NULL) ERROR_EXIT(REG_ESPACE); offs = xmalloc(sizeof(int) * parse_ctx.position); if (offs == NULL) ERROR_EXIT(REG_ESPACE); for (i = 0; i < parse_ctx.position; i++) counts[i] = 0; tre_ast_to_tnfa(tree, NULL, counts, NULL); add = 0; for (i = 0; i < parse_ctx.position; i++) { offs[i] = add; add += counts[i] + 1; counts[i] = 0; } transitions = xcalloc(add + 1, sizeof(*transitions)); if (transitions == NULL) ERROR_EXIT(REG_ESPACE); tnfa->transitions = transitions; tnfa->num_transitions = add; DPRINT(("Converting to TNFA:\n")); errcode = tre_ast_to_tnfa(tree, transitions, counts, offs); if (errcode != REG_OK) ERROR_EXIT(errcode); /* If in eight bit mode, compute a table of characters that can be the first character of a match. */ tnfa->first_char = -1; if (TRE_MB_CUR_MAX == 1 && !tmp_ast_l->nullable) { int count = 0; int k; DPRINT(("Characters that can start a match:")); tnfa->firstpos_chars = xcalloc(256, sizeof(char)); if (tnfa->firstpos_chars == NULL) ERROR_EXIT(REG_ESPACE); for (p = tree->firstpos; p->position >= 0; p++) { tre_tnfa_transition_t *j = transitions + offs[p->position]; while (j->state != NULL) { for (k = j->code_min; k <= j->code_max && k < 256; k++) { DPRINT((" %d", k)); tnfa->firstpos_chars[k] = 1; count++; } j++; } } DPRINT(("\n")); #define TRE_OPTIMIZE_FIRST_CHAR 1 #if TRE_OPTIMIZE_FIRST_CHAR if (count == 1) { for (k = 0; k < 256; k++) if (tnfa->firstpos_chars[k]) { DPRINT(("first char must be %d\n", k)); tnfa->first_char = k; xfree(tnfa->firstpos_chars); tnfa->firstpos_chars = NULL; break; } } #endif } else tnfa->firstpos_chars = NULL; p = tree->firstpos; i = 0; while (p->position >= 0) { i++; #ifdef TRE_DEBUG { int *tags; DPRINT(("initial: %d", p->position)); tags = p->tags; if (tags != NULL) { if (*tags >= 0) DPRINT(("/")); while (*tags >= 0) { DPRINT(("%d", *tags)); tags++; if (*tags >= 0) DPRINT((",")); } } DPRINT((", assert %d", p->assertions)); if (p->params) { DPRINT((", ")); tre_print_params(p->params); } DPRINT(("\n")); } #endif /* TRE_DEBUG */ p++; } initial = xcalloc(i + 1, sizeof(tre_tnfa_transition_t)); if (initial == NULL) ERROR_EXIT(REG_ESPACE); tnfa->initial = initial; i = 0; for (p = tree->firstpos; p->position >= 0; p++) { initial[i].state = transitions + offs[p->position]; initial[i].state_id = p->position; initial[i].tags = NULL; /* Copy the arrays p->tags, and p->params, they are allocated from a tre_mem object. */ if (p->tags) { int j; for (j = 0; p->tags[j] >= 0; j++); initial[i].tags = xmalloc(sizeof(*p->tags) * (j + 1)); if (!initial[i].tags) ERROR_EXIT(REG_ESPACE); memcpy(initial[i].tags, p->tags, sizeof(*p->tags) * (j + 1)); } initial[i].params = NULL; if (p->params) { initial[i].params = xmalloc(sizeof(*p->params) * TRE_PARAM_LAST); if (!initial[i].params) ERROR_EXIT(REG_ESPACE); memcpy(initial[i].params, p->params, sizeof(*p->params) * TRE_PARAM_LAST); } initial[i].assertions = p->assertions; i++; } initial[i].state = NULL; tnfa->num_transitions = add; tnfa->final = transitions + offs[tree->lastpos[0].position]; tnfa->num_states = parse_ctx.position; tnfa->cflags = cflags; DPRINT(("final state %p\n", (void *)tnfa->final)); tre_mem_destroy(mem); tre_stack_destroy(stack); xfree(counts); xfree(offs); preg->TRE_REGEX_T_FIELD = (void *)tnfa; return REG_OK; error_exit: /* Free everything that was allocated and return the error code. */ tre_mem_destroy(mem); if (stack != NULL) tre_stack_destroy(stack); if (counts != NULL) xfree(counts); if (offs != NULL) xfree(offs); preg->TRE_REGEX_T_FIELD = (void *)tnfa; tre_free(preg); return errcode; } void tre_free(regex_t *preg) { tre_tnfa_t *tnfa; unsigned int i; tre_tnfa_transition_t *trans; tnfa = (void *)preg->TRE_REGEX_T_FIELD; if (!tnfa) return; for (i = 0; i < tnfa->num_transitions; i++) if (tnfa->transitions[i].state) { if (tnfa->transitions[i].tags) xfree(tnfa->transitions[i].tags); if (tnfa->transitions[i].neg_classes) xfree(tnfa->transitions[i].neg_classes); if (tnfa->transitions[i].params) xfree(tnfa->transitions[i].params); } if (tnfa->transitions) xfree(tnfa->transitions); if (tnfa->initial) { for (trans = tnfa->initial; trans->state; trans++) { if (trans->tags) xfree(trans->tags); if (trans->params) xfree(trans->params); } xfree(tnfa->initial); } if (tnfa->submatch_data) { for (i = 0; i < tnfa->num_submatches; i++) if (tnfa->submatch_data[i].parents) xfree(tnfa->submatch_data[i].parents); xfree(tnfa->submatch_data); } if (tnfa->tag_directions) xfree(tnfa->tag_directions); if (tnfa->firstpos_chars) xfree(tnfa->firstpos_chars); if (tnfa->minimal_tags) xfree(tnfa->minimal_tags); xfree(tnfa); } char * tre_version(void) { static char str[256]; char *version; if (str[0] == 0) { tre_config(TRE_CONFIG_VERSION, &version); sprintf(str, "TRE %s (LGPL)", version); } return str; } int tre_config(int query, void *result) { int *int_result = result; char **string_result = result; switch (query) { case TRE_CONFIG_APPROX: #ifdef TRE_APPROX *int_result = 1; #else /* !TRE_APPROX */ *int_result = 0; #endif /* !TRE_APPROX */ return REG_OK; case TRE_CONFIG_WCHAR: #ifdef TRE_WCHAR *int_result = 1; #else /* !TRE_WCHAR */ *int_result = 0; #endif /* !TRE_WCHAR */ return REG_OK; case TRE_CONFIG_MULTIBYTE: #ifdef TRE_MULTIBYTE *int_result = 1; #else /* !TRE_MULTIBYTE */ *int_result = 0; #endif /* !TRE_MULTIBYTE */ return REG_OK; case TRE_CONFIG_SYSTEM_ABI: #ifdef TRE_CONFIG_SYSTEM_ABI *int_result = 1; #else /* !TRE_CONFIG_SYSTEM_ABI */ *int_result = 0; #endif /* !TRE_CONFIG_SYSTEM_ABI */ return REG_OK; case TRE_CONFIG_VERSION: *string_result = TRE_VERSION; return REG_OK; } return REG_NOMATCH; } /* EOF */ lensfun-0.3.4/libs/regex/tre-compile.h000066400000000000000000000021351445356770400176440ustar00rootroot00000000000000/* tre-compile.h: Regex compilation definitions Copyright (c) 2001-2006 Ville Laurikari This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TRE_COMPILE_H #define TRE_COMPILE_H 1 typedef struct { int position; int code_min; int code_max; int *tags; int assertions; tre_ctype_t class; tre_ctype_t *neg_classes; int backref; int *params; } tre_pos_and_tags_t; #endif /* TRE_COMPILE_H */ /* EOF */ lensfun-0.3.4/libs/regex/tre-internal.h000066400000000000000000000202031445356770400200240ustar00rootroot00000000000000/* tre-internal.h - TRE internal definitions Copyright (c) 2001-2006 Ville Laurikari . This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TRE_INTERNAL_H #define TRE_INTERNAL_H 1 #ifdef HAVE_WCHAR_H #include #endif /* HAVE_WCHAR_H */ #ifdef HAVE_WCTYPE_H #include #endif /* !HAVE_WCTYPE_H */ #include #include "regex.h" #ifdef TRE_DEBUG #include #define DPRINT(msg) do {printf msg; fflush(stdout);} while(0) #else /* !TRE_DEBUG */ #define DPRINT(msg) do { } while(0) #endif /* !TRE_DEBUG */ #define elementsof(x) ( sizeof(x) / sizeof(x[0]) ) #ifdef HAVE_MBRTOWC #define tre_mbrtowc(pwc, s, n, ps) (mbrtowc((pwc), (s), (n), (ps))) #else /* !HAVE_MBRTOWC */ #ifdef HAVE_MBTOWC #define tre_mbrtowc(pwc, s, n, ps) (mbtowc((pwc), (s), (n))) #endif /* HAVE_MBTOWC */ #endif /* !HAVE_MBRTOWC */ #ifdef TRE_MULTIBYTE #ifdef HAVE_MBSTATE_T #define TRE_MBSTATE #endif /* TRE_MULTIBYTE */ #endif /* HAVE_MBSTATE_T */ /* Define the character types and functions. */ #ifdef TRE_WCHAR /* Wide characters. */ typedef wint_t tre_cint_t; #define TRE_CHAR_MAX WCHAR_MAX #ifdef TRE_MULTIBYTE #define TRE_MB_CUR_MAX MB_CUR_MAX #else /* !TRE_MULTIBYTE */ #define TRE_MB_CUR_MAX 1 #endif /* !TRE_MULTIBYTE */ #define tre_isalnum iswalnum #define tre_isalpha iswalpha #ifdef HAVE_ISWBLANK #define tre_isblank iswblank #endif /* HAVE_ISWBLANK */ #define tre_iscntrl iswcntrl #define tre_isdigit iswdigit #define tre_isgraph iswgraph #define tre_islower iswlower #define tre_isprint iswprint #define tre_ispunct iswpunct #define tre_isspace iswspace #define tre_isupper iswupper #define tre_isxdigit iswxdigit #define tre_tolower towlower #define tre_toupper towupper #define tre_strlen wcslen #else /* !TRE_WCHAR */ /* 8 bit characters. */ typedef short tre_cint_t; #define TRE_CHAR_MAX 255 #define TRE_MB_CUR_MAX 1 #define tre_isalnum isalnum #define tre_isalpha isalpha #ifdef HAVE_ISASCII #define tre_isascii isascii #endif /* HAVE_ISASCII */ #ifdef HAVE_ISBLANK #define tre_isblank isblank #endif /* HAVE_ISBLANK */ #define tre_iscntrl iscntrl #define tre_isdigit isdigit #define tre_isgraph isgraph #define tre_islower islower #define tre_isprint isprint #define tre_ispunct ispunct #define tre_isspace isspace #define tre_isupper isupper #define tre_isxdigit isxdigit #define tre_tolower(c) (tre_cint_t)(tolower(c)) #define tre_toupper(c) (tre_cint_t)(toupper(c)) #define tre_strlen(s) (strlen((const char*)s)) #endif /* !TRE_WCHAR */ #if defined(TRE_WCHAR) && defined(HAVE_ISWCTYPE) && defined(HAVE_WCTYPE) #define TRE_USE_SYSTEM_WCTYPE 1 #endif #ifdef TRE_USE_SYSTEM_WCTYPE /* Use system provided iswctype() and wctype(). */ typedef wctype_t tre_ctype_t; #define tre_isctype iswctype #define tre_ctype wctype #else /* !TRE_USE_SYSTEM_WCTYPE */ /* Define our own versions of iswctype() and wctype(). */ typedef int (*tre_ctype_t)(tre_cint_t); #define tre_isctype(c, type) ( (type)(c) ) tre_ctype_t tre_ctype(const char *name); #endif /* !TRE_USE_SYSTEM_WCTYPE */ typedef enum { STR_WIDE, STR_BYTE, STR_MBS, STR_USER } tre_str_type_t; /* Returns number of bytes to add to (char *)ptr to make it properly aligned for the type. */ #define ALIGN(ptr, type) \ ((((long)ptr) % sizeof(type)) \ ? (sizeof(type) - (((long)ptr) % sizeof(type))) \ : 0) #undef MAX #undef MIN #define MAX(a, b) (((a) >= (b)) ? (a) : (b)) #define MIN(a, b) (((a) <= (b)) ? (a) : (b)) /* Define STRF to the correct printf formatter for strings. */ #ifdef TRE_WCHAR #define STRF "ls" #else /* !TRE_WCHAR */ #define STRF "s" #endif /* !TRE_WCHAR */ /* TNFA transition type. A TNFA state is an array of transitions, the terminator is a transition with NULL `state'. */ typedef struct tnfa_transition tre_tnfa_transition_t; struct tnfa_transition { /* Range of accepted characters. */ tre_cint_t code_min; tre_cint_t code_max; /* Pointer to the destination state. */ tre_tnfa_transition_t *state; /* ID number of the destination state. */ int state_id; /* -1 terminated array of tags (or NULL). */ int *tags; /* Matching parameters settings (or NULL). */ int *params; /* Assertion bitmap. */ int assertions; /* Assertion parameters. */ union { /* Character class assertion. */ tre_ctype_t class; /* Back reference assertion. */ int backref; } u; /* Negative character class assertions. */ tre_ctype_t *neg_classes; }; /* Assertions. */ #define ASSERT_AT_BOL 1 /* Beginning of line. */ #define ASSERT_AT_EOL 2 /* End of line. */ #define ASSERT_CHAR_CLASS 4 /* Character class in `class'. */ #define ASSERT_CHAR_CLASS_NEG 8 /* Character classes in `neg_classes'. */ #define ASSERT_AT_BOW 16 /* Beginning of word. */ #define ASSERT_AT_EOW 32 /* End of word. */ #define ASSERT_AT_WB 64 /* Word boundary. */ #define ASSERT_AT_WB_NEG 128 /* Not a word boundary. */ #define ASSERT_BACKREF 256 /* A back reference in `backref'. */ #define ASSERT_LAST 256 /* Tag directions. */ typedef enum { TRE_TAG_MINIMIZE = 0, TRE_TAG_MAXIMIZE = 1 } tre_tag_direction_t; /* Parameters that can be changed dynamically while matching. */ typedef enum { TRE_PARAM_COST_INS = 0, TRE_PARAM_COST_DEL = 1, TRE_PARAM_COST_SUBST = 2, TRE_PARAM_COST_MAX = 3, TRE_PARAM_MAX_INS = 4, TRE_PARAM_MAX_DEL = 5, TRE_PARAM_MAX_SUBST = 6, TRE_PARAM_MAX_ERR = 7, TRE_PARAM_DEPTH = 8, TRE_PARAM_LAST = 9 } tre_param_t; /* Unset matching parameter */ #define TRE_PARAM_UNSET -1 /* Signifies the default matching parameter value. */ #define TRE_PARAM_DEFAULT -2 /* Instructions to compute submatch register values from tag values after a successful match. */ struct tre_submatch_data { /* Tag that gives the value for rm_so (submatch start offset). */ int so_tag; /* Tag that gives the value for rm_eo (submatch end offset). */ int eo_tag; /* List of submatches this submatch is contained in. */ int *parents; }; typedef struct tre_submatch_data tre_submatch_data_t; /* TNFA definition. */ typedef struct tnfa tre_tnfa_t; struct tnfa { tre_tnfa_transition_t *transitions; unsigned int num_transitions; tre_tnfa_transition_t *initial; tre_tnfa_transition_t *final; tre_submatch_data_t *submatch_data; char *firstpos_chars; int first_char; unsigned int num_submatches; tre_tag_direction_t *tag_directions; int *minimal_tags; int num_tags; int num_minimals; int end_tag; int num_states; int cflags; int have_backrefs; int have_approx; int params_depth; }; int tre_compile(regex_t *preg, const tre_char_t *regex, size_t n, int cflags); void tre_free(regex_t *preg); void tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags, const tre_tnfa_t *tnfa, int *tags, int match_eo); reg_errcode_t tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len, tre_str_type_t type, int *match_tags, int eflags, int *match_end_ofs); reg_errcode_t tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len, tre_str_type_t type, int *match_tags, int eflags, int *match_end_ofs); reg_errcode_t tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, int len, tre_str_type_t type, int *match_tags, int eflags, int *match_end_ofs); #ifdef TRE_APPROX reg_errcode_t tre_tnfa_run_approx(const tre_tnfa_t *tnfa, const void *string, int len, tre_str_type_t type, int *match_tags, regamatch_t *match, regaparams_t params, int eflags, int *match_end_ofs); #endif /* TRE_APPROX */ #endif /* TRE_INTERNAL_H */ /* EOF */ lensfun-0.3.4/libs/regex/tre-match-approx.c000066400000000000000000000575701445356770400206270ustar00rootroot00000000000000/* tre-match-approx.c - TRE approximate regex matching engine Copyright (c) 2001-2006 Ville Laurikari . This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ /* AIX requires this to be the first thing in the file. */ #ifdef TRE_USE_ALLOCA #ifndef __GNUC__ # if HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif #endif #endif /* TRE_USE_ALLOCA */ #define __USE_STRING_INLINES #undef __NO_INLINE__ #include #include #include #include #ifdef HAVE_WCHAR_H #include #endif /* HAVE_WCHAR_H */ #ifdef HAVE_WCTYPE_H #include #endif /* HAVE_WCTYPE_H */ #ifndef TRE_WCHAR #include #endif /* !TRE_WCHAR */ #ifdef HAVE_MALLOC_H #include #endif /* HAVE_MALLOC_H */ #include "tre-internal.h" #include "tre-match-utils.h" #include "regex.h" #include "xmalloc.h" #ifdef TRE_APPROX #define TRE_M_COST 0 #define TRE_M_NUM_INS 1 #define TRE_M_NUM_DEL 2 #define TRE_M_NUM_SUBST 3 #define TRE_M_NUM_ERR 4 #define TRE_M_LAST 5 #define TRE_M_MAX_DEPTH 3 typedef struct { /* State in the TNFA transition table. */ tre_tnfa_transition_t *state; /* Position in input string. */ int pos; /* Tag values. */ int *tags; /* Matching parameters. */ regaparams_t params; /* Nesting depth of parameters. This is used as an index in the `costs' array. */ int depth; /* Costs and counter values for different parameter nesting depths. */ int costs[TRE_M_MAX_DEPTH + 1][TRE_M_LAST]; } tre_tnfa_approx_reach_t; #ifdef TRE_DEBUG /* Prints the `reach' array in a readable fashion with DPRINT. */ static void tre_print_reach(const tre_tnfa_t *tnfa, tre_tnfa_approx_reach_t *reach, int pos, int num_tags) { int id; /* Print each state on one line. */ DPRINT((" reach:\n")); for (id = 0; id < tnfa->num_states; id++) { int i, j; if (reach[id].pos < pos) continue; /* Not reached. */ DPRINT((" %03d, costs ", id)); for (i = 0; i <= reach[id].depth; i++) { DPRINT(("[")); for (j = 0; j < TRE_M_LAST; j++) { DPRINT(("%2d", reach[id].costs[i][j])); if (j + 1 < TRE_M_LAST) DPRINT((",")); } DPRINT(("]")); if (i + 1 <= reach[id].depth) DPRINT((", ")); } DPRINT(("\n tags ")); for (i = 0; i < num_tags; i++) { DPRINT(("%02d", reach[id].tags[i])); if (i + 1 < num_tags) DPRINT((",")); } DPRINT(("\n")); } DPRINT(("\n")); } #endif /* TRE_DEBUG */ /* Sets the matching parameters in `reach' to the ones defined in the `pa' array. If `pa' specifies default values, they are taken from `default_params'. */ inline static void tre_set_params(tre_tnfa_approx_reach_t *reach, int *pa, regaparams_t default_params) { int value; /* If depth is increased reset costs and counters to zero for the new levels. */ value = pa[TRE_PARAM_DEPTH]; assert(value <= TRE_M_MAX_DEPTH); if (value > reach->depth) { int i, j; for (i = reach->depth + 1; i <= value; i++) for (j = 0; j < TRE_M_LAST; j++) reach->costs[i][j] = 0; } reach->depth = value; /* Set insert cost. */ value = pa[TRE_PARAM_COST_INS]; if (value == TRE_PARAM_DEFAULT) reach->params.cost_ins = default_params.cost_ins; else if (value != TRE_PARAM_UNSET) reach->params.cost_ins = value; /* Set delete cost. */ value = pa[TRE_PARAM_COST_DEL]; if (value == TRE_PARAM_DEFAULT) reach->params.cost_del = default_params.cost_del; else if (value != TRE_PARAM_UNSET) reach->params.cost_del = value; /* Set substitute cost. */ value = pa[TRE_PARAM_COST_SUBST]; if (value == TRE_PARAM_DEFAULT) reach->params.cost_subst = default_params.cost_subst; else reach->params.cost_subst = value; /* Set maximum cost. */ value = pa[TRE_PARAM_COST_MAX]; if (value == TRE_PARAM_DEFAULT) reach->params.max_cost = default_params.max_cost; else if (value != TRE_PARAM_UNSET) reach->params.max_cost = value; /* Set maximum inserts. */ value = pa[TRE_PARAM_MAX_INS]; if (value == TRE_PARAM_DEFAULT) reach->params.max_ins = default_params.max_ins; else if (value != TRE_PARAM_UNSET) reach->params.max_ins = value; /* Set maximum deletes. */ value = pa[TRE_PARAM_MAX_DEL]; if (value == TRE_PARAM_DEFAULT) reach->params.max_del = default_params.max_del; else if (value != TRE_PARAM_UNSET) reach->params.max_del = value; /* Set maximum substitutes. */ value = pa[TRE_PARAM_MAX_SUBST]; if (value == TRE_PARAM_DEFAULT) reach->params.max_subst = default_params.max_subst; else if (value != TRE_PARAM_UNSET) reach->params.max_subst = value; /* Set maximum number of errors. */ value = pa[TRE_PARAM_MAX_ERR]; if (value == TRE_PARAM_DEFAULT) reach->params.max_err = default_params.max_err; else if (value != TRE_PARAM_UNSET) reach->params.max_err = value; } reg_errcode_t tre_tnfa_run_approx(const tre_tnfa_t *tnfa, const void *string, int len, tre_str_type_t type, int *match_tags, regamatch_t *match, regaparams_t default_params, int eflags, int *match_end_ofs) { /* State variables required by GET_NEXT_WCHAR. */ tre_char_t prev_c = 0, next_c = 0; const char *str_byte = string; int pos = -1; unsigned int pos_add_next = 1; #ifdef TRE_WCHAR const wchar_t *str_wide = string; #ifdef TRE_MBSTATE mbstate_t mbstate; #endif /* !TRE_WCHAR */ #endif /* TRE_WCHAR */ int reg_notbol = eflags & REG_NOTBOL; int reg_noteol = eflags & REG_NOTEOL; int reg_newline = tnfa->cflags & REG_NEWLINE; int str_user_end = 0; int prev_pos; /* Compilation flags for this regexp. */ int cflags = tnfa->cflags; /* Number of tags. */ int num_tags; /* The reach tables. */ tre_tnfa_approx_reach_t *reach, *reach_next; /* Tag array for temporary use. */ int *tmp_tags; /* End offset of best match so far, or -1 if no match found yet. */ int match_eo = -1; /* Costs of the match. */ int match_costs[TRE_M_LAST]; /* Space for temporary data required for matching. */ unsigned char *buf; int i, id; if (!match_tags) num_tags = 0; else num_tags = tnfa->num_tags; #ifdef TRE_MBSTATE memset(&mbstate, '\0', sizeof(mbstate)); #endif /* TRE_MBSTATE */ DPRINT(("tre_tnfa_run_approx, input type %d, len %d, eflags %d, " "match_tags %p\n", type, len, eflags, match_tags)); DPRINT(("max cost %d, ins %d, del %d, subst %d\n", default_params.max_cost, default_params.cost_ins, default_params.cost_del, default_params.cost_subst)); /* Allocate memory for temporary data required for matching. This needs to be done for every matching operation to be thread safe. This allocates everything in a single large block from the stack frame using alloca() or with malloc() if alloca is unavailable. */ { unsigned char *buf_cursor; /* Space needed for one array of tags. */ int tag_bytes = sizeof(*tmp_tags) * num_tags; /* Space needed for one reach table. */ int reach_bytes = sizeof(*reach_next) * tnfa->num_states; /* Total space needed. */ int total_bytes = reach_bytes * 2 + (tnfa->num_states * 2 + 1 ) * tag_bytes; /* Add some extra to make sure we can align the pointers. The multiplier used here must be equal to the number of ALIGN calls below. */ total_bytes += (sizeof(long) - 1) * 3; /* Allocate the memory. */ #ifdef TRE_USE_ALLOCA buf = alloca(total_bytes); #else /* !TRE_USE_ALLOCA */ buf = xmalloc(total_bytes); #endif /* !TRE_USE_ALLOCA */ if (!buf) return REG_ESPACE; memset(buf, 0, total_bytes); /* Allocate `tmp_tags' from `buf'. */ tmp_tags = (void *)buf; buf_cursor = buf + tag_bytes; buf_cursor += ALIGN(buf_cursor, long); /* Allocate `reach' from `buf'. */ reach = (void *)buf_cursor; buf_cursor += reach_bytes; buf_cursor += ALIGN(buf_cursor, long); /* Allocate `reach_next' from `buf'. */ reach_next = (void *)buf_cursor; buf_cursor += reach_bytes; buf_cursor += ALIGN(buf_cursor, long); /* Allocate tag arrays for `reach' and `reach_next' from `buf'. */ for (i = 0; i < tnfa->num_states; i++) { reach[i].tags = (void *)buf_cursor; buf_cursor += tag_bytes; reach_next[i].tags = (void *)buf_cursor; buf_cursor += tag_bytes; } assert(buf_cursor <= buf + total_bytes); } for (i = 0; i < TRE_M_LAST; i++) match_costs[i] = INT_MAX; /* Mark the reach arrays empty. */ for (i = 0; i < tnfa->num_states; i++) reach[i].pos = reach_next[i].pos = -2; prev_pos = pos; GET_NEXT_WCHAR(); pos = 0; while (1) { DPRINT(("%03d:%2lc/%05d\n", pos, (tre_cint_t)next_c, (int)next_c)); /* Add initial states to `reach_next' if an exact match has not yet been found. */ if (match_costs[TRE_M_COST] > 0) { tre_tnfa_transition_t *trans; DPRINT((" init")); for (trans = tnfa->initial; trans->state; trans++) { int id = trans->state_id; /* If this state is not currently in `reach_next', add it there. */ if (reach_next[id].pos < pos) { if (trans->assertions && CHECK_ASSERTIONS(trans->assertions)) { /* Assertions failed, don't add this state. */ DPRINT((" !%d (assert)", id)); continue; } DPRINT((" %d", id)); reach_next[id].state = trans->state; reach_next[id].pos = pos; /* Compute tag values after this transition. */ for (i = 0; i < num_tags; i++) reach_next[id].tags[i] = -1; if (trans->tags) for (i = 0; trans->tags[i] >= 0; i++) if (trans->tags[i] < num_tags) reach_next[id].tags[trans->tags[i]] = pos; /* Set the parameters, depth, and costs. */ reach_next[id].params = default_params; reach_next[id].depth = 0; for (i = 0; i < TRE_M_LAST; i++) reach_next[id].costs[0][i] = 0; if (trans->params) tre_set_params(&reach_next[id], trans->params, default_params); /* If this is the final state, mark the exact match. */ if (trans->state == tnfa->final) { match_eo = pos; for (i = 0; i < num_tags; i++) match_tags[i] = reach_next[id].tags[i]; for (i = 0; i < TRE_M_LAST; i++) match_costs[i] = 0; } } } DPRINT(("\n")); } /* Handle inserts. This is done by pretending there's an epsilon transition from each state in `reach' back to the same state. We don't need to worry about the final state here; this will never give a better match than what we already have. */ for (id = 0; id < tnfa->num_states; id++) { int depth; int cost, cost0; if (reach[id].pos != prev_pos) { DPRINT((" insert: %d not reached\n", id)); continue; /* Not reached. */ } depth = reach[id].depth; /* Compute and check cost at current depth. */ cost = reach[id].costs[depth][TRE_M_COST]; if (reach[id].params.cost_ins != TRE_PARAM_UNSET) cost += reach[id].params.cost_ins; if (cost > reach[id].params.max_cost) continue; /* Cost too large. */ /* Check number of inserts at current depth. */ if (reach[id].costs[depth][TRE_M_NUM_INS] + 1 > reach[id].params.max_ins) continue; /* Too many inserts. */ /* Check total number of errors at current depth. */ if (reach[id].costs[depth][TRE_M_NUM_ERR] + 1 > reach[id].params.max_err) continue; /* Too many errors. */ /* Compute overall cost. */ cost0 = cost; if (depth > 0) { cost0 = reach[id].costs[0][TRE_M_COST]; if (reach[id].params.cost_ins != TRE_PARAM_UNSET) cost0 += reach[id].params.cost_ins; else cost0 += default_params.cost_ins; } DPRINT((" insert: from %d to %d, cost %d: ", id, id, reach[id].costs[depth][TRE_M_COST])); if (reach_next[id].pos == pos && (cost0 >= reach_next[id].costs[0][TRE_M_COST])) { DPRINT(("lose\n")); continue; } DPRINT(("win\n")); /* Copy state, position, tags, parameters, and depth. */ reach_next[id].state = reach[id].state; reach_next[id].pos = pos; for (i = 0; i < num_tags; i++) reach_next[id].tags[i] = reach[id].tags[i]; reach_next[id].params = reach[id].params; reach_next[id].depth = reach[id].depth; /* Set the costs after this transition. */ memcpy(reach_next[id].costs, reach[id].costs, sizeof(reach_next[id].costs[0][0]) * TRE_M_LAST * (depth + 1)); reach_next[id].costs[depth][TRE_M_COST] = cost; reach_next[id].costs[depth][TRE_M_NUM_INS]++; reach_next[id].costs[depth][TRE_M_NUM_ERR]++; if (depth > 0) { reach_next[id].costs[0][TRE_M_COST] = cost0; reach_next[id].costs[0][TRE_M_NUM_INS]++; reach_next[id].costs[0][TRE_M_NUM_ERR]++; } } /* Handle deletes. This is done by traversing through the whole TNFA pretending that all transitions are epsilon transitions, until no more states can be reached with better costs. */ { /* XXX - dynamic ringbuffer size */ tre_tnfa_approx_reach_t *ringbuffer[512]; tre_tnfa_approx_reach_t **deque_start, **deque_end; deque_start = deque_end = ringbuffer; /* Add all states in `reach_next' to the deque. */ for (id = 0; id < tnfa->num_states; id++) { if (reach_next[id].pos != pos) continue; *deque_end = &reach_next[id]; deque_end++; assert(deque_end != deque_start); } /* Repeat until the deque is empty. */ while (deque_end != deque_start) { tre_tnfa_approx_reach_t *reach_p; int id; int depth; int cost, cost0; tre_tnfa_transition_t *trans; /* Pop the first item off the deque. */ reach_p = *deque_start; id = reach_p - reach_next; depth = reach_p->depth; /* Compute cost at current depth. */ cost = reach_p->costs[depth][TRE_M_COST]; if (reach_p->params.cost_del != TRE_PARAM_UNSET) cost += reach_p->params.cost_del; /* Check cost, number of deletes, and total number of errors at current depth. */ if (cost > reach_p->params.max_cost || (reach_p->costs[depth][TRE_M_NUM_DEL] + 1 > reach_p->params.max_del) || (reach_p->costs[depth][TRE_M_NUM_ERR] + 1 > reach_p->params.max_err)) { /* Too many errors or cost too large. */ DPRINT((" delete: from %03d: cost too large\n", id)); deque_start++; if (deque_start >= (ringbuffer + 512)) deque_start = ringbuffer; continue; } /* Compute overall cost. */ cost0 = cost; if (depth > 0) { cost0 = reach_p->costs[0][TRE_M_COST]; if (reach_p->params.cost_del != TRE_PARAM_UNSET) cost0 += reach_p->params.cost_del; else cost0 += default_params.cost_del; } for (trans = reach_p->state; trans->state; trans++) { int dest_id = trans->state_id; DPRINT((" delete: from %03d to %03d, cost %d (%d): ", id, dest_id, cost0, reach_p->params.max_cost)); if (trans->assertions && CHECK_ASSERTIONS(trans->assertions)) { DPRINT(("assertion failed\n")); continue; } /* Compute tag values after this transition. */ for (i = 0; i < num_tags; i++) tmp_tags[i] = reach_p->tags[i]; if (trans->tags) for (i = 0; trans->tags[i] >= 0; i++) if (trans->tags[i] < num_tags) tmp_tags[trans->tags[i]] = pos; /* If another path has also reached this state, choose the one with the smallest cost or best tags if costs are equal. */ if (reach_next[dest_id].pos == pos && (cost0 > reach_next[dest_id].costs[0][TRE_M_COST] || (cost0 == reach_next[dest_id].costs[0][TRE_M_COST] && (!match_tags || !tre_tag_order(num_tags, tnfa->tag_directions, tmp_tags, reach_next[dest_id].tags))))) { DPRINT(("lose, cost0 %d, have %d\n", cost0, reach_next[dest_id].costs[0][TRE_M_COST])); continue; } DPRINT(("win\n")); /* Set state, position, tags, parameters, depth, and costs. */ reach_next[dest_id].state = trans->state; reach_next[dest_id].pos = pos; for (i = 0; i < num_tags; i++) reach_next[dest_id].tags[i] = tmp_tags[i]; reach_next[dest_id].params = reach_p->params; if (trans->params) tre_set_params(&reach_next[dest_id], trans->params, default_params); reach_next[dest_id].depth = reach_p->depth; memcpy(&reach_next[dest_id].costs, reach_p->costs, sizeof(reach_p->costs[0][0]) * TRE_M_LAST * (depth + 1)); reach_next[dest_id].costs[depth][TRE_M_COST] = cost; reach_next[dest_id].costs[depth][TRE_M_NUM_DEL]++; reach_next[dest_id].costs[depth][TRE_M_NUM_ERR]++; if (depth > 0) { reach_next[dest_id].costs[0][TRE_M_COST] = cost0; reach_next[dest_id].costs[0][TRE_M_NUM_DEL]++; reach_next[dest_id].costs[0][TRE_M_NUM_ERR]++; } if (trans->state == tnfa->final && (match_eo < 0 || match_costs[TRE_M_COST] > cost0 || (match_costs[TRE_M_COST] == cost0 && (num_tags > 0 && tmp_tags[0] <= match_tags[0])))) { DPRINT((" setting new match at %d, cost %d\n", pos, cost0)); match_eo = pos; memcpy(match_costs, reach_next[dest_id].costs[0], sizeof(match_costs[0]) * TRE_M_LAST); for (i = 0; i < num_tags; i++) match_tags[i] = tmp_tags[i]; } /* Add to the end of the deque. */ *deque_end = &reach_next[dest_id]; deque_end++; if (deque_end >= (ringbuffer + 512)) deque_end = ringbuffer; assert(deque_end != deque_start); } deque_start++; if (deque_start >= (ringbuffer + 512)) deque_start = ringbuffer; } } #ifdef TRE_DEBUG tre_print_reach(tnfa, reach_next, pos, num_tags); #endif /* TRE_DEBUG */ /* Check for end of string. */ if (len < 0) { if (type == STR_USER) { if (str_user_end) break; } else if (next_c == L'\0') break; } else { if (pos >= len) break; } prev_pos = pos; GET_NEXT_WCHAR(); /* Swap `reach' and `reach_next'. */ { tre_tnfa_approx_reach_t *tmp; tmp = reach; reach = reach_next; reach_next = tmp; } /* Handle exact matches and substitutions. */ for (id = 0; id < tnfa->num_states; id++) { tre_tnfa_transition_t *trans; if (reach[id].pos < prev_pos) continue; /* Not reached. */ for (trans = reach[id].state; trans->state; trans++) { int dest_id; int depth; int cost, cost0, err; if (trans->assertions && (CHECK_ASSERTIONS(trans->assertions) /* Handle character class transitions. */ || ((trans->assertions & ASSERT_CHAR_CLASS) && !(cflags & REG_ICASE) && !tre_isctype((tre_cint_t)prev_c, trans->u.class)) || ((trans->assertions & ASSERT_CHAR_CLASS) && (cflags & REG_ICASE) && (!tre_isctype(tre_tolower((tre_cint_t)prev_c), trans->u.class) && !tre_isctype(tre_toupper((tre_cint_t)prev_c), trans->u.class))) || ((trans->assertions & ASSERT_CHAR_CLASS_NEG) && tre_neg_char_classes_match(trans->neg_classes, (tre_cint_t)prev_c, cflags & REG_ICASE)))) { DPRINT((" exact, from %d: assert failed\n", id)); continue; } depth = reach[id].depth; dest_id = trans->state_id; cost = reach[id].costs[depth][TRE_M_COST]; cost0 = reach[id].costs[0][TRE_M_COST]; err = 0; if (trans->code_min > prev_c || trans->code_max < prev_c) { /* Handle substitutes. The required character was not in the string, so match it in place of whatever was supposed to be there and increase costs accordingly. */ err = 1; /* Compute and check cost at current depth. */ cost = reach[id].costs[depth][TRE_M_COST]; if (reach[id].params.cost_subst != TRE_PARAM_UNSET) cost += reach[id].params.cost_subst; if (cost > reach[id].params.max_cost) continue; /* Cost too large. */ /* Check number of substitutes at current depth. */ if (reach[id].costs[depth][TRE_M_NUM_SUBST] + 1 > reach[id].params.max_subst) continue; /* Too many substitutes. */ /* Check total number of errors at current depth. */ if (reach[id].costs[depth][TRE_M_NUM_ERR] + 1 > reach[id].params.max_err) continue; /* Too many errors. */ /* Compute overall cost. */ cost0 = cost; if (depth > 0) { cost0 = reach[id].costs[0][TRE_M_COST]; if (reach[id].params.cost_subst != TRE_PARAM_UNSET) cost0 += reach[id].params.cost_subst; else cost0 += default_params.cost_subst; } DPRINT((" subst, from %03d to %03d, cost %d: ", id, dest_id, cost0)); } else DPRINT((" exact, from %03d to %03d, cost %d: ", id, dest_id, cost0)); /* Compute tag values after this transition. */ for (i = 0; i < num_tags; i++) tmp_tags[i] = reach[id].tags[i]; if (trans->tags) for (i = 0; trans->tags[i] >= 0; i++) if (trans->tags[i] < num_tags) tmp_tags[trans->tags[i]] = pos; /* If another path has also reached this state, choose the one with the smallest cost or best tags if costs are equal. */ if (reach_next[dest_id].pos == pos && (cost0 > reach_next[dest_id].costs[0][TRE_M_COST] || (cost0 == reach_next[dest_id].costs[0][TRE_M_COST] && !tre_tag_order(num_tags, tnfa->tag_directions, tmp_tags, reach_next[dest_id].tags)))) { DPRINT(("lose\n")); continue; } DPRINT(("win %d %d\n", reach_next[dest_id].pos, reach_next[dest_id].costs[0][TRE_M_COST])); /* Set state, position, tags, and depth. */ reach_next[dest_id].state = trans->state; reach_next[dest_id].pos = pos; for (i = 0; i < num_tags; i++) reach_next[dest_id].tags[i] = tmp_tags[i]; reach_next[dest_id].depth = reach[id].depth; /* Set parameters. */ reach_next[dest_id].params = reach[id].params; if (trans->params) tre_set_params(&reach_next[dest_id], trans->params, default_params); /* Set the costs after this transition. */ memcpy(&reach_next[dest_id].costs, reach[id].costs, sizeof(reach[id].costs[0][0]) * TRE_M_LAST * (depth + 1)); reach_next[dest_id].costs[depth][TRE_M_COST] = cost; reach_next[dest_id].costs[depth][TRE_M_NUM_SUBST] += err; reach_next[dest_id].costs[depth][TRE_M_NUM_ERR] += err; if (depth > 0) { reach_next[dest_id].costs[0][TRE_M_COST] = cost0; reach_next[dest_id].costs[0][TRE_M_NUM_SUBST] += err; reach_next[dest_id].costs[0][TRE_M_NUM_ERR] += err; } if (trans->state == tnfa->final && (match_eo < 0 || cost0 < match_costs[TRE_M_COST] || (cost0 == match_costs[TRE_M_COST] && num_tags > 0 && tmp_tags[0] <= match_tags[0]))) { DPRINT((" setting new match at %d, cost %d\n", pos, cost0)); match_eo = pos; for (i = 0; i < TRE_M_LAST; i++) match_costs[i] = reach_next[dest_id].costs[0][i]; for (i = 0; i < num_tags; i++) match_tags[i] = tmp_tags[i]; } } } } DPRINT(("match end offset = %d, match cost = %d\n", match_eo, match_costs[TRE_M_COST])); #ifndef TRE_USE_ALLOCA if (buf) xfree(buf); #endif /* !TRE_USE_ALLOCA */ match->cost = match_costs[TRE_M_COST]; match->num_ins = match_costs[TRE_M_NUM_INS]; match->num_del = match_costs[TRE_M_NUM_DEL]; match->num_subst = match_costs[TRE_M_NUM_SUBST]; *match_end_ofs = match_eo; return match_eo >= 0 ? REG_OK : REG_NOMATCH; } #endif /* TRE_APPROX */ lensfun-0.3.4/libs/regex/tre-match-backtrack.c000066400000000000000000000442111445356770400212270ustar00rootroot00000000000000/* tre-match-backtrack.c - TRE backtracking regex matching engine Copyright (c) 2001-2006 Ville Laurikari . This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This matcher is for regexps that use back referencing. Regexp matching with back referencing is an NP-complete problem on the number of back references. The easiest way to match them is to use a backtracking routine which basically goes through all possible paths in the TNFA and chooses the one which results in the best (leftmost and longest) match. This can be spectacularly expensive and may run out of stack space, but there really is no better known generic algorithm. Quoting Henry Spencer from comp.compilers: POSIX.2 REs require longest match, which is really exciting to implement since the obsolete ("basic") variant also includes \. I haven't found a better way of tackling this than doing a preliminary match using a DFA (or simulation) on a modified RE that just replicates subREs for \, and then doing a backtracking match to determine whether the subRE matches were right. This can be rather slow, but I console myself with the thought that people who use \ deserve very slow execution. (Pun unintentional but very appropriate.) */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #ifdef TRE_USE_ALLOCA /* AIX requires this to be the first thing in the file. */ #ifndef __GNUC__ # if HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif #endif #endif /* TRE_USE_ALLOCA */ #include #include #include #ifdef HAVE_WCHAR_H #include #endif /* HAVE_WCHAR_H */ #ifdef HAVE_WCTYPE_H #include #endif /* HAVE_WCTYPE_H */ #ifndef TRE_WCHAR #include #endif /* !TRE_WCHAR */ #ifdef HAVE_MALLOC_H #include #endif /* HAVE_MALLOC_H */ #include "tre-internal.h" #include "tre-mem.h" #include "tre-match-utils.h" #include "regex.h" #include "xmalloc.h" typedef struct { int pos; const char *str_byte; #ifdef TRE_WCHAR const wchar_t *str_wide; #endif /* TRE_WCHAR */ tre_tnfa_transition_t *state; int state_id; int next_c; int *tags; #ifdef TRE_MBSTATE mbstate_t mbstate; #endif /* TRE_MBSTATE */ } tre_backtrack_item_t; typedef struct tre_backtrack_struct { tre_backtrack_item_t item; struct tre_backtrack_struct *prev; struct tre_backtrack_struct *next; } *tre_backtrack_t; #ifdef TRE_WHAR #define BT_STACK_WIDE_IN stack->item.str_wide = (_str_wide) #define BT_STACK_WIDE_OUT (_str_wide) = stack->item.str_wide #else /* !TRE_WCHAR */ #define BT_STACK_WIDE_IN #define BT_STACK_WIDE_OUT #endif /* !TRE_WCHAR */ #ifdef TRE_MBSTATE #define BT_STACK_MBSTATE_IN stack->item.mbstate = (mbstate) #define BT_STACK_MBSTATE_OUT (mbstate) = stack->item.mbstate #else /* !TRE_MBSTATE */ #define BT_STACK_MBSTATE_IN #define BT_STACK_MBSTATE_OUT #endif /* !TRE_MBSTATE */ #ifdef TRE_USE_ALLOCA #define tre_bt_mem_new tre_mem_newa #define tre_bt_mem_alloc tre_mem_alloca #define tre_bt_mem_destroy(obj) do { } while (0) #else /* !TRE_USE_ALLOCA */ #define tre_bt_mem_new tre_mem_new #define tre_bt_mem_alloc tre_mem_alloc #define tre_bt_mem_destroy tre_mem_destroy #endif /* !TRE_USE_ALLOCA */ #define BT_STACK_PUSH(_pos, _str_byte, _str_wide, _state, _state_id, _next_c, _tags, _mbstate) \ do \ { \ int i; \ if (!stack->next) \ { \ tre_backtrack_t s; \ s = tre_bt_mem_alloc(mem, sizeof(*s)); \ if (!s) \ { \ tre_bt_mem_destroy(mem); \ if (tags) \ xfree(tags); \ if (pmatch) \ xfree(pmatch); \ if (states_seen) \ xfree(states_seen); \ return REG_ESPACE; \ } \ s->prev = stack; \ s->next = NULL; \ s->item.tags = tre_bt_mem_alloc(mem, \ sizeof(*tags) * tnfa->num_tags); \ if (!s->item.tags) \ { \ tre_bt_mem_destroy(mem); \ if (tags) \ xfree(tags); \ if (pmatch) \ xfree(pmatch); \ if (states_seen) \ xfree(states_seen); \ return REG_ESPACE; \ } \ stack->next = s; \ stack = s; \ } \ else \ stack = stack->next; \ stack->item.pos = (_pos); \ stack->item.str_byte = (_str_byte); \ BT_STACK_WIDE_IN; \ stack->item.state = (_state); \ stack->item.state_id = (_state_id); \ stack->item.next_c = (_next_c); \ for (i = 0; i < tnfa->num_tags; i++) \ stack->item.tags[i] = (_tags)[i]; \ BT_STACK_MBSTATE_IN; \ } \ while (0) #define BT_STACK_POP() \ do \ { \ int i; \ assert(stack->prev); \ pos = stack->item.pos; \ str_byte = stack->item.str_byte; \ BT_STACK_WIDE_OUT; \ state = stack->item.state; \ next_c = stack->item.next_c; \ for (i = 0; i < tnfa->num_tags; i++) \ tags[i] = stack->item.tags[i]; \ BT_STACK_MBSTATE_OUT; \ stack = stack->prev; \ } \ while (0) #undef MIN #define MIN(a, b) ((a) <= (b) ? (a) : (b)) reg_errcode_t tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, int len, tre_str_type_t type, int *match_tags, int eflags, int *match_end_ofs) { /* State variables required by GET_NEXT_WCHAR. */ tre_char_t prev_c = 0, next_c = 0; const char *str_byte = string; int pos = 0; unsigned int pos_add_next = 1; #ifdef TRE_WCHAR const wchar_t *str_wide = string; #ifdef TRE_MBSTATE mbstate_t mbstate; #endif /* TRE_MBSTATE */ #endif /* TRE_WCHAR */ int reg_notbol = eflags & REG_NOTBOL; int reg_noteol = eflags & REG_NOTEOL; int reg_newline = tnfa->cflags & REG_NEWLINE; int str_user_end = 0; /* These are used to remember the necessary values of the above variables to return to the position where the current search started from. */ int next_c_start; const char *str_byte_start; int pos_start = -1; #ifdef TRE_WCHAR const wchar_t *str_wide_start; #endif /* TRE_WCHAR */ #ifdef TRE_MBSTATE mbstate_t mbstate_start; #endif /* TRE_MBSTATE */ /* Compilation flags for this regexp. */ int cflags = tnfa->cflags; /* End offset of best match so far, or -1 if no match found yet. */ int match_eo = -1; /* Tag arrays. */ int *next_tags, *tags = NULL; /* Current TNFA state. */ tre_tnfa_transition_t *state; int *states_seen = NULL; /* Memory allocator to for allocating the backtracking stack. */ tre_mem_t mem = tre_bt_mem_new(); /* The backtracking stack. */ tre_backtrack_t stack; tre_tnfa_transition_t *trans_i; regmatch_t *pmatch = NULL; int ret; #ifdef TRE_MBSTATE memset(&mbstate, '\0', sizeof(mbstate)); #endif /* TRE_MBSTATE */ if (!mem) return REG_ESPACE; stack = tre_bt_mem_alloc(mem, sizeof(*stack)); if (!stack) { ret = REG_ESPACE; goto error_exit; } stack->prev = NULL; stack->next = NULL; DPRINT(("tnfa_execute_backtrack, input type %d\n", type)); DPRINT(("len = %d\n", len)); #ifdef TRE_USE_ALLOCA tags = alloca(sizeof(*tags) * tnfa->num_tags); pmatch = alloca(sizeof(*pmatch) * tnfa->num_submatches); states_seen = alloca(sizeof(*states_seen) * tnfa->num_states); #else /* !TRE_USE_ALLOCA */ if (tnfa->num_tags) { tags = xmalloc(sizeof(*tags) * tnfa->num_tags); if (!tags) { ret = REG_ESPACE; goto error_exit; } } if (tnfa->num_submatches) { pmatch = xmalloc(sizeof(*pmatch) * tnfa->num_submatches); if (!pmatch) { ret = REG_ESPACE; goto error_exit; } } if (tnfa->num_states) { states_seen = xmalloc(sizeof(*states_seen) * tnfa->num_states); if (!states_seen) { ret = REG_ESPACE; goto error_exit; } } #endif /* !TRE_USE_ALLOCA */ retry: { int i; for (i = 0; i < tnfa->num_tags; i++) { tags[i] = -1; if (match_tags) match_tags[i] = -1; } for (i = 0; i < tnfa->num_states; i++) states_seen[i] = 0; } state = NULL; pos = pos_start; if (type == STR_USER) str_source->rewind(pos + pos_add_next, str_source->context); GET_NEXT_WCHAR(); pos_start = pos; next_c_start = next_c; str_byte_start = str_byte; #ifdef TRE_WCHAR str_wide_start = str_wide; #endif /* TRE_WCHAR */ #ifdef TRE_MBSTATE mbstate_start = mbstate; #endif /* TRE_MBSTATE */ /* Handle initial states. */ next_tags = NULL; for (trans_i = tnfa->initial; trans_i->state; trans_i++) { DPRINT(("> init %p, prev_c %lc\n", trans_i->state, (tre_cint_t)prev_c)); if (trans_i->assertions && CHECK_ASSERTIONS(trans_i->assertions)) { DPRINT(("assert failed\n")); continue; } if (state == NULL) { /* Start from this state. */ state = trans_i->state; next_tags = trans_i->tags; } else { /* Backtrack to this state. */ DPRINT(("saving state %d for backtracking\n", trans_i->state_id)); BT_STACK_PUSH(pos, str_byte, str_wide, trans_i->state, trans_i->state_id, next_c, tags, mbstate); { int *tmp = trans_i->tags; if (tmp) while (*tmp >= 0) stack->item.tags[*tmp++] = pos; } } } if (next_tags) for (; *next_tags >= 0; next_tags++) tags[*next_tags] = pos; DPRINT(("entering match loop, pos %d, str_byte %p\n", pos, str_byte)); DPRINT(("pos:chr/code | state and tags\n")); DPRINT(("-------------+------------------------------------------------\n")); if (state == NULL) goto backtrack; while (1) { tre_tnfa_transition_t *trans_i, *next_state; int empty_br_match; DPRINT(("start loop\n")); if (state == tnfa->final) { DPRINT((" match found, %d %d\n", match_eo, pos)); if (match_eo < pos || (match_eo == pos && match_tags && tre_tag_order(tnfa->num_tags, tnfa->tag_directions, tags, match_tags))) { int i; /* This match wins the previous match. */ DPRINT((" win previous\n")); match_eo = pos; if (match_tags) for (i = 0; i < tnfa->num_tags; i++) match_tags[i] = tags[i]; } /* Our TNFAs never have transitions leaving from the final state, so we jump right to backtracking. */ goto backtrack; } #ifdef TRE_DEBUG DPRINT(("%3d:%2lc/%05d | %p ", pos, (tre_cint_t)next_c, (int)next_c, state)); { int i; for (i = 0; i < tnfa->num_tags; i++) DPRINT(("%d%s", tags[i], i < tnfa->num_tags - 1 ? ", " : "")); DPRINT(("\n")); } #endif /* TRE_DEBUG */ /* Go to the next character in the input string. */ empty_br_match = 0; trans_i = state; if (trans_i->state && trans_i->assertions & ASSERT_BACKREF) { /* This is a back reference state. All transitions leaving from this state have the same back reference "assertion". Instead of reading the next character, we match the back reference. */ int so, eo, bt = trans_i->u.backref; int bt_len; int result; DPRINT((" should match back reference %d\n", bt)); /* Get the substring we need to match against. Remember to turn off REG_NOSUB temporarily. */ tre_fill_pmatch(bt + 1, pmatch, tnfa->cflags & !REG_NOSUB, tnfa, tags, pos); so = pmatch[bt].rm_so; eo = pmatch[bt].rm_eo; bt_len = eo - so; #ifdef TRE_DEBUG { int slen; if (len < 0) slen = bt_len; else slen = MIN(bt_len, len - pos); if (type == STR_BYTE) { DPRINT((" substring (len %d) is [%d, %d[: '%.*s'\n", bt_len, so, eo, bt_len, (char*)string + so)); DPRINT((" current string is '%.*s'\n", slen, str_byte - 1)); } #ifdef TRE_WCHAR else if (type == STR_WIDE) { DPRINT((" substring (len %d) is [%d, %d[: '%.*" STRF "'\n", bt_len, so, eo, bt_len, (wchar_t*)string + so)); DPRINT((" current string is '%.*" STRF "'\n", slen, str_wide - 1)); } #endif /* TRE_WCHAR */ } #endif if (len < 0) { if (type == STR_USER) result = str_source->compare(so, pos, bt_len, str_source->context); #ifdef TRE_WCHAR else if (type == STR_WIDE) result = wcsncmp((wchar_t*)string + so, str_wide - 1, bt_len); #endif /* TRE_WCHAR */ else result = strncmp((char*)string + so, str_byte - 1, bt_len); } else if (len - pos < bt_len) result = 1; else /* We can ignore multibyte characters here because the backref string is already aligned at character boundaries. */ result = memcmp((char*)string + so, str_byte - 1, bt_len); if (result == 0) { /* Back reference matched. Check for infinite loop. */ if (bt_len == 0) empty_br_match = 1; if (empty_br_match && states_seen[trans_i->state_id]) { DPRINT((" avoid loop\n")); goto backtrack; } states_seen[trans_i->state_id] = empty_br_match; /* Advance in input string and resync `prev_c', `next_c' and pos. */ DPRINT((" back reference matched\n")); str_byte += bt_len - 1; pos += bt_len - 1; GET_NEXT_WCHAR(); DPRINT((" pos now %d\n", pos)); } else { DPRINT((" back reference did not match\n")); goto backtrack; } } else { /* Check for end of string. */ if (len < 0) { if (type == STR_USER) { if (str_user_end) goto backtrack; } else if (next_c == L'\0') goto backtrack; } else { if (pos >= len) goto backtrack; } /* Read the next character. */ GET_NEXT_WCHAR(); } next_state = NULL; for (trans_i = state; trans_i->state; trans_i++) { DPRINT((" transition %d-%d (%c-%c) %d to %d\n", trans_i->code_min, trans_i->code_max, trans_i->code_min, trans_i->code_max, trans_i->assertions, trans_i->state_id)); if (trans_i->code_min <= prev_c && trans_i->code_max >= prev_c) { if (trans_i->assertions && (CHECK_ASSERTIONS(trans_i->assertions) /* Handle character class transitions. */ || ((trans_i->assertions & ASSERT_CHAR_CLASS) && !(cflags & REG_ICASE) && !tre_isctype((tre_cint_t)prev_c, trans_i->u.class)) || ((trans_i->assertions & ASSERT_CHAR_CLASS) && (cflags & REG_ICASE) && (!tre_isctype(tre_tolower((tre_cint_t)prev_c), trans_i->u.class) && !tre_isctype(tre_toupper((tre_cint_t)prev_c), trans_i->u.class))) || ((trans_i->assertions & ASSERT_CHAR_CLASS_NEG) && tre_neg_char_classes_match(trans_i->neg_classes, (tre_cint_t)prev_c, cflags & REG_ICASE)))) { DPRINT((" assertion failed\n")); continue; } if (next_state == NULL) { /* First matching transition. */ DPRINT((" Next state is %d\n", trans_i->state_id)); next_state = trans_i->state; next_tags = trans_i->tags; } else { /* Second matching transition. We may need to backtrack here to take this transition instead of the first one, so we push this transition in the backtracking stack so we can jump back here if needed. */ DPRINT((" saving state %d for backtracking\n", trans_i->state_id)); BT_STACK_PUSH(pos, str_byte, str_wide, trans_i->state, trans_i->state_id, next_c, tags, mbstate); { int *tmp; for (tmp = trans_i->tags; tmp && *tmp >= 0; tmp++) stack->item.tags[*tmp] = pos; } #if 0 /* XXX - it's important not to look at all transitions here to keep the stack small! */ break; #endif } } } if (next_state != NULL) { /* Matching transitions were found. Take the first one. */ state = next_state; /* Update the tag values. */ if (next_tags) while (*next_tags >= 0) tags[*next_tags++] = pos; } else { backtrack: /* A matching transition was not found. Try to backtrack. */ if (stack->prev) { DPRINT((" backtracking\n")); if (stack->item.state->assertions && ASSERT_BACKREF) { DPRINT((" states_seen[%d] = 0\n", stack->item.state_id)); states_seen[stack->item.state_id] = 0; } BT_STACK_POP(); } else if (match_eo < 0) { /* Try starting from a later position in the input string. */ /* Check for end of string. */ if (len < 0) { if (next_c == L'\0') { DPRINT(("end of string.\n")); break; } } else { if (pos >= len) { DPRINT(("end of string.\n")); break; } } DPRINT(("restarting from next start position\n")); next_c = next_c_start; #ifdef TRE_MBSTATE mbstate = mbstate_start; #endif /* TRE_MBSTATE */ str_byte = str_byte_start; #ifdef TRE_WCHAR str_wide = str_wide_start; #endif /* TRE_WCHAR */ goto retry; } else { DPRINT(("finished\n")); break; } } } ret = match_eo >= 0 ? REG_OK : REG_NOMATCH; *match_end_ofs = match_eo; error_exit: tre_bt_mem_destroy(mem); #ifndef TRE_USE_ALLOCA if (tags) xfree(tags); if (pmatch) xfree(pmatch); if (states_seen) xfree(states_seen); #endif /* !TRE_USE_ALLOCA */ return ret; } lensfun-0.3.4/libs/regex/tre-match-parallel.c000066400000000000000000000334501445356770400211010ustar00rootroot00000000000000/* tre-match-parallel.c - TRE parallel regex matching engine Copyright (c) 2001-2006 Ville Laurikari . This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This algorithm searches for matches basically by reading characters in the searched string one by one, starting at the beginning. All matching paths in the TNFA are traversed in parallel. When two or more paths reach the same state, exactly one is chosen according to tag ordering rules; if returning submatches is not required it does not matter which path is chosen. The worst case time required for finding the leftmost and longest match, or determining that there is no match, is always linearly dependent on the length of the text being searched. This algorithm cannot handle TNFAs with back referencing nodes. See `tre-match-backtrack.c'. */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #ifdef TRE_USE_ALLOCA /* AIX requires this to be the first thing in the file. */ #ifndef __GNUC__ # if HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif #endif #endif /* TRE_USE_ALLOCA */ #include #include #include #ifdef HAVE_WCHAR_H #include #endif /* HAVE_WCHAR_H */ #ifdef HAVE_WCTYPE_H #include #endif /* HAVE_WCTYPE_H */ #ifndef TRE_WCHAR #include #endif /* !TRE_WCHAR */ #ifdef HAVE_MALLOC_H #include #endif /* HAVE_MALLOC_H */ #include "tre-internal.h" #include "tre-match-utils.h" #include "regex.h" #include "xmalloc.h" typedef struct { tre_tnfa_transition_t *state; int *tags; } tre_tnfa_reach_t; typedef struct { int pos; int **tags; } tre_reach_pos_t; #ifdef TRE_DEBUG static void tre_print_reach(const tre_tnfa_t *tnfa, tre_tnfa_reach_t *reach, int num_tags) { int i; while (reach->state != NULL) { DPRINT((" %p", (void *)reach->state)); if (num_tags > 0) { DPRINT(("/")); for (i = 0; i < num_tags; i++) { DPRINT(("%d:%d", i, reach->tags[i])); if (i < (num_tags-1)) DPRINT((",")); } } reach++; } DPRINT(("\n")); } #endif /* TRE_DEBUG */ reg_errcode_t tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len, tre_str_type_t type, int *match_tags, int eflags, int *match_end_ofs) { /* State variables required by GET_NEXT_WCHAR. */ tre_char_t prev_c = 0, next_c = 0; const char *str_byte = string; int pos = -1; unsigned int pos_add_next = 1; #ifdef TRE_WCHAR const wchar_t *str_wide = string; #ifdef TRE_MBSTATE mbstate_t mbstate; #endif /* TRE_MBSTATE */ #endif /* TRE_WCHAR */ int reg_notbol = eflags & REG_NOTBOL; int reg_noteol = eflags & REG_NOTEOL; int reg_newline = tnfa->cflags & REG_NEWLINE; int str_user_end = 0; char *buf; tre_tnfa_transition_t *trans_i; tre_tnfa_reach_t *reach, *reach_next, *reach_i, *reach_next_i; tre_reach_pos_t *reach_pos; int *tag_i; int num_tags, i; int match_eo = -1; /* end offset of match (-1 if no match found yet) */ int new_match = 0; int *tmp_tags = NULL; int *tmp_iptr; #ifdef TRE_MBSTATE memset(&mbstate, '\0', sizeof(mbstate)); #endif /* TRE_MBSTATE */ DPRINT(("tre_tnfa_run_parallel, input type %d\n", type)); if (!match_tags) num_tags = 0; else num_tags = tnfa->num_tags; /* Allocate memory for temporary data required for matching. This needs to be done for every matching operation to be thread safe. This allocates everything in a single large block from the stack frame using alloca() or with malloc() if alloca is unavailable. */ { int tbytes, rbytes, pbytes, xbytes, total_bytes; char *tmp_buf; /* Compute the length of the block we need. */ tbytes = sizeof(*tmp_tags) * num_tags; rbytes = sizeof(*reach_next) * (tnfa->num_states + 1); pbytes = sizeof(*reach_pos) * tnfa->num_states; xbytes = sizeof(int) * num_tags; total_bytes = (sizeof(long) - 1) * 4 /* for alignment paddings */ + (rbytes + xbytes * tnfa->num_states) * 2 + tbytes + pbytes; /* Allocate the memory. */ #ifdef TRE_USE_ALLOCA buf = alloca(total_bytes); #else /* !TRE_USE_ALLOCA */ buf = xmalloc(total_bytes); #endif /* !TRE_USE_ALLOCA */ if (buf == NULL) return REG_ESPACE; memset(buf, 0, total_bytes); /* Get the various pointers within tmp_buf (properly aligned). */ tmp_tags = (void *)buf; tmp_buf = buf + tbytes; tmp_buf += ALIGN(tmp_buf, long); reach_next = (void *)tmp_buf; tmp_buf += rbytes; tmp_buf += ALIGN(tmp_buf, long); reach = (void *)tmp_buf; tmp_buf += rbytes; tmp_buf += ALIGN(tmp_buf, long); reach_pos = (void *)tmp_buf; tmp_buf += pbytes; tmp_buf += ALIGN(tmp_buf, long); for (i = 0; i < tnfa->num_states; i++) { reach[i].tags = (void *)tmp_buf; tmp_buf += xbytes; reach_next[i].tags = (void *)tmp_buf; tmp_buf += xbytes; } } for (i = 0; i < tnfa->num_states; i++) reach_pos[i].pos = -1; /* If only one character can start a match, find it first. */ if (tnfa->first_char >= 0 && type == STR_BYTE && str_byte) { const char *orig_str = str_byte; int first = tnfa->first_char; if (len >= 0) str_byte = memchr(orig_str, first, len); else str_byte = strchr(orig_str, first); if (str_byte == NULL) { #ifndef TRE_USE_ALLOCA if (buf) xfree(buf); #endif /* !TRE_USE_ALLOCA */ return REG_NOMATCH; } DPRINT(("skipped %lu chars\n", (unsigned long)(str_byte - orig_str))); if (str_byte >= orig_str + 1) prev_c = (unsigned char)*(str_byte - 1); next_c = (unsigned char)*str_byte; pos = str_byte - orig_str; if (len < 0 || pos < len) str_byte++; } else { GET_NEXT_WCHAR(); pos = 0; } #if 0 /* Skip over characters that cannot possibly be the first character of a match. */ if (tnfa->firstpos_chars != NULL) { char *chars = tnfa->firstpos_chars; if (len < 0) { const char *orig_str = str_byte; /* XXX - use strpbrk() and wcspbrk() because they might be optimized for the target architecture. Try also strcspn() and wcscspn() and compare the speeds. */ while (next_c != L'\0' && !chars[next_c]) { next_c = *str_byte++; } prev_c = *(str_byte - 2); pos += str_byte - orig_str; DPRINT(("skipped %d chars\n", str_byte - orig_str)); } else { while (pos <= len && !chars[next_c]) { prev_c = next_c; next_c = (unsigned char)(*str_byte++); pos++; } } } #endif DPRINT(("length: %d\n", len)); DPRINT(("pos:chr/code | states and tags\n")); DPRINT(("-------------+------------------------------------------------\n")); reach_next_i = reach_next; while (1) { /* If no match found yet, add the initial states to `reach_next'. */ if (match_eo < 0) { DPRINT((" init >")); trans_i = tnfa->initial; while (trans_i->state != NULL) { if (reach_pos[trans_i->state_id].pos < pos) { if (trans_i->assertions && CHECK_ASSERTIONS(trans_i->assertions)) { DPRINT(("assertion failed\n")); trans_i++; continue; } DPRINT((" %p", (void *)trans_i->state)); reach_next_i->state = trans_i->state; for (i = 0; i < num_tags; i++) reach_next_i->tags[i] = -1; tag_i = trans_i->tags; if (tag_i) while (*tag_i >= 0) { if (*tag_i < num_tags) reach_next_i->tags[*tag_i] = pos; tag_i++; } if (reach_next_i->state == tnfa->final) { DPRINT((" found empty match\n")); match_eo = pos; new_match = 1; for (i = 0; i < num_tags; i++) match_tags[i] = reach_next_i->tags[i]; } reach_pos[trans_i->state_id].pos = pos; reach_pos[trans_i->state_id].tags = &reach_next_i->tags; reach_next_i++; } trans_i++; } DPRINT(("\n")); reach_next_i->state = NULL; } else { if (num_tags == 0 || reach_next_i == reach_next) /*We have found a match. */ break; } /* Check for end of string. */ if (len < 0) { if (type == STR_USER) { if (str_user_end) break; } else if (next_c == L'\0') break; } else { if (pos >= len) break; } GET_NEXT_WCHAR(); #ifdef TRE_DEBUG DPRINT(("%3d:%2lc/%05d |", pos - 1, (tre_cint_t)prev_c, (int)prev_c)); tre_print_reach(tnfa, reach_next, num_tags); DPRINT(("%3d:%2lc/%05d |", pos, (tre_cint_t)next_c, (int)next_c)); tre_print_reach(tnfa, reach_next, num_tags); #endif /* TRE_DEBUG */ /* Swap `reach' and `reach_next'. */ reach_i = reach; reach = reach_next; reach_next = reach_i; /* For each state in `reach', weed out states that don't fulfill the minimal matching conditions. */ if (tnfa->num_minimals && new_match) { new_match = 0; reach_next_i = reach_next; for (reach_i = reach; reach_i->state; reach_i++) { int i; int skip = 0; for (i = 0; tnfa->minimal_tags[i] >= 0; i += 2) { int end = tnfa->minimal_tags[i]; int start = tnfa->minimal_tags[i + 1]; DPRINT((" Minimal start %d, end %d\n", start, end)); if (end >= num_tags) { DPRINT((" Throwing %p out.\n", reach_i->state)); skip = 1; break; } else if (reach_i->tags[start] == match_tags[start] && reach_i->tags[end] < match_tags[end]) { DPRINT((" Throwing %p out because t%d < %d\n", reach_i->state, end, match_tags[end])); skip = 1; break; } } if (!skip) { int *tmp_iptr; reach_next_i->state = reach_i->state; tmp_iptr = reach_next_i->tags; reach_next_i->tags = reach_i->tags; reach_i->tags = tmp_iptr; reach_next_i++; } } reach_next_i->state = NULL; /* Swap `reach' and `reach_next'. */ reach_i = reach; reach = reach_next; reach_next = reach_i; } /* For each state in `reach' see if there is a transition leaving with the current input symbol to a state not yet in `reach_next', and add the destination states to `reach_next'. */ reach_next_i = reach_next; for (reach_i = reach; reach_i->state; reach_i++) { for (trans_i = reach_i->state; trans_i->state; trans_i++) { /* Does this transition match the input symbol? */ if (trans_i->code_min <= prev_c && trans_i->code_max >= prev_c) { if (trans_i->assertions && (CHECK_ASSERTIONS(trans_i->assertions) /* Handle character class transitions. */ || ((trans_i->assertions & ASSERT_CHAR_CLASS) && !(tnfa->cflags & REG_ICASE) && !tre_isctype((tre_cint_t)prev_c, trans_i->u.class)) || ((trans_i->assertions & ASSERT_CHAR_CLASS) && (tnfa->cflags & REG_ICASE) && (!tre_isctype(tre_tolower((tre_cint_t)prev_c), trans_i->u.class) && !tre_isctype(tre_toupper((tre_cint_t)prev_c), trans_i->u.class))) || ((trans_i->assertions & ASSERT_CHAR_CLASS_NEG) && tre_neg_char_classes_match(trans_i->neg_classes, (tre_cint_t)prev_c, tnfa->cflags & REG_ICASE)))) { DPRINT(("assertion failed\n")); continue; } /* Compute the tags after this transition. */ for (i = 0; i < num_tags; i++) tmp_tags[i] = reach_i->tags[i]; tag_i = trans_i->tags; if (tag_i != NULL) while (*tag_i >= 0) { if (*tag_i < num_tags) tmp_tags[*tag_i] = pos; tag_i++; } if (reach_pos[trans_i->state_id].pos < pos) { /* Found an unvisited node. */ reach_next_i->state = trans_i->state; tmp_iptr = reach_next_i->tags; reach_next_i->tags = tmp_tags; tmp_tags = tmp_iptr; reach_pos[trans_i->state_id].pos = pos; reach_pos[trans_i->state_id].tags = &reach_next_i->tags; if (reach_next_i->state == tnfa->final && (match_eo == -1 || (num_tags > 0 && reach_next_i->tags[0] <= match_tags[0]))) { DPRINT((" found match %p\n", trans_i->state)); match_eo = pos; new_match = 1; for (i = 0; i < num_tags; i++) match_tags[i] = reach_next_i->tags[i]; } reach_next_i++; } else { assert(reach_pos[trans_i->state_id].pos == pos); /* Another path has also reached this state. We choose the winner by examining the tag values for both paths. */ if (tre_tag_order(num_tags, tnfa->tag_directions, tmp_tags, *reach_pos[trans_i->state_id].tags)) { /* The new path wins. */ tmp_iptr = *reach_pos[trans_i->state_id].tags; *reach_pos[trans_i->state_id].tags = tmp_tags; if (trans_i->state == tnfa->final) { DPRINT((" found better match\n")); match_eo = pos; new_match = 1; for (i = 0; i < num_tags; i++) match_tags[i] = tmp_tags[i]; } tmp_tags = tmp_iptr; } } } } } reach_next_i->state = NULL; } DPRINT(("match end offset = %d\n", match_eo)); #ifndef TRE_USE_ALLOCA if (buf) xfree(buf); #endif /* !TRE_USE_ALLOCA */ *match_end_ofs = match_eo; return match_eo >= 0 ? REG_OK : REG_NOMATCH; } /* EOF */ lensfun-0.3.4/libs/regex/tre-match-utils.h000066400000000000000000000146541445356770400204570ustar00rootroot00000000000000/* tre-match-utils.h - TRE matcher helper definitions Copyright (c) 2001-2006 Ville Laurikari . This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define str_source ((tre_str_source*)string) #ifdef TRE_WCHAR #ifdef TRE_MULTIBYTE /* Wide character and multibyte support. */ #define GET_NEXT_WCHAR() \ do { \ prev_c = next_c; \ if (type == STR_BYTE) \ { \ pos++; \ if (len >= 0 && pos >= len) \ next_c = '\0'; \ else \ next_c = (unsigned char)(*str_byte++); \ } \ else if (type == STR_WIDE) \ { \ pos++; \ if (len >= 0 && pos >= len) \ next_c = L'\0'; \ else \ next_c = *str_wide++; \ } \ else if (type == STR_MBS) \ { \ pos += pos_add_next; \ if (str_byte == NULL) \ next_c = L'\0'; \ else \ { \ size_t w; \ int max; \ if (len >= 0) \ max = len - pos; \ else \ max = 32; \ if (max <= 0) \ { \ next_c = L'\0'; \ pos_add_next = 1; \ } \ else \ { \ w = tre_mbrtowc(&next_c, str_byte, max, &mbstate); \ if (w == (size_t)-1 || w == (size_t)-2) \ return REG_NOMATCH; \ if (w == 0 && len >= 0) \ { \ pos_add_next = 1; \ next_c = 0; \ str_byte++; \ } \ else \ { \ pos_add_next = w; \ str_byte += w; \ } \ } \ } \ } \ else if (type == STR_USER) \ { \ pos += pos_add_next; \ str_user_end = str_source->get_next_char(&next_c, &pos_add_next, \ str_source->context); \ } \ } while(0) #else /* !TRE_MULTIBYTE */ /* Wide character support, no multibyte support. */ #define GET_NEXT_WCHAR() \ do { \ prev_c = next_c; \ if (type == STR_BYTE) \ { \ pos++; \ if (len >= 0 && pos >= len) \ next_c = '\0'; \ else \ next_c = (unsigned char)(*str_byte++); \ } \ else if (type == STR_WIDE) \ { \ pos++; \ if (len >= 0 && pos >= len) \ next_c = L'\0'; \ else \ next_c = *str_wide++; \ } \ else if (type == STR_USER) \ { \ pos += pos_add_next; \ str_user_end = str_source->get_next_char(&next_c, &pos_add_next, \ str_source->context); \ } \ } while(0) #endif /* !TRE_MULTIBYTE */ #else /* !TRE_WCHAR */ /* No wide character or multibyte support. */ #define GET_NEXT_WCHAR() \ do { \ prev_c = next_c; \ if (type == STR_BYTE) \ { \ pos++; \ if (len >= 0 && pos >= len) \ next_c = '\0'; \ else \ next_c = (unsigned char)(*str_byte++); \ } \ else if (type == STR_USER) \ { \ pos += pos_add_next; \ str_user_end = str_source->get_next_char(&next_c, &pos_add_next, \ str_source->context); \ } \ } while(0) #endif /* !TRE_WCHAR */ #define IS_WORD_CHAR(c) ((c) == L'_' || tre_isalnum(c)) #define CHECK_ASSERTIONS(assertions) \ (((assertions & ASSERT_AT_BOL) \ && (pos > 0 || reg_notbol) \ && (prev_c != L'\n' || !reg_newline)) \ || ((assertions & ASSERT_AT_EOL) \ && (next_c != L'\0' || reg_noteol) \ && (next_c != L'\n' || !reg_newline)) \ || ((assertions & ASSERT_AT_BOW) \ && (pos > 0 && (IS_WORD_CHAR(prev_c) || !IS_WORD_CHAR(next_c)))) \ || ((assertions & ASSERT_AT_EOW) \ && (!IS_WORD_CHAR(prev_c) || IS_WORD_CHAR(next_c))) \ || ((assertions & ASSERT_AT_WB) \ && (pos != 0 && next_c != L'\0' \ && IS_WORD_CHAR(prev_c) == IS_WORD_CHAR(next_c))) \ || ((assertions & ASSERT_AT_WB_NEG) \ && (pos == 0 || next_c == L'\0' \ || IS_WORD_CHAR(prev_c) != IS_WORD_CHAR(next_c)))) /* Returns 1 if `t1' wins `t2', 0 otherwise. */ static int tre_tag_order(int num_tags, tre_tag_direction_t *tag_directions, int *t1, int *t2) { int i; for (i = 0; i < num_tags; i++) { if (tag_directions[i] == TRE_TAG_MINIMIZE) { if (t1[i] < t2[i]) return 1; if (t1[i] > t2[i]) return 0; } else { if (t1[i] > t2[i]) return 1; if (t1[i] < t2[i]) return 0; } } /* assert(0);*/ return 0; } static int tre_neg_char_classes_match(tre_ctype_t *classes, tre_cint_t wc, int icase) { DPRINT(("neg_char_classes_test: %p, %d, %d\n", classes, wc, icase)); while (*classes != (tre_ctype_t)0) if ((!icase && tre_isctype(wc, *classes)) || (icase && (tre_isctype(tre_toupper(wc), *classes) || tre_isctype(tre_tolower(wc), *classes)))) return 1; /* Match. */ else classes++; return 0; /* No match. */ } lensfun-0.3.4/libs/regex/tre-mem.c000066400000000000000000000074221445356770400167710ustar00rootroot00000000000000/* tre-mem.c - TRE memory allocator Copyright (c) 2001-2006 Ville Laurikari This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This memory allocator is for allocating small memory blocks efficiently in terms of memory overhead and execution speed. The allocated blocks cannot be freed individually, only all at once. There can be multiple allocators, though. */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #include #include #include "tre-internal.h" #include "tre-mem.h" #include "xmalloc.h" /* Returns a new memory allocator or NULL if out of memory. */ tre_mem_t tre_mem_new_impl(int provided, void *provided_block) { tre_mem_t mem; if (provided) { mem = provided_block; memset(mem, 0, sizeof(*mem)); } else mem = xcalloc(1, sizeof(*mem)); if (mem == NULL) return NULL; return mem; } /* Frees the memory allocator and all memory allocated with it. */ void tre_mem_destroy(tre_mem_t mem) { tre_list_t *tmp, *l = mem->blocks; while (l != NULL) { xfree(l->data); tmp = l->next; xfree(l); l = tmp; } xfree(mem); } /* Allocates a block of `size' bytes from `mem'. Returns a pointer to the allocated block or NULL if an underlying malloc() failed. */ void * tre_mem_alloc_impl(tre_mem_t mem, int provided, void *provided_block, int zero, size_t size) { void *ptr; if (mem->failed) { DPRINT(("tre_mem_alloc: oops, called after failure?!\n")); return NULL; } #ifdef MALLOC_DEBUGGING if (!provided) { ptr = xmalloc(1); if (ptr == NULL) { DPRINT(("tre_mem_alloc: xmalloc forced failure\n")); mem->failed = 1; return NULL; } xfree(ptr); } #endif /* MALLOC_DEBUGGING */ if (mem->n < size) { /* We need more memory than is available in the current block. Allocate a new block. */ tre_list_t *l; if (provided) { DPRINT(("tre_mem_alloc: using provided block\n")); if (provided_block == NULL) { DPRINT(("tre_mem_alloc: provided block was NULL\n")); mem->failed = 1; return NULL; } mem->ptr = provided_block; mem->n = TRE_MEM_BLOCK_SIZE; } else { int block_size; if (size * 8 > TRE_MEM_BLOCK_SIZE) block_size = size * 8; else block_size = TRE_MEM_BLOCK_SIZE; DPRINT(("tre_mem_alloc: allocating new %d byte block\n", block_size)); l = xmalloc(sizeof(*l)); if (l == NULL) { mem->failed = 1; return NULL; } l->data = xmalloc(block_size); if (l->data == NULL) { xfree(l); mem->failed = 1; return NULL; } l->next = NULL; if (mem->current != NULL) mem->current->next = l; if (mem->blocks == NULL) mem->blocks = l; mem->current = l; mem->ptr = l->data; mem->n = block_size; } } /* Make sure the next pointer will be aligned. */ size += ALIGN(mem->ptr + size, long); /* Allocate from current block. */ ptr = mem->ptr; mem->ptr += size; mem->n -= size; /* Set to zero if needed. */ if (zero) memset(ptr, 0, size); return ptr; } /* EOF */ lensfun-0.3.4/libs/regex/tre-mem.h000066400000000000000000000046771445356770400170070ustar00rootroot00000000000000/* tre-mem.h - TRE memory allocator interface Copyright (c) 2001-2006 Ville Laurikari This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TRE_MEM_H #define TRE_MEM_H 1 #include #define TRE_MEM_BLOCK_SIZE 1024 typedef struct tre_list { void *data; struct tre_list *next; } tre_list_t; typedef struct tre_mem_struct { tre_list_t *blocks; tre_list_t *current; char *ptr; size_t n; int failed; void **provided; } *tre_mem_t; tre_mem_t tre_mem_new_impl(int provided, void *provided_block); void *tre_mem_alloc_impl(tre_mem_t mem, int provided, void *provided_block, int zero, size_t size); /* Returns a new memory allocator or NULL if out of memory. */ #define tre_mem_new() tre_mem_new_impl(0, NULL) /* Allocates a block of `size' bytes from `mem'. Returns a pointer to the allocated block or NULL if an underlying malloc() failed. */ #define tre_mem_alloc(mem, size) tre_mem_alloc_impl(mem, 0, NULL, 0, size) /* Allocates a block of `size' bytes from `mem'. Returns a pointer to the allocated block or NULL if an underlying malloc() failed. The memory is set to zero. */ #define tre_mem_calloc(mem, size) tre_mem_alloc_impl(mem, 0, NULL, 1, size) #ifdef TRE_USE_ALLOCA /* alloca() versions. Like above, but memory is allocated with alloca() instead of malloc(). */ #define tre_mem_newa() \ tre_mem_new_impl(1, alloca(sizeof(struct tre_mem_struct))) #define tre_mem_alloca(mem, size) \ ((mem)->n >= (size) \ ? tre_mem_alloc_impl((mem), 1, NULL, 0, (size)) \ : tre_mem_alloc_impl((mem), 1, alloca(TRE_MEM_BLOCK_SIZE), 0, (size))) #endif /* TRE_USE_ALLOCA */ /* Frees the memory allocator and all memory allocated with it. */ void tre_mem_destroy(tre_mem_t mem); #endif /* TRE_MEM_H */ /* EOF */ lensfun-0.3.4/libs/regex/tre-parse.c000066400000000000000000001304411445356770400173230ustar00rootroot00000000000000/* tre-parse.c - Regexp parser Copyright (c) 2001-2006 Ville Laurikari This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This parser is just a simple recursive descent parser for POSIX.2 regexps. The parser supports both the obsolete default syntax and the "extended" syntax, and some nonstandard extensions. */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #include #include #include #include "xmalloc.h" #include "tre-mem.h" #include "tre-ast.h" #include "tre-stack.h" #include "tre-parse.h" /* Characters with special meanings in regexp syntax. */ #define CHAR_PIPE L'|' #define CHAR_LPAREN L'(' #define CHAR_RPAREN L')' #define CHAR_LBRACE L'{' #define CHAR_RBRACE L'}' #define CHAR_LBRACKET L'[' #define CHAR_RBRACKET L']' #define CHAR_MINUS L'-' #define CHAR_STAR L'*' #define CHAR_QUESTIONMARK L'?' #define CHAR_PLUS L'+' #define CHAR_PERIOD L'.' #define CHAR_COLON L':' #define CHAR_EQUAL L'=' #define CHAR_COMMA L',' #define CHAR_CARET L'^' #define CHAR_DOLLAR L'$' #define CHAR_BACKSLASH L'\\' #define CHAR_HASH L'#' #define CHAR_TILDE L'~' /* Some macros for expanding \w, \s, etc. */ static const struct tre_macro_struct { const char c; const char *expansion; } tre_macros[] = { {'t', "\t"}, {'n', "\n"}, {'r', "\r"}, {'f', "\f"}, {'a', "\a"}, {'e', "\033"}, {'w', "[[:alnum:]_]"}, {'W', "[^[:alnum:]_]"}, {'s', "[[:space:]]"}, {'S', "[^[:space:]]"}, {'d', "[[:digit:]]"}, {'D', "[^[:digit:]]"}, { 0, NULL } }; /* Expands a macro delimited by `regex' and `regex_end' to `buf', which must have at least `len' items. Sets buf[0] to zero if the there is no match in `tre_macros'. */ static void tre_expand_macro(const tre_char_t *regex, const tre_char_t *regex_end, tre_char_t *buf, size_t buf_len) { int i; buf[0] = 0; if (regex >= regex_end) return; for (i = 0; tre_macros[i].expansion; i++) { if (tre_macros[i].c == *regex) { unsigned int j; DPRINT(("Expanding macro '%c' => '%s'\n", tre_macros[i].c, tre_macros[i].expansion)); for (j = 0; tre_macros[i].expansion[j] && j < buf_len; j++) buf[j] = tre_macros[i].expansion[j]; buf[j] = 0; break; } } } static reg_errcode_t tre_new_item(tre_mem_t mem, int min, int max, int *i, int *max_i, tre_ast_node_t ***items) { reg_errcode_t status; tre_ast_node_t **array = *items; /* Allocate more space if necessary. */ if (*i >= *max_i) { tre_ast_node_t **new_items; DPRINT(("out of array space, i = %d\n", *i)); /* If the array is already 1024 items large, give up -- there's probably an error in the regexp (e.g. not a '\0' terminated string and missing ']') */ if (*max_i > 1024) return REG_ESPACE; *max_i *= 2; new_items = xrealloc(array, sizeof(*items) * *max_i); if (new_items == NULL) return REG_ESPACE; *items = array = new_items; } array[*i] = tre_ast_new_literal(mem, min, max, -1); status = array[*i] == NULL ? REG_ESPACE : REG_OK; (*i)++; return status; } /* Expands a character class to character ranges. */ static reg_errcode_t tre_expand_ctype(tre_mem_t mem, tre_ctype_t class, tre_ast_node_t ***items, int *i, int *max_i, int cflags) { reg_errcode_t status = REG_OK; tre_cint_t c; int j, min = -1, max = 0; assert(TRE_MB_CUR_MAX == 1); DPRINT((" expanding class to character ranges\n")); for (j = 0; (j < 256) && (status == REG_OK); j++) { c = j; if (tre_isctype(c, class) || ((cflags & REG_ICASE) && (tre_isctype(tre_tolower(c), class) || tre_isctype(tre_toupper(c), class)))) { if (min < 0) min = c; max = c; } else if (min >= 0) { DPRINT((" range %c (%d) to %c (%d)\n", min, min, max, max)); status = tre_new_item(mem, min, max, i, max_i, items); min = -1; } } if (min >= 0 && status == REG_OK) status = tre_new_item(mem, min, max, i, max_i, items); return status; } static int tre_compare_items(const void *a, const void *b) { tre_ast_node_t *node_a = *(tre_ast_node_t **)a; tre_ast_node_t *node_b = *(tre_ast_node_t **)b; tre_literal_t *l_a = node_a->obj, *l_b = node_b->obj; int a_min = l_a->code_min, b_min = l_b->code_min; if (a_min < b_min) return -1; else if (a_min > b_min) return 1; else return 0; } #ifndef TRE_USE_SYSTEM_WCTYPE /* isalnum() and the rest may be macros, so wrap them to functions. */ int tre_isalnum_func(tre_cint_t c) { return tre_isalnum(c); } int tre_isalpha_func(tre_cint_t c) { return tre_isalpha(c); } #ifdef tre_isascii int tre_isascii_func(tre_cint_t c) { return tre_isascii(c); } #else /* !tre_isascii */ int tre_isascii_func(tre_cint_t c) { return !(c >> 7); } #endif /* !tre_isascii */ #ifdef tre_isblank int tre_isblank_func(tre_cint_t c) { return tre_isblank(c); } #else /* !tre_isblank */ int tre_isblank_func(tre_cint_t c) { return ((c == ' ') || (c == '\t')); } #endif /* !tre_isblank */ int tre_iscntrl_func(tre_cint_t c) { return tre_iscntrl(c); } int tre_isdigit_func(tre_cint_t c) { return tre_isdigit(c); } int tre_isgraph_func(tre_cint_t c) { return tre_isgraph(c); } int tre_islower_func(tre_cint_t c) { return tre_islower(c); } int tre_isprint_func(tre_cint_t c) { return tre_isprint(c); } int tre_ispunct_func(tre_cint_t c) { return tre_ispunct(c); } int tre_isspace_func(tre_cint_t c) { return tre_isspace(c); } int tre_isupper_func(tre_cint_t c) { return tre_isupper(c); } int tre_isxdigit_func(tre_cint_t c) { return tre_isxdigit(c); } struct { char *name; int (*func)(tre_cint_t); } tre_ctype_map[] = { { "alnum", &tre_isalnum_func }, { "alpha", &tre_isalpha_func }, #ifdef tre_isascii { "ascii", &tre_isascii_func }, #endif /* tre_isascii */ #ifdef tre_isblank { "blank", &tre_isblank_func }, #endif /* tre_isblank */ { "cntrl", &tre_iscntrl_func }, { "digit", &tre_isdigit_func }, { "graph", &tre_isgraph_func }, { "lower", &tre_islower_func }, { "print", &tre_isprint_func }, { "punct", &tre_ispunct_func }, { "space", &tre_isspace_func }, { "upper", &tre_isupper_func }, { "xdigit", &tre_isxdigit_func }, { NULL, NULL} }; tre_ctype_t tre_ctype(const char *name) { int i; for (i = 0; tre_ctype_map[i].name != NULL; i++) { if (strcmp(name, tre_ctype_map[i].name) == 0) return tre_ctype_map[i].func; } return (tre_ctype_t)0; } #endif /* !TRE_USE_SYSTEM_WCTYPE */ /* Maximum number of character classes that can occur in a negated bracket expression. */ #define MAX_NEG_CLASSES 64 /* Maximum length of character class names. */ #define MAX_CLASS_NAME #define REST(re) (int)(ctx->re_end - (re)), (re) static reg_errcode_t tre_parse_bracket_items(tre_parse_ctx_t *ctx, int negate, tre_ctype_t neg_classes[], int *num_neg_classes, tre_ast_node_t ***items, int *num_items, int *items_size) { const tre_char_t *re = ctx->re; reg_errcode_t status = REG_OK; tre_ctype_t class = (tre_ctype_t)0; int i = *num_items; int max_i = *items_size; int skip; /* Build an array of the items in the bracket expression. */ while (status == REG_OK) { skip = 0; if (re == ctx->re_end) { status = REG_EBRACK; } else if (*re == CHAR_RBRACKET && re > ctx->re) { DPRINT(("tre_parse_bracket: done: '%.*" STRF "'\n", REST(re))); re++; break; } else { tre_cint_t min = 0, max = 0; class = (tre_ctype_t)0; if (re + 2 < ctx->re_end && *(re + 1) == CHAR_MINUS && *(re + 2) != CHAR_RBRACKET) { DPRINT(("tre_parse_bracket: range: '%.*" STRF "'\n", REST(re))); min = *re; max = *(re + 2); re += 3; /* XXX - Should use collation order instead of encoding values in character ranges. */ if (min > max) status = REG_ERANGE; } else if (re + 1 < ctx->re_end && *re == CHAR_LBRACKET && *(re + 1) == CHAR_PERIOD) status = REG_ECOLLATE; else if (re + 1 < ctx->re_end && *re == CHAR_LBRACKET && *(re + 1) == CHAR_EQUAL) status = REG_ECOLLATE; else if (re + 1 < ctx->re_end && *re == CHAR_LBRACKET && *(re + 1) == CHAR_COLON) { char tmp_str[64]; const tre_char_t *endptr = re + 2; int len; DPRINT(("tre_parse_bracket: class: '%.*" STRF "'\n", REST(re))); while (endptr < ctx->re_end && *endptr != CHAR_COLON) endptr++; if (endptr != ctx->re_end) { len = MIN(endptr - re - 2, 63); #ifdef TRE_WCHAR { tre_char_t tmp_wcs[64]; wcsncpy(tmp_wcs, re + 2, len); tmp_wcs[len] = L'\0'; #if defined HAVE_WCSRTOMBS { mbstate_t state; const tre_char_t *src = tmp_wcs; memset(&state, '\0', sizeof(state)); len = wcsrtombs(tmp_str, &src, sizeof(tmp_str), &state); } #elif defined HAVE_WCSTOMBS len = wcstombs(tmp_str, tmp_wcs, 63); #endif /* defined HAVE_WCSTOMBS */ } #else /* !TRE_WCHAR */ strncpy(tmp_str, (const char*)re + 2, len); #endif /* !TRE_WCHAR */ tmp_str[len] = '\0'; DPRINT((" class name: %s\n", tmp_str)); class = tre_ctype(tmp_str); if (!class) status = REG_ECTYPE; /* Optimize character classes for 8 bit character sets. */ if (status == REG_OK && TRE_MB_CUR_MAX == 1) { status = tre_expand_ctype(ctx->mem, class, items, &i, &max_i, ctx->cflags); class = (tre_ctype_t)0; skip = 1; } re = endptr + 2; } else status = REG_ECTYPE; min = 0; max = TRE_CHAR_MAX; } else { DPRINT(("tre_parse_bracket: char: '%.*" STRF "'\n", REST(re))); if (*re == CHAR_MINUS && *(re + 1) != CHAR_RBRACKET && ctx->re != re) /* Two ranges are not allowed to share and endpoint. */ status = REG_ERANGE; min = max = *re++; } if (status != REG_OK) break; if (class && negate) if (*num_neg_classes >= MAX_NEG_CLASSES) status = REG_ESPACE; else neg_classes[(*num_neg_classes)++] = class; else if (!skip) { status = tre_new_item(ctx->mem, min, max, &i, &max_i, items); if (status != REG_OK) break; ((tre_literal_t*)((*items)[i-1])->obj)->u.class = class; } /* Add opposite-case counterpoints if REG_ICASE is present. This is broken if there are more than two "same" characters. */ if (ctx->cflags & REG_ICASE && !class && status == REG_OK && !skip) { int cmin, ccurr; DPRINT(("adding opposite-case counterpoints\n")); while (min <= max) { if (tre_islower(min)) { cmin = ccurr = tre_toupper(min++); while (tre_islower(min) && tre_toupper(min) == ccurr + 1 && min <= max) ccurr = tre_toupper(min++); status = tre_new_item(ctx->mem, cmin, ccurr, &i, &max_i, items); } else if (tre_isupper(min)) { cmin = ccurr = tre_tolower(min++); while (tre_isupper(min) && tre_tolower(min) == ccurr + 1 && min <= max) ccurr = tre_tolower(min++); status = tre_new_item(ctx->mem, cmin, ccurr, &i, &max_i, items); } else min++; if (status != REG_OK) break; } if (status != REG_OK) break; } } } *num_items = i; *items_size = max_i; ctx->re = re; return status; } static reg_errcode_t tre_parse_bracket(tre_parse_ctx_t *ctx, tre_ast_node_t **result) { tre_ast_node_t *node = NULL; int negate = 0; reg_errcode_t status = REG_OK; tre_ast_node_t **items, *u, *n; int i = 0, j, max_i = 32, curr_max, curr_min; tre_ctype_t neg_classes[MAX_NEG_CLASSES]; int num_neg_classes = 0; /* Start off with an array of `max_i' elements. */ items = xmalloc(sizeof(*items) * max_i); if (items == NULL) return REG_ESPACE; if (*ctx->re == CHAR_CARET) { DPRINT(("tre_parse_bracket: negate: '%.*" STRF "'\n", REST(ctx->re))); negate = 1; ctx->re++; } status = tre_parse_bracket_items(ctx, negate, neg_classes, &num_neg_classes, &items, &i, &max_i); if (status != REG_OK) goto parse_bracket_done; /* Sort the array if we need to negate it. */ if (negate) qsort(items, i, sizeof(*items), tre_compare_items); curr_max = curr_min = 0; /* Build a union of the items in the array, negated if necessary. */ for (j = 0; j < i && status == REG_OK; j++) { int min, max; tre_literal_t *l = items[j]->obj; min = l->code_min; max = l->code_max; DPRINT(("item: %d - %d, class %ld, curr_max = %d\n", (int)l->code_min, (int)l->code_max, (long)l->u.class, curr_max)); if (negate) { if (min < curr_max) { /* Overlap. */ curr_max = MAX(max + 1, curr_max); DPRINT(("overlap, curr_max = %d\n", curr_max)); l = NULL; } else { /* No overlap. */ curr_max = min - 1; if (curr_max >= curr_min) { DPRINT(("no overlap\n")); l->code_min = curr_min; l->code_max = curr_max; } else { DPRINT(("no overlap, zero room\n")); l = NULL; } curr_min = curr_max = max + 1; } } if (l != NULL) { int k; DPRINT(("creating %d - %d\n", (int)l->code_min, (int)l->code_max)); l->position = ctx->position; if (num_neg_classes > 0) { l->neg_classes = tre_mem_alloc(ctx->mem, (sizeof(l->neg_classes) * (num_neg_classes + 1))); if (l->neg_classes == NULL) { status = REG_ESPACE; break; } for (k = 0; k < num_neg_classes; k++) l->neg_classes[k] = neg_classes[k]; l->neg_classes[k] = (tre_ctype_t)0; } else l->neg_classes = NULL; if (node == NULL) node = items[j]; else { u = tre_ast_new_union(ctx->mem, node, items[j]); if (u == NULL) status = REG_ESPACE; node = u; } } } if (status != REG_OK) goto parse_bracket_done; if (negate) { int k; DPRINT(("final: creating %d - %d\n", curr_min, (int)TRE_CHAR_MAX)); n = tre_ast_new_literal(ctx->mem, curr_min, TRE_CHAR_MAX, ctx->position); if (n == NULL) status = REG_ESPACE; else { tre_literal_t *l = n->obj; if (num_neg_classes > 0) { l->neg_classes = tre_mem_alloc(ctx->mem, (sizeof(l->neg_classes) * (num_neg_classes + 1))); if (l->neg_classes == NULL) { status = REG_ESPACE; goto parse_bracket_done; } for (k = 0; k < num_neg_classes; k++) l->neg_classes[k] = neg_classes[k]; l->neg_classes[k] = (tre_ctype_t)0; } else l->neg_classes = NULL; if (node == NULL) node = n; else { u = tre_ast_new_union(ctx->mem, node, n); if (u == NULL) status = REG_ESPACE; node = u; } } } if (status != REG_OK) goto parse_bracket_done; #ifdef TRE_DEBUG tre_ast_print(node); #endif /* TRE_DEBUG */ parse_bracket_done: xfree(items); ctx->position++; *result = node; return status; } /* Parses a positive decimal integer. Returns -1 if the string does not contain a valid number. */ static int tre_parse_int(const tre_char_t **regex, const tre_char_t *regex_end) { int num = -1; const tre_char_t *r = *regex; while (r < regex_end && *r >= L'0' && *r <= L'9') { if (num < 0) num = 0; num = num * 10 + *r - L'0'; r++; } *regex = r; return num; } static reg_errcode_t tre_parse_bound(tre_parse_ctx_t *ctx, tre_ast_node_t **result) { int min, max, i; int cost_ins, cost_del, cost_subst, cost_max; int limit_ins, limit_del, limit_subst, limit_err; const tre_char_t *r = ctx->re; const tre_char_t *start; int minimal = (ctx->cflags & REG_UNGREEDY) ? 1 : 0; int approx = 0; int costs_set = 0; int counts_set = 0; cost_ins = cost_del = cost_subst = cost_max = TRE_PARAM_UNSET; limit_ins = limit_del = limit_subst = limit_err = TRE_PARAM_UNSET; /* Parse number (minimum repetition count). */ min = -1; if (r < ctx->re_end && *r >= L'0' && *r <= L'9') { DPRINT(("tre_parse: min count: '%.*" STRF "'\n", REST(r))); min = tre_parse_int(&r, ctx->re_end); } /* Parse comma and second number (maximum repetition count). */ max = min; if (r < ctx->re_end && *r == CHAR_COMMA) { r++; DPRINT(("tre_parse: max count: '%.*" STRF "'\n", REST(r))); max = tre_parse_int(&r, ctx->re_end); } /* Check that the repeat counts are sane. */ if ((max >= 0 && min > max) || max > RE_DUP_MAX) return REG_BADBR; /* '{' optionally followed immediately by a number == minimum repcount optionally followed by , then a number == maximum repcount + then a number == maximum insertion count - then a number == maximum deletion count # then a number == maximum substitution count ~ then a number == maximum number of errors Any of +, -, # or ~ without followed by a number means that the maximum count/number of errors is infinite. An equation of the form Xi + Yd + Zs < C can be specified to set costs and the cost limit to a value different from the default value: - X is the cost of an insertion - Y is the cost of a deletion - Z is the cost of a substitution - C is the maximum cost If no count limit or cost is set for an operation, the operation is not allowed at all. */ do { int done; start = r; /* Parse count limit settings */ done = 0; if (!counts_set) while (r + 1 < ctx->re_end && !done) { switch (*r) { case CHAR_PLUS: /* Insert limit */ DPRINT(("tre_parse: ins limit: '%.*" STRF "'\n", REST(r))); r++; limit_ins = tre_parse_int(&r, ctx->re_end); if (limit_ins < 0) limit_ins = INT_MAX; counts_set = 1; break; case CHAR_MINUS: /* Delete limit */ DPRINT(("tre_parse: del limit: '%.*" STRF "'\n", REST(r))); r++; limit_del = tre_parse_int(&r, ctx->re_end); if (limit_del < 0) limit_del = INT_MAX; counts_set = 1; break; case CHAR_HASH: /* Substitute limit */ DPRINT(("tre_parse: subst limit: '%.*" STRF "'\n", REST(r))); r++; limit_subst = tre_parse_int(&r, ctx->re_end); if (limit_subst < 0) limit_subst = INT_MAX; counts_set = 1; break; case CHAR_TILDE: /* Maximum number of changes */ DPRINT(("tre_parse: count limit: '%.*" STRF "'\n", REST(r))); r++; limit_err = tre_parse_int(&r, ctx->re_end); if (limit_err < 0) limit_err = INT_MAX; approx = 1; break; case CHAR_COMMA: r++; break; case L' ': r++; break; case L'}': done = 1; break; default: done = 1; break; } } /* Parse cost restriction equation. */ done = 0; if (!costs_set) while (r + 1 < ctx->re_end && !done) { switch (*r) { case CHAR_PLUS: case L' ': r++; break; case L'<': DPRINT(("tre_parse: max cost: '%.*" STRF "'\n", REST(r))); r++; while (*r == L' ') r++; cost_max = tre_parse_int(&r, ctx->re_end); if (cost_max < 0) cost_max = INT_MAX; else cost_max--; approx = 1; break; case CHAR_COMMA: r++; done = 1; break; default: if (*r >= L'0' && *r <= L'9') { #ifdef TRE_DEBUG const tre_char_t *sr = r; #endif /* TRE_DEBUG */ int cost = tre_parse_int(&r, ctx->re_end); /* XXX - make sure r is not past end. */ switch (*r) { case L'i': /* Insert cost */ DPRINT(("tre_parse: ins cost: '%.*" STRF "'\n", REST(sr))); r++; cost_ins = cost; costs_set = 1; break; case L'd': /* Delete cost */ DPRINT(("tre_parse: del cost: '%.*" STRF "'\n", REST(sr))); r++; cost_del = cost; costs_set = 1; break; case L's': /* Substitute cost */ DPRINT(("tre_parse: subst cost: '%.*" STRF "'\n", REST(sr))); r++; cost_subst = cost; costs_set = 1; break; default: return REG_BADBR; } } else { done = 1; break; } } } } while (start != r); /* Missing }. */ if (r >= ctx->re_end) return REG_EBRACE; /* Empty contents of {}. */ if (r == ctx->re) return REG_BADBR; /* Parse the ending '}' or '\}'.*/ if (ctx->cflags & REG_EXTENDED) { if (r >= ctx->re_end || *r != CHAR_RBRACE) return REG_BADBR; r++; } else { if (r + 1 >= ctx->re_end || *r != CHAR_BACKSLASH || *(r + 1) != CHAR_RBRACE) return REG_BADBR; r += 2; } /* Parse trailing '?' marking minimal repetition. */ if (r < ctx->re_end) { if (*r == CHAR_QUESTIONMARK) { minimal = !(ctx->cflags & REG_UNGREEDY); r++; } else if (*r == CHAR_STAR || *r == CHAR_PLUS) { /* These are reserved for future extensions. */ return REG_BADRPT; } } /* Create the AST node(s). */ if (min == 0 && max == 0) { *result = tre_ast_new_literal(ctx->mem, EMPTY, -1, -1); if (*result == NULL) return REG_ESPACE; } else { if (min < 0 && max < 0) /* Only approximate parameters set, no repetitions. */ min = max = 1; *result = tre_ast_new_iter(ctx->mem, *result, min, max, minimal); if (!*result) return REG_ESPACE; /* If approximate matching parameters are set, add them to the iteration node. */ if (approx || costs_set || counts_set) { int *params; tre_iteration_t *iter = (*result)->obj; if (costs_set || counts_set) { if (limit_ins == TRE_PARAM_UNSET) { if (cost_ins == TRE_PARAM_UNSET) limit_ins = 0; else limit_ins = INT_MAX; } if (limit_del == TRE_PARAM_UNSET) { if (cost_del == TRE_PARAM_UNSET) limit_del = 0; else limit_del = INT_MAX; } if (limit_subst == TRE_PARAM_UNSET) { if (cost_subst == TRE_PARAM_UNSET) limit_subst = 0; else limit_subst = INT_MAX; } } if (cost_max == TRE_PARAM_UNSET) cost_max = INT_MAX; if (limit_err == TRE_PARAM_UNSET) limit_err = INT_MAX; ctx->have_approx = 1; params = tre_mem_alloc(ctx->mem, sizeof(*params) * TRE_PARAM_LAST); if (!params) return REG_ESPACE; for (i = 0; i < TRE_PARAM_LAST; i++) params[i] = TRE_PARAM_UNSET; params[TRE_PARAM_COST_INS] = cost_ins; params[TRE_PARAM_COST_DEL] = cost_del; params[TRE_PARAM_COST_SUBST] = cost_subst; params[TRE_PARAM_COST_MAX] = cost_max; params[TRE_PARAM_MAX_INS] = limit_ins; params[TRE_PARAM_MAX_DEL] = limit_del; params[TRE_PARAM_MAX_SUBST] = limit_subst; params[TRE_PARAM_MAX_ERR] = limit_err; iter->params = params; } } DPRINT(("tre_parse_bound: min %d, max %d, costs [%d,%d,%d, total %d], " "limits [%d,%d,%d, total %d]\n", min, max, cost_ins, cost_del, cost_subst, cost_max, limit_ins, limit_del, limit_subst, limit_err)); ctx->re = r; return REG_OK; } typedef enum { PARSE_RE = 0, PARSE_ATOM, PARSE_MARK_FOR_SUBMATCH, PARSE_BRANCH, PARSE_PIECE, PARSE_CATENATION, PARSE_POST_CATENATION, PARSE_UNION, PARSE_POST_UNION, PARSE_POSTFIX, PARSE_RESTORE_CFLAGS } tre_parse_re_stack_symbol_t; reg_errcode_t tre_parse(tre_parse_ctx_t *ctx) { tre_ast_node_t *result = NULL; tre_parse_re_stack_symbol_t symbol; reg_errcode_t status = REG_OK; tre_stack_t *stack = ctx->stack; int bottom = tre_stack_num_objects(stack); int depth = 0; int temporary_cflags = 0; DPRINT(("tre_parse: parsing '%.*" STRF "', len = %d\n", ctx->len, ctx->re, ctx->len)); if (!ctx->nofirstsub) { STACK_PUSH(stack, int, ctx->submatch_id); STACK_PUSH(stack, int, PARSE_MARK_FOR_SUBMATCH); ctx->submatch_id++; } STACK_PUSH(stack, int, PARSE_RE); ctx->re_start = ctx->re; ctx->re_end = ctx->re + ctx->len; /* The following is basically just a recursive descent parser. I use an explicit stack instead of recursive functions mostly because of two reasons: compatibility with systems which have an overflowable call stack, and efficiency (both in lines of code and speed). */ while (tre_stack_num_objects(stack) > bottom && status == REG_OK) { if (status != REG_OK) break; symbol = tre_stack_pop_int(stack); switch (symbol) { case PARSE_RE: /* Parse a full regexp. A regexp is one or more branches, separated by the union operator `|'. */ #ifdef REG_LITERAL if (!(ctx->cflags & REG_LITERAL) && ctx->cflags & REG_EXTENDED) #endif /* REG_LITERAL */ STACK_PUSHX(stack, int, PARSE_UNION); STACK_PUSHX(stack, int, PARSE_BRANCH); break; case PARSE_BRANCH: /* Parse a branch. A branch is one or more pieces, concatenated. A piece is an atom possibly followed by a postfix operator. */ STACK_PUSHX(stack, int, PARSE_CATENATION); STACK_PUSHX(stack, int, PARSE_PIECE); break; case PARSE_PIECE: /* Parse a piece. A piece is an atom possibly followed by one or more postfix operators. */ #ifdef REG_LITERAL if (!(ctx->cflags & REG_LITERAL)) #endif /* REG_LITERAL */ STACK_PUSHX(stack, int, PARSE_POSTFIX); STACK_PUSHX(stack, int, PARSE_ATOM); break; case PARSE_CATENATION: /* If the expression has not ended, parse another piece. */ { tre_char_t c; if (ctx->re >= ctx->re_end) break; c = *ctx->re; #ifdef REG_LITERAL if (!(ctx->cflags & REG_LITERAL)) { #endif /* REG_LITERAL */ if (ctx->cflags & REG_EXTENDED && c == CHAR_PIPE) break; if ((ctx->cflags & REG_EXTENDED && c == CHAR_RPAREN && depth > 0) || (!(ctx->cflags & REG_EXTENDED) && (c == CHAR_BACKSLASH && *(ctx->re + 1) == CHAR_RPAREN))) { if (!(ctx->cflags & REG_EXTENDED) && depth == 0) status = REG_EPAREN; DPRINT(("tre_parse: group end: '%.*" STRF "'\n", REST(ctx->re))); depth--; if (!(ctx->cflags & REG_EXTENDED)) ctx->re += 2; break; } #ifdef REG_LITERAL } #endif /* REG_LITERAL */ #ifdef REG_RIGHT_ASSOC if (ctx->cflags & REG_RIGHT_ASSOC) { /* Right associative concatenation. */ STACK_PUSHX(stack, voidptr, result); STACK_PUSHX(stack, int, PARSE_POST_CATENATION); STACK_PUSHX(stack, int, PARSE_CATENATION); STACK_PUSHX(stack, int, PARSE_PIECE); } else #endif /* REG_RIGHT_ASSOC */ { /* Default case, left associative concatenation. */ STACK_PUSHX(stack, int, PARSE_CATENATION); STACK_PUSHX(stack, voidptr, result); STACK_PUSHX(stack, int, PARSE_POST_CATENATION); STACK_PUSHX(stack, int, PARSE_PIECE); } break; } case PARSE_POST_CATENATION: { tre_ast_node_t *tree = tre_stack_pop_voidptr(stack); tre_ast_node_t *tmp_node; tmp_node = tre_ast_new_catenation(ctx->mem, tree, result); if (!tmp_node) return REG_ESPACE; result = tmp_node; break; } case PARSE_UNION: if (ctx->re >= ctx->re_end) break; #ifdef REG_LITERAL if (ctx->cflags & REG_LITERAL) break; #endif /* REG_LITERAL */ switch (*ctx->re) { case CHAR_PIPE: DPRINT(("tre_parse: union: '%.*" STRF "'\n", REST(ctx->re))); STACK_PUSHX(stack, int, PARSE_UNION); STACK_PUSHX(stack, voidptr, result); STACK_PUSHX(stack, int, PARSE_POST_UNION); STACK_PUSHX(stack, int, PARSE_BRANCH); ctx->re++; break; case CHAR_RPAREN: ctx->re++; break; default: break; } break; case PARSE_POST_UNION: { tre_ast_node_t *tmp_node; tre_ast_node_t *tree = tre_stack_pop_voidptr(stack); tmp_node = tre_ast_new_union(ctx->mem, tree, result); if (!tmp_node) return REG_ESPACE; result = tmp_node; break; } case PARSE_POSTFIX: /* Parse postfix operators. */ if (ctx->re >= ctx->re_end) break; #ifdef REG_LITERAL if (ctx->cflags & REG_LITERAL) break; #endif /* REG_LITERAL */ switch (*ctx->re) { case CHAR_PLUS: case CHAR_QUESTIONMARK: if (!(ctx->cflags & REG_EXTENDED)) break; case CHAR_STAR: { tre_ast_node_t *tmp_node; int minimal = (ctx->cflags & REG_UNGREEDY) ? 1 : 0; int rep_min = 0; int rep_max = -1; const tre_char_t *tmp_re; if (*ctx->re == CHAR_PLUS) rep_min = 1; if (*ctx->re == CHAR_QUESTIONMARK) rep_max = 1; tmp_re = ctx->re; if (ctx->re + 1 < ctx->re_end) { if (*(ctx->re + 1) == CHAR_QUESTIONMARK) { minimal = !(ctx->cflags & REG_UNGREEDY); ctx->re++; } else if (*(ctx->re + 1) == CHAR_STAR || *(ctx->re + 1) == CHAR_PLUS) { /* These are reserved for future extensions. */ return REG_BADRPT; } } DPRINT(("tre_parse: %s star: '%.*" STRF "'\n", minimal ? " minimal" : "greedy", REST(tmp_re))); ctx->re++; tmp_node = tre_ast_new_iter(ctx->mem, result, rep_min, rep_max, minimal); if (tmp_node == NULL) return REG_ESPACE; result = tmp_node; STACK_PUSHX(stack, int, PARSE_POSTFIX); break; } case CHAR_BACKSLASH: /* "\{" is special without REG_EXTENDED */ if (!(ctx->cflags & REG_EXTENDED) && ctx->re + 1 < ctx->re_end && *(ctx->re + 1) == CHAR_LBRACE) { ctx->re++; goto parse_brace; } else break; case CHAR_LBRACE: /* "{" is literal without REG_EXTENDED */ if (!(ctx->cflags & REG_EXTENDED)) break; parse_brace: DPRINT(("tre_parse: bound: '%.*" STRF "'\n", REST(ctx->re))); ctx->re++; status = tre_parse_bound(ctx, &result); if (status != REG_OK) return status; STACK_PUSHX(stack, int, PARSE_POSTFIX); break; } break; case PARSE_ATOM: /* Parse an atom. An atom is a regular expression enclosed in `()', an empty set of `()', a bracket expression, `.', `^', `$', a `\' followed by a character, or a single character. */ /* End of regexp? (empty string). */ if (ctx->re >= ctx->re_end) goto parse_literal; #ifdef REG_LITERAL if (ctx->cflags & REG_LITERAL) goto parse_literal; #endif /* REG_LITERAL */ switch (*ctx->re) { case CHAR_LPAREN: /* parenthesized subexpression */ /* Handle "(?...)" extensions. They work in a way similar to Perls corresponding extensions. */ if (ctx->cflags & REG_EXTENDED && *(ctx->re + 1) == CHAR_QUESTIONMARK) { int new_cflags = ctx->cflags; int bit = 1; DPRINT(("tre_parse: extension: '%.*" STRF "\n", REST(ctx->re))); ctx->re += 2; while (1) { if (*ctx->re == L'i') { DPRINT(("tre_parse: icase: '%.*" STRF "\n", REST(ctx->re))); if (bit) new_cflags |= REG_ICASE; else new_cflags &= ~REG_ICASE; ctx->re++; } else if (*ctx->re == L'n') { DPRINT(("tre_parse: newline: '%.*" STRF "\n", REST(ctx->re))); if (bit) new_cflags |= REG_NEWLINE; else new_cflags &= ~REG_NEWLINE; ctx->re++; } #ifdef REG_RIGHT_ASSOC else if (*ctx->re == L'r') { DPRINT(("tre_parse: right assoc: '%.*" STRF "\n", REST(ctx->re))); if (bit) new_cflags |= REG_RIGHT_ASSOC; else new_cflags &= ~REG_RIGHT_ASSOC; ctx->re++; } #endif /* REG_RIGHT_ASSOC */ #ifdef REG_UNGREEDY else if (*ctx->re == L'U') { DPRINT(("tre_parse: ungreedy: '%.*" STRF "\n", REST(ctx->re))); if (bit) new_cflags |= REG_UNGREEDY; else new_cflags &= ~REG_UNGREEDY; ctx->re++; } #endif /* REG_UNGREEDY */ else if (*ctx->re == CHAR_MINUS) { DPRINT(("tre_parse: turn off: '%.*" STRF "\n", REST(ctx->re))); ctx->re++; bit = 0; } else if (*ctx->re == CHAR_COLON) { DPRINT(("tre_parse: no group: '%.*" STRF "\n", REST(ctx->re))); ctx->re++; depth++; break; } else if (*ctx->re == CHAR_HASH) { DPRINT(("tre_parse: comment: '%.*" STRF "\n", REST(ctx->re))); /* A comment can contain any character except a right parenthesis */ while (*ctx->re != CHAR_RPAREN && ctx->re < ctx->re_end) ctx->re++; if (*ctx->re == CHAR_RPAREN && ctx->re < ctx->re_end) { ctx->re++; break; } else return REG_BADPAT; } else if (*ctx->re == CHAR_RPAREN) { ctx->re++; break; } else return REG_BADPAT; } /* Turn on the cflags changes for the rest of the enclosing group. */ STACK_PUSHX(stack, int, ctx->cflags); STACK_PUSHX(stack, int, PARSE_RESTORE_CFLAGS); STACK_PUSHX(stack, int, PARSE_RE); ctx->cflags = new_cflags; break; } if (ctx->cflags & REG_EXTENDED || (ctx->re > ctx->re_start && *(ctx->re - 1) == CHAR_BACKSLASH)) { depth++; if (ctx->re + 2 < ctx->re_end && *(ctx->re + 1) == CHAR_QUESTIONMARK && *(ctx->re + 2) == CHAR_COLON) { DPRINT(("tre_parse: group begin: '%.*" STRF "', no submatch\n", REST(ctx->re))); /* Don't mark for submatching. */ ctx->re += 3; STACK_PUSHX(stack, int, PARSE_RE); } else { DPRINT(("tre_parse: group begin: '%.*" STRF "', submatch %d\n", REST(ctx->re), ctx->submatch_id)); ctx->re++; /* First parse a whole RE, then mark the resulting tree for submatching. */ STACK_PUSHX(stack, int, ctx->submatch_id); STACK_PUSHX(stack, int, PARSE_MARK_FOR_SUBMATCH); STACK_PUSHX(stack, int, PARSE_RE); ctx->submatch_id++; } } else goto parse_literal; break; case CHAR_RPAREN: /* end of current subexpression */ if ((ctx->cflags & REG_EXTENDED && depth > 0) || (ctx->re > ctx->re_start && *(ctx->re - 1) == CHAR_BACKSLASH)) { DPRINT(("tre_parse: empty: '%.*" STRF "'\n", REST(ctx->re))); /* We were expecting an atom, but instead the current subexpression was closed. POSIX leaves the meaning of this to be implementation-defined. We interpret this as an empty expression (which matches an empty string). */ result = tre_ast_new_literal(ctx->mem, EMPTY, -1, -1); if (result == NULL) return REG_ESPACE; if (!(ctx->cflags & REG_EXTENDED)) ctx->re--; } else goto parse_literal; break; case CHAR_LBRACKET: /* bracket expression */ DPRINT(("tre_parse: bracket: '%.*" STRF "'\n", REST(ctx->re))); ctx->re++; status = tre_parse_bracket(ctx, &result); if (status != REG_OK) return status; break; case CHAR_BACKSLASH: /* If this is "\(" or "\)" chew off the backslash and try again. */ if (!(ctx->cflags & REG_EXTENDED) && ctx->re + 1 < ctx->re_end && (*(ctx->re + 1) == CHAR_LPAREN || *(ctx->re + 1) == CHAR_RPAREN)) { ctx->re++; STACK_PUSHX(stack, int, PARSE_ATOM); break; } /* If a macro is used, parse the expanded macro recursively. */ { tre_char_t buf[64]; tre_expand_macro(ctx->re + 1, ctx->re_end, buf, elementsof(buf)); if (buf[0] != 0) { tre_parse_ctx_t subctx; memcpy(&subctx, ctx, sizeof(subctx)); subctx.re = buf; subctx.len = tre_strlen(buf); subctx.nofirstsub = 1; status = tre_parse(&subctx); if (status != REG_OK) return status; ctx->re += 2; ctx->position = subctx.position; result = subctx.result; break; } } if (ctx->re + 1 >= ctx->re_end) /* Trailing backslash. */ return REG_EESCAPE; #ifdef REG_LITERAL if (*(ctx->re + 1) == L'Q') { DPRINT(("tre_parse: tmp literal: '%.*" STRF "'\n", REST(ctx->re))); ctx->cflags |= REG_LITERAL; temporary_cflags |= REG_LITERAL; ctx->re += 2; STACK_PUSHX(stack, int, PARSE_ATOM); break; } #endif /* REG_LITERAL */ DPRINT(("tre_parse: bleep: '%.*" STRF "'\n", REST(ctx->re))); ctx->re++; switch (*ctx->re) { case L'b': result = tre_ast_new_literal(ctx->mem, ASSERTION, ASSERT_AT_WB, -1); ctx->re++; break; case L'B': result = tre_ast_new_literal(ctx->mem, ASSERTION, ASSERT_AT_WB_NEG, -1); ctx->re++; break; case L'<': result = tre_ast_new_literal(ctx->mem, ASSERTION, ASSERT_AT_BOW, -1); ctx->re++; break; case L'>': result = tre_ast_new_literal(ctx->mem, ASSERTION, ASSERT_AT_EOW, -1); ctx->re++; break; case L'x': ctx->re++; if (ctx->re[0] != CHAR_LBRACE && ctx->re < ctx->re_end) { /* 8 bit hex char. */ char tmp[3] = {0, 0, 0}; long val; DPRINT(("tre_parse: 8 bit hex: '%.*" STRF "'\n", REST(ctx->re - 2))); if (tre_isxdigit(ctx->re[0]) && ctx->re < ctx->re_end) { tmp[0] = (char)ctx->re[0]; ctx->re++; } if (tre_isxdigit(ctx->re[0]) && ctx->re < ctx->re_end) { tmp[1] = (char)ctx->re[0]; ctx->re++; } val = strtol(tmp, NULL, 16); result = tre_ast_new_literal(ctx->mem, val, val, ctx->position); ctx->position++; break; } else if (ctx->re < ctx->re_end) { /* Wide char. */ char tmp[32]; long val; int i = 0; ctx->re++; while (ctx->re_end - ctx->re >= 0) { if (ctx->re[0] == CHAR_RBRACE) break; if (tre_isxdigit(ctx->re[0])) { tmp[i] = (char)ctx->re[0]; i++; ctx->re++; continue; } return REG_EBRACE; } ctx->re++; tmp[i] = 0; val = strtol(tmp, NULL, 16); result = tre_ast_new_literal(ctx->mem, val, val, ctx->position); ctx->position++; break; } default: if (tre_isdigit(*ctx->re)) { /* Back reference. */ int val = *ctx->re - L'0'; DPRINT(("tre_parse: backref: '%.*" STRF "'\n", REST(ctx->re - 1))); result = tre_ast_new_literal(ctx->mem, BACKREF, val, ctx->position); if (result == NULL) return REG_ESPACE; ctx->position++; ctx->max_backref = MAX(val, ctx->max_backref); ctx->re++; } else { /* Escaped character. */ DPRINT(("tre_parse: escaped: '%.*" STRF "'\n", REST(ctx->re - 1))); result = tre_ast_new_literal(ctx->mem, *ctx->re, *ctx->re, ctx->position); ctx->position++; ctx->re++; } break; } if (result == NULL) return REG_ESPACE; break; case CHAR_PERIOD: /* the any-symbol */ DPRINT(("tre_parse: any: '%.*" STRF "'\n", REST(ctx->re))); if (ctx->cflags & REG_NEWLINE) { tre_ast_node_t *tmp1; tre_ast_node_t *tmp2; tmp1 = tre_ast_new_literal(ctx->mem, 0, L'\n' - 1, ctx->position); if (!tmp1) return REG_ESPACE; tmp2 = tre_ast_new_literal(ctx->mem, L'\n' + 1, TRE_CHAR_MAX, ctx->position + 1); if (!tmp2) return REG_ESPACE; result = tre_ast_new_union(ctx->mem, tmp1, tmp2); if (!result) return REG_ESPACE; ctx->position += 2; } else { result = tre_ast_new_literal(ctx->mem, 0, TRE_CHAR_MAX, ctx->position); if (!result) return REG_ESPACE; ctx->position++; } ctx->re++; break; case CHAR_CARET: /* beginning of line assertion */ /* '^' has a special meaning everywhere in EREs, and in the beginning of the RE and after \( is BREs. */ if (ctx->cflags & REG_EXTENDED || (ctx->re - 2 >= ctx->re_start && *(ctx->re - 2) == CHAR_BACKSLASH && *(ctx->re - 1) == CHAR_LPAREN) || ctx->re == ctx->re_start) { DPRINT(("tre_parse: BOL: '%.*" STRF "'\n", REST(ctx->re))); result = tre_ast_new_literal(ctx->mem, ASSERTION, ASSERT_AT_BOL, -1); if (result == NULL) return REG_ESPACE; ctx->re++; } else goto parse_literal; break; case CHAR_DOLLAR: /* end of line assertion. */ /* '$' is special everywhere in EREs, and in the end of the string and before \) is BREs. */ if (ctx->cflags & REG_EXTENDED || (ctx->re + 2 < ctx->re_end && *(ctx->re + 1) == CHAR_BACKSLASH && *(ctx->re + 2) == CHAR_RPAREN) || ctx->re + 1 == ctx->re_end) { DPRINT(("tre_parse: EOL: '%.*" STRF "'\n", REST(ctx->re))); result = tre_ast_new_literal(ctx->mem, ASSERTION, ASSERT_AT_EOL, -1); if (result == NULL) return REG_ESPACE; ctx->re++; } else goto parse_literal; break; default: parse_literal: if (temporary_cflags && ctx->re + 1 < ctx->re_end && *ctx->re == CHAR_BACKSLASH && *(ctx->re + 1) == L'E') { DPRINT(("tre_parse: end tmps: '%.*" STRF "'\n", REST(ctx->re))); ctx->cflags &= ~temporary_cflags; temporary_cflags = 0; ctx->re += 2; STACK_PUSHX(stack, int, PARSE_PIECE); break; } /* We are expecting an atom. If the subexpression (or the whole regexp ends here, we interpret it as an empty expression (which matches an empty string). */ if ( #ifdef REG_LITERAL !(ctx->cflags & REG_LITERAL) && #endif /* REG_LITERAL */ (ctx->re >= ctx->re_end || *ctx->re == CHAR_STAR || (ctx->cflags & REG_EXTENDED && (*ctx->re == CHAR_PIPE || *ctx->re == CHAR_LBRACE || *ctx->re == CHAR_PLUS || *ctx->re == CHAR_QUESTIONMARK)) /* Test for "\)" in BRE mode. */ || (!(ctx->cflags & REG_EXTENDED) && ctx->re + 1 < ctx->re_end && *ctx->re == CHAR_BACKSLASH && *(ctx->re + 1) == CHAR_LBRACE))) { DPRINT(("tre_parse: empty: '%.*" STRF "'\n", REST(ctx->re))); result = tre_ast_new_literal(ctx->mem, EMPTY, -1, -1); if (!result) return REG_ESPACE; break; } DPRINT(("tre_parse: literal: '%.*" STRF "'\n", REST(ctx->re))); /* Note that we can't use an tre_isalpha() test here, since there may be characters which are alphabetic but neither upper or lower case. */ if (ctx->cflags & REG_ICASE && (tre_isupper(*ctx->re) || tre_islower(*ctx->re))) { tre_ast_node_t *tmp1; tre_ast_node_t *tmp2; /* XXX - Can there be more than one opposite-case counterpoints for some character in some locale? Or more than two characters which all should be regarded the same character if case is ignored? If yes, there does not seem to be a portable way to detect it. I guess that at least for multi-character collating elements there could be several opposite-case counterpoints, but they cannot be supported portably anyway. */ tmp1 = tre_ast_new_literal(ctx->mem, tre_toupper(*ctx->re), tre_toupper(*ctx->re), ctx->position); if (!tmp1) return REG_ESPACE; tmp2 = tre_ast_new_literal(ctx->mem, tre_tolower(*ctx->re), tre_tolower(*ctx->re), ctx->position); if (!tmp2) return REG_ESPACE; result = tre_ast_new_union(ctx->mem, tmp1, tmp2); if (!result) return REG_ESPACE; } else { result = tre_ast_new_literal(ctx->mem, *ctx->re, *ctx->re, ctx->position); if (!result) return REG_ESPACE; } ctx->position++; ctx->re++; break; } break; case PARSE_MARK_FOR_SUBMATCH: { int submatch_id = tre_stack_pop_int(stack); if (result->submatch_id >= 0) { tre_ast_node_t *n, *tmp_node; n = tre_ast_new_literal(ctx->mem, EMPTY, -1, -1); if (n == NULL) return REG_ESPACE; tmp_node = tre_ast_new_catenation(ctx->mem, n, result); if (tmp_node == NULL) return REG_ESPACE; tmp_node->num_submatches = result->num_submatches; result = tmp_node; } result->submatch_id = submatch_id; result->num_submatches++; break; } case PARSE_RESTORE_CFLAGS: ctx->cflags = tre_stack_pop_int(stack); break; default: assert(0); break; } } /* Check for missing closing parentheses. */ if (depth > 0) return REG_EPAREN; if (status == REG_OK) ctx->result = result; return status; } /* EOF */ lensfun-0.3.4/libs/regex/tre-parse.h000066400000000000000000000040661445356770400173330ustar00rootroot00000000000000/* tre-parse.c - Regexp parser definitions Copyright (c) 2001-2006 Ville Laurikari This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TRE_PARSE_H #define TRE_PARSE_H 1 /* Parse context. */ typedef struct { /* Memory allocator. The AST is allocated using this. */ tre_mem_t mem; /* Stack used for keeping track of regexp syntax. */ tre_stack_t *stack; /* The parse result. */ tre_ast_node_t *result; /* The regexp to parse and its length. */ const tre_char_t *re; /* The first character of the entire regexp. */ const tre_char_t *re_start; /* The first character after the end of the regexp. */ const tre_char_t *re_end; int len; /* Current submatch ID. */ int submatch_id; /* Current position (number of literal). */ int position; /* The highest back reference or -1 if none seen so far. */ int max_backref; /* This flag is set if the regexp uses approximate matching. */ int have_approx; /* Compilation flags. */ int cflags; /* If this flag is set the top-level submatch is not captured. */ int nofirstsub; /* The currently set approximate matching parameters. */ int params[TRE_PARAM_LAST]; } tre_parse_ctx_t; /* Parses a wide character regexp pattern into a syntax tree. This parser handles both syntaxes (BRE and ERE), including the TRE extensions. */ reg_errcode_t tre_parse(tre_parse_ctx_t *ctx); #endif /* TRE_PARSE_H */ /* EOF */ lensfun-0.3.4/libs/regex/tre-stack.c000066400000000000000000000057601445356770400173230ustar00rootroot00000000000000/* tre-stack.c - Simple stack implementation Copyright (c) 2001-2006 Ville Laurikari This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #include #include #include "tre-internal.h" #include "tre-stack.h" #include "xmalloc.h" union tre_stack_item { void *voidptr_value; int int_value; }; struct tre_stack_rec { int size; int max_size; int increment; int ptr; union tre_stack_item *stack; }; tre_stack_t * tre_stack_new(int size, int max_size, int increment) { tre_stack_t *s; s = xmalloc(sizeof(*s)); if (s != NULL) { s->stack = xmalloc(sizeof(*s->stack) * size); if (s->stack == NULL) { xfree(s); return NULL; } s->size = size; s->max_size = max_size; s->increment = increment; s->ptr = 0; } return s; } void tre_stack_destroy(tre_stack_t *s) { xfree(s->stack); xfree(s); } int tre_stack_num_objects(tre_stack_t *s) { return s->ptr; } static reg_errcode_t tre_stack_push(tre_stack_t *s, union tre_stack_item value) { if (s->ptr < s->size) { s->stack[s->ptr] = value; s->ptr++; } else { if (s->size >= s->max_size) { DPRINT(("tre_stack_push: stack full\n")); return REG_ESPACE; } else { union tre_stack_item *new_buffer; int new_size; DPRINT(("tre_stack_push: trying to realloc more space\n")); new_size = s->size + s->increment; if (new_size > s->max_size) new_size = s->max_size; new_buffer = xrealloc(s->stack, sizeof(*new_buffer) * new_size); if (new_buffer == NULL) { DPRINT(("tre_stack_push: realloc failed.\n")); return REG_ESPACE; } DPRINT(("tre_stack_push: realloc succeeded.\n")); assert(new_size > s->size); s->size = new_size; s->stack = new_buffer; tre_stack_push(s, value); } } return REG_OK; } #define define_pushf(typetag, type) \ declare_pushf(typetag, type) { \ union tre_stack_item item; \ item.typetag ## _value = value; \ return tre_stack_push(s, item); \ } define_pushf(int, int) define_pushf(voidptr, void *) #define define_popf(typetag, type) \ declare_popf(typetag, type) { \ return s->stack[--s->ptr].typetag ## _value; \ } define_popf(int, int) define_popf(voidptr, void *) /* EOF */ lensfun-0.3.4/libs/regex/tre-stack.h000066400000000000000000000055131445356770400173240ustar00rootroot00000000000000/* tre-stack.h: Stack definitions Copyright (c) 2001-2006 Ville Laurikari This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TRE_STACK_H #define TRE_STACK_H 1 #include "regex.h" typedef struct tre_stack_rec tre_stack_t; /* Creates a new stack object. `size' is initial size in bytes, `max_size' is maximum size, and `increment' specifies how much more space will be allocated with realloc() if all space gets used up. Returns the stack object or NULL if out of memory. */ tre_stack_t * tre_stack_new(int size, int max_size, int increment); /* Frees the stack object. */ void tre_stack_destroy(tre_stack_t *s); /* Returns the current number of objects in the stack. */ int tre_stack_num_objects(tre_stack_t *s); /* Each tre_stack_push_*(tre_stack_t *s, value) function pushes `value' on top of stack `s'. Returns REG_ESPACE if out of memory. This tries to realloc() more space before failing if maximum size has not yet been reached. Returns REG_OK if successful. */ #define declare_pushf(typetag, type) \ reg_errcode_t tre_stack_push_ ## typetag(tre_stack_t *s, type value) declare_pushf(voidptr, void *); declare_pushf(int, int); /* Each tre_stack_pop_*(tre_stack_t *s) function pops the topmost element off of stack `s' and returns it. The stack must not be empty. */ #define declare_popf(typetag, type) \ type tre_stack_pop_ ## typetag(tre_stack_t *s) declare_popf(voidptr, void *); declare_popf(int, int); /* Just to save some typing. */ #define STACK_PUSH(s, typetag, value) \ do \ { \ status = tre_stack_push_ ## typetag(s, value); \ } \ while (0) #define STACK_PUSHX(s, typetag, value) \ { \ status = tre_stack_push_ ## typetag(s, value); \ if (status != REG_OK) \ break; \ } #define STACK_PUSHR(s, typetag, value) \ { \ reg_errcode_t _status; \ _status = tre_stack_push_ ## typetag(s, value); \ if (_status != REG_OK) \ return _status; \ } #endif /* TRE_STACK_H */ /* EOF */ lensfun-0.3.4/libs/regex/xmalloc.c000066400000000000000000000161641445356770400170650ustar00rootroot00000000000000/* xmalloc.c - Simple malloc debugging library implementation Copyright (c) 2001-2006 Ville Laurikari . This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* TODO: - red zones - group dumps by source location */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #include #include #include /* Internal stuff. */ typedef struct hashTableItemRec { void *ptr; int bytes; const char *file; int line; const char *func; struct hashTableItemRec *next; } hashTableItem; typedef struct { hashTableItem **table; } hashTable; static int xmalloc_peak; int xmalloc_current; static int xmalloc_peak_blocks; int xmalloc_current_blocks; static int xmalloc_fail_after; #define TABLE_BITS 8 #define TABLE_MASK ((1 << TABLE_BITS) - 1) #define TABLE_SIZE (1 << TABLE_BITS) static hashTable * hash_table_new(void) { hashTable *tbl; tbl = malloc(sizeof(*tbl)); if (tbl != NULL) { tbl->table = calloc(TABLE_SIZE, sizeof(*tbl->table)); if (tbl->table == NULL) { free(tbl); return NULL; } } return tbl; } static int hash_void_ptr(void *ptr) { int hash; int i; /* I took this hash function just off the top of my head, I have no idea whether it is bad or very bad. */ hash = 0; for (i = 0; i < sizeof(ptr)*8 / TABLE_BITS; i++) { hash ^= (long)ptr >> i*8; hash += i * 17; hash &= TABLE_MASK; } return hash; } static void hash_table_add(hashTable *tbl, void *ptr, int bytes, const char *file, int line, const char *func) { int i; hashTableItem *item, *new; i = hash_void_ptr(ptr); item = tbl->table[i]; if (item != NULL) while (item->next != NULL) item = item->next; new = malloc(sizeof(*new)); assert(new != NULL); new->ptr = ptr; new->bytes = bytes; new->file = file; new->line = line; new->func = func; new->next = NULL; if (item != NULL) item->next = new; else tbl->table[i] = new; xmalloc_current += bytes; if (xmalloc_current > xmalloc_peak) xmalloc_peak = xmalloc_current; xmalloc_current_blocks++; if (xmalloc_current_blocks > xmalloc_peak_blocks) xmalloc_peak_blocks = xmalloc_current_blocks; } static void hash_table_del(hashTable *tbl, void *ptr) { int i; hashTableItem *item, *prev; i = hash_void_ptr(ptr); item = tbl->table[i]; if (item == NULL) { printf("xfree: invalid ptr %p\n", ptr); abort(); } prev = NULL; while (item->ptr != ptr) { prev = item; item = item->next; } if (item->ptr != ptr) { printf("xfree: invalid ptr %p\n", ptr); abort(); } xmalloc_current -= item->bytes; xmalloc_current_blocks--; if (prev != NULL) { prev->next = item->next; free(item); } else { tbl->table[i] = item->next; free(item); } } static hashTable *xmalloc_table = NULL; static void xmalloc_init(void) { if (xmalloc_table == NULL) { xmalloc_table = hash_table_new(); xmalloc_peak = 0; xmalloc_peak_blocks = 0; xmalloc_current = 0; xmalloc_current_blocks = 0; xmalloc_fail_after = -1; } assert(xmalloc_table != NULL); assert(xmalloc_table->table != NULL); } /* Public API. */ void xmalloc_configure(int fail_after) { xmalloc_init(); xmalloc_fail_after = fail_after; } int xmalloc_dump_leaks(void) { int i; int num_leaks = 0; int leaked_bytes = 0; hashTableItem *item; xmalloc_init(); for (i = 0; i < TABLE_SIZE; i++) { item = xmalloc_table->table[i]; while (item != NULL) { printf("%s:%d: %s: %d bytes at %p not freed\n", item->file, item->line, item->func, item->bytes, item->ptr); num_leaks++; leaked_bytes += item->bytes; item = item->next; } } if (num_leaks == 0) printf("No memory leaks.\n"); else printf("%d unfreed memory chuncks, total %d unfreed bytes.\n", num_leaks, leaked_bytes); printf("Peak memory consumption %d bytes (%.1f kB, %.1f MB) in %d blocks ", xmalloc_peak, (double)xmalloc_peak / 1024, (double)xmalloc_peak / (1024*1024), xmalloc_peak_blocks); printf("(average "); if (xmalloc_peak_blocks) printf("%d", ((xmalloc_peak + xmalloc_peak_blocks / 2) / xmalloc_peak_blocks)); else printf("N/A"); printf(" bytes per block).\n"); return num_leaks; } void * xmalloc_impl(size_t size, const char *file, int line, const char *func) { void *ptr; xmalloc_init(); assert(size > 0); if (xmalloc_fail_after == 0) { xmalloc_fail_after = -2; #if 0 printf("xmalloc: forced failure %s:%d: %s\n", file, line, func); #endif return NULL; } else if (xmalloc_fail_after == -2) { printf("xmalloc: called after failure from %s:%d: %s\n", file, line, func); assert(0); } else if (xmalloc_fail_after > 0) xmalloc_fail_after--; ptr = malloc(size); if (ptr != NULL) hash_table_add(xmalloc_table, ptr, size, file, line, func); return ptr; } void * xcalloc_impl(size_t nmemb, size_t size, const char *file, int line, const char *func) { void *ptr; xmalloc_init(); assert(size > 0); if (xmalloc_fail_after == 0) { xmalloc_fail_after = -2; #if 0 printf("xcalloc: forced failure %s:%d: %s\n", file, line, func); #endif return NULL; } else if (xmalloc_fail_after == -2) { printf("xcalloc: called after failure from %s:%d: %s\n", file, line, func); assert(0); } else if (xmalloc_fail_after > 0) xmalloc_fail_after--; ptr = calloc(nmemb, size); if (ptr != NULL) hash_table_add(xmalloc_table, ptr, nmemb * size, file, line, func); return ptr; } void xfree_impl(void *ptr, const char *file, int line, const char *func) { xmalloc_init(); if (ptr != NULL) hash_table_del(xmalloc_table, ptr); free(ptr); } void * xrealloc_impl(void *ptr, size_t new_size, const char *file, int line, const char *func) { void *new_ptr; xmalloc_init(); assert(ptr != NULL); assert(new_size > 0); if (xmalloc_fail_after == 0) { xmalloc_fail_after = -2; return NULL; } else if (xmalloc_fail_after == -2) { printf("xrealloc: called after failure from %s:%d: %s\n", file, line, func); assert(0); } else if (xmalloc_fail_after > 0) xmalloc_fail_after--; new_ptr = realloc(ptr, new_size); if (new_ptr != NULL) { hash_table_del(xmalloc_table, ptr); hash_table_add(xmalloc_table, new_ptr, new_size, file, line, func); } return new_ptr; } /* EOF */ lensfun-0.3.4/libs/regex/xmalloc.h000066400000000000000000000057031445356770400170670ustar00rootroot00000000000000/* xmalloc.h - Simple malloc debugging library API Copyright (c) 2001-2006 Ville Laurikari . This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _XMALLOC_H #define _XMALLOC_H 1 #ifdef MALLOC_DEBUGGING /* Version 2.4 and later of GCC define a magical variable `__PRETTY_FUNCTION__' which contains the name of the function currently being defined. # define __XMALLOC_FUNCTION __PRETTY_FUNCTION__ This is broken in G++ before version 2.6. C9x has a similar variable called __func__, but prefer the GCC one since it demangles C++ function names. */ # ifdef __GNUC__ # if __GNUC__ > 2 || (__GNUC__ == 2 \ && __GNUC_MINOR__ >= (defined __cplusplus ? 6 : 4)) # define __XMALLOC_FUNCTION __PRETTY_FUNCTION__ # else # define __XMALLOC_FUNCTION ((const char *) 0) # endif # else # if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L # define __XMALLOC_FUNCTION __func__ # else # define __XMALLOC_FUNCTION ((const char *) 0) # endif # endif #define xmalloc(size) xmalloc_impl(size, __FILE__, __LINE__, \ __XMALLOC_FUNCTION) #define xcalloc(nmemb, size) xcalloc_impl(nmemb, size, __FILE__, __LINE__, \ __XMALLOC_FUNCTION) #define xfree(ptr) xfree_impl(ptr, __FILE__, __LINE__, __XMALLOC_FUNCTION) #define xrealloc(ptr, new_size) xrealloc_impl(ptr, new_size, __FILE__, \ __LINE__, __XMALLOC_FUNCTION) void *xmalloc_impl(size_t size, const char *file, int line, const char *func); void *xcalloc_impl(size_t nmemb, size_t size, const char *file, int line, const char *func); void xfree_impl(void *ptr, const char *file, int line, const char *func); void *xrealloc_impl(void *ptr, size_t new_size, const char *file, int line, const char *func); int xmalloc_dump_leaks(void); void xmalloc_configure(int fail_after); #undef malloc #undef calloc #undef free #undef realloc #define malloc USE_XMALLOC_INSTEAD_OF_MALLOC #define calloc USE_XCALLOC_INSTEAD_OF_CALLOC #define free USE_XFREE_INSTEAD_OF_FREE #define realloc USE_XREALLOC_INSTEAD_OF_REALLOC #else /* !MALLOC_DEBUGGING */ #include #define xmalloc(size) malloc(size) #define xcalloc(nmemb, size) calloc(nmemb, size) #define xfree(ptr) free(ptr) #define xrealloc(ptr, new_size) realloc(ptr, new_size) #endif /* !MALLOC_DEBUGGING */ #endif /* _XMALLOC_H */ /* EOF */ lensfun-0.3.4/tests/000077500000000000000000000000001445356770400143515ustar00rootroot00000000000000lensfun-0.3.4/tests/CMakeLists.txt000066400000000000000000000031001445356770400171030ustar00rootroot00000000000000ADD_EXECUTABLE(test_database test_database.cpp) TARGET_LINK_LIBRARIES(test_database lensfun ${COMMON_LIBS}) ADD_TEST(NAME Database WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND test_database) ADD_EXECUTABLE(test_modifier test_modifier.cpp) TARGET_LINK_LIBRARIES(test_modifier lensfun ${COMMON_LIBS}) ADD_TEST(Modifier test_modifier) find_package(OpenMP) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") ADD_EXECUTABLE(test_modifier_color test_modifier_color.cpp) TARGET_LINK_LIBRARIES(test_modifier_color lensfun ${COMMON_LIBS}) ADD_TEST(Modifier_color test_modifier_color) ADD_EXECUTABLE(test_modifier_subpix test_modifier_subpix.cpp) TARGET_LINK_LIBRARIES(test_modifier_subpix lensfun ${COMMON_LIBS}) ADD_TEST(Modifier_subpix test_modifier_subpix) ADD_EXECUTABLE(test_modifier_coord_scale test_modifier_coord_scale.cpp) TARGET_LINK_LIBRARIES(test_modifier_coord_scale lensfun ${COMMON_LIBS}) ADD_TEST(Modifier_coord_scale test_modifier_coord_scale) ADD_EXECUTABLE(test_modifier_coord_distortion test_modifier_coord_distortion.cpp) TARGET_LINK_LIBRARIES(test_modifier_coord_distortion lensfun ${COMMON_LIBS}) ADD_TEST(Modifier_coord_distortion test_modifier_coord_distortion) ADD_EXECUTABLE(test_modifier_coord_geometry test_modifier_coord_geometry.cpp) TARGET_LINK_LIBRARIES(test_modifier_coord_geometry lensfun ${COMMON_LIBS}) ADD_TEST(Modifier_coord_geometry test_modifier_coord_geometry) FIND_PACKAGE(PythonInterp REQUIRED) ADD_TEST(NAME Database_integrity COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/check_database/check_database.py ${CMAKE_SOURCE_DIR}/data/db) lensfun-0.3.4/tests/README.md000066400000000000000000000012561445356770400156340ustar00rootroot00000000000000The tests in this folder are implemented using the GLib test framework. https://developer.gnome.org/glib/2.42/glib-Testing.html When CMake is configured with `-DBUILD_TESTS=on` the tests are build. The individual tests are stand-alone exceutables and can also be run in a debugger or for example in `valgrind` for deeper analysis. By running the tool `ctest` in the build directory the tests are executed and the results are summarized. Further commands: * `ctest -VV` to show verbose output from the individual tests * `ctest -R Modifier` to run all tests with the string `Modifier` in the name * `ctest -E Modifier` to exclude tests with the string `Modifier` in the name lensfun-0.3.4/tests/common_code.hpp000066400000000000000000000010231445356770400173400ustar00rootroot00000000000000#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) #include #endif #ifdef __APPLE__ #include #endif void *lf_alloc_align(size_t alignment, size_t size) { #if defined(__WIN32__) return _aligned_malloc(size, alignment); #else void *ptr = NULL; if(posix_memalign(&ptr, alignment, size) != 0) return NULL; return ptr; #endif } #ifdef __WIN32__ void lf_free_align(void *mem) { _aligned_free(mem); } #else #define lf_free_align(A) free(A) #endif lensfun-0.3.4/tests/test_database.cpp000066400000000000000000000047071445356770400176700ustar00rootroot00000000000000#include #include #include "lensfun.h" typedef struct { lfDatabase* db; } lfFixture; void db_setup(lfFixture *lfFix, gconstpointer data) { lfFix->db = new lfDatabase (); lfFix->db->LoadDirectory("data/db"); } void db_teardown(lfFixture *lfFix, gconstpointer data) { delete lfFix->db; } // test different lens search strings void test_DB_lens_search(lfFixture* lfFix, gconstpointer data) { const lfLens **lenses = NULL; lenses = lfFix->db->FindLenses (NULL, NULL, "pEntax 50-200 ED"); g_assert_nonnull(lenses); g_assert_cmpstr(lenses[0]->Model, ==, "smc Pentax-DA 50-200mm f/4-5.6 DA ED"); lf_free (lenses); lenses = lfFix->db->FindLenses (NULL, NULL, "smc Pentax-DA 50-200mm f/4-5.6 DA ED"); g_assert_nonnull(lenses); g_assert_cmpstr(lenses[0]->Model, ==, "smc Pentax-DA 50-200mm f/4-5.6 DA ED"); lf_free (lenses); lenses = lfFix->db->FindLenses (NULL, NULL, "PENTAX fa 28mm 2.8"); g_assert_nonnull(lenses); g_assert_cmpstr(lenses[0]->Model, ==, "smc Pentax-FA 28mm f/2.8 AL"); lf_free (lenses); /*lenses = lfFix->db->FindLenses (NULL, NULL, "Fotasy M3517 35mm f/1.7"); g_assert_nonnull(lenses); g_assert_cmpstr(lenses[0]->Model, ==, "Fotasy M3517 35mm f/1.7"); lf_free (lenses); lenses = lfFix->db->FindLenses (NULL, NULL, "Minolta MD 35mm 1/2.8"); g_assert_nonnull(lenses); g_assert_cmpstr(lenses[0]->Model, ==, "Minolta MD 35mm 1/2.8"); lf_free (lenses);*/ } // test different camera search strings void test_DB_cam_search(lfFixture* lfFix, gconstpointer data) { const lfCamera **cameras = NULL; cameras = lfFix->db->FindCamerasExt("pentax", "K100D"); g_assert_nonnull(cameras); g_assert_cmpstr(cameras[0]->Model, ==, "Pentax K100D"); lf_free (cameras); cameras = lfFix->db->FindCamerasExt(NULL, "K 100 D"); g_assert_nonnull(cameras); g_assert_cmpstr(cameras[0]->Model, ==, "Pentax K100D"); lf_free (cameras); cameras = lfFix->db->FindCamerasExt(NULL, "PentAX K100 D"); g_assert_nonnull(cameras); g_assert_cmpstr(cameras[0]->Model, ==, "Pentax K100D"); lf_free (cameras); } int main (int argc, char **argv) { setlocale (LC_ALL, ""); g_test_init(&argc, &argv, NULL); g_test_add("/database/lens search", lfFixture, NULL, db_setup, test_DB_lens_search, db_teardown); g_test_add("/database/camera search", lfFixture, NULL, db_setup, test_DB_cam_search, db_teardown); return g_test_run(); } lensfun-0.3.4/tests/test_modifier.cpp000066400000000000000000000111161445356770400177120ustar00rootroot00000000000000#include #include #ifdef _MSC_VER #define _USE_MATH_DEFINES #endif #include #include "lensfun.h" typedef struct { size_t img_width, img_height; lfLens* lens; lfModifier* mod; } lfFixture; // setup a standard lens void mod_setup(lfFixture *lfFix, gconstpointer data) { lfFix->lens = new lfLens(); lfFix->lens->CropFactor = 1.0f; lfFix->lens->AspectRatio = 1.0f; lfFix->lens->Type = LF_RECTILINEAR; lfLensCalibDistortion lensCalibDist = {LF_DIST_MODEL_POLY3, 12.0f, {0.1,0.5,0.5}}; lfFix->lens->AddCalibDistortion(&lensCalibDist); // width and height have to be odd, so we have a non fractional center position lfFix->img_height = 301; lfFix->img_width = 301; } void mod_teardown(lfFixture *lfFix, gconstpointer data) { delete lfFix->lens; } // test to verifiy that projection center is image center void test_mod_projection_center(lfFixture* lfFix, gconstpointer data) { float in[2] = {0, 0}; float res[2] = {0, 0}; // check mapping of center to center lfLensType geom_types [] = {LF_RECTILINEAR, LF_PANORAMIC, LF_EQUIRECTANGULAR , LF_FISHEYE, LF_FISHEYE_EQUISOLID, LF_FISHEYE_ORTHOGRAPHIC, LF_FISHEYE_THOBY, LF_UNKNOWN}; const char* geom_names [] = {"rectilinear", "panoramic", "equirect", "fisheye", "fisheye-equisolid", "fisheye-orthographic", "fisheye-thoby", NULL}; int j = 0; while (geom_types[j]!=LF_UNKNOWN) { lfFix->lens->Type = geom_types[j]; int i = 0; while (geom_types[i]!=LF_UNKNOWN) { if(g_test_verbose()) g_print(" ~ Conversion from %s -> %s \n", geom_names[j], geom_names[i]); lfFix->mod = new lfModifier (lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); lfFix->mod->Initialize ( lfFix->lens, LF_PF_U8, 12.0f, 6.7f, 2.0f, 1.0f, geom_types[i], LF_MODIFY_GEOMETRY, false); // check if center is not influenced in[0] = (lfFix->img_width-1)/2; in[1] = (lfFix->img_height-1)/2; if (lfFix->mod->ApplyGeometryDistortion(in[0],in[1],1,1,res)) { g_assert_cmpfloat(in[0],==,res[0]); g_assert_cmpfloat(in[1],==,res[1]); } delete lfFix->mod; i++; } j++; } } // check if output becomes NaN when processing geometry conversion void test_mod_projection_borders(lfFixture* lfFix, gconstpointer data) { float in[2] = {(float) lfFix->img_width, (float) lfFix->img_height}; float in2[2] = {(float) (lfFix->img_width-1)/2, (float) (lfFix->img_height-1)/2}; float res[2] = {0, 0}; lfLensType geom_types [] = {LF_RECTILINEAR, LF_PANORAMIC, LF_EQUIRECTANGULAR, LF_FISHEYE_STEREOGRAPHIC, LF_FISHEYE, LF_FISHEYE_EQUISOLID, LF_FISHEYE_ORTHOGRAPHIC, LF_FISHEYE_THOBY, LF_UNKNOWN}; const char* geom_names [] = {"rectilinear", "panoramic", "equirect", "fisheye-sterographic", "fisheye", "fisheye-equisolid", "fisheye-orthographic", "fisheye-thoby", NULL}; int j = 0; while (geom_types[j]!=LF_UNKNOWN) { lfFix->lens->Type = geom_types[j]; int i = 0; while (geom_types[i]!=LF_UNKNOWN) { if(g_test_verbose()) g_print(" ~ Conversion from %s -> %s \n", geom_names[j], geom_names[i]); lfFix->mod = new lfModifier (lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); lfFix->mod->Initialize ( lfFix->lens, LF_PF_U8, 12.0f, 6.7f, 2.0f, 1.0f, geom_types[i], LF_MODIFY_GEOMETRY, false); if (lfFix->mod->ApplyGeometryDistortion(0,0,1,1,res)) { g_assert_false(std::isnan(res[0])); g_assert_false(std::isnan(res[1])); } if (lfFix->mod->ApplyGeometryDistortion(in[0],in[1],1,1,res)) { g_assert_false(std::isnan(res[0])); g_assert_false(std::isnan(res[1])); } if (lfFix->mod->ApplyGeometryDistortion(in2[0],in2[1],1,1,res)) { g_assert_false(std::isnan(res[0])); g_assert_false(std::isnan(res[1])); } delete lfFix->mod; i++; } j++; } } int main (int argc, char **argv) { setlocale (LC_ALL, ""); g_test_init(&argc, &argv, NULL); g_test_add("/modifier/projection center", lfFixture, NULL, mod_setup, test_mod_projection_center, mod_teardown); g_test_add("/modifier/projection borders", lfFixture, NULL, mod_setup, test_mod_projection_borders, mod_teardown); return g_test_run(); } lensfun-0.3.4/tests/test_modifier_color.cpp000066400000000000000000000151501445356770400211120ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include "lensfun.h" #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) #include #endif #ifdef __APPLE__ #include #endif #include "common_code.hpp" //TODO: find better place for cTypeToLfPixelFormat() template lfPixelFormat cTypeToLfPixelFormat() { return LF_PF_U8; } template<> lfPixelFormat cTypeToLfPixelFormat() { return LF_PF_U8; } template<> lfPixelFormat cTypeToLfPixelFormat() { return LF_PF_U16; } template<> lfPixelFormat cTypeToLfPixelFormat() { return LF_PF_U32; } template<> lfPixelFormat cTypeToLfPixelFormat() { return LF_PF_F32; } template<> lfPixelFormat cTypeToLfPixelFormat() { return LF_PF_F64; } typedef struct { void *image; size_t img_width, img_height; lfLens *lens; lfModifier *mod; } lfFixture; typedef struct { bool reverse; size_t cpp; gchar *pixDesc; int comp_role; size_t alignment; } lfTestParams; template void generateImage(lfFixture *lfFix, lfTestParams *p, T *pixels) { T halfmax = std::numeric_limits::max() / T(2); for(size_t i = 0; i < p->cpp * lfFix->img_width * lfFix->img_height; i++) pixels[i] = halfmax; } template<> void generateImage(lfFixture *lfFix, lfTestParams *p, float *pixels) { for(size_t i = 0; i < p->cpp * lfFix->img_width * lfFix->img_height; i++) pixels[i] = 0.5f; } template<> void generateImage(lfFixture *lfFix, lfTestParams *p, double *pixels) { for(size_t i = 0; i < p->cpp * lfFix->img_width * lfFix->img_height; i++) pixels[i] = 0.5; } // setup a standard lens template void mod_setup(lfFixture *lfFix, gconstpointer data) { lfTestParams *p = (lfTestParams *)data; lfFix->lens = new lfLens(); lfFix->lens->CropFactor = 1.0f; lfFix->lens->Type = LF_RECTILINEAR; // Canon EOS 5D Mark III + Canon EF 24-70mm f/2.8L II USM lfLensCalibVignetting lensCalibVign = {LF_VIGNETTING_MODEL_PA, 24.0f, 2.8f, 1000.0f, { -0.5334f, -0.7926f, 0.5243f}}; lfFix->lens->AddCalibVignetting(&lensCalibVign); lfFix->img_height = 300; lfFix->img_width = 300; lfFix->mod = new lfModifier(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); lfFix->mod->Initialize( lfFix->lens, cTypeToLfPixelFormat(), 24.0f, 2.8f, 1000.0f, 1.0f, LF_RECTILINEAR, LF_MODIFY_VIGNETTING, p->reverse); lfFix->image = NULL; const size_t bufsize = p->cpp * lfFix->img_width * lfFix->img_height * sizeof(T); if(p->alignment == 0) lfFix->image = g_malloc(bufsize); else lfFix->image = lf_alloc_align(p->alignment, bufsize); generateImage(lfFix, p, (T *)lfFix->image); } void mod_teardown(lfFixture *lfFix, gconstpointer data) { lfTestParams *p = (lfTestParams *)data; if(p->alignment == 0) g_free(lfFix->image); else lf_free_align(lfFix->image); delete lfFix->mod; delete lfFix->lens; } template void test_mod_color(lfFixture *lfFix, gconstpointer data) { lfTestParams *p = (lfTestParams *)data; for(size_t y = 0; y < lfFix->img_height; y++) { T *imgdata = (T *)lfFix->image + (size_t)p->cpp * y * lfFix->img_width; g_assert_true( lfFix->mod->ApplyColorModification( imgdata, 0.0, y, lfFix->img_width, 1, p->comp_role, p->cpp * lfFix->img_width)); } } #ifdef _OPENMP template void test_mod_color_parallel(lfFixture *lfFix, gconstpointer data) { const lfTestParams *const p = (lfTestParams *)data; #pragma omp parallel for schedule(static) for(size_t y = 0; y < lfFix->img_height; y++) { T *imgdata = (T *)lfFix->image + (size_t)p->cpp * y * lfFix->img_width; g_assert_true( lfFix->mod->ApplyColorModification( imgdata, 0.0, y, lfFix->img_width, 1, p->comp_role, p->cpp * lfFix->img_width)); } } #endif gchar *describe(lfTestParams *p, const char *prefix, const char *f) { gchar alignment[32] = ""; g_snprintf(alignment, sizeof(alignment), "%lu-byte", p->alignment); return g_strdup_printf( "/%s/%s/%s/%s/%s", prefix, p->reverse ? "Vignetting" : "DeVignetting", p->pixDesc, f, p->alignment == 0 ? "unaligned" : alignment ); } template void add_set_item(lfTestParams *p, const char *f) { gchar *desc = NULL; desc = describe(p, "modifier/color/serialFor", f); g_test_add(desc, lfFixture, p, mod_setup, test_mod_color, mod_teardown); g_free(desc); desc = NULL; #ifdef _OPENMP desc = describe(p, "modifier/color/parallelFor", f); g_test_add(desc, lfFixture, p, mod_setup, test_mod_color_parallel, mod_teardown); g_free(desc); desc = NULL; #endif } void add_sets(lfTestParams *p) { add_set_item(p, "lf_u8"); add_set_item(p, "lf_u16"); add_set_item(p, "lf_u32"); add_set_item(p, "lf_f32"); add_set_item(p, "lf_f64"); } void free_params(gpointer mem) { lfTestParams *p = (lfTestParams *)mem; g_free(p->pixDesc); g_free(mem); } int main(int argc, char **argv) { setlocale(LC_ALL, ""); g_test_init(&argc, &argv, NULL); GSList *slist = NULL; std::vector reverse; reverse.push_back(false); reverse.push_back(true); for(std::vector::iterator it_reverse = reverse.begin(); it_reverse != reverse.end(); ++it_reverse) { std::map pixDesc; pixDesc["RGB"] = LF_CR_3(RED, GREEN, BLUE); pixDesc["RGBA"] = LF_CR_4(RED, GREEN, BLUE, UNKNOWN); pixDesc["ARGB"] = LF_CR_4(UNKNOWN, RED, GREEN, BLUE); for(std::map::iterator it_pixDesc = pixDesc.begin(); it_pixDesc != pixDesc.end(); ++it_pixDesc) { std::vector align; align.push_back(0); align.push_back(4 * sizeof(float)); // SSE //align.push_back(8 * sizeof(float)); // AVX //align.push_back(16 * sizeof(float)); // AVX512 for(std::vector::iterator it_align = align.begin(); it_align != align.end(); ++it_align) { lfTestParams *p = (lfTestParams *)g_malloc(sizeof(lfTestParams)); p->reverse = *it_reverse; p->cpp = it_pixDesc->first.length(); p->pixDesc = g_strdup(it_pixDesc->first.c_str()); p->comp_role = it_pixDesc->second; p->alignment = *it_align; add_sets(p); slist = g_slist_append(slist, p); } } } const int res = g_test_run(); g_slist_free_full(slist, (GDestroyNotify)free_params); return res; } lensfun-0.3.4/tests/test_modifier_coord_distortion.cpp000066400000000000000000000123121445356770400233550ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include "lensfun.h" #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) #include #endif #ifdef __APPLE__ #include #endif #include "common_code.hpp" typedef struct { void *coordBuff; size_t img_width, img_height; lfLens *lens; lfModifier *mod; } lfFixture; typedef struct { bool reverse; gchar *distortionModel; lfLensCalibDistortion calib; size_t alignment; } lfTestParams; // setup a standard lens void mod_setup(lfFixture *lfFix, gconstpointer data) { lfTestParams *p = (lfTestParams *)data; lfFix->lens = new lfLens(); lfFix->lens->CropFactor = 1.0f; lfFix->lens->Type = LF_RECTILINEAR; lfFix->lens->AddCalibDistortion(&p->calib); lfFix->img_height = 300; lfFix->img_width = 300; lfFix->mod = new lfModifier(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); lfFix->mod->Initialize( lfFix->lens, LF_PF_F32, 24.0f, 2.8f, 1000.0f, 1.0f, LF_RECTILINEAR, LF_MODIFY_DISTORTION, p->reverse); lfFix->coordBuff = NULL; const size_t bufsize = 2 * lfFix->img_width * lfFix->img_height * sizeof(float); if(p->alignment == 0) lfFix->coordBuff = g_malloc(bufsize); else lfFix->coordBuff = lf_alloc_align(p->alignment, bufsize); } void mod_teardown(lfFixture *lfFix, gconstpointer data) { lfTestParams *p = (lfTestParams *)data; if(p->alignment == 0) g_free(lfFix->coordBuff); else lf_free_align(lfFix->coordBuff); delete lfFix->mod; delete lfFix->lens; } void test_mod_coord_distortion(lfFixture *lfFix, gconstpointer data) { for(size_t y = 0; y < lfFix->img_height; y++) { float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; g_assert_true( lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) ); } } #ifdef _OPENMP void test_mod_coord_distortion_parallel(lfFixture *lfFix, gconstpointer data) { #pragma omp parallel for schedule(static) for(size_t y = 0; y < lfFix->img_height; y++) { float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; g_assert_true( lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) ); } } #endif gchar *describe(lfTestParams *p, const char *prefix) { gchar alignment[32] = ""; g_snprintf(alignment, sizeof(alignment), "%lu-byte", p->alignment); return g_strdup_printf( "/%s/%s/%s/%s", prefix, p->reverse ? "UnDist" : "Dist", p->distortionModel, p->alignment == 0 ? "unaligned" : alignment ); } void add_set_item(lfTestParams *p) { gchar *desc = NULL; desc = describe(p, "modifier/coord/serialFor"); g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_distortion, mod_teardown); g_free(desc); desc = NULL; #ifdef _OPENMP desc = describe(p, "modifier/coord/parallelFor"); g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_distortion_parallel, mod_teardown); g_free(desc); desc = NULL; #endif } void free_params(gpointer mem) { lfTestParams *p = (lfTestParams *)mem; g_free(p->distortionModel); g_free(mem); } int main(int argc, char **argv) { setlocale(LC_ALL, ""); g_test_init(&argc, &argv, NULL); GSList *slist = NULL; std::vector reverse; reverse.push_back(false); reverse.push_back(true); for(std::vector::iterator it_reverse = reverse.begin(); it_reverse != reverse.end(); ++it_reverse) { std::map distortCalib; // ??? + Canon EF 85mm f/1.2L II USM distortCalib["LF_DIST_MODEL_POLY3"] = (lfLensCalibDistortion) { LF_DIST_MODEL_POLY3, 85.0f, { -0.00412} }; //Canon PowerShot G12 (fixed lens) distortCalib["LF_DIST_MODEL_POLY5"] = (lfLensCalibDistortion) { LF_DIST_MODEL_POLY5, 6.1f, { -0.030571633, 0.004658548} }; //Canon EOS 5D Mark III + Canon EF 24-70mm f/2.8L II USM distortCalib["LF_DIST_MODEL_PTLENS"] = (lfLensCalibDistortion) { LF_DIST_MODEL_PTLENS, 24.0f, {0.02964, -0.07853, 0.02943} }; for(std::map::iterator it_distortCalib = distortCalib.begin(); it_distortCalib != distortCalib.end(); ++it_distortCalib) { std::vector align; align.push_back(0); align.push_back(4 * sizeof(float)); // SSE //align.push_back(8 * sizeof(float)); // AVX //align.push_back(16 * sizeof(float)); // AVX512 for(std::vector::iterator it_align = align.begin(); it_align != align.end(); ++it_align) { lfTestParams *p = (lfTestParams *)g_malloc(sizeof(lfTestParams)); p->reverse = *it_reverse; p->distortionModel = g_strdup(it_distortCalib->first.c_str()); p->calib = it_distortCalib->second; p->alignment = *it_align; add_set_item(p); slist = g_slist_append(slist, p); } } } const int res = g_test_run(); g_slist_free_full(slist, (GDestroyNotify)free_params); return res; } lensfun-0.3.4/tests/test_modifier_coord_geometry.cpp000066400000000000000000000127601445356770400230210ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include "lensfun.h" #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) #include #endif #ifdef __APPLE__ #include #endif #include "common_code.hpp" typedef struct { void *coordBuff; size_t img_width, img_height; lfLens *lens; lfModifier *mod; } lfFixture; typedef struct { bool reverse; gchar *sourceType; lfLensType sourceLensType; gchar *targetType; lfLensType targetLensType; size_t alignment; } lfTestParams; // setup a standard lens void mod_setup(lfFixture *lfFix, gconstpointer data) { lfTestParams *p = (lfTestParams *)data; lfFix->lens = new lfLens(); lfFix->lens->CropFactor = 1.0f; lfFix->lens->Type = p->sourceLensType; lfFix->img_height = 300; lfFix->img_width = 300; lfFix->mod = new lfModifier(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); lfFix->mod->Initialize( lfFix->lens, LF_PF_F32, 24.0f, 2.8f, 1000.0f, 1.0f, p->targetLensType, LF_MODIFY_GEOMETRY, p->reverse); lfFix->coordBuff = NULL; const size_t bufsize = 2 * lfFix->img_width * lfFix->img_height * sizeof(float); if(p->alignment == 0) lfFix->coordBuff = g_malloc(bufsize); else lfFix->coordBuff = lf_alloc_align(p->alignment, bufsize); } void mod_teardown(lfFixture *lfFix, gconstpointer data) { lfTestParams *p = (lfTestParams *)data; if(p->alignment == 0) g_free(lfFix->coordBuff); else lf_free_align(lfFix->coordBuff); delete lfFix->mod; delete lfFix->lens; } void test_mod_coord_geometry(lfFixture *lfFix, gconstpointer data) { for(size_t y = 0; y < lfFix->img_height; y++) { float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; g_assert_true( lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) ); } } #ifdef _OPENMP void test_mod_coord_geometry_parallel(lfFixture *lfFix, gconstpointer data) { #pragma omp parallel for schedule(static) for(size_t y = 0; y < lfFix->img_height; y++) { float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; g_assert_true( lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) ); } } #endif gchar *describe(lfTestParams *p, const char *prefix) { gchar alignment[32] = ""; g_snprintf(alignment, sizeof(alignment), "%lu-byte", p->alignment); return g_strdup_printf( "/%s/%s/%s/%s/%s", prefix, p->reverse ? "unGeom" : "Geom", p->sourceType, p->targetType, p->alignment == 0 ? "unaligned" : alignment ); } void add_set_item(lfTestParams *p) { gchar *desc = NULL; desc = describe(p, "modifier/coord/serialFor"); g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_geometry, mod_teardown); g_free(desc); desc = NULL; #ifdef _OPENMP desc = describe(p, "modifier/coord/parallelFor"); g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_geometry_parallel, mod_teardown); g_free(desc); desc = NULL; #endif } void free_params(gpointer mem) { lfTestParams *p = (lfTestParams *)mem; g_free(p->sourceType); g_free(p->targetType); g_free(mem); } int main(int argc, char **argv) { setlocale(LC_ALL, ""); g_test_init(&argc, &argv, NULL); GSList *slist = NULL; std::vector reverse; reverse.push_back(false); reverse.push_back(true); for(std::vector::iterator it_reverse = reverse.begin(); it_reverse != reverse.end(); ++it_reverse) { std::map lensType; lensType["LF_RECTILINEAR"] = LF_RECTILINEAR; lensType["LF_FISHEYE"] = LF_FISHEYE; lensType["LF_PANORAMIC"] = LF_PANORAMIC; lensType["LF_EQUIRECTANGULAR"] = LF_EQUIRECTANGULAR; lensType["LF_FISHEYE_ORTHOGRAPHIC"] = LF_FISHEYE_ORTHOGRAPHIC; lensType["LF_FISHEYE_STEREOGRAPHIC"] = LF_FISHEYE_STEREOGRAPHIC; lensType["LF_FISHEYE_EQUISOLID"] = LF_FISHEYE_EQUISOLID; lensType["LF_FISHEYE_THOBY"] = LF_FISHEYE_THOBY; for(std::map::iterator it_sourceType = lensType.begin(); it_sourceType != lensType.end(); ++it_sourceType) { for(std::map::iterator it_targetType = lensType.begin(); it_targetType != lensType.end(); ++it_targetType) { if(it_sourceType->second == it_targetType->second) continue; std::vector align; align.push_back(0); align.push_back(4 * sizeof(float)); // SSE //align.push_back(8 * sizeof(float)); // AVX //align.push_back(16 * sizeof(float)); // AVX512 for(std::vector::iterator it_align = align.begin(); it_align != align.end(); ++it_align) { lfTestParams *p = (lfTestParams *)g_malloc(sizeof(lfTestParams)); p->reverse = *it_reverse; p->sourceType = g_strdup(it_sourceType->first.c_str()); p->sourceLensType = it_sourceType->second; p->targetType = g_strdup(it_targetType->first.c_str()); p->targetLensType = it_targetType->second; p->alignment = *it_align; add_set_item(p); slist = g_slist_append(slist, p); } } } } const int res = g_test_run(); g_slist_free_full(slist, (GDestroyNotify)free_params); return res; } lensfun-0.3.4/tests/test_modifier_coord_scale.cpp000066400000000000000000000103631445356770400222520ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include "lensfun.h" #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) #include #endif #ifdef __APPLE__ #include #endif #include "common_code.hpp" typedef struct { void *coordBuff; size_t img_width, img_height; lfLens *lens; lfModifier *mod; } lfFixture; typedef struct { bool reverse; float scale; size_t alignment; } lfTestParams; // setup a standard lens void mod_setup(lfFixture *lfFix, gconstpointer data) { lfTestParams *p = (lfTestParams *)data; lfFix->lens = new lfLens(); lfFix->lens->CropFactor = 1.0f; lfFix->lens->Type = LF_RECTILINEAR; lfFix->img_height = 300; lfFix->img_width = 300; lfFix->mod = new lfModifier(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); lfFix->mod->Initialize( lfFix->lens, LF_PF_F32, 24.0f, 2.8f, 1000.0f, p->scale, LF_RECTILINEAR, LF_MODIFY_SCALE, p->reverse); lfFix->coordBuff = NULL; const size_t bufsize = 2 * lfFix->img_width * lfFix->img_height * sizeof(float); if(p->alignment == 0) lfFix->coordBuff = g_malloc(bufsize); else lfFix->coordBuff = lf_alloc_align(p->alignment, bufsize); } void mod_teardown(lfFixture *lfFix, gconstpointer data) { lfTestParams *p = (lfTestParams *)data; if(p->alignment == 0) g_free(lfFix->coordBuff); else lf_free_align(lfFix->coordBuff); delete lfFix->mod; delete lfFix->lens; } void test_mod_coord_scale(lfFixture *lfFix, gconstpointer data) { for(size_t y = 0; y < lfFix->img_height; y++) { float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; g_assert_true( lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) ); } } #ifdef _OPENMP void test_mod_coord_scale_parallel(lfFixture *lfFix, gconstpointer data) { #pragma omp parallel for schedule(static) for(size_t y = 0; y < lfFix->img_height; y++) { float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; g_assert_true( lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) ); } } #endif gchar *describe(lfTestParams *p, const char *prefix) { gchar alignment[32] = ""; g_snprintf(alignment, sizeof(alignment), "%lu-byte", p->alignment); return g_strdup_printf( "/%s/%s/%f/%s", prefix, p->reverse ? "unScale" : "Scale", p->scale, p->alignment == 0 ? "unaligned" : alignment ); } void add_set_item(lfTestParams *p) { gchar *desc = NULL; desc = describe(p, "modifier/coord/serialFor"); g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_scale, mod_teardown); g_free(desc); desc = NULL; #ifdef _OPENMP desc = describe(p, "modifier/coord/parallelFor"); g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_scale_parallel, mod_teardown); g_free(desc); desc = NULL; #endif } int main(int argc, char **argv) { setlocale(LC_ALL, ""); g_test_init(&argc, &argv, NULL); GSList *slist = NULL; std::vector reverse; reverse.push_back(false); reverse.push_back(true); for(std::vector::iterator it_reverse = reverse.begin(); it_reverse != reverse.end(); ++it_reverse) { std::vector scale; scale.push_back(0.75f); scale.push_back(1.25f); for(std::vector::iterator it_scale = scale.begin(); it_scale != scale.end(); ++it_scale) { std::vector align; align.push_back(0); align.push_back(4 * sizeof(float)); // SSE //align.push_back(8 * sizeof(float)); // AVX //align.push_back(16 * sizeof(float)); // AVX512 for(std::vector::iterator it_align = align.begin(); it_align != align.end(); ++it_align) { lfTestParams *p = (lfTestParams *)g_malloc(sizeof(lfTestParams)); p->reverse = *it_reverse; p->scale = *it_scale; p->alignment = *it_align; add_set_item(p); slist = g_slist_append(slist, p); } } } const int res = g_test_run(); g_slist_free_full(slist, (GDestroyNotify)g_free); return res; } lensfun-0.3.4/tests/test_modifier_subpix.cpp000066400000000000000000000116051445356770400213070ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include "lensfun.h" #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) #include #endif #ifdef __APPLE__ #include #endif #include "common_code.hpp" typedef struct { void *coordBuff; size_t img_width, img_height; lfLens *lens; lfModifier *mod; } lfFixture; typedef struct { bool reverse; gchar *tcaModel; lfLensCalibTCA calib; size_t alignment; } lfTestParams; // setup a standard lens void mod_setup(lfFixture *lfFix, gconstpointer data) { lfTestParams *p = (lfTestParams *)data; lfFix->lens = new lfLens(); lfFix->lens->CropFactor = 1.0f; lfFix->lens->Type = LF_RECTILINEAR; lfFix->lens->AddCalibTCA(&p->calib); lfFix->img_height = 300; lfFix->img_width = 300; lfFix->mod = new lfModifier(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); lfFix->mod->Initialize( lfFix->lens, LF_PF_F32, 24.0f, 2.8f, 1000.0f, 1.0f, LF_RECTILINEAR, LF_MODIFY_TCA, p->reverse); lfFix->coordBuff = NULL; const size_t bufsize = 2 * 3 * lfFix->img_width * lfFix->img_height * sizeof(float); if(p->alignment == 0) lfFix->coordBuff = g_malloc(bufsize); else lfFix->coordBuff = lf_alloc_align(p->alignment, bufsize); } void mod_teardown(lfFixture *lfFix, gconstpointer data) { lfTestParams *p = (lfTestParams *)data; if(p->alignment == 0) g_free(lfFix->coordBuff); else lf_free_align(lfFix->coordBuff); delete lfFix->mod; delete lfFix->lens; } void test_mod_subpix(lfFixture *lfFix, gconstpointer data) { for(size_t y = 0; y < lfFix->img_height; y++) { float *coordData = (float *)lfFix->coordBuff + (size_t)2 * 3 * y * lfFix->img_width; g_assert_true( lfFix->mod->ApplySubpixelDistortion(0.0, y, lfFix->img_width, 1, coordData) ); } } #ifdef _OPENMP void test_mod_subpix_parallel(lfFixture *lfFix, gconstpointer data) { #pragma omp parallel for schedule(static) for(size_t y = 0; y < lfFix->img_height; y++) { float *coordData = (float *)lfFix->coordBuff + (size_t)2 * 3 * y * lfFix->img_width; g_assert_true( lfFix->mod->ApplySubpixelDistortion(0.0, y, lfFix->img_width, 1, coordData) ); } } #endif gchar *describe(lfTestParams *p, const char *prefix) { gchar alignment[32] = ""; g_snprintf(alignment, sizeof(alignment), "%lu-byte", p->alignment); return g_strdup_printf( "/%s/%s/%s/%s", prefix, p->reverse ? "UnTCA" : "TCA", p->tcaModel, p->alignment == 0 ? "unaligned" : alignment ); } void add_set_item(lfTestParams *p) { gchar *desc = NULL; desc = describe(p, "modifier/subpix/serialFor"); g_test_add(desc, lfFixture, p, mod_setup, test_mod_subpix, mod_teardown); g_free(desc); desc = NULL; #ifdef _OPENMP desc = describe(p, "modifier/subpix/parallelFor"); g_test_add(desc, lfFixture, p, mod_setup, test_mod_subpix_parallel, mod_teardown); g_free(desc); desc = NULL; #endif } void free_params(gpointer mem) { lfTestParams *p = (lfTestParams *)mem; g_free(p->tcaModel); g_free(mem); } int main(int argc, char **argv) { setlocale(LC_ALL, ""); g_test_init(&argc, &argv, NULL); GSList *slist = NULL; std::vector reverse; reverse.push_back(false); reverse.push_back(true); for(std::vector::iterator it_reverse = reverse.begin(); it_reverse != reverse.end(); ++it_reverse) { std::map tcaCalib; // ??? + Nikon AF-S DX Nikkor 35mm f/1.8G tcaCalib["LF_TCA_MODEL_LINEAR"] = (lfLensCalibTCA) { LF_TCA_MODEL_LINEAR, 35.0f, {1.0003, 1.0003} }; // Canon EOS 5D Mark III + Canon EF 24-70mm f/2.8L II USM tcaCalib["LF_TCA_MODEL_POLY3"] = (lfLensCalibTCA) { LF_TCA_MODEL_POLY3, 24.0f, {1.0002104, 1.0000529, 0.0f, 0.0f, -0.0000220, -0.0000000} }; for(std::map::iterator it_tcaCalib = tcaCalib.begin(); it_tcaCalib != tcaCalib.end(); ++it_tcaCalib) { std::vector align; align.push_back(0); align.push_back(4 * sizeof(float)); // SSE //align.push_back(8 * sizeof(float)); // AVX //align.push_back(16 * sizeof(float)); // AVX512 for(std::vector::iterator it_align = align.begin(); it_align != align.end(); ++it_align) { lfTestParams *p = (lfTestParams *)g_malloc(sizeof(lfTestParams)); p->reverse = *it_reverse; p->tcaModel = g_strdup(it_tcaCalib->first.c_str()); p->calib = it_tcaCalib->second; p->alignment = *it_align; add_set_item(p); slist = g_slist_append(slist, p); } } } const int res = g_test_run(); g_slist_free_full(slist, (GDestroyNotify)free_params); return res; } lensfun-0.3.4/tools/000077500000000000000000000000001445356770400143475ustar00rootroot00000000000000lensfun-0.3.4/tools/check_database/000077500000000000000000000000001445356770400172505ustar00rootroot00000000000000lensfun-0.3.4/tools/check_database/check_database.py000066400000000000000000000040341445356770400225240ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- """Checks sanity of the database. Pass the path to the database on the command line. If you want to add a check, just add a "check_..." function to this program. It must take a set of ElementTree roots. """ import glob, sys, os, inspect from xml.etree import ElementTree ERROR_FOUND = False def normalize_string(string): return " ".join(string.lower().split()) def name(element, tag_name): for subelement in element.findall(tag_name): if not subelement.attrib: return normalize_string(subelement.text) def check_primary_keys_uniqueness(roots): global ERROR_FOUND lenses, mounts, cameras = set(), set(), set() for root in roots: for element in root.findall("lens"): lens = (name(element, "maker"), name(element, "model"), float(element.find("cropfactor").text)) if lens in lenses: print("Double primary key for lens! {}".format(lens)) ERROR_FOUND = True else: lenses.add(lens) for element in root.findall("mount"): mount = name(element, "name") if mount in mounts: print("Double primary key for mounts! {}".format(mount)) ERROR_FOUND = True else: mounts.add(mount) for element in root.findall("camera"): camera = (name(element, "maker"), name(element, "model"), name(element, "variant")) if camera in cameras: print("Double primary key for cameras! {}".format(camera)) ERROR_FOUND = True else: cameras.add(camera) roots = set() for filepath in glob.glob(os.path.join(sys.argv[1], "*.xml")): roots.add(ElementTree.parse(filepath).getroot()) for check_function in [function for function in globals().copy().values() if inspect.isfunction(function) and function.__name__.startswith("check_")]: check_function(roots) if ERROR_FOUND: sys.exit(1) else: sys.exit(0) lensfun-0.3.4/tools/find_missing_cameras/000077500000000000000000000000001445356770400205135ustar00rootroot00000000000000lensfun-0.3.4/tools/find_missing_cameras/find_missing_cameras.py000066400000000000000000000035321445356770400252340ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- """Finds cameras that are known to rawspeed's database but not to Lensfun. Maybe this could be extended to look for missing cameras in other places, too. Moreover, it may be good to optionally exclude compact cameras from the result – their only purpose might be to look for optically equivalent entries in Lensfun. Call: python3 find_missing_cameras.py path/to/lensfun/db path/to/rawspeeds/cameras.xml """ import glob, sys, os, re from xml.etree import ElementTree pattern = re.compile(r"[a-z]+|\d+|[^ a-z0-9]+") def normalize_string(string): components = sorted(token for token in pattern.findall(string.lower()) if token.isalnum() and token != "f" or len(token) > 1) return " ".join(components) def name(element, tag_name): for subelement in element.findall(tag_name): if not subelement.attrib: return normalize_string(subelement.text) cameras_in_lensfun = set() for filepath in glob.glob(os.path.join(sys.argv[1], "*.xml")): root = ElementTree.parse(filepath).getroot() for element in root.findall("camera"): cameras_in_lensfun.add(name(element, "model")) cameras_in_rawspeed = set() full_data = {} def add_camera(make, model): normalized_name = normalize_string(model) cameras_in_rawspeed.add(normalized_name) full_data[normalized_name] = (make, model) root = ElementTree.parse(sys.argv[2]).getroot() for element in root.findall("Camera"): make = element.attrib.get("make") add_camera(make, element.attrib.get("model")) for alias in element.find("Aliases") or []: add_camera(make, alias.text) missing_cameras = cameras_in_rawspeed - cameras_in_lensfun for maker, camera in sorted(data for normalized_name, data in full_data.items() if normalized_name in missing_cameras): print("{}: {}".format(maker, camera)) lensfun-0.3.4/tools/git-hooks/000077500000000000000000000000001445356770400162535ustar00rootroot00000000000000lensfun-0.3.4/tools/git-hooks/post-commit000077500000000000000000000006421445356770400204560ustar00rootroot00000000000000#!/bin/bash # # Updates the file data/db/timestamp.txt if the current commit has changed an # XML database file. You install these scripts by copying them into # .git/hooks. Watch out for existing hooks that you may overwrite there. if [ -a .update_timestamp ] then rm .update_timestamp date +%s > data/db/timestamp.txt git add data/db/timestamp.txt git commit --amend -C HEAD --no-verify fi exit 0 lensfun-0.3.4/tools/git-hooks/pre-commit000077500000000000000000000006101445356770400202520ustar00rootroot00000000000000#!/bin/bash # # Creates the file .update_timestamp if the current commit has changed an XML # database file. This is then used by post-commit to update the database # timestamp. You install these scripts by copying them into .git/hooks. Watch # out for existing hooks that you may overwrite there. if [[ -n $(git diff --cached data/db/*.xml) ]] then touch .update_timestamp fi exit 0 lensfun-0.3.4/tools/lensfun_convert_db_v2_to_v1.py000077500000000000000000000121131445356770400223200ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- # original file: https://github.com/lensfun/lensfun/blob/master/tools/update_database/follow_db_changes.py # modifications: stripped down to db conversion import glob, os, subprocess, calendar, time, tarfile, io, argparse, shutil, configparser, smtplib, textwrap from subprocess import DEVNULL from email.mime.text import MIMEText from lxml import etree parser = argparse.ArgumentParser(description="Generate tar balls of the Lensfun database, also for older versions.") parser.add_argument("output_path", help="Directory where to put the XML files. They are put in the db/ subdirectory. " "It needn't exist yet.") parser.add_argument("db_path", help="Path to database.") args = parser.parse_args() class XMLFile: def __init__(self, root, filepath): self.filepath = filepath self.tree = etree.parse(os.path.join(root, filepath)) @staticmethod def indent(tree, level=0): i = "\n" + level*" " if len(tree): if not tree.text or not tree.text.strip(): tree.text = i + " " if not tree.tail or not tree.tail.strip(): tree.tail = i for tree in tree: XMLFile.indent(tree, level + 1) if not tree.tail or not tree.tail.strip(): tree.tail = i else: if level and (not tree.tail or not tree.tail.strip()): tree.tail = i def write_to_tar(self, tar): tarinfo = tarfile.TarInfo(self.filepath) root = self.tree.getroot() self.indent(root) content = etree.tostring(root, encoding="utf-8") tarinfo.size = len(content) tar.addfile(tarinfo, io.BytesIO(content)) def fetch_xml_files(): os.chdir(args.db_path) xml_filenames = glob.glob("*.xml") xml_files = set(XMLFile(os.getcwd(), filename) for filename in xml_filenames) return xml_files class Converter: from_version = None to_version = None def __call__(self, tree): root = tree.getroot() if self.to_version == 0: if "version" in root.attrib: del root.attrib["version"] else: root.attrib["version"] = str(self.to_version) converters = [] current_version = 0 def converter(converter_class): global current_version current_version = max(current_version, converter_class.from_version) converters.append(converter_class()) return converter_class @converter class From1To0(Converter): from_version = 1 to_version = 0 @staticmethod def round_aps_c_cropfactor(lens_or_camera): element = lens_or_camera.find("cropfactor") if element is not None: cropfactor = float(element.text) if 1.5 < cropfactor < 1.56: element.text = "1.5" elif 1.6 < cropfactor < 1.63: element.text = "1.6" def __call__(self, tree): super().__call__(tree) for lens in tree.findall("lens"): element = lens.find("aspect-ratio") if element is not None: lens.remove(element) calibration = lens.find("calibration") if calibration is not None: for real_focal_length in calibration.findall("real-focal-length"): # Note that while one could convert it to the old # element, we simply remove it. It is not # worth the effort. calibration.remove(real_focal_length) self.round_aps_c_cropfactor(lens) for camera in tree.findall("camera"): self.round_aps_c_cropfactor(camera) @converter class From2To1(Converter): from_version = 2 to_version = 1 def __call__(self, tree): super().__call__(tree) for acm_model in tree.findall("//calibration/*[@model='acm']"): acm_model.getparent().remove(acm_model) for distortion in tree.findall("//calibration/distortion[@real-focal]"): etree.SubElement(distortion.getparent(), "real-focal-length", {"focal": distortion.get("focal"), "real-focal": distortion.get("real-focal")}) del distortion.attrib["real-focal"] def generate_database_tarballs(xml_files): version = current_version output_path = os.path.join(args.output_path, "db") shutil.rmtree(output_path, ignore_errors=True) os.makedirs(output_path) metadata = [[], []] while True: metadata[1].insert(0, version) tar = tarfile.open(os.path.join(output_path, "version_{}.tar".format(version)), "w") for xml_file in xml_files: xml_file.write_to_tar(tar) tar.close() try: converter_instance = converters.pop() except IndexError: break assert converter_instance.from_version == version for xml_file in xml_files: converter_instance(xml_file.tree) version = converter_instance.to_version xml_files = fetch_xml_files() generate_database_tarballs(xml_files) lensfun-0.3.4/tools/lenslist/000077500000000000000000000000001445356770400162045ustar00rootroot00000000000000lensfun-0.3.4/tools/lenslist/show_lensfun_coverage.py000077500000000000000000000207671445356770400231620ustar00rootroot00000000000000#!/usr/bin/env python3 #====================================================================== import subprocess, os, glob, datetime, tempfile, argparse from xml.etree import ElementTree import re import argparse import shutil #====================================================================== # Function and class definitions #---------------------------------------------------------------------- #---------------------------------------------------------------------- def find_best(root, tagname): texts = [(len(element.text), element.text) for element in root.findall(tagname) if element.attrib.get("lang") == "en"] if texts: return sorted(texts)[0][1] texts = [(len(element.text), element.text) for element in root.findall(tagname)] if texts: return sorted(texts)[0][1] else: return None def print_x(value): return ' class="lenslist-highlight lenslist-check">yes' if value else ' class="lenslist-check">no' #---------------------------------------------------------------------- # class to hold camera information class Camera: camera_makers = {} def __init__(self, element): self.maker = find_best(element, "maker") self.model = find_best(element, "model") variant = find_best(element, "variant"); if variant: self.model = self.model + " " + variant self.crop = float(element.find("cropfactor").text) self.camera_makers.setdefault(self.maker, set()).add(self.model) def __lt__(self, other): return (self.maker, self.model) < (other.maker, other.model) #---------------------------------------------------------------------- # class to hold lens information class Lens: def __init__(self, element, root, camtype): self.maker = find_best(element, "maker") self.model = find_best(element, "model") if camtype == "compact": mount = element.find("mount").text for camera in root.findall("camera"): if camera.find("mount").text == mount: self.maker = find_best(camera, "maker") camname = find_best(camera, "model") variant = find_best(camera, "variant"); if variant: camname = camname + " " + variant break self.model = "Fixed lens {}".format(camname) try: self.crop = float(element.find("cropfactor").text) except: self.crop = None self.distortion = element.find("calibration/distortion") is not None self.tca = element.find("calibration/tca") is not None self.vignetting = element.find("calibration/vignetting") is not None def __lt__(self, other): return (self.maker, self.model, self.crop) < (other.maker, other.model, self.crop) #====================================================================== #====================================================================== # Main routine #---------------------------------------------------------------------- # set up the commandline parser and define some arguemnts parser = argparse.ArgumentParser(description='Create a list of all cameras and lenses in the Lensfun database.') parser.add_argument('db_path', metavar='DB_PATH', help='path to the Lensfun database', default='/usr/share/lensfun/', nargs='?') parser.add_argument('-g', dest='git', action='store_true', help='use current database from git repository') parser.add_argument('-t', dest='table_only', action='store_true', help='pure table/list without surrounding header and description') parser.add_argument('-m', dest='markdown', action='store_true', help='output markdown instead of HTML') parser.add_argument('-o', dest='outfile', action='store', help='output filename and path', default='./lensfun_coverage.html') cmdline_args = vars(parser.parse_args()) # decide wether to get the most up to date database from git or use the locally installed database if cmdline_args['git']==True: XmlDBPath = os.path.join(tempfile.gettempdir(), "lensfun") print("~ Lensfun database is retrieved directly from git") if os.path.isdir(XmlDBPath): shutil.rmtree(XmlDBPath) subprocess.check_output(["git", "clone", "http://git.code.sf.net/p/lensfun/code", XmlDBPath]) XmlDBPath = os.path.join(XmlDBPath, "data", "db") else: XmlDBPath = cmdline_args['db_path'] print("~ Lensfun database is searched in "+XmlDBPath) # parse the database create a list of camera and lens objects cameras, lenses = [], [] for filename in glob.glob(os.path.join(XmlDBPath,"*.xml")): root = ElementTree.parse(filename) camtype_search = re.search('.*/([^-]*)-(.*).xml', filename, re.IGNORECASE) if camtype_search: camtype = camtype_search.group(1) else: camtype = 'generic' cameras.extend(Camera(camera_element) for camera_element in root.findall("camera")) lenses_list = [Lens(lens_element, root, camtype) for lens_element in root.findall("lens")] lenses.extend(lens for lens in lenses_list if lens.distortion or lens.tca or lens.vignetting) cameras.sort() lenses.sort(key=lambda Lens: Lens.model.lower()) lenses.sort(key=lambda Lens: Lens.maker.lower()) # finally write the table into the output file outfile = open(cmdline_args['outfile'], "w") #---------------------------------------------------------------------- # write HTML table or markdown formatted list if cmdline_args['markdown'] == False: #---------------------------------------------------------------------- # HTML table if cmdline_args['table_only'] == False: outfile.write("Lensfun's coverage

Lensfun coverage

Lenses (count: {})

" "

This table was generated on {} from current Lensfun sources. Your Lensfun version may be older, resulting in " "less coverage. If your lens is not included, see

\n".format( len(lenses), datetime.date.today())) outfile.write("" "\n") number_of_makers = 0 previous_maker = None for lens in lenses: if lens.maker.lower() != previous_maker: number_of_makers += 1 outfile.write("""\n""".format( ' class="lenslist-bg1"' if number_of_makers % 2 else ' class="lenslist-bg2"', lens.maker if lens.maker.lower() != previous_maker else "", lens.model, lens.crop or "?", print_x(lens.distortion), print_x(lens.tca), print_x(lens.vignetting))) previous_maker = lens.maker.lower() outfile.write("
manufacturermodelcropdist.TCAvign.
{}{}{}

Cameras

Note that new camera models can be added very easily. " "Contact the Lensfun maintainers for this.

") for maker, cameras in sorted(Camera.camera_makers.items()): outfile.write("

{}: {}

".format(maker, ", ".join(sorted(cameras)))) if cmdline_args['table_only'] == False: outfile.write("") else: #---------------------------------------------------------------------- # Markdown list if cmdline_args['table_only'] == False: outfile.write("= Lensfun's coverage = \n\n == Lenses (count: {}) ==\n\n" "This list was generated on {} from current Lensfun sources. Your Lensfun version may be older, resulting in " "less coverage. \nIf your lens is not included, see \n\n* Upload calibration pictures\n" "* Lens calibration for Lensfun\n\n".format( len(lenses), datetime.date.today())) number_of_makers = 0 previous_maker = None for lens in lenses: if lens.maker.lower() != previous_maker: number_of_makers += 1 if lens.maker.lower() != previous_maker: outfile.write("\n== {} ==\n\n".format(lens.maker)) outfile.write("* {} ({}, {}/{}/{})\n".format(lens.model, lens.crop or "?", "D" if lens.distortion else "-", "T" if lens.tca else "-", "V" if lens.vignetting else "-")) previous_maker = lens.maker.lower() outfile.close() print("~ List of lenses was written to "+cmdline_args['outfile']) lensfun-0.3.4/tools/perspective_control/000077500000000000000000000000001445356770400204405ustar00rootroot00000000000000lensfun-0.3.4/tools/perspective_control/perspective_control.py000066400000000000000000000543611445356770400251140ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- """This program demonstrates how perspective control could work in Lensfun. It must be converted to Lensfun C++ code of course. However, its structure is already very similar to how Lensfun is structured. Usage: python3 perspective_control.py Every image file must have a sidecar JSON file with the extension .json with the following content: [ 18, 1.534, 6, [ 8, 59, 289, 229, 8, 289], [ 188, 154, 187, 154, 188, 187] ] Here, 18 is the focal length in mm, 1.534 is the crop factor, 6 is a scaling parameter, the first array are the x values of the control points, and the second array are the y values. The (x, y) values must be image pixel coordinates. There are 4, 6, or 8 points allowed, see `initialize_perspective_correction` below. """ import sys, subprocess, os, array, json, multiprocessing, tempfile from math import sin, cos, tan, atan, sqrt, copysign, acos, log from math import pi as π def read_ppm(input_file, read_data=True): def read_token(skip_trailing_whitespace=True): nonlocal current_character token = b"" while current_character: if current_character == b"#": while current_character and current_character not in b"\r\n": current_character = input_file.read(1) elif current_character.isspace(): if skip_trailing_whitespace: while current_character.isspace(): current_character = input_file.read(1) return token else: token += current_character current_character = input_file.read(1) state = "start" current_character = input_file.read(1) magic_number = read_token() assert magic_number == b"P6" width = int(read_token()) height = int(read_token()) max_value = int(read_token(skip_trailing_whitespace=False)) assert max_value == 255 if read_data: image_data = array.array("B") image_data.fromfile(input_file, width * height * 3) image_data.byteswap() return image_data, width, height else: return width, height def read_image_file(filepath): convert_process = subprocess.Popen( ["convert", filepath, "-set", "colorspace", "RGB", "ppm:-"], stderr=open(os.devnull, "w"), stdout=subprocess.PIPE) return read_ppm(convert_process.stdout) def write_image_file(image_data, width, height, filepath): image_data.byteswap() with tempfile.NamedTemporaryFile(delete=False) as outfile: outfile.write("P6\n{} {}\n255\n".format(width, height).encode("ascii") + image_data.tobytes()) subprocess.call(["convert", outfile.name, "-set", "colorspace", "RGB", filepath]) image_data.byteswap() def intersection(x1, y1, x2, y2, x3, y3, x4, y4): A = x1 * y2 - y1 * x2 B = x3 * y4 - y3 * x4 C = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4) numerator_x = (A * (x3 - x4) - B * (x1 - x2)) numerator_y = (A * (y3 - y4) - B * (y1 - y2)) try: return numerator_x / C, numerator_y / C except ZeroDivisionError: return math.copysign(float("inf"), numerator_x), math.copysign(float("inf"), numerator_y) # In the following, I refer to these two rotation matrices: (See # .) # # ⎛ 1 0 0 ⎞ # Rₓ(ϑ) = ⎜ 0 cos ϑ - sin ϑ ⎟ # ⎝ 0 sin ϑ cos ϑ ⎠ # # ⎛ cos ϑ 0 sin ϑ ⎞ # R_y(ϑ) = ⎜ 0 1 0 ⎟ # ⎝- sin ϑ 0 cos ϑ ⎠ # # ⎛ cos ϑ - sin ϑ 0 ⎞ # R_z(ϑ) = ⎜ sin ϑ cos ϑ 0 ⎟ # ⎝ 0 0 1 ⎠ def rotate_ρ_δ(ρ, δ, x, y, z): # This matrix is: Rₓ(δ) · R_y(ρ) A11, A12, A13 = cos(ρ), 0, sin(ρ) A21, A22, A23 = sin(ρ) * sin(δ), cos(δ), - cos(ρ) * sin(δ) A31, A32, A33 = - sin(ρ) * cos(δ), sin(δ), cos(ρ) * cos(δ) return \ A11 * x + A12 * y + A13 * z, \ A21 * x + A22 * y + A23 * z, \ A31 * x + A32 * y + A33 * z def rotate_ρ_δ_ρh(ρ, δ, ρ_h, x, y, z): # This matrix is: R_y(ρₕ) · Rₓ(δ) · R_y(ρ) A11, A12, A13 = cos(ρ) * cos(ρ_h) - sin(ρ) * cos(δ) * sin(ρ_h), sin(δ) * sin(ρ_h), sin(ρ) * cos(ρ_h) + cos(ρ) * cos(δ) * sin(ρ_h) A21, A22, A23 = sin(ρ) * sin(δ), cos(δ), - cos(ρ) * sin(δ) A31, A32, A33 = - cos(ρ) * sin(ρ_h) - sin(ρ) * cos(δ) * cos(ρ_h), \ sin(δ) * cos(ρ_h), \ - sin(ρ) * sin(ρ_h) + cos(ρ) * cos(δ) * cos(ρ_h) return \ A11 * x + A12 * y + A13 * z, \ A21 * x + A22 * y + A23 * z, \ A31 * x + A32 * y + A33 * z def calculate_angles(x, y, f, normalized_in_millimeters): # Calculate the center of gravity of the control points if len(x) == 8: center_x = sum(x) / 8 center_y = sum(y) / 8 else: center_x = sum(x[:4]) / 4 center_y = sum(y[:4]) / 4 x_v, y_v = intersection(x[0], y[0], x[1], y[1], x[2], y[2], x[3], y[3]) if len(x) == 8: # The problem is over-determined. I prefer the fourth line over the # focal length. Maybe this is useful in cases where the focal length # is not known. x_h, y_h = intersection(x[4], y[4], x[5], y[5], x[6], y[6], x[7], y[7]) try: f_normalized = sqrt(- x_h * x_v - y_h * y_v) except ValueError: # FixMe: Is really always an f given (even if it is inaccurate)? f_normalized = f / normalized_in_millimeters else: print(f_normalized * normalized_in_millimeters, "mm") else: f_normalized = f / normalized_in_millimeters # Calculate vertex in polar coordinates ρ = atan(- x_v / f_normalized) δ = π / 2 - atan(- y_v / sqrt(x_v**2 + f_normalized**2)) if rotate_ρ_δ(ρ, δ, center_x, center_y, f_normalized)[2] < 0: # We have to move the vertex into the nadir instead of the zenith. δ -= π a = normalize(x_v - x[0], y_v - y[0]) b = normalize(x_v - x[2], y_v - y[2]) c = (a[0] + b[0], a[1] + b[1]) if abs(c[0]) > abs(c[1]): # The first two lines denote *horizontal* lines, the last two # *verticals*. The final rotation is by final_rotation·π/2. final_rotation = copysign(1, ρ) else: final_rotation = 0 # Calculate angle of intersection of horizontal great circle with equator, # after the vertex was moved into the zenith if len(x) == 4: # This results from assuming that at y = 0, there is a horizontal in # the picture. y = 0 is arbitrary, but then, so is every other value. ρ_h = 0 else: z4 = z5 = f_normalized x4_, y4_, z4_ = rotate_ρ_δ(ρ, δ, x[4], y[4], z4) x5_, y5_, z5_ = rotate_ρ_δ(ρ, δ, x[5], y[5], z5) if y4_ == y5_: # The horizontal vanishing point is perfectly to the left/right, so # no rotation necessary. ρ_h is undefined if also y4_ == 0 # (horizontal great circle is on the equator), but we simply set # ρ_h = 0 in this case, too. ρ_h = 0 else: λ = y4_ / (y4_ - y5_) x_h = x4_ + λ * (x5_ - x4_) z_h = z4_ + λ * (z5_ - z4_) if z_h == 0: ρ_h = 0 if x_h > 0 else π else: ρ_h = π / 2 - atan(x_h / z_h) if rotate_ρ_δ_ρh(ρ, δ, ρ_h, center_x, center_y, f_normalized)[2] < 0: # We have to move the vertex to the left instead of right ρ_h -= π return ρ, δ, ρ_h, f_normalized, final_rotation, center_x, center_y def generate_rotation_matrix(ρ1, δ, ρ2, d): """Returns a rotation matrix which combines three rotations. First, around the y axis by ρ₁, then, around the x axis by δ, and finally, around the y axis again by ρ₂. """ # We calculate the quaternion by multiplying the three quaternions for the # three rotations (in reverse order). We use quaternions here to be able # to apply the d parameter in a reasonable way. s_ρ2, c_ρ2 = sin(ρ2/2), cos(ρ2/2) s_δ, c_δ = sin(δ/2), cos(δ/2) s_ρ1, c_ρ1 = sin(ρ1/2), cos(ρ1/2) w = c_ρ2 * c_δ * c_ρ1 - s_ρ2 * c_δ * s_ρ1 x = c_ρ2 * s_δ * c_ρ1 + s_ρ2 * s_δ * s_ρ1 y = c_ρ2 * c_δ * s_ρ1 + s_ρ2 * c_δ * c_ρ1 z = c_ρ2 * s_δ * s_ρ1 - s_ρ2 * s_δ * c_ρ1 # Now, decompose the quaternion into θ and the axis unit vector. θ = 2 * acos(w) if θ > π: θ -= 2*π s_θ = sin(θ/2) x, y, z = x / s_θ, y / s_θ, z / s_θ # Apply d compression = 10 θ *= d + 1 if d <= 0 else 1 + 1 / compression * log(compression * d + 1) if θ > 0.9 * π: θ = 0.9 * π elif θ < - 0.9 * π: θ = - 0.9 * π # Compose the quaternion again. w = cos(θ/2) s_θ = sin(θ/2) x, y, z = x * s_θ, y * s_θ, z * s_θ # Convert the quaternion to a rotation matrix, see e.g. # . This matrix # is (if d=0): R_y(ρ2) · Rₓ(δ) · R_y(ρ1) A11, A12, A13 = 1 - 2 * y**2 - 2 * z**2, 2 * x * y - 2 * z * w, 2 * x * z + 2 * y * w A21, A22, A23 = 2 * x * y + 2 * z * w, 1 - 2 * x**2 - 2 * z**2, 2 * y * z - 2 * x * w A31, A32, A33 = 2 * x * z - 2 * y * w, 2 * y * z + 2 * x * w, 1 - 2 * x**2 - 2 * y**2 return A11, A12, A13, \ A21, A22, A23, \ A31, A32, A33 def normalize(x, y): norm = sqrt(x**2 + y**2) try: return x / norm, y / norm except ZeroDivisionError: return math.copysign(float("inf"), x), math.copysign(float("inf"), y) class Modifier: """First, the coordinate system. It is right-handed. The centre of the image is the origin of the x-y plane. x is to the right, y to the bottom, and z into the back. All rotations rotate points in mathematical positive direction around the axes. The axes keep their position (extrinsic rotations). The general algorithm is as follows: The original image (note that the sensor sees everything mirror-inverted, but this is annihilated by the back-projection later) is positioned parallely to the x-y plane at z = - focal length. Then, it is central-projected to the full sphere (radius equals focal length), so it gets positive z coordinates and can be viewed properly from the origin. This way, also the vertical vanishing point is on the sphere at (- ρ, 90° - δ). Then, the sphere with the image is rotated around the y axis by ρ so that the vanishing point is on the y-z plane with z > 0. Then, the sphere is rotated around the y axis by δ so that the vanishing point is in the zenith – where it belongs. Next, the intersection of the horizontal control line with the x-z plane is determined. Its rectascension is called 90° - ρₕ. So, the sphere is rotation around the y axis a second time, this time by ρₕ. Now, the right vanishing point truely is to the right. The rotated image plane is central-projected back into the sensor plane at z = - focal length. In general, it will be way off the center of the image, so that the image must be shifted. We shift so that the image center is a fix point. If however the image center is not visible in the result, or too close to the pole (i.e. magnification > 10), we use the center of gravity of the control points instead. Finally, the scaling in the center of the image is kept constant. One can finetune with an additinal scaling, but this way, one has a good starting point. Note that in reality, this whole process is performed backwards because we make a lookup in the original picture. In particular, the rotation by ρ, δ, ρₕ becomes - ρₕ, - δ, - ρ. We still need the forward direction in some places. And then there is the d parameter which allows finetuning of the correction. It is between -1 and 1, with 0 meaning full correction, -1 no correction, and 1 increased rotation by factor 1.25. For example, if you have tilted the camera by 40°, d = -1 means the original tilt of 40°, d = 0 means no tilt (perfect correction), and d = 1 means a tilt of 10° in the opposite direction (over-correction). This way, one can finetune the slope of the lines as well as the aspect ratio. """ def __init__(self, crop_factor, width, height): assert width > height self.crop_factor, self.width, self.height = crop_factor, width, height aspect_ratio = width / height aspect_ratio_correction = sqrt(1 + aspect_ratio**2) self.normalized_in_millimeters = sqrt(36**2 + 24**2) / 2 / aspect_ratio_correction / self.crop_factor self.norm_scale = 2 / (height - 1) self.norm_unscale = (height - 1) / 2 self.center_x = width / height self.center_y = 1 def initialize(self, focal_length): self.focal_length = focal_length def initialize_perspective_correction(self, x, y, d): """Depending on the number of control points given, there are three possible modes: 4 control points: c0 and c1 define one vertical lines, c2 and c3 the other. The focal length is used to get the proper aspect ratio. 6 control points: c0 to c3 like above. c4 and c5 define a horizontal line. The focal length is used to get the proper aspect ratio. 8 control points: c0 to c5 like above. c6 and c7 define a second horizontal line. The focal length given is discarded and calculated from the control points. If the lines constructed from the first four control points are more horizontal than vertical, in all of the above, "horizontal" and "vertical" need to be swapped. All control points must be given as pixel coordinates in the original image. In particular, cropping, rotating, shifting, or scaling must be switched off or removed by mapping. For best precision, anti-distortion should have been applied already. Moreover, fisheye images must have been transformed into rectilinear of the same focal length. The control points can be written to a sidecar file because they describe the perspective correction universally, i.e. independently of all corrections that can be activated (scaling, anti-distortion, projection transform, etc). FixMe: Maybe a static routine should be offered which takes a modifier, and an (x, y) pair, and maps them on x and y coordinates as if only the anti-distortion and the geometry transformation to rectilinear was active. The d parameter is supposed to be offered to the user as a slider. It can take values from -1 to +1. 0 denotes the perfect correction. -1 is the unchanged image. +1 is an increase of the tilting angle by 25%. """ if self.focal_length <= 0 or len(x) not in [4, 6, 8] or len(x) != len(y): # Don't add any callback return False if d <= - 1: d = - 1 elif d >= 1: d = 1 # x, y = x[:4], y[:4] # For testing only four points # x[0:6] = x[0], x[2], x[1], x[3], x[0], x[1] # For testing horizonal mode # y[0:6] = y[0], y[2], y[1], y[3], y[0], y[1] # For testing horizonal mode # x[6:8] = [x[1], x[3]] # for faking an explicit second horizonal line # y[6:8] = [y[1], y[3]] # for faking an explicit second horizonal line x = [value * self.norm_scale - self.center_x for value in x] y = [value * self.norm_scale - self.center_y for value in y] ρ, δ, ρ_h, f_normalized, final_rotation, center_of_control_points_x, center_of_control_points_y = \ calculate_angles(x, y, self.focal_length, self.normalized_in_millimeters) # Transform center point to get shift z = rotate_ρ_δ_ρh(ρ, δ, ρ_h, 0, 0, f_normalized)[2] # If the image centre is too much outside, or even at infinity, take the # center of gravity of the control points instead. new_image_center = "control points center" if z <= 0 or f_normalized / z > 10 else "old image center" # Generate a rotation matrix in forward direction, for getting the # proper shift of the image center. A11, A12, A13, \ A21, A22, A23, \ A31, A32, A33 = generate_rotation_matrix(ρ, δ, ρ_h, d) if new_image_center == "old image center": x, y, z = A13 * f_normalized, A23 * f_normalized, A33 * f_normalized elif new_image_center == "control points center": x, y, z = A11 * center_of_control_points_x + A12 * center_of_control_points_y + A13 * f_normalized, \ A21 * center_of_control_points_x + A22 * center_of_control_points_y + A23 * f_normalized, \ A31 * center_of_control_points_x + A32 * center_of_control_points_y + A33 * f_normalized if z <= 0: return False # This is the mapping scale in the image center mapping_scale = f_normalized / z # Central projection through the origin Δa = - x * mapping_scale Δb = - y * mapping_scale # print(ρ * 180 / π, δ * 180 / π, ρ_h * 180 / π, final_rotation * 90) # Finally, generate a rotation matrix in backward (lookup) direction A11, A12, A13, \ A21, A22, A23, \ A31, A32, A33 = generate_rotation_matrix(- ρ_h, - δ, - ρ, d) if final_rotation: # This matrix is: R_y(- ρ) · Rₓ(- δ) · R_y(- ρₕ) · # R_z(final_rotation·π/2). final_rotation is eigher -1 or +1. A11, A12, A13 = final_rotation * A12, - final_rotation * A11, A13 A21, A22, A23 = final_rotation * A22, - final_rotation * A21, A23 A31, A32, A33 = final_rotation * A32, - final_rotation * A31, A33 Δa, Δb = final_rotation * Δb, - final_rotation * Δa # The occurances of mapping_scale here avoid an additional # multiplication in the inner loop of perspective_correction_callback. self.callback_data = A11 * mapping_scale, A12 * mapping_scale, A13, \ A21 * mapping_scale, A22 * mapping_scale, A23, \ A31 * mapping_scale, A32 * mapping_scale, A33, \ f_normalized, Δa / mapping_scale, Δb / mapping_scale return True @staticmethod def perspective_correction_callback(data, iocoord, offset, count): A11, A12, A13, \ A21, A22, A23, \ A31, A32, A33 = data[:9] f_normalized = data[9] Δa, Δb = data[10:12] for i in range(count): x = iocoord[offset + i * 2] - Δa y = iocoord[offset + i * 2 + 1] - Δb z_ = A31 * x + A32 * y + A33 * f_normalized if z_ > 0: x_ = A11 * x + A12 * y + A13 * f_normalized y_ = A21 * x + A22 * y + A23 * f_normalized # Central projection through the origin stretch_factor = f_normalized / z_ iocoord[offset + i * 2] = x_ * stretch_factor iocoord[offset + i * 2 + 1] = y_ * stretch_factor else: iocoord[offset + i * 2] = iocoord[offset + i * 2 + 1] = float("nan") @staticmethod def scaling_callback(data, iocoord, offset, count): scaling = data[0] for i in range(count): iocoord[offset + i * 2] *= scaling iocoord[offset + i * 2 + 1] *= scaling def apply_perspective_correction(self, xu, yu, width, height, res): y = yu * self.norm_scale - self.center_y offset = 0 # In the C code, res itself is moved forward for j in range(height): x = xu * self.norm_scale - self.center_x for i in range(width): res[offset + i * 2] = x res[offset + i * 2 + 1] = y x += self.norm_scale self.scaling_callback([self.scaling_factor], res, offset, width) self.perspective_correction_callback(self.callback_data, res, offset, width) for i in range(width): res[offset] = (res[offset] + self.center_x) * self.norm_unscale res[offset + 1] = (res[offset + 1] + self.center_y) * self.norm_unscale offset += 2 y += self.norm_scale def process_image(filepath, d, index): image_data, width, height = read_image_file(filepath) f, crop_factor, shrinking, x, y = json.load(open(os.path.splitext(filepath)[0] + ".json")) modifier = Modifier(crop_factor, width, height) modifier.initialize(f) if modifier.initialize_perspective_correction(x, y, d): res = array.array("f", width * height * 2 * [0]) modifier.scaling_factor = shrinking modifier.apply_perspective_correction(0, 0, width, height, res) destination_image_data = array.array("B", width * height * 3 * [0]) for y in range(height): for x in range(width): offset = (width * y + x) * 2 try: a = int(round(res[offset])) b = int(round(res[offset + 1])) except ValueError: # NaN continue if 0 <= a < width and 0 <= b < height: destination_offset = (width * y + x) * 3 image_offset = (width * b + a) * 3 destination_image_data[destination_offset] = image_data[image_offset] destination_image_data[destination_offset + 1] = image_data[image_offset + 1] destination_image_data[destination_offset + 2] = image_data[image_offset + 2] else: destination_image_data = image_data basename, extension = os.path.splitext(filepath) write_image_file(destination_image_data, width, height, "{}_{:03}_{}{}".format(basename, index, d, extension)) pool = multiprocessing.Pool() results = set() for filename in sys.argv[1:]: results.add(pool.apply_async(process_image, (filename, 0, 0))) # for i, d in enumerate(numpy.arange(-1, 1.02, 0.02)): # results.add(pool.apply_async(process_image, (filename, d, i))) pool.close() pool.join() for result in results: # Just to get tracebacks if necessary result.get() lensfun-0.3.4/tools/ptlensconv/000077500000000000000000000000001445356770400165425ustar00rootroot00000000000000lensfun-0.3.4/tools/ptlensconv/ptlensconv.py000077500000000000000000000151601445356770400213150ustar00rootroot00000000000000#!/usr/bin/python # # NOTE: Due to simplifications made during PTLens database development, # the resulting files are not 100% accurate. Every output from this script # must be manually reviewed. # # Some things to take care of: many lenses available for several platforms # (for example using the KAF, EFS, Sigma and Nikon mounts) are listed in # PTLens database in the "genericSLR" group, which is translated as "M42" # but in fact the lens must have attached a list of really available mounts. # import sys; from optparse import OptionParser; # This is not the Ultimate Truth, it's rather a try to guess # what the author of PTLens was meaning to say ... KnownMounts = { "canonEfsSLR": "Canon EF-S", "canonSLR": "Canon EF", "genericSLR": "M42", "pentaxSLR": "Pentax KAF2", "contaxSLR": "Contax/Yashica", "minoltaSLR": "Minolta AF", "nikonSLR": "Nikon F AF", "olympusSLR": "4/3 System", }; class Error: def __init__(self, str): self.str = str def __str__(self): return self.str def CompatMount (mount, basemount): global Mounts if not Mounts.has_key (basemount): Mounts [basemount] = [] if mount: if not Mounts [basemount].__contains__ (mount): Mounts [basemount].append (mount) def ParseCamera (lines): global Cameras, KnownMounts cam = {} variant = None for l in lines: l = l.strip () if l [:10] == "menu_make:": if not cam.has_key ("maker"): cam ["maker"] = l [10:].lstrip () elif l [:11] == "menu_model:": variant = l [11:].lstrip () if not cam.has_key ("model"): cam ["model"] = variant elif l [:10] == "exif_make:": l = l [10:].lstrip () if l != "none": cam ["maker"] = l elif l [:11] == "exif_model:": l = l [11:].lstrip () if l != "none": cam ["model"] = l elif l [:6] == "group:": l = l [6:].lstrip () l = KnownMounts.get (l, l) if not cam.has_key ("mount"): cam ["mount"] = l l = None CompatMount (l, cam ["mount"]) elif l [:11] == "multiplier:": cam ["cropfactor"] = l [11:].lstrip () else: raise Error ("Unknown keyword in camera section: " + l) if not cam.has_key ("maker") or not cam.has_key ("model"): print "Camera does not have maker or model defined:", cam return if not cam.has_key ("mount"): print "Camera does not have a mount defined:", cam return if not cam ["model"].lower ().__contains__ (variant.lower ()): cam ["variant"] = variant; Cameras.append (cam) def ParseLens (lines): global Lenses, KnownMounts lens = {} for l in lines: l = l.strip () if l [:10] == "menu_lens:": lens ["model"] = l [10:].lstrip () elif l [:6] == "group:": if not lens.has_key ("mount"): lens ["mount"] = [] l = l [6:].lstrip () lens ["mount"].append (KnownMounts.get (l, l)) elif l [:11] == "multiplier:": lens ["cropfactor"] = l [11:].lstrip () elif l [:10] == "converter_": pass # ignored elif l [:8] == "cal_abc:": if not lens.has_key ("calibration"): lens ["calibration"] = [] l = l [8:].split () l [0] = float (l [0]) l [1] = float (l [1]) l [2] = float (l [2]) l [3] = float (l [3]) lens ["calibration"].append (l) else: raise Error ("Unknown keyword in camera section: " + l) if not lens.has_key ("model"): print "Lens does not have model name defined:", lens return Lenses.append (lens) def WriteOut (ofn): global Mounts, Cameras, Lenses fw = open (ofn, "w") fw.write ("\n\n") for c in Mounts: fw.write (" \n") fw.write (" %s\n" % c) for x in Mounts [c]: fw.write (" %s\n" % x) fw.write (" \n\n") for c in Cameras: fw.write (" \n") fw.write (" %s\n" % c ["maker"]) fw.write (" %s\n" % c ["model"]) if c.has_key ("variant"): fw.write (" %s\n" % c ["variant"]) fw.write (" %s\n" % c ["mount"]) if c.has_key ("cropfactor"): fw.write (" %s\n" % c ["cropfactor"]) fw.write (" \n\n") for c in Lenses: fw.write (" \n") fw.write (" %s\n" % c ["model"]) for m in c ["mount"]: fw.write (" %s\n" % m) if c.has_key ("cropfactor"): fw.write (" %s\n" % c ["cropfactor"]) fw.write (" \n"); for x in c ["calibration"]: fw.write (" \n" % (x [0], x [1], x [2], x [3])) fw.write (" \n"); fw.write (" \n\n") fw.write ("\n") def Parse (fn): global opts print "Parsing %s ..." % fn try: fr = open (fn, "r") lines = [] for l in fr.readlines (): l = l.strip () if l [:1] == "#": continue; elif l [:6] == "begin ": l = l [6:].lstrip () lines = [] if l == "camera": func = ParseCamera elif l == "lens": func = ParseLens else: raise Error ("Unknown section: " + l) elif l == "end": func (lines) else: lines.append (l) name = fn.partition (".") [0] or "" ext = fn.partition (".") [2] or "" WriteOut (opts.Output % {"name": name, "ext": ext}); except Error, e: print "FAILED: ", e parser = OptionParser (usage="%prog [-o FILE] FILE1.txt [FILE2.txt [...]]", version="%prog 0.0.1") parser.add_option("-o", "--output", dest="Output", default="%(name)s.xml", help="write output to FILE", metavar="FILE") (opts, args) = parser.parse_args () if len (args) == 0: parser.print_help () for f in args: Cameras = [] Lenses = [] Mounts = {} Parse (f) lensfun-0.3.4/tools/spline/000077500000000000000000000000001445356770400156415ustar00rootroot00000000000000lensfun-0.3.4/tools/spline/spline.py000077500000000000000000000044361445356770400175170ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: windows-1251 -*- # # Visualization of a Hermite spline. # # Used to evaluate how much differs a two-interpolated-coordinates spline # from a single-interpolated-coordinate variant (which is used to interpolate # lens model terms). # from sys import *; from time import *; from pygame import *; TENSION = 0.5 # 0..1 def spline(P1, P2, P3, P4, t): t2 = t * t; t3 = t2 * t; if P1 != None: tg2 = TENSION * (P3 - P1); else: tg2 = P3 - P2; if P4 != None: tg3 = TENSION * (P4 - P2); else: tg3 = P3 - P2; return (2 * t3 - 3 * t2 + 1) * P2 + \ (t3 - 2 * t2 + t) * tg2 + \ (-2 * t3 + 3 * t2) * P3 + \ (t3 - t2) * tg3; init () dpy = display.set_mode ((800, 800)) WHITE = (255, 255, 255) GREEN = (0, 255, 0) RED = (255, 0, 0) # Control points points = ((10, 10), (100, 200), (200, 300), (300, 500), (400, 400), (500, 500), (600, 200), (700, 100), (790, 790), (790, 790)) # Display a single-interpolated-coordinate spline pi = 0; p2 = (None, None); p3 = points [0]; for x in range(points [0][0], points [len (points) - 1][0]): if (x >= p3 [0]) and (pi < len (points) - 1): p1 = p2; p2 = points [pi]; p3 = points [pi + 1]; if pi < len (points) - 2: p4 = points [pi + 2]; else: p4 = (None, None); pi = pi + 1; t = float (x - p2 [0]) / (p3 [0] - p2 [0]); p = spline (p1 [1], p2 [1], p3 [1], p4 [1], t); draw.line (dpy, WHITE, (x, p), (x, p)); # Display a two-interpolated-coordinates spline p2 = points [0]; p3 = points [0]; p4 = points [0]; for p in points: p1 = p2; p2 = p3; p3 = p4; p4 = p; t = 0.0; while t < 1.0: px = spline (p1 [0], p2 [0], p3 [0], p4 [0], t); py = spline (p1 [1], p2 [1], p3 [1], p4 [1], t); draw.line (dpy, GREEN, (px, py), (px, py)); t = t + 0.01; # Mark control points for p in points: draw.line (dpy, RED, (p [0]-2, p [1]-2), (p [0]+2, p [1]+2)); draw.line (dpy, RED, (p [0]-2, p [1]+2), (p [0]+2, p [1]-2)); # Display the stuff display.flip () # Wait for ESC or close window while True: for e in event.get(): if e.type == QUIT or (e.type == KEYDOWN and e.key == K_ESCAPE): exit () sleep (0.1) lensfun-0.3.4/tools/test_autoscale/000077500000000000000000000000001445356770400173665ustar00rootroot00000000000000lensfun-0.3.4/tools/test_autoscale/test_autoscale.py000066400000000000000000000176751445356770400227770ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- """This program checks the accuracy of Lensfun's autoscaling algorithm. Lensfun calculates the autoscaling by testing all four corner points and the four edge centres. For each of these 8 points, it calculates the scaling necessary, and then takes the maximal value. It calculates the scaling necessary by determining the distance of the point of the corrected image edge which lies in the same direction as the corner point. (Because these two points should lie in top of each other after the autoscaling.) Then, it divides the distance of the corner point by the distance of the corrected edge point. “Distance” means “distance from origin”. The choice of those 8 points is the critical compromise here. In most cases, the maximal scaling is indeed necessary for one of these points. For example, a corrected pincushion distortion pulls the corners most closely to the centre, so they need the maximal scaling. On the other hand, a corrected barrel distorion leaves the edge centres most closely to the origin, so their position is critical. In case of a nasty moustache distortion, the maximal scaling may be inbetween, and in these cases, Lensfun's approach fails. This program shows for which lenses it fails, and how badly. For non-rectilinear lenses, the projection is changed to rectilinear first. Currenly (as of April 2015), there is nothing to worry about. Only three lenses fail, and all of them exhibit only very slim black areas after the correction. If one leaves the original projection, two fisheyes join the pack. The simple reason why the current approach works well is that the used distortion polynomials usually have monotonic behaviour in the important region, so the maximal values are at the borders of the region. This is even more true for projection changes. For problematic lenses, this program prints the number of sampling points on the longer edges necessary to get a decent autoscaling (< 1‰). Lensfun itself only uses 2. If the problem of black areas increases, one can increase the number of edge sampling points to the maximal value this program prints. The only safe approach is to test *all* edge pixels. Really. This is most wasteful in almost all cases, so Lensfun doesn't do it (for now). On the other hand, its complexity is O(size). All other operations of Lensfun are O(size²). """ import math, glob, multiprocessing, argparse, os.path from xml.etree import ElementTree from scipy.optimize import brentq parser = argparse.ArgumentParser(description="Check autoscaling algorithm.") parser.add_argument("database_path", metavar="database_path", help="The full path to the Lensfun database.") parser.add_argument("--original-geometry", dest="original_geometry", action="store_true", help="Use original geometry of fisheyes rather than transforming to rectilinear.") args = parser.parse_args() class Calibration: def __init__(self, f_per_half_height, a=None, b=None, c=None, k1=None, type_="rectilinear", aspect_ratio=1.5): self.f_per_half_height, self.a, self.b, self.c, self.k1, self.type_, self.aspect_ratio = \ f_per_half_height, a, b, c, k1, type_, aspect_ratio def de_ptlens(self, r_): try: return brentq(lambda r: r * (self.a * r**3 + self.b * r**2 + self.c * r + 1 - self.a - self.b - self.c) - r_, 0, 2.1) except ValueError: return float("inf") def de_poly3(self, r_): try: return brentq(lambda r: r * (self.k1 * r**2 + 1 - self.k1) - r_, 0, 2) except ValueError: return float("inf") def de_fisheye(self, r): angle = r / self.f_per_half_height if angle < math.pi / 2: return self.f_per_half_height * math.tan(angle) else: return float("inf") def de_equisolidangle(self, r): try: return self.f_per_half_height * math.tan(2 * math.asin(r / self.f_per_half_height / 2)) except ValueError: return float("inf") def de_stereographic(self, r): angle = 2 * math.atan(r / self.f_per_half_height / 2) if angle < math.pi / 2: return self.f_per_half_height * math.tan(angle) else: return float("inf") def get_scaling(self, x, y): r_ = math.hypot(x, y) r = self.de_poly3(r_) if self.a is None else self.de_ptlens(r_) if self.type_ == "rectilinear" or args.original_geometry: pass elif self.type_ == "fisheye": r = self.de_fisheye(r) elif self.type_ == "equisolid": r = self.de_equisolidangle(r) elif self.type_ == "stereographic": r = self.de_stereographic(r) return r_ / r def get_autoscale(self, samples): scalings = [] for i in range(samples): x = self.aspect_ratio * (-1 + i / samples * 2) scalings.append(self.get_scaling(x, +1)) samples = int(math.ceil(samples / self.aspect_ratio / 2)) * 2 for i in range(samples): y = -1 + i / samples * 2 scalings.append(self.get_scaling(+ self.aspect_ratio, y)) return max(scalings) or 1 def get_perfect_sample_number(self): perfect_autoscale = self.get_autoscale(100) samples = 2 scalings = [] while True: scalings.append(self.get_autoscale(samples)) if all(abs(scaling - perfect_autoscale) / perfect_autoscale < 1e-3 for scaling in scalings[-3:]): return samples samples += 2 def process_calibration(distortion, lens, crop_factor, type_, aspect_ratio): f_per_half_height = float(distortion.attrib.get("focal")) / (12 / crop_factor) model = distortion.attrib.get("model") if model == "ptlens": calibration = Calibration(f_per_half_height, a=float(distortion.attrib.get("a", 0)), b=float(distortion.attrib.get("b", 0)), c=float(distortion.attrib.get("c", 0)), type_=type_, aspect_ratio=aspect_ratio) elif model == "poly3": calibration = Calibration(f_per_half_height, k1=float(distortion.attrib.get("k1", 0)), type_=type_, aspect_ratio=aspect_ratio) else: return None, None, None return lens.find("model").text, distortion.attrib.get("focal"), calibration.get_perfect_sample_number() results = set() pool = multiprocessing.Pool() for filename in glob.glob(os.path.join(args.database_path, "*.xml")): tree = ElementTree.parse(filename) for lens in tree.findall("lens"): type_element = lens.find("type") type_ = "rectilinear" if type_element is None else type_element.text.strip() crop_factor = float(lens.find("cropfactor").text) aspect_ratio_element = lens.find("aspect-ratio") if aspect_ratio_element is None: aspect_ratio = 1.5 else: numerator, __, denominator = aspect_ratio_element.text.partition(":") if denominator: aspect_ratio = float(numerator) / float(denominator) else: aspect_ratio = float(numerator) calibration_element = lens.find("calibration") if calibration_element is not None: for distortion in calibration_element.findall("distortion"): results.add(pool.apply_async(process_calibration, (distortion, lens, crop_factor, type_, aspect_ratio))) pool.close() pool.join() problematic_lenses = {} for result in results: model, focal_length, perfect_sample_number = result.get() if perfect_sample_number and perfect_sample_number > 2: problematic_lenses.setdefault(perfect_sample_number, set()).add((model, focal_length)) if problematic_lenses: print("Number of equidistant samples on the long edge:\n") for perfect_sample_number, lenses in problematic_lenses.items(): print(",\n".join("{} at {}mm".format(*lens) for lens in lenses), ": ", perfect_sample_number) lensfun-0.3.4/tools/testimage/000077500000000000000000000000001445356770400163315ustar00rootroot00000000000000lensfun-0.3.4/tools/testimage/testimage.py000066400000000000000000000561741445356770400207020ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- """This program generates a bitmap which simulates lens errors. Then, Lensfun can be used to rectify them. This way, one can check whether Lensfun is working properly. The test image contains vignetting and a rectangular grid. The grid lines exhibit distortion and TCA. The lens projection can be non-rectilinear. External dependencies: Python version 3, ImageMagick, exiv2. The program takes the lens parameters from Lensfun's database. To the usual search path it adds the current path (the xml files of which would override those found in the usual locations). As for the used camera, it takes the crop factor from the database. The aspect ratio needs to be provided on the command line. It is sensible to read the help output of this program (the --help option). The following things are particularly interesting to check: 1. Vignetting, TCA, and distortion need to be corrected fully (apart from rounding errors) Note that for seeing the perfect grid, you must transform fisheyes into rectilinear. 2. Vignetting has to be corrected first, then TCA, then distortion. This is because this is the way they are calibrated: Vignetting is calibrated on a totally uncorrected image. TCA is so, too, however, TCA doesn't care about vignetting noticably. Well, and then the image is un-distorted. Note that Lensfun seems to work the other way round. But this is only because it uses the corrected destination image as the starting point: It uses the distortion formula to find the pixel on the distorted sensor image, then it applies the TCA correction formula to find the subpixel position, and finally, it applies the vignetting. 3. If he crop factor of the camera does not match the one of the calibration, it must work nevertheless. If you have a sensor smaller than the one used for calibration, this program testimage.py has an easy job: It just has to use the corresponsing inner part of the resulting picture. However, for Lensfun, it is more difficult because it works on the destination image. But is must still work properly. 4. If the aspect ratio of the camera does not match the one of the calibration, it must work nevertheless. Classical case: Calibration with APS-C, but to-be-corrected image taken with a Four-Thirds sensor. 5. An insanely small calibration sensor must not affect pure geometry transformation. I stumbled upon this one accidentally. If the cropfactor of the tag is very large, e.g. 10 or 100, a correction is rejected because the to-be-corrected sensor is larger (much larger actually). However, one can use at least convert from fisheye to rectilinear, where the cropfactor of the calibration sensor should not matter. Due to ``size - 1`` occurences in modifier.cpp, strange things happened, because the ``size`` didn't refer to pixel size at this point. """ import array, subprocess, math, os, argparse, sys from math import sin, tan, atan, floor, ceil, sqrt from math import pi as π from xml.etree import ElementTree import lensfun parser = argparse.ArgumentParser(description="Generate test images for Lensfun.") parser.add_argument("lens_model_name", metavar="lens", help="Lens model name. Must match an entry in Lensfun's database exactly.") parser.add_argument("camera_model_name", metavar="camera", help="Camera model name. Must match an entry in Lensfun's database exactly.") parser.add_argument("focal_length", type=float, help="Focal length in mm. Must match an entry in Lensfun's database exactly, no interpolation is done.") parser.add_argument("aperture", type=float, help="Aperture in f-stops. Must match an entry in Lensfun's database exactly, no interpolation is done.") parser.add_argument("distance", type=float, help="Distance in metres. Must match an entry in Lensfun's database exactly, no interpolation is done.") parser.add_argument("--width", type=int, default=600, help="The resulting bitmap's long edge width in pixels. Default: 600") parser.add_argument("--aspect-ratio", type=float, default=1.5, help="The resulting bitmap's aspect ratio, >= 1. Default: 1.5") parser.add_argument("--portrait", action="store_true", help="Whether the resulting bitmap should be in portrait orientation. Default: landscape") parser.add_argument("--outfile", default="testimage.tiff", help="Path to the output file. Default: testimage.tiff") parser.add_argument("--db-path", help="Path to the database. If not given, look in the same places as Lensfun.") parser.add_argument("--no-vignetting", dest="vignetting", action="store_false", help="Supresses simulation of vignetting. *Much* faster.") args = parser.parse_args() lens_model_name, camera_model_name, focal_length, aperture, distance = \ args.lens_model_name, args.camera_model_name, args.focal_length, args.aperture, args.distance focal_length, aperture, distance = float(focal_length), float(aperture), float(distance) width, aspect_ratio, portrait = args.width, args.aspect_ratio, args.portrait def get_database_elements(): lens_element = camera_element = None distortion_element = tca_element = vignetting_element = real_focal_length_element = fov_element = None files_found = False def crawl_directory(dirpath): nonlocal lens_element, camera_element, distortion_element, tca_element, vignetting_element, real_focal_length_element, \ fov_element, files_found for root, __, filenames in os.walk(dirpath): for filename in filenames: if filename.endswith(".xml"): files_found = True tree = ElementTree.parse(os.path.join(root, filename)).getroot() for element in tree: if camera_element is None and \ element.tag == "camera" and element.find("model").text == camera_model_name: camera_element = element elif element.tag == "lens" and element.find("model").text == lens_model_name: if lens_element is not None: print("This program cannot handle lens model names that occur multiple times in the\n" "read XML files. Please use another lens.") sys.exit(1) lens_element = element if element.find("calibration") is not None: for calibration_element in element.find("calibration"): if calibration_element.tag == "distortion" and \ float(calibration_element.attrib["focal"]) == focal_length: distortion_element = calibration_element elif calibration_element.tag == "tca" and \ float(calibration_element.attrib["focal"]) == focal_length: tca_element = calibration_element elif calibration_element.tag == "vignetting" and \ float(calibration_element.attrib["focal"]) == focal_length and \ float(calibration_element.attrib["aperture"]) == aperture and \ float(calibration_element.attrib["distance"]) == distance: vignetting_element = calibration_element elif calibration_element.tag == "real-focal-length" and \ float(calibration_element.attrib["focal"]) == focal_length: real_focal_length_element = calibration_element elif calibration_element.tag == "field_of_view" and \ float(calibration_element.attrib["focal"]) == focal_length: fov_element = calibration_element paths_search_list = [args.db_path] if args.db_path else lensfun.get_database_directories() for path in paths_search_list: crawl_directory(path) if not files_found: print("No XML files found.") sys.exit(1) if lens_element is None: print("Lens model name not found.") sys.exit(1) if camera_element is None: print("Camera model name not found.") sys.exit(1) return lens_element, camera_element, distortion_element, tca_element, vignetting_element, real_focal_length_element, fov_element lens_element, camera_element, distortion_element, tca_element, vignetting_element, real_focal_length_element, fov_element = \ get_database_elements() camera_cropfactor = float(camera_element.find("cropfactor").text) lens_cropfactor = float(lens_element.find("cropfactor").text) R_cf = lens_cropfactor / camera_cropfactor if lens_element.find("center") is not None: center_x = float(lens_element.find("center").get("x", "0")) center_y = float(lens_element.find("center").get("y", "0")) else: center_x = center_y = 0 def get_lens_aspect_ratio(lens_element): try: aspect_ratio = lens_element.find("aspect-ratio").text except AttributeError: return 1.5 if ":" in aspect_ratio: numerator, denominator = aspect_ratio.split(":") return int(numerator) / int(denominator) return float(aspect_ratio) lens_aspect_ratio = get_lens_aspect_ratio(lens_element) def get_float_attribute(element, attribute_name, default=0): try: return float(element.attrib[attribute_name]) except KeyError: return default try: lens_type = lens_element.find("type").text except AttributeError: lens_type = "rectilinear" def get_hugin_correction(): """Get the correction factor for the focal length. This is necessary because the Hugin distortion models PTLens and Poly3 menipulate the focal length. """ if distortion_element is not None: model = distortion_element.attrib["model"] if model == "ptlens": a = get_float_attribute(distortion_element, "a") b = get_float_attribute(distortion_element, "b") c = get_float_attribute(distortion_element, "c") return 1 - a - b - c elif model == "poly3": k1 = get_float_attribute(distortion_element, "k1") return 1 - k1 return 1 hugin_correction = get_hugin_correction() def get_real_focal_length(): if real_focal_length_element is not None: return float(real_focal_length_element.attrib["real-focal"]) elif fov_element is not None: fov = float(fov_element.attrib["fov"]) * π / 180 half_width_in_millimeters = \ sqrt(36**2 + 24**2) / 2 / sqrt(lens_aspect_ratio**2 + 1) * lens_aspect_ratio / lens_cropfactor if lens_type == "stereographic": result = half_width_in_millimeters / (2 * tan(fov / 4)) elif lens_type in ["fisheye", "panoramic", "equirectangular"]: result = half_width_in_millimeters / (fov / 2) elif lens_type == "orthographic": result = half_width_in_millimeters / sin(fov / 2) elif lens_type == "equisolid": result = half_width_in_millimeters / (2 * sin(fov / 4)) elif lens_type == "fisheye_thoby": result = half_width_in_millimeters / (1.47 * sin(0.713 * fov / 2)) else: assert lens_type == "rectilinear" result = half_width_in_millimeters / tan(fov / 2) return result * hugin_correction else: # Interpret the nominal focal length Hugin-compatibly; it's guesswork # and a fallback anyway. return focal_length * hugin_correction def get_projection_function(): projection = None if lens_type == "stereographic": def projection(ϑ): return 2 * tan(ϑ / 2) elif lens_type == "fisheye": def projection(ϑ): return ϑ elif lens_type == "panoramic": assert False, "Panoramic lenses are not yet supported." elif lens_type == "equirectangular": assert False, "Equirectangular lenses are not yet supported." elif lens_type == "orthographic": def projection(ϑ): return sin(ϑ) elif lens_type == "equisolid": def projection(ϑ): return 2 * sin(ϑ / 2) elif lens_type == "fisheye_thoby": def projection(ϑ): return 1.47 * sin(0.713 * ϑ) return projection projection = get_projection_function() def get_distortion_function(): def distortion(r): return r if distortion_element is not None: model = distortion_element.attrib["model"] if model == "ptlens": a = get_float_attribute(distortion_element, "a") b = get_float_attribute(distortion_element, "b") c = get_float_attribute(distortion_element, "c") def distortion(r): return a * r**4 + b * r**3 + c * r**2 + (1 - a - b - c) * r elif model == "poly3": k1 = get_float_attribute(distortion_element, "k1") def distortion(r): return k1 * r**3 + (1 - k1) * r elif model == "poly5": k1 = get_float_attribute(distortion_element, "k1") k2 = get_float_attribute(distortion_element, "k2") def distortion(r): return r * (1 + k1 * r**2 + k2 * r**4) return distortion distortion = get_distortion_function() def get_tca_functions(): def tca_red(r): return r def tca_blue(r): return r if tca_element is not None: model = tca_element.attrib["model"] if model == "linear": kr = get_float_attribute(tca_element, "kr", 1) def tca_red(r): return r * kr kb = get_float_attribute(tca_element, "kb", 1) def tca_blue(r): return r * kb elif model == "poly3": br = get_float_attribute(tca_element, "br") cr = get_float_attribute(tca_element, "cr") vr = get_float_attribute(tca_element, "vr", 1) def tca_red(r): return r**3 * br + r**2 * cr + r * vr bb = get_float_attribute(tca_element, "bb") cb = get_float_attribute(tca_element, "cb") vb = get_float_attribute(tca_element, "vb", 1) def tca_blue(r): return r**3 * bb + r**2 * cb + r * vb return tca_red, tca_blue tca_red, tca_blue = get_tca_functions() def get_vignetting_function(): def vignetting(r): return 1 if vignetting_element is not None: model = vignetting_element.attrib["model"] if model == "pa": k1 = get_float_attribute(vignetting_element, "k1") k2 = get_float_attribute(vignetting_element, "k2") k3 = get_float_attribute(vignetting_element, "k3") def vignetting(r): return 1 + k1 * r**2 + k2 * r**4 + k3 * r**6 return vignetting vignetting = get_vignetting_function() class Image: def __init__(self, width, height): """width and height in pixels.""" self.pixels = array.array("H", width * height * 3 * [16383]) self.width = width self.height = height self.half_height = height / 2 self.half_width = width / 2 self.half_diagonal = sqrt(width**2 + height**2) / 2 self.pixel_scaling = (self.height - 1) / 2 # This factor transforms from the vignetting cooredinate system of the # to-be-corrected sensor to its distortion coordinate system. self.aspect_ratio_correction = sqrt(aspect_ratio**2 + 1) # This factor transforms from the distortion coordinate system of the # to-be-corrected sensor to the distortion coordinate system of the # calibration sensor. self.ar_plus_cf_correction = (1 / self.aspect_ratio_correction) * R_cf * sqrt(lens_aspect_ratio**2 + 1) def add_to_pixel(self, x, y, weighting, red, green, blue): """Adds the given brightness (from 0 to 1) to the pixel at the position x, y. `weighting` is multiplied with `red`, `green`, and `blue` before it is added, so it is some sort of opacity. Coordinates must be integers. Coordinates outside the picture are ignored. """ if 0 < x < self.width and 0 < y < self.height: offset = 3 * (y * width + x) weighting *= 65535 self.pixels[offset] = max(min(self.pixels[offset] + int(red * weighting), 65535), 0) self.pixels[offset + 1] = max(min(self.pixels[offset + 1] + int(green * weighting), 65535), 0) self.pixels[offset + 2] = max(min(self.pixels[offset + 2] + int(blue * weighting), 65535), 0) def add_to_position(self, x, y, red, green, blue): """Adds the given brightness (from 0 to 1) to the pixel at the position x, y. x = y = 0 is the image centre. The special bit here is that x and y are floats in the relative Hugin distortion coordinate system, and bilinear interpolation is performed. """ x = (x + aspect_ratio + center_x) * self.pixel_scaling y = (y + 1 + center_y) * self.pixel_scaling floor_x = int(floor(x)) floor_y = int(floor(y)) ceil_x = int(ceil(x)) if x != floor_x else int(x) + 1 ceil_y = int(ceil(y)) if y != floor_y else int(y) + 1 self.add_to_pixel(floor_x, floor_y, (ceil_x - x) * (ceil_y - y), red, green, blue) self.add_to_pixel(floor_x, ceil_y, (ceil_x - x) * (y - floor_y), red, green, blue) self.add_to_pixel(ceil_x, floor_y, (x - floor_x) * (ceil_y - y), red, green, blue) self.add_to_pixel(ceil_x, ceil_y, (x - floor_x) * (y - floor_y), red, green, blue) def r_vignetting(self, x, y): """Returns the r coordinate in the calibration coordinate system to the pixel coordinates (x, y) for vignetting, i.e. r = 1 is half-diagonal. """ x = x / self.pixel_scaling - aspect_ratio - center_x y = y / self.pixel_scaling - 1 - center_y return sqrt(x**2 + y**2) / self.aspect_ratio_correction * R_cf def set_vignetting(self, function): for y in range(self.height): for x in range(self.width): offset = 3 * (y * self.width + x) for index in range(3): self.pixels[offset + index] = \ max(min(int(self.pixels[offset + index] * function(self.r_vignetting(x, y))), 65535), 0) def rotate_by_90_degrees(self): """This changes the orientation to portrait. Use this method shortly before writing the image, because further operations (creating grid etc) are undefined. """ new_pixels = array.array("H", self.width * self.height * 3 * [0]) for y in range(self.height): for x in range(self.width): offset_source = 3 * (y * self.width + x) offset_destination = 3 * ((self.width - x - 1) * self.height + y) new_pixels[offset_destination] = self.pixels[offset_source] new_pixels[offset_destination + 1] = self.pixels[offset_source + 1] new_pixels[offset_destination + 2] = self.pixels[offset_source + 2] self.pixels = new_pixels self.width, self.height = self.height, self.width def write(self, filepath): """Writes the image to a file. If it is a TIFF or a JPEG, EXIF information is written, too. ImageMagick and exiv2 are needed for anything beyond PPM output. """ self.pixels.byteswap() ppm_data = "P6\n{} {}\n65535\n".format(self.width, self.height).encode("ascii") + self.pixels.tostring() self.pixels.byteswap() if filepath.endswith(".ppm"): open(filepath, "wb").write(ppm_data) else: subprocess.Popen( ["convert", "ppm:-", "-set", "colorspace", "RGB", filepath], stdin=subprocess.PIPE).communicate(ppm_data) if os.path.splitext(filepath)[1].lower() in [".tiff", ".tif", ".jpeg", "jpg"]: subprocess.call(["exiv2", "-Mset Exif.Photo.FocalLength {}/10".format(int(focal_length * 10)), "-Mset Exif.Photo.FNumber {}/10".format(int(aperture * 10)), "-Mset Exif.Photo.SubjectDistance {}/10".format(int(distance * 10)), "-Mset Exif.Photo.LensModel {}".format(lens_model_name), "-Mset Exif.Image.Model {}".format(camera_model_name), "-Mset Exif.Image.Make {}".format(camera_element.find("maker").text), filepath]) def create_grid(self, distortion, projection, tca_red, tca_blue): full_frame_diagonal = sqrt(36**2 + 24**2) diagonal_by_focal_length = full_frame_diagonal / 2 / camera_cropfactor / (get_real_focal_length() / hugin_correction) def apply_lens_projection(x, y): r_vignetting = sqrt(x**2 + y**2) / self.aspect_ratio_correction ϑ = atan(r_vignetting * diagonal_by_focal_length) scaling = (projection(ϑ) / diagonal_by_focal_length) / r_vignetting return x * scaling, y * scaling line_brightness = 0.4 def set_pixel(x, y): """y goes from -1 to 1, x domain depends on aspect ratio.""" if x == y == 0: self.add_to_position(0, 0, 1, 1, 1) else: # 1. Lens projection (fisheye etc) if projection: x, y = apply_lens_projection(x, y) # 2. Distortion on top of that r = sqrt(x**2 + y**2) * self.ar_plus_cf_correction r_distorted = distortion(r) distortion_scaling = r_distorted / r x *= distortion_scaling y *= distortion_scaling self.add_to_position(x, y, 0, line_brightness, 0) # 3. TCA of red and blue channels on top of that tca_scaling = tca_red(r_distorted) / r_distorted self.add_to_position(x * tca_scaling, y * tca_scaling, line_brightness, 0, 0) tca_scaling = tca_blue(r_distorted) / r_distorted self.add_to_position(x * tca_scaling, y * tca_scaling, 0, 0, line_brightness) number_of_lines = 30 for i in range(number_of_lines + 1): points_per_line = self.width y = i * (2 / number_of_lines) - 1 for j in range(points_per_line): x = j * (2 * lens_aspect_ratio / points_per_line) - lens_aspect_ratio set_pixel(x, y) points_per_line = self.height x = i * (2 * lens_aspect_ratio / number_of_lines) - lens_aspect_ratio for j in range(points_per_line + 1): y = j * (2 / points_per_line) - 1 set_pixel(x, y) image = Image(width, int(round(width / aspect_ratio))) image.create_grid(distortion, projection, tca_red, tca_blue) if args.vignetting: image.set_vignetting(vignetting) if portrait: image.rotate_by_90_degrees() image.write(args.outfile) lensfun-0.3.4/tools/update_database/000077500000000000000000000000001445356770400174555ustar00rootroot00000000000000lensfun-0.3.4/tools/update_database/generate_database_tarballs.py000066400000000000000000000133541445356770400253370ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- """Generator for database tarballs, in different Lensfun versions. This program is intended to run as a cronjob, and possibly be run as needed. It creates a versions.json file and tarballs in the given output directory. If desired, it also pushes its content to sourceforge.de. If a new database version is created in Lensfun, you must add a new `Converter` class. Simply use `From1to0` as a starting point. You prepend the decorator `@converter` so that the rest of the program finds the new class. The rest is automatic. Note that this script also creates a database with version 0. This may be downloaded manually by people who use Lensfun <= 0.2.8. """ import glob, os, subprocess, calendar, json, time, tarfile, io, argparse, shutil from lxml import etree root = "/tmp/" parser = argparse.ArgumentParser(description="Generate tar balls of the Lensfun database, also for older versions.") parser.add_argument("output_path", help="Directory where to put the XML files. They are put in the db/ subdirectory. " "It needn't exist yet.") parser.add_argument("--upload", action="store_true", help="Upload the files to Sourceforge, too.") args = parser.parse_args() class XMLFile: def __init__(self, root, filepath): self.filepath = filepath self.tree = etree.parse(os.path.join(root, filepath)) @staticmethod def indent(tree, level=0): i = "\n" + level*" " if len(tree): if not tree.text or not tree.text.strip(): tree.text = i + " " if not tree.tail or not tree.tail.strip(): tree.tail = i for tree in tree: XMLFile.indent(tree, level + 1) if not tree.tail or not tree.tail.strip(): tree.tail = i else: if level and (not tree.tail or not tree.tail.strip()): tree.tail = i def write_to_tar(self, tar): tarinfo = tarfile.TarInfo(self.filepath) root = self.tree.getroot() self.indent(root) content = etree.tostring(root, encoding="utf-8") tarinfo.size = len(content) tarinfo.mtime = timestamp tar.addfile(tarinfo, io.BytesIO(content)) def fetch_xml_files(): try: os.chdir(root + "lensfun-git") except FileNotFoundError: os.chdir(root) subprocess.check_call(["git", "clone", "git://git.code.sf.net/p/lensfun/code", "lensfun-git"], stdout=open(os.devnull, "w"), stderr=open(os.devnull, "w")) else: subprocess.check_call(["git", "pull"], stdout=open(os.devnull, "w"), stderr=open(os.devnull, "w")) os.chdir(root + "lensfun-git/data/db") xml_filenames = glob.glob("*.xml") xml_files = set(XMLFile(os.getcwd(), filename) for filename in xml_filenames) timestamp = int(subprocess.check_output(["git", "log", "-1", '--format=%ad', "--date=raw", "--"] + xml_filenames). \ decode("utf-8").split()[0]) return xml_files, timestamp xml_files, timestamp = fetch_xml_files() class Converter: from_version = None to_version = None def __call__(self, tree): root = tree.getroot() if self.to_version == 0: if "version" in root.attrib: del root.attrib["version"] else: root.attrib["version"] = str(self.to_version) converters = [] current_version = 0 def converter(converter_class): global current_version current_version = max(current_version, converter_class.from_version) converters.append(converter_class()) return converter_class @converter class From1To0(Converter): from_version = 1 to_version = 0 @staticmethod def round_aps_c_cropfactor(lens_or_camera): element = lens_or_camera.find("cropfactor") if element is not None: cropfactor = float(element.text) if 1.5 < cropfactor < 1.56: element.text = "1.5" elif 1.6 < cropfactor < 1.63: element.text = "1.6" def __call__(self, tree): super().__call__(tree) for lens in tree.findall("lens"): element = lens.find("aspect-ratio") if element is not None: lens.remove(element) calibration = lens.find("calibration") if calibration is not None: for real_focal_length in calibration.findall("real-focal-length"): # Note that while one could convert it to the old # element, we simply remove it. It is not # worth the effort. calibration.remove(real_focal_length) self.round_aps_c_cropfactor(lens) for camera in tree.findall("camera"): self.round_aps_c_cropfactor(camera) output_path = os.path.join(args.output_path, "db") shutil.rmtree(output_path, ignore_errors=True) os.makedirs(output_path) metadata = [timestamp, [], []] while True: metadata[1].insert(0, current_version) tar = tarfile.open(os.path.join(output_path, "version_{}.tar.bz2".format(current_version)), "w:bz2") for xml_file in xml_files: xml_file.write_to_tar(tar) tar.close() try: converter_instance = converters.pop() except IndexError: break assert converter_instance.from_version == current_version for xml_file in xml_files: converter_instance(xml_file.tree) current_version = converter_instance.to_version json.dump(metadata, open(os.path.join(output_path, "versions.json"), "w")) if args.upload: subprocess.check_call(["rsync", "-a", "--delete", output_path if output_path.endswith("/") else output_path + "/", "web.sourceforge.net:/home/project-web/lensfun/htdocs/db"])