├── data └── db │ ├── timestamp.txt │ ├── slr-panasonic.xml │ ├── mil-tokina.xml │ ├── slr-soligor.xml │ ├── slr-hasselblad.xml │ ├── slr-samsung.xml │ ├── mil-pentax.xml │ ├── slr-leica.xml │ ├── mil-leica.xml │ ├── contax.xml │ ├── rf-leica.xml │ ├── compact-kodak.xml │ ├── slr-vivitar.xml │ ├── slr-ricoh.xml │ ├── slr-schneider.xml │ ├── lensfun-database.dtd │ ├── compact-sigma.xml │ ├── 6x6.xml │ └── compact-leica.xml ├── tools ├── calibration_webserver │ ├── __init__.py │ ├── calibration │ │ ├── __init__.py │ │ ├── templates │ │ │ ├── 404.html │ │ │ └── calibration │ │ │ │ ├── success.html │ │ │ │ ├── error.html │ │ │ │ ├── pending.html │ │ │ │ ├── base.html │ │ │ │ ├── missing_exif.html │ │ │ │ ├── good_bad_ugly.html │ │ │ │ └── upload.html │ │ ├── static │ │ │ └── calibration │ │ │ │ ├── images │ │ │ │ ├── no_long_line.jpg │ │ │ │ ├── too_far_away.jpg │ │ │ │ └── good_test_picture.jpg │ │ │ │ └── css │ │ │ │ └── main.css │ │ ├── urls.py │ │ └── context_processors.py │ ├── manage.py │ ├── django.wsgi │ ├── calibration_webserver.ini │ ├── utils.py │ ├── README.rst │ ├── workflow.rst │ ├── owncloud.py │ └── settings.py ├── vagrant │ ├── clean.sh │ ├── buildpackages.sh │ └── Vagrantfile ├── abi-compliance-check │ ├── LF_tmp_new.xml │ ├── LF_tmp_old.xml │ └── run_check.sh ├── perspective_control │ ├── testimages │ │ ├── DSC02279.json │ │ ├── DSC02275.png │ │ ├── DSC02277.png │ │ ├── DSC02278.png │ │ ├── DSC02279.png │ │ ├── DSC02280.png │ │ ├── DSC02281.png │ │ ├── DSC02384.png │ │ ├── DSC02275.json │ │ ├── DSC02277.json │ │ ├── DSC02281.json │ │ ├── DSC02384.json │ │ ├── DSC02278.json │ │ └── DSC02281_with_7_points.json │ └── test_image.svg ├── check_database │ ├── reformat_database.sh │ ├── min_max_parameters.py │ └── check_database.py ├── git-hooks │ ├── post-commit │ └── pre-commit ├── calibration_statistics │ └── README.rst ├── calibrate │ └── nd_correction.py ├── find_missing_cameras │ └── find_missing_cameras.py ├── spline │ └── spline.py └── database-ng │ └── transform_db.py ├── docs ├── mathjaxConfiguration.js ├── images │ └── pc-examples.svg.gz ├── calibration_tutorial │ ├── DSC03194.jpg │ ├── hugin_half.png │ ├── vignetting_setup.jpg │ ├── vignetting_setup_tn.jpg │ └── lens.cpp.patch ├── lensfun-manual.css ├── man │ ├── README │ ├── g-lensfun-update-data.1.rst │ ├── lensfun-update-data.1.rst │ ├── lensfun-convert-lcp.1.rst │ └── lensfun-add-adapter.1.rst ├── footer.html ├── CMakeLists.txt ├── mounts.txt └── example │ └── example.c ├── libs ├── getopt │ ├── CMakeLists.txt │ └── getopt.h ├── CMakeLists.txt └── lensfun │ ├── lensfun.pc.cmake │ ├── windows │ └── mathconstants.h │ ├── CMakeLists.txt │ ├── mod-color-sse.cpp │ ├── camera.cpp │ └── mount.cpp ├── apps ├── g-lensfun-update-data ├── setup.py.in ├── CMakeLists.txt ├── lensfun │ └── __init__.py.in └── lenstool │ ├── auxfun.h │ ├── rgbpixel.h │ └── image.h ├── tests ├── common_code.hpp ├── README.md ├── test_lffuzzystrcmp.cpp ├── test_modifier_coord_tiny_image.cpp ├── test_modifier_coord_tiny_image_old.cpp ├── test_database_old.cpp ├── test_modifier_performance.cpp ├── test_modifier_coord_centering.cpp ├── test_lens.cpp ├── test_modifier_coord_centering_old.cpp ├── test_database.cpp ├── test_modifier_coord_scale.cpp ├── test_modifier.cpp ├── test_modifier_coord_scale_old.cpp └── test_modifier_old.cpp ├── cmake └── modules │ ├── toolchain_win32.cmake │ └── FindGLIB2.cmake ├── .github └── workflows │ └── cmake.yml ├── include └── lensfun │ └── config.h.in.cmake └── appveyor.yml /data/db/timestamp.txt: -------------------------------------------------------------------------------- 1 | 1577948414 2 | -------------------------------------------------------------------------------- /tools/calibration_webserver/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/vagrant/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -Rf ../../lensfun* ../../liblensfun* 4 | -------------------------------------------------------------------------------- /docs/mathjaxConfiguration.js: -------------------------------------------------------------------------------- 1 | MathJax.Hub.Config({ 2 | messageStyle: "none" 3 | }); 4 | -------------------------------------------------------------------------------- /docs/images/pc-examples.svg.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/lensfun/master/docs/images/pc-examples.svg.gz -------------------------------------------------------------------------------- /docs/calibration_tutorial/DSC03194.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/lensfun/master/docs/calibration_tutorial/DSC03194.jpg -------------------------------------------------------------------------------- /docs/calibration_tutorial/hugin_half.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/lensfun/master/docs/calibration_tutorial/hugin_half.png -------------------------------------------------------------------------------- /tools/abi-compliance-check/LF_tmp_new.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | LF_new/include 4 | 5 | LF_new/lib 6 | -------------------------------------------------------------------------------- /tools/abi-compliance-check/LF_tmp_old.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | LF_old/include 4 | 5 | LF_old/lib 6 | -------------------------------------------------------------------------------- /libs/getopt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_LIBRARY(getopt STATIC getopt.c getopt.h) 2 | TARGET_INCLUDE_DIRECTORIES(getopt PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -------------------------------------------------------------------------------- /apps/g-lensfun-update-data: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | lensfun-update-data 4 | 5 | if [ $? -eq 2 ] ; then 6 | gksudo lensfun-update-data 7 | fi 8 | -------------------------------------------------------------------------------- /tools/perspective_control/testimages/DSC02279.json: -------------------------------------------------------------------------------- 1 | [ 2 | "DSC02279.png", 3 | 50.89, 4 | 1.534, 5 | 1, 6 | [], 7 | [] 8 | ] 9 | -------------------------------------------------------------------------------- /docs/calibration_tutorial/vignetting_setup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/lensfun/master/docs/calibration_tutorial/vignetting_setup.jpg -------------------------------------------------------------------------------- /docs/calibration_tutorial/vignetting_setup_tn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/lensfun/master/docs/calibration_tutorial/vignetting_setup_tn.jpg -------------------------------------------------------------------------------- /tools/perspective_control/testimages/DSC02275.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/lensfun/master/tools/perspective_control/testimages/DSC02275.png -------------------------------------------------------------------------------- /tools/perspective_control/testimages/DSC02277.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/lensfun/master/tools/perspective_control/testimages/DSC02277.png -------------------------------------------------------------------------------- /tools/perspective_control/testimages/DSC02278.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/lensfun/master/tools/perspective_control/testimages/DSC02278.png -------------------------------------------------------------------------------- /tools/perspective_control/testimages/DSC02279.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/lensfun/master/tools/perspective_control/testimages/DSC02279.png -------------------------------------------------------------------------------- /tools/perspective_control/testimages/DSC02280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/lensfun/master/tools/perspective_control/testimages/DSC02280.png -------------------------------------------------------------------------------- /tools/perspective_control/testimages/DSC02281.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/lensfun/master/tools/perspective_control/testimages/DSC02281.png -------------------------------------------------------------------------------- /tools/perspective_control/testimages/DSC02384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/lensfun/master/tools/perspective_control/testimages/DSC02384.png -------------------------------------------------------------------------------- /libs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_SUBDIRECTORY(lensfun) 2 | 3 | # also build getopt on windows 4 | IF(WIN32 AND BUILD_LENSTOOL) 5 | ADD_SUBDIRECTORY(getopt) 6 | ENDIF() 7 | -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration/templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends "calibration/base.html" %} 2 | 3 | {% block content %} 4 |

Page not found.

5 | {% endblock %} 6 | -------------------------------------------------------------------------------- /tools/perspective_control/testimages/DSC02275.json: -------------------------------------------------------------------------------- 1 | [ 2 | "DSC02275.png", 3 | 50.89, 4 | 1.534, 5 | 1, 6 | [503, 1063, 509, 1066], 7 | [150, 197, 860, 759] 8 | ] 9 | -------------------------------------------------------------------------------- /tools/perspective_control/testimages/DSC02277.json: -------------------------------------------------------------------------------- 1 | [ 2 | "DSC02277.png", 3 | 50.89, 4 | 1.534, 5 | 1, 6 | [145, 208, 748, 850], 7 | [1060, 666, 668, 1060] 8 | ] 9 | -------------------------------------------------------------------------------- /tools/perspective_control/testimages/DSC02281.json: -------------------------------------------------------------------------------- 1 | [ 2 | "DSC02281.png", 3 | 50.89, 4 | 1.534, 5 | 1, 6 | [661, 594, 461, 426, 530], 7 | [501, 440, 442, 534, 562] 8 | ] 9 | -------------------------------------------------------------------------------- /tools/perspective_control/testimages/DSC02384.json: -------------------------------------------------------------------------------- 1 | [ 2 | "DSC02384.png", 3 | 21, 4 | 1.534, 5 | 1, 6 | [1043, 903, 1105, 1300, 1043, 1300], 7 | [947, 832, 822, 930, 947, 930] 8 | ] 9 | -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration/static/calibration/images/no_long_line.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/lensfun/master/tools/calibration_webserver/calibration/static/calibration/images/no_long_line.jpg -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration/static/calibration/images/too_far_away.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/lensfun/master/tools/calibration_webserver/calibration/static/calibration/images/too_far_away.jpg -------------------------------------------------------------------------------- /tools/perspective_control/testimages/DSC02278.json: -------------------------------------------------------------------------------- 1 | [ 2 | "DSC02278.png", 3 | 50.89, 4 | 1.534, 5 | 1, 6 | [615, 264, 1280, 813, 615, 1280, 264, 813], 7 | [755, 292, 622, 220, 755, 622, 292, 220] 8 | ] 9 | -------------------------------------------------------------------------------- /tools/perspective_control/testimages/DSC02281_with_7_points.json: -------------------------------------------------------------------------------- 1 | [ 2 | "DSC02281.png", 3 | 50.89, 4 | 1.534, 5 | 1, 6 | [661, 594, 461, 426, 530, 302, 815], 7 | [501, 440, 442, 534, 562, 491, 279] 8 | ] 9 | -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration/static/calibration/images/good_test_picture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/lensfun/master/tools/calibration_webserver/calibration/static/calibration/images/good_test_picture.jpg -------------------------------------------------------------------------------- /tools/vagrant/buildpackages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export LC_ALL=en_US.UTF-8 5 | 6 | if [ ! -f .vagrant/machines/default/virtualbox/id ] 7 | then 8 | vagrant up 9 | fi 10 | vagrant ssh -c "cd lensfun ; ./buildpackages.sh" 11 | -------------------------------------------------------------------------------- /docs/lensfun-manual.css: -------------------------------------------------------------------------------- 1 | .image { float: right; margin-left: 1em; margin-bottom: 2ex } 2 | .image-landscape img { width: 18em; height: 12em } 3 | .image-portrait43 img { height: 17.33em; width: 13em } 4 | .image-portrait43 .caption { max-width: 13em } 5 | h1, h2, h3, h4, h5, h6, hr.footer { clear: both } 6 | -------------------------------------------------------------------------------- /tools/calibration_webserver/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | 6 | if __name__ == "__main__": 7 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") 8 | 9 | from django.core.management import execute_from_command_line 10 | 11 | execute_from_command_line(sys.argv) 12 | -------------------------------------------------------------------------------- /tools/calibration_webserver/django.wsgi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import sys 6 | 7 | sys.path.append(os.path.dirname(__file__)) 8 | 9 | os.environ["DJANGO_SETTINGS_MODULE"] = "settings" 10 | 11 | from django.core.wsgi import get_wsgi_application 12 | application = get_wsgi_application() 13 | -------------------------------------------------------------------------------- /apps/setup.py.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """This setup script installs the “lensfun” package.""" 5 | 6 | from distutils.core import setup 7 | 8 | 9 | setup(name="lensfun", 10 | version="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO}", 11 | package_dir={"": r"${PY_PACKAGE_DIR}"}, 12 | packages=["lensfun"]) 13 | -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration/templates/calibration/success.html: -------------------------------------------------------------------------------- 1 | {% extends "calibration/base.html" %} 2 | 3 | {% block content %} 4 |

Success!

5 | 6 |

Your upload has been successfully processed (i.e., unpacked and 7 | EXIF-tagged). {{ admin_name }} will 8 | contact you as soon as he has analysed the pictures.

9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /docs/man/README: -------------------------------------------------------------------------------- 1 | The man pages are created from restructuredText files (extension .rst). So 2 | please do not edit the man pages (extension .1). Edit the rst files instead an 3 | call 4 | 5 | rst2man xxx.1.rst > xxx.1 6 | 7 | rst2man is part of the package python3-docutils. 8 | 9 | The .1 file are included for convenience into the repository. They may be 10 | removed someday, possiby along with this README file. 11 | -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration/templates/calibration/error.html: -------------------------------------------------------------------------------- 1 | {% extends "calibration/base.html" %} 2 | 3 | {% block content %} 4 |

An error occured …

5 | 6 |

The following error occured after your upload:

7 | 8 |
{{ error }}
9 | 10 |

If you have questions regarding this, 11 | contact {{ admin_name }}.

12 | 13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /tools/check_database/reformat_database.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | SCRIPT=$(realpath -e "$0") 4 | SCRIPTPATH=$(dirname "$SCRIPT") 5 | 6 | for A in "$SCRIPTPATH"/../../data/db/*.xml 7 | do 8 | XMLLINT_INDENT=" " xmllint --format --encode utf-8 "$A" > /tmp/lensfun_xmllint.xml 9 | sed 's+\( \)+\1\n+;s/\(\)/\1\n/' < /tmp/lensfun_xmllint.xml \ 10 | | sed ':a;N;$!ba;s/\n//' > "$A" 11 | done 12 | -------------------------------------------------------------------------------- /tools/git-hooks/post-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Updates the file data/db/timestamp.txt if the current commit has changed an 4 | # XML database file. You install these scripts by copying them into 5 | # .git/hooks. Watch out for existing hooks that you may overwrite there. 6 | 7 | if [ -a .update_timestamp ] 8 | then 9 | rm .update_timestamp 10 | date +%s > data/db/timestamp.txt 11 | git add data/db/timestamp.txt 12 | git commit --amend -C HEAD --no-verify 13 | fi 14 | exit 0 15 | -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration/templates/calibration/pending.html: -------------------------------------------------------------------------------- 1 | {% extends "calibration/base.html" %} 2 | 3 | {% block content %} 4 |

Have patience …

5 | 6 |

Your upload is now being processed. This may take a couple of minutes. If 7 | something wents wrong, you get an email. 8 | Otherwise, {{ admin_name }} will 9 | contact you as soon as he has analysed the pictures.

10 | 11 |

Thank you for your upload!

12 | 13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /data/db/slr-panasonic.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Panasonic 6 | DMC-L1 7 | 4/3 System 8 | 2 9 | 10 | 11 | 12 | Panasonic 13 | DMC-L10 14 | 4/3 System 15 | 2 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /libs/lensfun/lensfun.pc.cmake: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | bindir=@CMAKE_INSTALL_FULL_BINDIR@ 3 | libdir=@CMAKE_INSTALL_FULL_LIBDIR@ 4 | includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ 5 | datadir=@CMAKE_INSTALL_FULL_DATADIR@ 6 | docdir=@CMAKE_INSTALL_FULL_DOCDIR@ 7 | 8 | Name: lensfun 9 | Description: A photographic lens database and access library 10 | Version: @VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_MICRO@.@VERSION_BUGFIX@ 11 | Requires.private: glib-2.0 12 | Libs: -L${libdir} -llensfun 13 | Cflags: -I${includedir} -I${includedir}/lensfun 14 | -------------------------------------------------------------------------------- /data/db/mil-tokina.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tokina 6 | E 20mm f/2 7 | Sony E 8 | 1 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/common_code.hpp: -------------------------------------------------------------------------------- 1 | #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) 2 | #include 3 | #endif 4 | #ifdef __APPLE__ 5 | #include 6 | #endif 7 | 8 | void *lf_alloc_align(size_t alignment, size_t size) 9 | { 10 | #ifdef _WIN32 11 | return _aligned_malloc(size, alignment); 12 | #else 13 | void *ptr = NULL; 14 | if(posix_memalign(&ptr, alignment, size) != 0) 15 | return NULL; 16 | return ptr; 17 | #endif 18 | } 19 | #ifdef _WIN32 20 | void lf_free_align(void *mem) 21 | { 22 | _aligned_free(mem); 23 | } 24 | #else 25 | #define lf_free_align(A) free(A) 26 | #endif 27 | -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration/templates/calibration/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 6 | 7 | {% block title %}{{ title }}{% endblock %} 8 | 9 | 10 | {% block extrahead %}{% endblock %} 11 | {% block css %}{% endblock %} 12 | 13 | 14 | {% block content %}{% endblock %} 15 | 16 | 17 | -------------------------------------------------------------------------------- /data/db/slr-soligor.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Soligor 6 | MC Soligor C/D Wide-Auto 1:2.8 f=24mm 7 | Pentax KAF2 8 | 1.531 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /libs/lensfun/windows/mathconstants.h: -------------------------------------------------------------------------------- 1 | /* 2 | Math constants definitions for non-POSIX or old compilers. 3 | Should be included if necessary after . 4 | Copyright (C) 2014 by Torsten Bronger 5 | */ 6 | 7 | #ifndef __MATHCONSTANTS_H__ 8 | #define __MATHCONSTANTS_H__ 9 | 10 | #include 11 | 12 | #ifndef M_PI 13 | #define M_PI 3.14159265358979323846 14 | #endif 15 | 16 | #ifndef M_PI_2 17 | #define M_PI_2 1.57079632679489661923 18 | #endif 19 | 20 | #ifndef NAN 21 | #define NAN std::numeric_limits::quiet_NaN() 22 | #endif 23 | 24 | #ifndef INF 25 | #define INF std::numeric_limits::infinity() 26 | #endif 27 | 28 | #endif /* __MATHCONSTANTS_H__ */ 29 | -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from django.views.generic import TemplateView 3 | from calibration.views import upload, show_issues, thumbnail 4 | 5 | 6 | # Uncomment the next two lines to enable the admin: 7 | # from django.contrib import admin 8 | # admin.autodiscover() 9 | 10 | urlpatterns = [ 11 | url(r"^$", upload), 12 | # If you change this, change the path in process_upload.py, too! 13 | url(r"^results/(?P.+)", show_issues, name="show_issues"), 14 | url(r"^target_tips$", TemplateView.as_view(template_name="calibration/good_bad_ugly.html")), 15 | url(r"^thumbnails/(?P.+?)/(?P[0-9a-f]+)", thumbnail), 16 | ] 17 | -------------------------------------------------------------------------------- /cmake/modules/toolchain_win32.cmake: -------------------------------------------------------------------------------- 1 | #me of the target operating system 2 | SET(CMAKE_SYSTEM_NAME Windows) 3 | 4 | # which compilers to use for C and C++ 5 | SET(CMAKE_C_COMPILER i686-w64-mingw32-gcc) 6 | SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) 7 | SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres) 8 | 9 | # here is the target environment located 10 | SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32/) 11 | SET(LENSFUN_INSTALL_PREFIX /usr/i686-w64-mingw32/) 12 | 13 | # adjust the default behaviour of the FIND_XXX() commands: 14 | # search headers and libraries in the target environment, search 15 | # programs in the host environment 16 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 17 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 18 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 19 | -------------------------------------------------------------------------------- /data/db/slr-hasselblad.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hasselblad 500 6 | Generic 7 | 8 | 9 | 10 | Hasselblad H 11 | Generic 12 | 13 | 14 | 15 | Hasselblad 16 | Hasselblad 500 mech. 17 | Hasselblad 500 18 | 0.66 19 | 20 | 21 | 22 | Hasselblad 23 | Hasselblad H3D 24 | Hasselblad H 25 | 0.72 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration/context_processors.py: -------------------------------------------------------------------------------- 1 | # This file is Python 2.7. 2 | 3 | """Context processor for getting the admin's name and email into the templates. 4 | """ 5 | 6 | import os, configparser 7 | 8 | 9 | config = configparser.ConfigParser() 10 | config.read(os.path.expanduser("~/calibration_webserver.ini")) 11 | 12 | 13 | def default(request): 14 | """Injects admin contact information into the template context. 15 | 16 | :param request: the current HTTP Request object 17 | 18 | :type request: HttpRequest 19 | 20 | :return: 21 | the (additional) context dictionary 22 | 23 | :rtype: dict mapping str to session data 24 | """ 25 | return {"admin_name": config["General"]["admin_name"], "admin_email": config["General"]["admin_email"]} 26 | -------------------------------------------------------------------------------- /docs/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration_webserver.ini: -------------------------------------------------------------------------------- 1 | ; This file must be in $HOME. Make it accessible only for $USER. 2 | 3 | [General] 4 | uploads_root = /mnt/media/ownCloud/calibration 5 | cache_root = /var/cache/apache2/calibrate 6 | admin_name = Torsten Bronger 7 | admin_email = bronger@physik.rwth-aachen.de 8 | ; This must not end in a slash. 9 | root_url = http://wilson.bronger.org/calibration 10 | archive_path = /path/to/upload/archive 11 | upload_temp_path = /tmp 12 | 13 | [SMTP] 14 | machine = mail.example.com 15 | port = 587 16 | login = username 17 | password = secret 18 | 19 | [GitHub] 20 | token = access_token 21 | 22 | [SourceForge] 23 | login = username 24 | 25 | [ownCloud] 26 | server_url = https://bob.ipv.kfa-juelich.de/owncloud 27 | local_root = /mnt/media/ownCloud 28 | login = username 29 | password = secret 30 | -------------------------------------------------------------------------------- /tools/git-hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Creates the file .update_timestamp if the current commit has changed an XML 4 | # database file. This is then used by post-commit to update the database 5 | # timestamp. You install these scripts by copying them into .git/hooks. Watch 6 | # out for existing hooks that you may overwrite there. 7 | 8 | if [[ -n $(git diff --cached data/db/*.xml) ]] 9 | then 10 | 11 | # run database checks before commit 12 | python3 tools/check_database/check_database.py data/db/ 13 | RETVAL=$? 14 | if [ $RETVAL -ne 0 ] 15 | then 16 | echo "Pre-commit hook returned an error!" 17 | echo "Please repair the corrupted database and try again." 18 | exit 1 19 | fi 20 | 21 | # finally update timestamp 22 | touch .update_timestamp 23 | fi 24 | exit 0 25 | -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration/static/calibration/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: "DejaVu Sans", "Bitstream Vera Sans", "Trebuchet MS", Verdana, sans-serif; 3 | } 4 | 5 | h1 { margin-top: 0pt } 6 | 7 | /* MESSAGES & ERRORS */ 8 | div.errorlist, td.error-messages { text-align: left; font-size: x-small; padding: 0pt } 9 | div.errorlist, td.error-messages p { padding: 0.5ex 0.5ex 0pt 0.5ex; margin: 0pt 0pt 0pt 0pt; 10 | color:white; background-color: maroon; font-weight: bold } 11 | ul.errorlist { margin:0 !important; background-color: maroon; font-weight: normal } 12 | .errorlist li { padding: 0pt 0.5ex 0pt 0.5ex; display:block; color:white } 13 | 14 | a > img, img[usemap] { border: none } 15 | 16 | ul.radio-select { list-style-type: none; display: inline; margin-left: 0; padding-left:0 } 17 | ul.radio-select li { display: inline; margin-right: 1em } 18 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | The tests in this folder are implemented using the GLib test framework. 2 | 3 | https://developer.gnome.org/glib/2.42/glib-Testing.html 4 | 5 | When CMake is configured with `-DBUILD_TESTS=on` the tests are build. The 6 | individual tests are stand-alone exceutables and can also be run in a 7 | debugger or for example in `valgrind` for deeper analysis. 8 | By running the tool `ctest` in the build directory the tests are executed 9 | and the results are summarized. 10 | 11 | Unit test code coverage can be analysed with the `lcov` tool. 12 | 13 | cmake -DCMAKE_BUILD_TYPE=Coverage -DBUILD_TESTS=ON ../ && \ 14 | make && make coverage && sensible-browser ./coverage/index.html 15 | 16 | Further commands: 17 | 18 | * `ctest -VV` to show verbose output from the individual tests 19 | * `ctest -R Modifier` to run all tests with the string `Modifier` in the name 20 | * `ctest -E Modifier` to exclude tests with the string `Modifier` in the name 21 | -------------------------------------------------------------------------------- /data/db/slr-samsung.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Samsung Techwin Co. 6 | Samsung 7 | SAMSUNG GX10 8 | GX10 9 | Pentax KAF2 10 | 1.531 11 | 12 | 13 | 14 | Samsung Techwin Co. 15 | Samsung 16 | GX20 17 | GX20 18 | Pentax KAF2 19 | 1.538 20 | 21 | 22 | 23 | Samsung Techwin 24 | Samsung 25 | GX-1S 26 | GX-1S 27 | Pentax KAF2 28 | 1.531 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration/templates/calibration/missing_exif.html: -------------------------------------------------------------------------------- 1 | {% extends "calibration/base.html" %} 2 | 3 | {% block content %} 4 |

Missing EXIF data

5 | 6 |

Some RAWs in your upload could not be fully tagged with EXIF data. Please 7 | complete the missing data manually.

8 | 9 |

If the images were produced by a compact camera, set the lens model name to 10 | “Standard”.

11 | 12 |

Note: Whenever you leave a field empty, the respective 13 | value of the preceding image is used.

14 | 15 |
16 | {% for raw_file_path, thumbnail_url, exif in images %} 17 |
18 | 19 |

{{ raw_file_path }}

20 | 21 | 22 | {{ exif }} 23 | 24 |
25 | {% endfor %} 26 |
27 |

28 |
29 | 30 | {% endblock %} 31 | -------------------------------------------------------------------------------- /data/db/mil-pentax.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Pentax Q 6 | Generic 7 | 8 | 9 | 10 | Pentax 11 | Pentax Q 12 | Pentax Q 13 | 5.53 14 | 15 | 16 | 17 | Pentax 18 | Pentax Q7 19 | Pentax Q 20 | 4.6 21 | 22 | 23 | 24 | Pentax 25 | Pentax Q10 26 | Pentax Q 27 | 5.53 28 | 29 | 30 | 31 | Pentax 32 | 01 Standard Prime 8.5mm f/1.9 AL [IF] 33 | Pentax Q 34 | 35 | 36 | 5.53 37 | 4:3 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /tools/check_database/min_max_parameters.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys, os, argparse 4 | from xml.etree import ElementTree 5 | from pathlib import Path 6 | 7 | 8 | parser = argparse.ArgumentParser(description="Find min/max values of parameters in the DB.") 9 | parser.add_argument("db_root", help="path to the DB") 10 | parser.add_argument("tag", choices={"distortion", "tca", "vignetting"}) 11 | parser.add_argument("model", choices={"ptlens", "poly3", "acm", "pa", "poly5", "linear"}) 12 | parser.add_argument("parameter", choices={"a", "b", "c", "k1", "k2", "k3", "kr", "kb", "br", "cr", "vr", "bb", "cb", "vb"}) 13 | args = parser.parse_args() 14 | 15 | 16 | values = set() 17 | for root, __, filenames in os.walk(args.db_root): 18 | root = Path(root) 19 | for filename in filenames: 20 | filepath = root/filename 21 | if filepath.suffix == ".xml": 22 | tree = ElementTree.parse(str(filepath)) 23 | for element in tree.findall(".//{0.tag}[@model='{0.model}']".format(args)): 24 | value = element.attrib.get(args.parameter) 25 | if value is not None: 26 | values.add(float(value)) 27 | if values: 28 | print("min: {}, max: {}".format(min(values), max(values))) 29 | else: 30 | print("No values found.") 31 | -------------------------------------------------------------------------------- /docs/man/g-lensfun-update-data.1.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | g-lensfun-update-data 3 | ======================== 4 | 5 | ---------------------------- 6 | update Lensfun's database 7 | ---------------------------- 8 | 9 | :Author: This manual page was written by Torsten Bronger 10 | :Date: 2013-12-23 11 | :Manual section: 1 12 | 13 | SYNOPSIS 14 | ============ 15 | 16 | ``g-lensfun-update-data`` 17 | 18 | DESCRIPTION 19 | =============== 20 | 21 | ``g-lensfun-update-data`` is a GUI version of ``lensfun-update-data``. Both 22 | programs do the same, however, ``g-lensfun-update-data`` will ask for a root 23 | password if needed in a popup window rather than on the command line. This 24 | way, it comes in handy if a GUI program wants to let the user update Lensfun's 25 | database. 26 | 27 | See the manpage of ``lensfun-update-data`` for further information, and pay 28 | special attention to the DIAGNOSTICS section. 29 | 30 | COPYRIGHT 31 | ============= 32 | 33 | Lensfun is Copyright © 2007 Andrew Zabolotny 34 | 35 | License of the code: GNU Lesser General Public License, version 3 36 | 37 | License of the database: Creative Commons Attribution-Share Alike 3.0 license 38 | 39 | SEE ALSO 40 | =========== 41 | 42 | lensfun-update-data(1), lensfun-add-adapter(1), lensfun-convert-lcp(1) 43 | -------------------------------------------------------------------------------- /docs/calibration_tutorial/lens.cpp.patch: -------------------------------------------------------------------------------- 1 | --- /tmp/lensfun-0.2.5/libs/lensfun/lens.cpp 2010-03-22 23:14:25.000000000 +0100 2 | +++ /home/bronger/temp/lens.cpp 2012-11-07 05:11:48.124714439 +0100 3 | @@ -817,7 +817,7 @@ 4 | lfVignettingModel vm = LF_VIGNETTING_MODEL_NONE; 5 | 6 | float min_dist = 0.01F; 7 | - for (guint i = 0; i < vc->len; i++) 8 | + for (guint i = 0; i < vc->len && i < 1000; i++) 9 | { 10 | lfLensCalibVignetting *c = 11 | (lfLensCalibVignetting *)g_ptr_array_index (vc, i); 12 | @@ -917,10 +917,6 @@ 13 | } 14 | } 15 | 16 | - // If we have found no points for the spline, drop 17 | - if (!spline [1] || !spline [2]) 18 | - continue; 19 | - 20 | // Sort the spline points according to the real distance 21 | // between p and the points, not by "rating". 22 | if (spline_dist [0] < spline_dist [1]) 23 | @@ -942,6 +938,10 @@ 24 | spline_dist [3] = tmpf; 25 | } 26 | 27 | + // If we have found no points for the spline, drop 28 | + if (!spline [1] || !spline [2]) 29 | + continue; 30 | + 31 | // Interpolate a new point given four spline points 32 | // For this we have to find first the 't' parameter 33 | // in the range 0..1 which gives the closest to p point 34 | -------------------------------------------------------------------------------- /tools/calibration_statistics/README.rst: -------------------------------------------------------------------------------- 1 | ====================== 2 | Calibration statistics 3 | ====================== 4 | 5 | 6 | Results 7 | ======= 8 | 9 | The results of this script with the current database are the following:: 10 | 11 | bronger@penny:~/src/lensfun/tools/calibration_statistics$ ./statistics.py --inverse && \ 12 | ./statistics.py --in-focal-length 13 | [0.06834731424201283, 0.04983392790356207, 0.11328902542292163] 14 | [0.09085023095526398, 0.058878117602132324, 0.11360064218315158] 15 | 16 | This shows: 17 | 18 | * Using the focal length as the unit system results in a slightly bigger error. 19 | * The difference is small enough to say that one can use both coordinate systems. 20 | 21 | The two other combinations of ``--inverse`` and ``-in-focal-length`` are worse, by the way. 22 | 23 | If you look at the resulting plot – for example, for the parameter b – you see 24 | that using the focal length for the unit system results in very nicely linear 25 | lines, even better than with ``--inverse``. Unfortunately, an increased number 26 | of lines don’t follow this trend, resulting in the worse figures above. I 27 | suspect changes of sign in the original curves result in difficult slopes when 28 | applying the transformation into the focal length unit system. 29 | -------------------------------------------------------------------------------- /tools/vagrant/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | def local_cache(basebox_name) 5 | # Mount the apt cache from the host, so that it survives re-starts of the VM. 6 | cache_dir = Pathname.new(File.join("#{Dir.home}", ".cache", "vagrant", "apt", basebox_name)) 7 | partial_dir = cache_dir.join("partial") 8 | partial_dir.mkpath unless partial_dir.exist? 9 | cache_dir 10 | end 11 | 12 | Vagrant.configure(2) do |config| 13 | config.vm.box = "ubuntu/trusty64" 14 | 15 | # Share an additional folder to the guest VM. The first argument is 16 | # the path on the host to the actual folder. The second argument is 17 | # the path on the guest to mount the folder. And the optional third 18 | # argument is a set of non-required options. 19 | config.vm.synced_folder "../..", "/home/vagrant/lensfun" 20 | 21 | cache_dir = local_cache(config.vm.box) 22 | config.vm.synced_folder cache_dir, "/var/cache/apt/archives/" 23 | 24 | # Enable provisioning with a shell script. Additional provisioners such as 25 | # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the 26 | # documentation for more information about their specific syntax and use. 27 | config.vm.provision "shell", inline: <<-SHELL 28 | sudo apt-get update 29 | sudo apt-get install -y git devscripts python-docutils 30 | sudo apt-get build-dep -y liblensfun0 31 | SHELL 32 | end 33 | -------------------------------------------------------------------------------- /tools/calibrate/nd_correction.py: -------------------------------------------------------------------------------- 1 | # This file is Python 2.7. 2 | 3 | from __future__ import unicode_literals, division, absolute_import 4 | 5 | import numpy 6 | from scipy.optimize.minpack import leastsq 7 | from matplotlib import pyplot 8 | 9 | ND = 1 10 | f = 210 11 | d = 30 12 | 13 | k1_vig = -0.93 14 | k2_vig = 0.63 15 | k3_vig = -0.34 16 | 17 | 18 | def error_function(p, x, y): 19 | k1, k2, k3 = p 20 | fitted_values = 1 + k1 * x**2 + k2 * x**4 + k3 * x**6 21 | difference = y - fitted_values 22 | result = [] 23 | for value, fitted_y in zip(difference, fitted_values): 24 | if fitted_y < 0.01: 25 | result.append(10 * value) 26 | if value < 0: 27 | result.append(value) 28 | else: 29 | result.append(3.3 * value) 30 | return numpy.array(result) 31 | 32 | def get_nd_parameters(k1, k2, k3, nd, focal_length, sensor_diagonal): 33 | x = numpy.arange(0, 1, 0.001) 34 | y_vig = 1 + k1 * x**2 + k2 * x**4 + k3 * x**6 35 | y_filter = 10**(nd * (1 - numpy.sqrt(1 + x**2 / (2 * focal_length / sensor_diagonal)**2))) 36 | y_total = y_vig * y_filter 37 | return leastsq(error_function, [k1, k2, k3], args=(x, y_total))[0] 38 | 39 | k1, k2, k3 = get_nd_parameters(k1_vig, k2_vig, k3_vig, ND, f, d) 40 | 41 | #pyplot.plot(x, y_vig) 42 | #pyplot.plot(x, y_filter) 43 | pyplot.plot(x, y_total) 44 | pyplot.plot(x, y_vig_new(x, k1, k2, k3)) 45 | pyplot.xlim(0, 1) 46 | pyplot.grid(True) 47 | pyplot.show() 48 | -------------------------------------------------------------------------------- /tools/calibration_webserver/utils.py: -------------------------------------------------------------------------------- 1 | import hashlib, subprocess, os 2 | 3 | 4 | class RawNotFound(FileNotFoundError): 5 | pass 6 | 7 | 8 | def generate_thumbnail(raw_filepath, cache_dir): 9 | """Generates a thumbnail for the given image. The thumbnail is written into 10 | the cache dir, given by ``cache_root`` in the INI file. This is a helper 11 | routine for `tag_image_files` in order to make the thumbnail generation 12 | parallel. 13 | 14 | :param str raw_filepath: filepath of the RAW image file 15 | :param str cache_dir: root path of the thumbnail cache 16 | """ 17 | hash_ = hashlib.sha1() 18 | hash_.update(raw_filepath.encode("utf-8")) 19 | out_filepath = os.path.join(cache_dir, hash_.hexdigest() + ".jpeg") 20 | try: 21 | os.mkdir(cache_dir) 22 | except FileExistsError: 23 | pass 24 | processes = [] 25 | if os.path.splitext(raw_filepath)[1].lower() in [".tif", ".tiff", ".jpeg", ".jpg"]: 26 | processes.append(subprocess.Popen(["convert", raw_filepath, "-resize", "131072@", out_filepath])) 27 | else: 28 | dcraw = subprocess.Popen(["dcraw", "-h", "-T", "-c", raw_filepath], stdout=subprocess.PIPE) 29 | processes.append(dcraw) 30 | processes.append(subprocess.Popen(["convert", "-", "-resize", "131072@", out_filepath], stdin=dcraw.stdout)) 31 | return_codes = [process.wait() for process in processes] 32 | if any(code != 0 for code in return_codes): 33 | raise RawNotFound 34 | -------------------------------------------------------------------------------- /libs/lensfun/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # build Lensfun library 2 | SET(LENSFUN_SRC camera.cpp database.cpp lens.cpp 3 | mount.cpp lensfunprv.h cpuid.cpp 4 | mod-color-sse.cpp mod-color-sse2.cpp mod-color.cpp 5 | mod-coord-sse.cpp mod-coord.cpp mod-pc.cpp 6 | mod-subpix.cpp modifier.cpp auxfun.cpp 7 | ../../include/lensfun/lensfun.h.in) 8 | 9 | SET_SOURCE_FILES_PROPERTIES(mod-color-sse.cpp mod-coord-sse.cpp 10 | PROPERTIES COMPILE_FLAGS "${VECTORIZATION_SSE_FLAGS}") 11 | SET_SOURCE_FILES_PROPERTIES(mod-color-sse2.cpp 12 | PROPERTIES COMPILE_FLAGS "${VECTORIZATION_SSE2_FLAGS}") 13 | 14 | IF(BUILD_STATIC) 15 | ADD_LIBRARY(lensfun STATIC ${LENSFUN_SRC}) 16 | ELSE() 17 | ADD_LIBRARY(lensfun SHARED ${LENSFUN_SRC}) 18 | SET_TARGET_PROPERTIES(lensfun PROPERTIES COMPILE_FLAGS -DCONF_SYMBOL_VISIBILITY) 19 | ENDIF() 20 | SET_TARGET_PROPERTIES(lensfun PROPERTIES SOVERSION "${VERSION_API}" VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO}") 21 | 22 | TARGET_LINK_LIBRARIES(lensfun ${GLIB2_LIBRARIES}) 23 | 24 | INSTALL(TARGETS lensfun 25 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 26 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 27 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) 28 | 29 | # pkgconfig support 30 | CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/lensfun.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/lensfun.pc @ONLY) 31 | INSTALL( FILES ${CMAKE_CURRENT_BINARY_DIR}/lensfun.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) 32 | 33 | -------------------------------------------------------------------------------- /tests/test_lffuzzystrcmp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "lensfun.h" 4 | #include "../libs/lensfun/lensfunprv.h" 5 | 6 | 7 | typedef struct 8 | { 9 | lfFuzzyStrCmp *fuzzycmp; 10 | } lfFixture; 11 | 12 | void mod_setup (lfFixture *lfFix, gconstpointer data) 13 | { 14 | } 15 | 16 | void mod_teardown (lfFixture *lfFix, gconstpointer data) 17 | { 18 | } 19 | 20 | void test_dot_zero_missing_in_raw (lfFixture *lfFix, gconstpointer data) 21 | { 22 | // Name in RAW file 23 | lfFix->fuzzycmp = new lfFuzzyStrCmp ("Nikkor 18mm f/4 DX", true); 24 | // Name in database file 25 | int score = lfFix->fuzzycmp->Compare ("Nikkor 18mm f/4.0 DX"); 26 | g_assert_cmpint (score, >, 0); 27 | delete lfFix->fuzzycmp; 28 | } 29 | 30 | void test_dot_zero_missing_in_db (lfFixture *lfFix, gconstpointer data) 31 | { 32 | // Name in RAW file 33 | lfFix->fuzzycmp = new lfFuzzyStrCmp ("Nikkor 18mm f/4.0 DX", true); 34 | // Name in database file 35 | int score = lfFix->fuzzycmp->Compare ("Nikkor 18mm f/4 DX"); 36 | g_assert_cmpint (score, >, 0); 37 | delete lfFix->fuzzycmp; 38 | } 39 | 40 | 41 | int main (int argc, char **argv) 42 | { 43 | setlocale (LC_ALL, ""); 44 | 45 | g_test_init (&argc, &argv, NULL); 46 | 47 | g_test_add ("/lfFuzzyStrCmp/\".0\" missing in RAW", lfFixture, NULL, 48 | mod_setup, test_dot_zero_missing_in_raw, mod_teardown); 49 | g_test_add ("/lfFuzzyStrCmp/\".0\" missing in DB", lfFixture, NULL, 50 | mod_setup, test_dot_zero_missing_in_db, mod_teardown); 51 | 52 | return g_test_run(); 53 | } 54 | -------------------------------------------------------------------------------- /tools/abi-compliance-check/run_check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # set commit, branch or tag to compare 6 | LF_COMMIT_NEW=$1 7 | LF_COMMIT_OLD=$2 8 | 9 | ACC_VERSION=1.99.21 10 | 11 | CURRENT_BRANCH=`git rev-parse --abbrev-ref HEAD` 12 | 13 | # download and unzip the abi-compliance-checker tool 14 | wget https://github.com/lvc/abi-compliance-checker/archive/$ACC_VERSION.zip 15 | unzip $ACC_VERSION.zip 16 | rm $ACC_VERSION.zip 17 | 18 | # prepare build directory 19 | mkdir -p build 20 | cd build 21 | 22 | # checkout and build new version 23 | git checkout $LF_COMMIT_NEW 24 | cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../LF_new/ ../../../ 25 | make && make install 26 | 27 | # checkout and build old version 28 | git checkout $LF_COMMIT_OLD 29 | cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../LF_old/ ../../../ 30 | make && make install 31 | 32 | cd ../ 33 | 34 | echo "Going back to branch <$CURRENT_BRANCH>" 35 | git checkout $CURRENT_BRANCH 36 | 37 | # prepare config 38 | sed "s|.*|${LF_COMMIT_OLD}|" LF_tmp_old.xml > LF_old.xml 39 | sed "s|.*|${LF_COMMIT_NEW}|" LF_tmp_new.xml > LF_new.xml 40 | 41 | # run check and show results in firefox 42 | perl abi-compliance-checker-$ACC_VERSION/abi-compliance-checker.pl -lib lensfun -new LF_new.xml -old LF_old.xml 43 | firefox compat_reports/lensfun/${LF_COMMIT_OLD}_to_${LF_COMMIT_NEW}/compat_report.html & 44 | 45 | # cleanup 46 | echo "Cleanup..." 47 | rm -rf build 48 | rm -rf LF_new 49 | rm -rf LF_old 50 | rm -rf logs 51 | rm -rf abi-compliance-checker-* 52 | rm LF_new.xml 53 | rm LF_old.xml 54 | -------------------------------------------------------------------------------- /.github/workflows/cmake.yml: -------------------------------------------------------------------------------- 1 | name: CMake 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) 11 | BUILD_TYPE: Release 12 | 13 | jobs: 14 | build: 15 | # The CMake configure and build commands are platform agnostic and should work equally 16 | # well on Windows or Mac. You can convert this to a matrix build if you need 17 | # cross-platform coverage. 18 | # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | 24 | - name: Install xmllint for db test 25 | run: sudo apt-get install libxml2-utils 26 | 27 | - name: Configure CMake 28 | # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. 29 | # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type 30 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_TESTS=ON 31 | - name: Build 32 | # Build your program with the given configuration 33 | run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} 34 | 35 | - name: Test 36 | working-directory: ${{github.workspace}}/build 37 | # Execute tests defined by the CMake configuration. 38 | # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail 39 | run: ctest -C ${{env.BUILD_TYPE}} --output-on-failure 40 | 41 | -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration/templates/calibration/good_bad_ugly.html: -------------------------------------------------------------------------------- 1 | {% extends "calibration/base.html" %} 2 | 3 | {% load static %} 4 | 5 | {% block content %} 6 |

How anti-distortion images should look like

7 | 8 | Good anti-distortion picture 11 | 12 | 13 |

The good one: Two horizonal lines, 14 | one very close to one of the long edges, the other one 1/3 from the 15 | top. Note that tilting and rotating the camera is allowed, as well as changing 16 | the distance.

17 | 18 |
19 | 20 | Bad calibration picture 22 | 23 |

A bad one: The horizonal lines are in the proper 24 | position (at the bottom, at least), but they are not running from one edge to 25 | the other. I need lines covering the full width.

26 | 27 |
28 | 29 | Bad calibration picture 32 | 33 |

Another bad one: All horizonal lines are too far 34 | away from the long edges. Put one line insanely mind-bogglingly staggeringly 35 | close to the edge.

36 | 37 |

Now go back to the upload page.

38 | {% endblock %} 39 | -------------------------------------------------------------------------------- /data/db/slr-leica.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leica R 6 | M42 7 | M39/1 8 | DKL 9 | T2 10 | Tamron Adaptall 11 | Generic 12 | 13 | 14 | 15 | Leica S 16 | Generic 17 | 18 | 19 | 20 | Leica 21 | Digilux 3 22 | 4/3 System 23 | 2 24 | 25 | 26 | 27 | Leica 28 | Leica D Vario-Elmar 14-150mm f/3.5-5.6 Asph. OIS 29 | 4/3 System 30 | 2 31 | 4:3 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /include/lensfun/config.h.in.cmake: -------------------------------------------------------------------------------- 1 | #ifndef __CONFIG_H__ 2 | #define __CONFIG_H__ 3 | 4 | /* config file for Lensfun library 5 | generated by CMake 6 | */ 7 | 8 | #define CONF_PACKAGE "lensfun" 9 | #define CONF_VERSION "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_MICRO@.@VERSION_BUGFIX@" 10 | 11 | #if defined(__APPLE__) 12 | #define PLATFORM_OSX 13 | #elif defined(_WIN32) 14 | #define PLATFORM_WINDOWS 15 | #elif defined(__unix__) 16 | #define PLATFORM_LINUX 17 | #endif 18 | 19 | 20 | #cmakedefine CMAKE_COMPILER_IS_GNUCC 21 | #ifdef CMAKE_COMPILER_IS_GNUCC 22 | #define CONF_COMPILER_GCC 1 23 | #endif 24 | 25 | #if defined(PLATFORM_LINUX) 26 | #define SYSTEM_DB_PATH "${CMAKE_INSTALL_FULL_DATAROOTDIR}/lensfun" 27 | #define SYSTEM_DB_UPDATE_PATH "/${CMAKE_INSTALL_LOCALSTATEDIR}/lib/lensfun-updates" 28 | #elif defined(PLATFORM_WINDOWS) 29 | #define SYSTEM_DB_PATH "${CMAKE_INSTALL_DATAROOTDIR}/lensfun" 30 | #define SYSTEM_DB_UPDATE_PATH "${CMAKE_INSTALL_DATAROOTDIR}/lensfun-updates" 31 | #elif defined(PLATFORM_OSX) 32 | #define SYSTEM_DB_PATH "${CMAKE_INSTALL_FULL_DATAROOTDIR}/lensfun" 33 | #define SYSTEM_DB_UPDATE_PATH "/${CMAKE_INSTALL_LOCALSTATEDIR}/lib/lensfun-updates" 34 | #endif 35 | 36 | #define DATABASE_SUBDIR "version_${LENSFUN_DB_VERSION}" 37 | 38 | // add a macro to know we're compiling Lensfun, not a client library 39 | #define CONF_LENSFUN_INTERNAL 40 | 41 | #cmakedefine VECTORIZATION_SSE 42 | #cmakedefine VECTORIZATION_SSE2 43 | 44 | #cmakedefine HAVE_ENDIAN_H 45 | 46 | #ifdef _MSC_VER 47 | #define _USE_MATH_DEFINES 48 | #endif 49 | 50 | #define GLIB_VERSION_MIN_REQUIRED (${LENSFUN_GLIB_REQUIREMENT_MACRO}) 51 | 52 | // to avoid usage of API that is not in GLIB_VERSION_MIN_REQUIRED version 53 | // and make it easy to detect when to bump requirements: 54 | #define GLIB_VERSION_MAX_ALLOWED (GLIB_VERSION_MIN_REQUIRED) 55 | 56 | #endif // __CONFIG_H__ 57 | -------------------------------------------------------------------------------- /docs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # find doxygen 2 | FIND_PACKAGE(Doxygen REQUIRED) 3 | 4 | # set some files/path for later user 5 | # we don't use path doc because path doc is used by cmake itself because 6 | # of target doc 7 | SET(CMAKE_DOC_OUT ${CMAKE_BINARY_DIR}/doc_doxygen) 8 | set(DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/doxyfile") 9 | 10 | # create doxyfile 11 | CONFIGURE_FILE(doxyfile.in.cmake ${DOXYFILE} @ONLY) 12 | 13 | # now build documentation 14 | ADD_CUSTOM_TARGET(doc 15 | ALL 16 | COMMAND "${DOXYGEN_EXECUTABLE}" 17 | DEPENDS "${DOXYFILE}" manual-main.txt ../include/lensfun/lensfun.h.in 18 | WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" 19 | COMMENT "Building documentation with doxygen" 20 | ) 21 | 22 | # install documentation 23 | INSTALL(DIRECTORY ${CMAKE_DOC_OUT}/ DESTINATION ${CMAKE_INSTALL_DOCDIR}) 24 | 25 | # create and install man pages 26 | FIND_PROGRAM(RST2MAN_EXECUTABLE NAMES rst2man rst2man.py rst2man2 rst2man2.py) 27 | ADD_CUSTOM_TARGET(man ALL) 28 | ADD_CUSTOM_COMMAND( 29 | TARGET man 30 | COMMAND ${RST2MAN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/man/g-lensfun-update-data.1.rst > ${CMAKE_CURRENT_BINARY_DIR}/g-lensfun-update-data.1 31 | COMMAND ${RST2MAN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/man/lensfun-update-data.1.rst > ${CMAKE_CURRENT_BINARY_DIR}/lensfun-update-data.1 32 | COMMAND ${RST2MAN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/man/lensfun-add-adapter.1.rst > ${CMAKE_CURRENT_BINARY_DIR}/lensfun-add-adapter.1 33 | COMMAND ${RST2MAN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/man/lensfun-convert-lcp.1.rst > ${CMAKE_CURRENT_BINARY_DIR}/lensfun-convert-lcp.1 34 | WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" 35 | ) 36 | 37 | INSTALL(FILES 38 | ${CMAKE_CURRENT_BINARY_DIR}/g-lensfun-update-data.1 39 | ${CMAKE_CURRENT_BINARY_DIR}/lensfun-update-data.1 40 | ${CMAKE_CURRENT_BINARY_DIR}/lensfun-add-adapter.1 41 | DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 42 | ) 43 | -------------------------------------------------------------------------------- /data/db/mil-leica.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leica L 6 | Leica M 7 | M42 8 | M39/1 9 | DKL 10 | T2 11 | Generic 12 | 13 | 14 | 15 | Leica Camera AG 16 | Leica SL (Typ 601) 17 | Leica L 18 | 1 19 | 20 | 21 | 22 | Leica Camera AG 23 | Leica T (Typ 701) 24 | Leica L 25 | 1.53 26 | 27 | 28 | 29 | Leica Camera AG 30 | Leica TL 31 | Leica L 32 | 1.53 33 | 34 | 35 | 36 | Leica Camera AG 37 | Leica TL2 38 | Leica L 39 | 1.53 40 | 41 | 42 | 43 | Leica Camera AG 44 | Leica CL (Typ 7323) 45 | Leica L 46 | 1.53 47 | 48 | 49 | 50 | Leica Camera AG 51 | Summicron TL 1:2 23 ASPH. 52 | Leica L 53 | 1.53 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /data/db/contax.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Contax/Yashica 6 | M42 7 | M39/1 8 | DKL 9 | T2 10 | Generic 11 | 12 | 13 | 14 | Contax G 15 | M42 16 | M39/1 17 | DKL 18 | T2 19 | Generic 20 | 21 | 22 | 23 | Contax 24 | 35mm film: full frame 25 | Contax/Yashica 26 | 1 27 | 28 | 29 | 30 | Contax 31 | Zeiss 21mm f/2.8 Distagon 32 | Contax/Yashica 33 | 1 34 | 35 | 36 | 37 | 38 | 39 | 40 | Contax 41 | Zeiss 28mm f/2.8 Distagon 42 | Contax/Yashica 43 | 1 44 | 45 | 46 | 47 | 48 | 49 | 50 | Contax 51 | Contax G Planar T* 2/35 52 | Contax G 53 | 1.534 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /tools/calibration_webserver/README.rst: -------------------------------------------------------------------------------- 1 | ======================= 2 | Calibration webserver 3 | ======================= 4 | 5 | This `Django`_ application enables you to collect lens calibration images in a 6 | well-organised manner. It is only partially customisable with settings. 7 | (Something that could certainly be improved.) Much of the local adaption has 8 | to be realised by changing the source code itself. 9 | 10 | .. _Django: https://www.djangoproject.com 11 | 12 | 13 | Configuration 14 | =============== 15 | 16 | * Some important prerequisites are Python 3, Django 1.9, exiv2, Exiftool, 17 | unrar, 7zip, unzip, PyGithub, ImageMagick, Apache, and Python WSGI. 18 | * Adjust the settings in ``settings.py``. This is an ordinary `Django 19 | settings`_ file. Settings you should change are ``ALLOWED_HOSTS`` and 20 | ``SECRET_KEY``. (The ``SECRET_KEY`` is not used by this appication 21 | currently, but this may change in a later version, so set the ``SECRET_KEY`` 22 | to a new value kanyway.) 23 | * Adjust the values in ``calibration_webserver.ini``. This file must be moved 24 | to the home directory of the user under which the webserver process runs 25 | (e.g. ``/var/www``). 26 | * The directory ``cache_root`` must be writable to the webserver user. 27 | * The script ``follow_db_changes.py`` should run as a cronjob, e.g. once 28 | per hour. 29 | 30 | .. _Django settings: https://docs.djangoproject.com/en/1.9/ref/settings/ 31 | 32 | 33 | Usage with Apache 34 | ===================== 35 | 36 | In a ```` section, you should insert something like:: 37 | 38 | WSGIScriptAlias /calibration /path/to/calibration_webserver/django.wsgi 39 | WSGIDaemonProcess calibration lang='en_US.UTF-8' locale='en_US.UTF-8' display-name=%{GROUP} 40 | WSGIProcessGroup calibration 41 | Alias /calibration/static /var/www/calibration 42 | 43 | .. LocalWords: www login WSGIScriptAlias WSGIDaemonProcess lang UTF 44 | .. LocalWords: WSGIProcessGroup 45 | -------------------------------------------------------------------------------- /data/db/rf-leica.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leica M 6 | M42 7 | M39/1 8 | DKL 9 | T2 10 | Generic 11 | 12 | 13 | 14 | Leica 15 | Leica M (Typ 240) 16 | Leica M 17 | 1 18 | 19 | 20 | 21 | Leica 22 | Elmarit-M 1:2.8/28 23 | Elmarit-M 28mm f/2.8 ASPH 24 | Leica M 25 | 1 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | Leica 34 | Elmarit-M 1:2.8/90 35 | Elmarit-M 90mm f/2.8 36 | Leica M 37 | 1 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | Leica 46 | Summicron-M 1:2/50 47 | 48 | Summicron-M 50mm f/2 49 | Leica M 50 | 1 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /tools/find_missing_cameras/find_missing_cameras.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """Finds cameras that are known to rawspeed's database but not to Lensfun. 4 | Maybe this could be extended to look for missing cameras in other places, too. 5 | Moreover, it may be good to optionally exclude compact cameras from the result 6 | – their only purpose might be to look for optically equivalent entries in 7 | Lensfun. 8 | 9 | Call: 10 | 11 | python3 find_missing_cameras.py path/to/lensfun/db path/to/rawspeeds/cameras.xml 12 | 13 | """ 14 | 15 | import glob, sys, os, re 16 | from xml.etree import ElementTree 17 | 18 | pattern = re.compile(r"[a-z]+|\d+|[^ a-z0-9]+") 19 | def normalize_string(string): 20 | components = sorted(token for token in pattern.findall(string.lower()) 21 | if token.isalnum() and token != "f" or len(token) > 1) 22 | return " ".join(components) 23 | 24 | def name(element, tag_name): 25 | for subelement in element.findall(tag_name): 26 | if not subelement.attrib: 27 | return normalize_string(subelement.text) 28 | 29 | cameras_in_lensfun = set() 30 | for filepath in glob.glob(os.path.join(sys.argv[1], "*.xml")): 31 | root = ElementTree.parse(filepath).getroot() 32 | for element in root.findall("camera"): 33 | cameras_in_lensfun.add(name(element, "model")) 34 | 35 | cameras_in_rawspeed = set() 36 | full_data = {} 37 | def add_camera(make, model): 38 | normalized_name = normalize_string(model) 39 | cameras_in_rawspeed.add(normalized_name) 40 | full_data[normalized_name] = (make, model) 41 | root = ElementTree.parse(sys.argv[2]).getroot() 42 | for element in root.findall("Camera"): 43 | make = element.attrib.get("make") 44 | add_camera(make, element.attrib.get("model")) 45 | for alias in element.find("Aliases") or []: 46 | add_camera(make, alias.text) 47 | 48 | missing_cameras = cameras_in_rawspeed - cameras_in_lensfun 49 | for maker, camera in sorted(data for normalized_name, data in full_data.items() if normalized_name in missing_cameras): 50 | print("{}: {}".format(maker, camera)) 51 | -------------------------------------------------------------------------------- /tests/test_modifier_coord_tiny_image.cpp: -------------------------------------------------------------------------------- 1 | /* This checks for off-by-one errors which occure most clearly in extremely 2 | * small images. */ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "lensfun.h" 12 | #include "../libs/lensfun/lensfunprv.h" 13 | 14 | 15 | typedef struct 16 | { 17 | void *coordBuff; 18 | size_t img_width, img_height; 19 | lfModifier *mod; 20 | lfLens *lens; 21 | } lfFixture; 22 | 23 | // setup a standard lens 24 | void mod_setup (lfFixture *lfFix, gconstpointer data) 25 | { 26 | lfFix->img_height = 2; 27 | lfFix->img_width = 3; 28 | 29 | lfFix->lens = new lfLens(); 30 | 31 | lfFix->mod = new lfModifier(lfFix->lens, 1.0f, 1.0f, lfFix->img_width, lfFix->img_height, LF_PF_F32, true); 32 | 33 | lfFix->mod->EnableScaling(10.0f); 34 | 35 | lfFix->coordBuff = NULL; 36 | 37 | const size_t bufsize = 2 * lfFix->img_width * lfFix->img_height * sizeof (float); 38 | lfFix->coordBuff = g_malloc (bufsize); 39 | } 40 | 41 | void mod_teardown (lfFixture *lfFix, gconstpointer data) 42 | { 43 | g_free (lfFix->coordBuff); 44 | 45 | delete lfFix->mod; 46 | delete lfFix->lens; 47 | } 48 | 49 | void test_mod_coord_scaling_only (lfFixture *lfFix, gconstpointer data) 50 | { 51 | const float epsilon = std::numeric_limits::epsilon(); 52 | float expected_coordinates[] = {-9.0f, -4.5f, 1.0f, -4.5f, 11.0f, -4.5f, 53 | -9.0f, 5.5f, 1.0f, 5.5f, 11.0f, 5.5}; 54 | std::vector coords (2 * 3 * 2); 55 | g_assert_true (lfFix->mod->ApplyGeometryDistortion (0, 0, 3, 2, &coords [0])); 56 | for (unsigned int i = 0; i < coords.size(); i++) 57 | g_assert_cmpfloat (fabs (coords [i] - expected_coordinates [i]), <=, epsilon); 58 | } 59 | 60 | 61 | int main (int argc, char **argv) 62 | { 63 | setlocale (LC_ALL, ""); 64 | 65 | g_test_init (&argc, &argv, NULL); 66 | 67 | g_test_add ("/modifier/coord/tiny_image/scaling only", lfFixture, NULL, 68 | mod_setup, test_mod_coord_scaling_only, mod_teardown); 69 | 70 | return g_test_run(); 71 | } 72 | -------------------------------------------------------------------------------- /data/db/compact-kodak.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Eastman Kodak Company 6 | Kodak 7 | Kodak DC120 ZOOM Digital Camera 8 | Kodak DC120 9 | kodakDC120 10 | 1 11 | 12 | 13 | 14 | Eastman Kodak Company 15 | Kodak 16 | Kodak Digital Science DC50 Zoom Camera 17 | Kodak DC50 18 | kodakDC50 19 | 1 20 | 21 | 22 | 23 | Eastman Kodak Company 24 | Kodak 25 | Kodak CX6330 Zoom Digital Camera 26 | Kodak CX6330 27 | kodakCX6330 28 | 6.593 29 | 30 | 31 | 32 | Eastman Kodak Company 33 | Kodak 34 | Kodak CX7525 Zoom Digital Camera 35 | Kodak CX7525 36 | kodakCX6330 37 | 6.07 38 | 39 | 40 | 41 | Kodak 42 | Kodak CX6330 & compatibles 43 | fixed lens 44 | festes Objektiv 45 | kodakCX6330 46 | 6.593 47 | 4:3 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /data/db/slr-vivitar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Vivitar 6 | Vivitar 100mm f/3.5 AF Macro 7 | Canon EF 8 | Sony Alpha 9 | Nikon F AF 10 | 1.523 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 25 | Vivitar 26 | 28 | Vivitar Series One 70-210mm 1:3.5 SN 22... 29 | Vivitar Series 1 70-210mm 1:3.5 SN 22… 30 | Nikon F 31 | Pentax K 32 | Canon FD 33 | Canon FL 34 | Olympus OM 35 | M42 36 | 37 | 38 | 1.534 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /cmake/modules/FindGLIB2.cmake: -------------------------------------------------------------------------------- 1 | IF (NOT MSVC) 2 | INCLUDE(FindPkgConfig) 3 | PKG_SEARCH_MODULE( GLIB2 glib-2.0 ) 4 | IF(WIN32 AND NOT BUILD_STATIC) 5 | FIND_FILE(GLIB2_DLL 6 | NAMES glib-2.dll glib-2-vs9.dll libglib-2.0-0.dll 7 | PATHS "${GLIB2_LIBRARY_DIRS}/../bin" 8 | NO_SYSTEM_ENVIRONMENT_PATH) 9 | ENDIF() 10 | ENDIF() 11 | 12 | IF (NOT GLIB2_FOUND OR NOT PKG_CONFIG_FOUND) 13 | FIND_PATH(GLIB2_GLIB2CONFIG_INCLUDE_PATH 14 | NAMES glibconfig.h 15 | PATHS 16 | /usr/local/lib 17 | /usr/lib 18 | /usr/lib64 19 | /opt/local/lib 20 | ${GLIB2_BASE_DIR}/lib 21 | ${GLIB2_BASE_DIR}/include 22 | ${CMAKE_LIBRARY_PATH} 23 | PATH_SUFFIXES glib-2.0/include 24 | ) 25 | 26 | 27 | FIND_PATH(GLIB2_INCLUDE_DIRS 28 | NAMES glib.h 29 | PATHS 30 | /usr/local/include 31 | /usr/include 32 | /opt/local/include 33 | ${GLIB2_BASE_DIR}/include 34 | PATH_SUFFIXES gtk-2.0 glib-2.0 glib20 35 | ) 36 | 37 | FIND_LIBRARY(GLIB2_LIBRARIES 38 | NAMES glib-2.0 glib20 glib 39 | PATHS 40 | /usr/local/lib 41 | /usr/lib 42 | /usr/lib64 43 | /opt/local/lib 44 | ${GLIB2_BASE_DIR}/lib 45 | ) 46 | 47 | IF(GLIB2_GLIB2CONFIG_INCLUDE_PATH AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES) 48 | SET( GLIB2_INCLUDE_DIRS ${GLIB2_GLIB2CONFIG_INCLUDE_PATH} ${GLIB2_INCLUDE_DIRS} ) 49 | SET( GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ) 50 | SET( GLIB2_FOUND 1 ) 51 | ELSE() 52 | SET( GLIB2_INCLUDE_DIRS ) 53 | SET( GLIB2_LIBRARIES ) 54 | SET( GLIB2_FOUND 0) 55 | ENDIF() 56 | 57 | IF(WIN32 AND NOT BUILD_STATIC) 58 | FIND_FILE(GLIB2_DLL 59 | NAMES glib-2.dll glib-2-vs9.dll libglib-2.0-0.dll 60 | PATHS "${GLIB2_BASE_DIR}/bin" 61 | NO_SYSTEM_ENVIRONMENT_PATH) 62 | ENDIF() 63 | ENDIF () 64 | 65 | #INCLUDE( FindPackageHandleStandardArgs ) 66 | #FIND_PACKAGE_HANDLE_STANDARD_ARGS( GLIB2 DEFAULT_MSG GLIB2_LIBRARIES GLIB2_GLIB2CONFIG_INCLUDE_PATH GLIB2_GLIB2_INCLUDE_PATH ) 67 | 68 | IF (NOT GLIB2_FOUND AND GLIB2_FIND_REQUIRED) 69 | MESSAGE(FATAL_ERROR "Could not find glib2") 70 | ENDIF() 71 | -------------------------------------------------------------------------------- /tests/test_modifier_coord_tiny_image_old.cpp: -------------------------------------------------------------------------------- 1 | /* This checks for off-by-one errors which occure most clearly in extremely 2 | * small images. */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "lensfun.h" 11 | #include "../libs/lensfun/lensfunprv.h" 12 | 13 | 14 | typedef struct 15 | { 16 | void *coordBuff; 17 | size_t img_width, img_height; 18 | lfLens *lens; 19 | lfModifier *mod; 20 | } lfFixture; 21 | 22 | // setup a standard lens 23 | void mod_setup (lfFixture *lfFix, gconstpointer data) 24 | { 25 | lfFix->lens = new lfLens(); 26 | //lfFix->lens->CropFactor = 1.5f; 27 | //lfFix->lens->AspectRatio = 4.0f / 3.0f; 28 | lfFix->lens->Type = LF_RECTILINEAR; 29 | 30 | lfFix->img_height = 2; 31 | lfFix->img_width = 3; 32 | 33 | lfFix->mod = new lfModifier (lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); 34 | 35 | lfFix->mod->Initialize (lfFix->lens, LF_PF_F32, 50.89f, 2.8f, 1000.0f, 10.0f, LF_RECTILINEAR, 36 | LF_MODIFY_SCALE, true); 37 | 38 | lfFix->coordBuff = NULL; 39 | 40 | const size_t bufsize = 2 * lfFix->img_width * lfFix->img_height * sizeof (float); 41 | lfFix->coordBuff = g_malloc (bufsize); 42 | } 43 | 44 | void mod_teardown (lfFixture *lfFix, gconstpointer data) 45 | { 46 | g_free (lfFix->coordBuff); 47 | 48 | delete lfFix->mod; 49 | delete lfFix->lens; 50 | } 51 | 52 | void test_mod_coord_scaling_only (lfFixture *lfFix, gconstpointer data) 53 | { 54 | const float epsilon = std::numeric_limits::epsilon() * 10; 55 | float expected_coordinates[] = {-9.0f, -4.5f, 1.0f, -4.5f, 11.0f, -4.5f, 56 | -9.0f, 5.5f, 1.0f, 5.5f, 11.0f, 5.5}; 57 | std::vector coords (2 * 3 * 2); 58 | g_assert_true (lfFix->mod->ApplyGeometryDistortion (0, 0, 3, 2, &coords [0])); 59 | for (unsigned int i = 0; i < coords.size(); i++) 60 | g_assert_cmpfloat (fabs (coords [i] - expected_coordinates [i]), <=, epsilon); 61 | } 62 | 63 | 64 | int main (int argc, char **argv) 65 | { 66 | setlocale (LC_ALL, ""); 67 | 68 | g_test_init (&argc, &argv, NULL); 69 | 70 | g_test_add ("/modifier/coord/tiny_image/scaling only", lfFixture, NULL, 71 | mod_setup, test_mod_coord_scaling_only, mod_teardown); 72 | 73 | return g_test_run(); 74 | } 75 | -------------------------------------------------------------------------------- /libs/lensfun/mod-color-sse.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Image modifier implementation 3 | Copyright (C) 2014 by Roman Lebedev 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #ifdef VECTORIZATION_SSE 9 | 10 | #include "lensfun.h" 11 | #include "lensfunprv.h" 12 | #include 13 | 14 | #if defined (_MSC_VER) 15 | typedef size_t uintptr_t; 16 | #else 17 | typedef __SIZE_TYPE__ uintptr_t; 18 | #endif 19 | 20 | void lfModifier::ModifyColor_DeVignetting_PA_SSE ( 21 | void *data, float x, float y, lf_f32 *pixels, int comp_role, int count) 22 | { 23 | int cr = comp_role; 24 | 25 | /* 26 | * If there are not four components per pixel, or buffer is not aligned, 27 | * fall back to plain code 28 | */ 29 | if (!(((cr & 15) > LF_CR_NEXT) && 30 | (((cr >> 4) & 15) > LF_CR_NEXT) && 31 | (((cr >> 8) & 15) > LF_CR_NEXT) && 32 | (((cr >> 12) & 15) > LF_CR_NEXT) && 33 | (((cr >> 16) & 15) == LF_CR_END)) || 34 | ((uintptr_t)(pixels) & 0xf)) 35 | { 36 | return ModifyColor_DeVignetting_PA(data, x, y, pixels, comp_role, count); 37 | } 38 | 39 | lfColorVignCallbackData* cddata = (lfColorVignCallbackData*) data; 40 | 41 | __m128 x2 = _mm_set_ps1 (x); 42 | 43 | __m128 r2 = _mm_set_ps1 (x * x + y * y); 44 | __m128 d1 = _mm_set_ps1 (2.0 * cddata->norm_scale); 45 | __m128 p0 = _mm_set_ps1 (cddata->terms [0]); 46 | __m128 p1 = _mm_set_ps1 (cddata->terms [1]); 47 | __m128 p2 = _mm_set_ps1 (cddata->terms [2]); 48 | __m128 p3 = _mm_set_ps1 (cddata->norm_scale); 49 | __m128 one = _mm_set_ps1 (1.0f); 50 | __m128 d2 = _mm_set_ps1 (cddata->norm_scale * cddata->norm_scale); 51 | 52 | // SSE Loop processes 1 pixel/loop 53 | for (int i = 0; i < count; i++) 54 | { 55 | __m128 pix = _mm_load_ps (&pixels [i * 4]); 56 | 57 | __m128 r4 = _mm_mul_ps (r2, r2); 58 | __m128 r6 = _mm_mul_ps (r4, r2); 59 | 60 | // c = 1.0 + param [0] * r2 + param [1] * r4 + param [2] * r6; 61 | __m128 c = _mm_add_ps (_mm_add_ps (_mm_add_ps ( 62 | one, _mm_mul_ps (p0, r2)), _mm_mul_ps (r4, p1)), _mm_mul_ps (r6, p2)); 63 | 64 | pix = _mm_div_ps(pix, c); 65 | 66 | pix = _mm_max_ps(pix, _mm_setzero_ps()); 67 | 68 | _mm_store_ps (&pixels [i * 4], pix); 69 | 70 | // Prepare for next iteration 71 | r2 = _mm_add_ps (_mm_add_ps (d2, r2), _mm_mul_ps (d1, x2)); 72 | x2 = _mm_add_ps (x2, p3); 73 | } 74 | } 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /libs/lensfun/camera.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Private constructors and destructors 3 | Copyright (C) 2007 by Andrew Zabolotny 4 | */ 5 | 6 | #include "config.h" 7 | #include "lensfun.h" 8 | #include "lensfunprv.h" 9 | 10 | lfCamera::lfCamera () 11 | { 12 | Maker = NULL; 13 | Model = NULL; 14 | Variant = NULL; 15 | Mount = NULL; 16 | CropFactor = 0.0f; 17 | } 18 | 19 | lfCamera::~lfCamera () 20 | { 21 | lf_free (Maker); 22 | lf_free (Model); 23 | lf_free (Variant); 24 | lf_free (Mount); 25 | } 26 | 27 | lfCamera::lfCamera (const lfCamera &other) 28 | { 29 | Maker = lf_mlstr_dup (other.Maker); 30 | Model = lf_mlstr_dup (other.Model); 31 | Variant = lf_mlstr_dup (other.Variant); 32 | Mount = g_strdup (other.Mount); 33 | CropFactor = other.CropFactor; 34 | } 35 | 36 | lfCamera &lfCamera::operator = (const lfCamera &other) 37 | { 38 | lf_free (Maker); 39 | Maker = lf_mlstr_dup (other.Maker); 40 | lf_free (Model); 41 | Model = lf_mlstr_dup (other.Model); 42 | lf_free (Variant); 43 | Variant = lf_mlstr_dup (other.Variant); 44 | _lf_setstr (&Mount, other.Mount); 45 | CropFactor = other.CropFactor; 46 | return *this; 47 | } 48 | 49 | void lfCamera::SetMaker (const char *val, const char *lang) 50 | { 51 | Maker = lf_mlstr_add (Maker, lang, val); 52 | } 53 | 54 | void lfCamera::SetModel (const char *val, const char *lang) 55 | { 56 | Model = lf_mlstr_add (Model, lang, val); 57 | } 58 | 59 | void lfCamera::SetVariant (const char *val, const char *lang) 60 | { 61 | Variant = lf_mlstr_add (Variant, lang, val); 62 | } 63 | 64 | void lfCamera::SetMount (const char *val) 65 | { 66 | _lf_setstr (&Mount, val); 67 | } 68 | 69 | bool lfCamera::Check () 70 | { 71 | if (!Maker || !Model || !Mount || CropFactor <= 0) 72 | return false; 73 | 74 | return true; 75 | } 76 | 77 | //---------------------------// The C interface //---------------------------// 78 | 79 | lfCamera *lf_camera_new () 80 | { 81 | return new lfCamera (); 82 | } 83 | 84 | lfCamera *lf_camera_create () 85 | { 86 | return new lfCamera (); 87 | } 88 | 89 | void lf_camera_destroy (lfCamera *camera) 90 | { 91 | delete camera; 92 | } 93 | 94 | void lf_camera_copy (lfCamera *dest, const lfCamera *source) 95 | { 96 | *dest = *source; 97 | } 98 | 99 | cbool lf_camera_check (lfCamera *camera) 100 | { 101 | return camera->Check (); 102 | } 103 | -------------------------------------------------------------------------------- /docs/man/lensfun-update-data.1.rst: -------------------------------------------------------------------------------- 1 | ====================== 2 | lensfun-update-data 3 | ====================== 4 | 5 | ---------------------------- 6 | update Lensfun's database 7 | ---------------------------- 8 | 9 | :Author: This manual page was written by Torsten Bronger 10 | :Date: 2015-03-11 11 | :Manual section: 1 12 | 13 | SYNOPSIS 14 | ============ 15 | 16 | ``lensfun-update-data`` 17 | 18 | DESCRIPTION 19 | =============== 20 | 21 | Lensfun is a library that corrects flaws in photographic images introduced by 22 | the lens. It also contains a comprehensive database of cameras and lenses 23 | together with their characteristics to be able to apply automatic corrections 24 | of images taken with these devices. Lensfun is used by darktable, digiKam, 25 | rawstudio, GimpLensfun, UFRaw, and others. 26 | 27 | ``lensfun-update-data`` is a command-line program that updates Lensfun's 28 | database. It looks whether a new version is available online, and if this is 29 | the case, it fetches the latest version and installs it locally. If called as 30 | root, the database is installed system-wide, otherwise, it is installed in the 31 | user's directory. 32 | 33 | FILES 34 | ====== 35 | 36 | ``lensfun-update-data`` will place the fetched database in 37 | ``/var/lib/lensfun-updates/`` (if called as root) or in 38 | ``~/.local/share/lensfun/updates/`` (otherwise). If necessary, it will create 39 | this directory. If there is already a database, it is replaced fully. If 40 | Lensfun detects a database in one of these directories, it will use that 41 | instead of the default location below ``/usr/...``. 42 | 43 | DIAGNOSTICS 44 | =============== 45 | 46 | ``lensfun-update-data`` prints log messages to stdout. 47 | 48 | Exit status: 49 | 50 | =========== ===================================== 51 | 0 if OK (updates were installed), 52 | 1 if no newer version could be found, 53 | 3 if no DB location responded validly. 54 | =========== ===================================== 55 | 56 | REPORTING BUGS 57 | ==================== 58 | 59 | Report bugs at . 60 | 61 | COPYRIGHT 62 | ============= 63 | 64 | Lensfun is Copyright © 2007 Andrew Zabolotny 65 | 66 | License of the code: GNU Lesser General Public License, version 3 67 | 68 | License of the database: Creative Commons Attribution-Share Alike 3.0 license 69 | 70 | SEE ALSO 71 | ============ 72 | 73 | g-lensfun-update-data(1), lensfun-add-adapter(1), lensfun-convert-lcp(1) 74 | -------------------------------------------------------------------------------- /apps/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | IF(BUILD_LENSTOOL) 2 | INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS}) 3 | INCLUDE_DIRECTORIES(${PNG_INCLUDE_DIRS}) 4 | INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS}) 5 | ADD_EXECUTABLE(lenstool lenstool/lenstool.cpp lenstool/image.cpp) 6 | TARGET_COMPILE_DEFINITIONS(lenstool PRIVATE -Dauxfun_EXPORTS) 7 | TARGET_LINK_LIBRARIES(lenstool lensfun ${PNG_LIBRARIES} ${ZLIB_LIBRARIES}) 8 | IF(WIN32) 9 | TARGET_LINK_LIBRARIES(lenstool getopt) 10 | ENDIF() 11 | INSTALL(TARGETS lenstool DESTINATION ${CMAKE_INSTALL_BINDIR}) 12 | ENDIF() 13 | 14 | 15 | IF(INSTALL_HELPER_SCRIPTS) 16 | INSTALL(PROGRAMS g-lensfun-update-data lensfun-add-adapter lensfun-update-data lensfun-convert-lcp 17 | DESTINATION ${CMAKE_INSTALL_BINDIR}) 18 | ENDIF(INSTALL_HELPER_SCRIPTS) 19 | 20 | 21 | # Inspired by http://bloerg.net/2012/11/10/cmake-and-distutils.html 22 | IF(INSTALL_PYTHON_MODULE) 23 | FIND_PACKAGE(PythonInterp) 24 | IF(PYTHONINTERP_FOUND) 25 | # Windows has a dummy python.exe in the PATH which opens the Microsoft Store, so check if Python is real. 26 | EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} --version RESULT_VARIABLE PY_RESULT) 27 | IF (NOT PY_RESULT EQUAL 0) 28 | SET(PYTHONINTERP_FOUND FALSE) 29 | ENDIF() 30 | ENDIF() 31 | IF(PYTHONINTERP_FOUND) 32 | SET(SETUP_PY_IN "${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in") 33 | SET(SETUP_PY "${CMAKE_CURRENT_BINARY_DIR}/setup.py") 34 | SET(DEPS_IN "${CMAKE_CURRENT_SOURCE_DIR}/lensfun/__init__.py.in") 35 | SET(DEPS "${CMAKE_CURRENT_BINARY_DIR}/lensfun/__init__.py") 36 | SET(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/build/timestamp") 37 | 38 | FILE(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}" PY_PACKAGE_DIR) 39 | CONFIGURE_FILE(${SETUP_PY_IN} ${SETUP_PY}) 40 | CONFIGURE_FILE(${DEPS_IN} ${DEPS}) 41 | 42 | ADD_CUSTOM_COMMAND(OUTPUT ${OUTPUT} 43 | COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} build 44 | COMMAND ${CMAKE_COMMAND} -E touch ${OUTPUT} 45 | DEPENDS ${SETUP_PY_IN} ${DEPS_IN}) 46 | 47 | ADD_CUSTOM_TARGET(python-package ALL DEPENDS ${OUTPUT}) 48 | 49 | IF(NOT DEFINED SETUP_PY_INSTALL_PREFIX) 50 | SET(SETUP_PY_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") 51 | ENDIF() 52 | INSTALL(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} install --prefix=\$ENV{DESTDIR}${SETUP_PY_INSTALL_PREFIX})") 53 | ENDIF() 54 | ENDIF() 55 | -------------------------------------------------------------------------------- /data/db/slr-ricoh.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ricoh 6 | Ricoh XR Rikenon 1:1.4 50mm 7 | Pentax K 8 | 1.523 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | Ricoh 18 | Ricoh 50mm 1:2.0 19 | Pentax K 20 | 1 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /data/db/slr-schneider.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Schneider 6 | Schneider 28mm f/2.8 PC 7 | Canon EF 8 | Nikon F AI-S 9 | 1 10 | 11 | 12 | 13 | 14 | 15 | 16 | Schneider 17 | D-Xenon 1:3.5-5.6 18-55mm AL 18 | Pentax KAF2 19 | 20 | 1.53 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | Schneider 32 | D-Xenon 1:4-5.6 50-200mm AL 33 | Pentax KAF2 34 | 35 | 1.53 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | Schneider 50 | Schneider Retina-Curtagon 1:4/28mm 51 | DKL 52 | 1.529 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /tools/spline/spline.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | # -*- coding: windows-1251 -*- 3 | 4 | # 5 | # Visualization of a Hermite spline. 6 | # 7 | # Used to evaluate how much differs a two-interpolated-coordinates spline 8 | # from a single-interpolated-coordinate variant (which is used to interpolate 9 | # lens model terms). 10 | # 11 | 12 | from sys import *; 13 | from time import *; 14 | from pygame import *; 15 | 16 | TENSION = 0.5 # 0..1 17 | 18 | def spline(P1, P2, P3, P4, t): 19 | t2 = t * t; 20 | t3 = t2 * t; 21 | if P1 != None: 22 | tg2 = TENSION * (P3 - P1); 23 | else: 24 | tg2 = P3 - P2; 25 | if P4 != None: 26 | tg3 = TENSION * (P4 - P2); 27 | else: 28 | tg3 = P3 - P2; 29 | return (2 * t3 - 3 * t2 + 1) * P2 + \ 30 | (t3 - 2 * t2 + t) * tg2 + \ 31 | (-2 * t3 + 3 * t2) * P3 + \ 32 | (t3 - t2) * tg3; 33 | 34 | init () 35 | dpy = display.set_mode ((800, 800)) 36 | 37 | WHITE = (255, 255, 255) 38 | GREEN = (0, 255, 0) 39 | RED = (255, 0, 0) 40 | 41 | # Control points 42 | points = ((10, 10), (100, 200), (200, 300), 43 | (300, 500), (400, 400), (500, 500), 44 | (600, 200), (700, 100), (790, 790), (790, 790)) 45 | 46 | # Display a single-interpolated-coordinate spline 47 | pi = 0; 48 | p2 = (None, None); 49 | p3 = points [0]; 50 | for x in range(points [0][0], points [len (points) - 1][0]): 51 | if (x >= p3 [0]) and (pi < len (points) - 1): 52 | p1 = p2; 53 | p2 = points [pi]; 54 | p3 = points [pi + 1]; 55 | if pi < len (points) - 2: 56 | p4 = points [pi + 2]; 57 | else: 58 | p4 = (None, None); 59 | pi = pi + 1; 60 | t = float (x - p2 [0]) / (p3 [0] - p2 [0]); 61 | p = spline (p1 [1], p2 [1], p3 [1], p4 [1], t); 62 | draw.line (dpy, WHITE, (x, p), (x, p)); 63 | 64 | # Display a two-interpolated-coordinates spline 65 | p2 = points [0]; 66 | p3 = points [0]; 67 | p4 = points [0]; 68 | for p in points: 69 | p1 = p2; 70 | p2 = p3; 71 | p3 = p4; 72 | p4 = p; 73 | t = 0.0; 74 | while t < 1.0: 75 | px = spline (p1 [0], p2 [0], p3 [0], p4 [0], t); 76 | py = spline (p1 [1], p2 [1], p3 [1], p4 [1], t); 77 | draw.line (dpy, GREEN, (px, py), (px, py)); 78 | t = t + 0.01; 79 | 80 | # Mark control points 81 | for p in points: 82 | draw.line (dpy, RED, (p [0]-2, p [1]-2), (p [0]+2, p [1]+2)); 83 | draw.line (dpy, RED, (p [0]-2, p [1]+2), (p [0]+2, p [1]-2)); 84 | 85 | # Display the stuff 86 | display.flip () 87 | 88 | # Wait for ESC or close window 89 | while True: 90 | for e in event.get(): 91 | if e.type == QUIT or (e.type == KEYDOWN and e.key == K_ESCAPE): 92 | exit () 93 | sleep (0.1) 94 | -------------------------------------------------------------------------------- /data/db/lensfun-database.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /data/db/compact-sigma.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Sigma 6 | Sigma DP1 7 | DP1 8 | sigmaDP1 9 | 1.739 10 | 11 | 12 | 13 | Sigma 14 | Sigma DP1 Merrill 15 | DP1 Merrill 16 | sigmaDP1M 17 | 1.531 18 | 19 | 20 | 21 | Sigma 22 | Sigma DP1S 23 | DP1S 24 | sigmaDP1 25 | 1.739 26 | 27 | 28 | 29 | Sigma 30 | Sigma DP1X 31 | DP1X 32 | sigmaDP1 33 | 1.739 34 | 35 | 36 | 37 | Sigma 38 | Sigma DP2 39 | DP2 40 | sigmaDP2 41 | 1.739 42 | 43 | 44 | 45 | Sigma 46 | Sigma DP2 Merrill 47 | DP2 Merrill 48 | sigmaDP2M 49 | 1.531 50 | 51 | 52 | 53 | Sigma 54 | Sigma DP2S 55 | DP2S 56 | sigmaDP2 57 | 1.739 58 | 59 | 60 | 61 | Sigma 62 | Sigma DP2X 63 | DP2X 64 | sigmaDP2 65 | 1.739 66 | 67 | 68 | 69 | Sigma 70 | Sigma DP3 Merrill 71 | DP3 Merrill 72 | sigmaDP3M 73 | 1.531 74 | 75 | 76 | 77 | Sigma 78 | Sigma DP2 & compatibles (Standard) 79 | fixed lens 80 | festes Objektiv 81 | sigmaDP2 82 | 1.739 83 | 3:2 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # becomes PLATFORM=X64|X86 environment variable (note uppercase!) 2 | platform: 3 | - x64 4 | - x86 5 | 6 | # becomes CONFIGURATION=Debug|Release environment variable 7 | configuration: 8 | - Debug 9 | - Release 10 | 11 | environment: 12 | global: 13 | BUILD_LENSTOOL: 'OFF' 14 | BUILD_STATIC: 'OFF' 15 | matrix: 16 | # VS 2015 17 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 18 | VS_INIT_CMD: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat 19 | GENERATOR: Visual Studio 14 2015 20 | 21 | # VS 2017 22 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 23 | VS_INIT_CMD: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat 24 | GENERATOR: Visual Studio 15 2017 25 | 26 | # VS 2019 27 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 28 | VS_INIT_CMD: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat 29 | GENERATOR: Visual Studio 16 2019 30 | 31 | # VS 2019 (with lenstool and static libraries) 32 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 33 | VS_INIT_CMD: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat 34 | GENERATOR: Visual Studio 16 2019 35 | BUILD_LENSTOOL: 'ON' 36 | BUILD_STATIC: 'ON' 37 | 38 | install: 39 | - set APPVEYOR_SAVE_CACHE_ON_ERROR=true 40 | 41 | # Select Visual Studio version and architecture 42 | - call "%VS_INIT_CMD%" %PLATFORM% 43 | - if /I %PLATFORM% == x86 ( set GENERATOR_PLATFORM=Win32 ) 44 | - if /I %PLATFORM% == x64 ( set GENERATOR_PLATFORM=x64 ) 45 | 46 | # Print environment variables 47 | - set 48 | 49 | # Update vcpkg 50 | # https://help.appveyor.com/discussions/problems/24684-problem-with-vcpkg-wrong-version-on-appveyor 51 | - powershell iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/build-images/master/scripts/Windows/install_vcpkg.ps1')) 52 | 53 | # Install dependencies 54 | - vcpkg install glib:%PLATFORM%-windows 55 | - if %BUILD_LENSTOOL% == ON ( vcpkg install libpng:%PLATFORM%-windows ) 56 | # xmllint tool for tests 57 | - choco install xsltproc 58 | 59 | build_script: 60 | - mkdir build 61 | - cd build 62 | - cmake .. -G "%GENERATOR%" -A %GENERATOR_PLATFORM% -DBUILD_STATIC=%BUILD_STATIC% -DBUILD_LENSTOOL=%BUILD_LENSTOOL% -DBUILD_TESTS=ON -DCMAKE_INSTALL_PREFIX=install -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -DGLIB2_BASE_DIR=c:/tools/vcpkg/installed/%PLATFORM%-windows 63 | - cmake --build . --config %CONFIGURATION% 64 | - cmake --build . --target install 65 | 66 | test_script: 67 | - ctest -C %CONFIGURATION% --output-on-failure 68 | 69 | cache: c:\tools\vcpkg\installed\ -------------------------------------------------------------------------------- /tools/calibration_webserver/workflow.rst: -------------------------------------------------------------------------------- 1 | ======================= 2 | Calibration workflow 3 | ======================= 4 | 5 | 6 | Setup 7 | ======= 8 | 9 | 10 | GitHub 11 | ------ 12 | 13 | If you want to help with calibrations, contact `Torsten Bronger`_. Then, you 14 | get access to Lensfun's GitHub repository. You need to have an account on 15 | GitHub for this. Then, watch the `Lensfun repository`_. New calibration 16 | requests bear the label “calibration request”. 17 | 18 | .. _Torsten Bronger: mailto:bronger@physik.rwth-aachen.de 19 | .. _Lensfun repository: https://github.com/lensfun/lensfun 20 | 21 | Note that the official Lensfun Git repository still resides on Sourceforge. 22 | The GitHub clone is only used for an easier calibration workflow. (And to make 23 | my GitHub profile look better.) 24 | 25 | 26 | ownCloud 27 | -------- 28 | 29 | We share the calibration images themselves via ownCloud. Any ownCloud client 30 | should work. Our server is at ``https://bob.ipv.kfa-juelich.de/owncloud``. 31 | You get credentials from Torsten. We cannot make it totally public because it 32 | contains email addresses. 33 | 34 | 35 | Workflow 36 | =========== 37 | 38 | 1. Assign an unassigned calibration request issue to you. 39 | 2. The issue title contains a hash. The respective directory in ownCloud 40 | starts with the same hash. 41 | 3. `Work on the calibration`_, probably changing the contents of the 42 | directory. 43 | 4. If you have questions to the uploader, contact them by email or in the 44 | GitHub issue. If the uploader prefers GitHub, they will add a comment like 45 | “I am the uploader” to the issue. 46 | 5. If you are done, you may add a comment starting with “@uploader:”. Please 47 | don't use this just to say thank you because the automatic email sent will 48 | include thanks anyway. Instead, use this feature for comments like “The 49 | images were good, but the target was not really trustworthy” or “Images of 50 | ducks on a lake cannot be used for calibration”. Note that it is not 51 | necessary to use this feature at all. 52 | 6. If the images are unusable for calibration, add the label “unsuccessful” to 53 | the issue. You needn’t close it. 54 | 7. If you need feedback, file a pull request with the calibration results. 55 | Else, commit them to the ``master`` branch and mark the issue with the label 56 | “successful”. 57 | 8. A `cronjob`_ on Torsten's computer will remove this label once per hour, 58 | close the issue, and send an email to the uploader, possibly with the latest 59 | “@uploader” comment. 60 | 61 | .. _Work on the calibration: 62 | https://github.com/lensfun/lensfun/blob/master/tools/calibration_webserver/calibration.rst 63 | .. _cronjob: 64 | https://github.com/lensfun/lensfun/blob/master/tools/update_database/follow_db_changes.py 65 | -------------------------------------------------------------------------------- /tests/test_database_old.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "lensfun.h" 4 | 5 | typedef struct { 6 | lfDatabase* db; 7 | } lfFixture; 8 | 9 | 10 | void db_setup(lfFixture *lfFix, gconstpointer data) 11 | { 12 | lfFix->db = new lfDatabase (); 13 | lfFix->db->LoadDirectory("data/db"); 14 | } 15 | 16 | 17 | void db_teardown(lfFixture *lfFix, gconstpointer data) 18 | { 19 | delete lfFix->db; 20 | } 21 | 22 | 23 | // test different lens search strings 24 | void test_DB_lens_search(lfFixture* lfFix, gconstpointer data) 25 | { 26 | const lfLens **lenses = NULL; 27 | 28 | lenses = lfFix->db->FindLenses (NULL, NULL, "pEntax 50-200 ED"); 29 | g_assert_nonnull(lenses); 30 | g_assert_cmpstr(lenses[0]->Model, ==, "smc Pentax-DA 50-200mm f/4-5.6 DA ED"); 31 | lf_free (lenses); 32 | 33 | lenses = lfFix->db->FindLenses (NULL, NULL, "smc Pentax-DA 50-200mm f/4-5.6 DA ED"); 34 | g_assert_nonnull(lenses); 35 | g_assert_cmpstr(lenses[0]->Model, ==, "smc Pentax-DA 50-200mm f/4-5.6 DA ED"); 36 | lf_free (lenses); 37 | 38 | lenses = lfFix->db->FindLenses (NULL, NULL, "PENTAX fa 28mm 2.8"); 39 | g_assert_nonnull(lenses); 40 | g_assert_cmpstr(lenses[0]->Model, ==, "smc Pentax-FA 28mm f/2.8 AL"); 41 | lf_free (lenses); 42 | 43 | /*lenses = lfFix->db->FindLenses (NULL, NULL, "Fotasy M3517 35mm f/1.7"); 44 | g_assert_nonnull(lenses); 45 | g_assert_cmpstr(lenses[0]->Model, ==, "Fotasy M3517 35mm f/1.7"); 46 | lf_free (lenses); 47 | 48 | lenses = lfFix->db->FindLenses (NULL, NULL, "Minolta MD 35mm 1/2.8"); 49 | g_assert_nonnull(lenses); 50 | g_assert_cmpstr(lenses[0]->Model, ==, "Minolta MD 35mm 1/2.8"); 51 | lf_free (lenses);*/ 52 | } 53 | 54 | // test different camera search strings 55 | void test_DB_cam_search(lfFixture* lfFix, gconstpointer data) 56 | { 57 | const lfCamera **cameras = NULL; 58 | 59 | cameras = lfFix->db->FindCamerasExt("pentax", "K100D"); 60 | g_assert_nonnull(cameras); 61 | g_assert_cmpstr(cameras[0]->Model, ==, "Pentax K100D"); 62 | lf_free (cameras); 63 | 64 | cameras = lfFix->db->FindCamerasExt(NULL, "K 100 D"); 65 | g_assert_nonnull(cameras); 66 | g_assert_cmpstr(cameras[0]->Model, ==, "Pentax K100D"); 67 | lf_free (cameras); 68 | 69 | cameras = lfFix->db->FindCamerasExt(NULL, "PentAX K100 D"); 70 | g_assert_nonnull(cameras); 71 | g_assert_cmpstr(cameras[0]->Model, ==, "Pentax K100D"); 72 | lf_free (cameras); 73 | 74 | } 75 | 76 | int main (int argc, char **argv) 77 | { 78 | 79 | setlocale (LC_ALL, ""); 80 | 81 | g_test_init(&argc, &argv, NULL); 82 | 83 | g_test_add("/database/lens search", lfFixture, NULL, db_setup, test_DB_lens_search, db_teardown); 84 | g_test_add("/database/camera search", lfFixture, NULL, db_setup, test_DB_cam_search, db_teardown); 85 | 86 | return g_test_run(); 87 | } 88 | -------------------------------------------------------------------------------- /libs/lensfun/mount.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Private constructors and destructors 3 | Copyright (C) 2007 by Andrew Zabolotny 4 | */ 5 | 6 | #include "config.h" 7 | #include "lensfun.h" 8 | #include "lensfunprv.h" 9 | #include 10 | 11 | lfMount::lfMount () 12 | { 13 | Name = NULL; 14 | Compat = NULL; 15 | } 16 | 17 | lfMount::~lfMount () 18 | { 19 | lf_free (Name); 20 | for (char* m: MountCompat) 21 | free(m); 22 | } 23 | 24 | lfMount::lfMount (const lfMount &other) 25 | { 26 | Name = lf_mlstr_dup (other.Name); 27 | Compat = NULL; 28 | 29 | MountCompat.clear(); 30 | const char* const* otherMounts = other.GetCompats(); 31 | for (int i = 0; otherMounts[i]; i++) 32 | AddCompat(otherMounts[i]); 33 | } 34 | 35 | lfMount &lfMount::operator = (const lfMount &other) 36 | { 37 | lf_free (Name); 38 | Name = lf_mlstr_dup (other.Name); 39 | Compat = NULL; 40 | 41 | MountCompat.clear(); 42 | const char* const* otherMounts = other.GetCompats(); 43 | for (int i = 0; otherMounts[i]; i++) 44 | AddCompat(otherMounts[i]); 45 | 46 | return *this; 47 | } 48 | 49 | bool lfMount::operator == (const lfMount& other) 50 | { 51 | return _lf_strcmp (Name, other.Name) == 0; 52 | } 53 | 54 | void lfMount::SetName (const char *val, const char *lang) 55 | { 56 | Name = lf_mlstr_add (Name, lang, val); 57 | } 58 | 59 | void lfMount::AddCompat (const char *val) 60 | { 61 | if (val) 62 | { 63 | char* p = (char*)malloc(strlen(val) + 1); 64 | strcpy(p, val); 65 | MountCompat.push_back(p); 66 | 67 | // add terminating NULL 68 | _lf_terminate_vec(MountCompat); 69 | 70 | // legacy compat pointer 71 | Compat = (char**)MountCompat.data(); 72 | } 73 | } 74 | 75 | const char* const* lfMount::GetCompats() const 76 | { 77 | return MountCompat.data(); 78 | } 79 | 80 | bool lfMount::Check () 81 | { 82 | if (!Name) 83 | return false; 84 | 85 | return true; 86 | } 87 | 88 | 89 | //---------------------------// The C interface //---------------------------// 90 | 91 | lfMount *lf_mount_new () 92 | { 93 | return new lfMount (); 94 | } 95 | 96 | lfMount *lf_mount_create () 97 | { 98 | return new lfMount (); 99 | } 100 | 101 | void lf_mount_destroy (lfMount *mount) 102 | { 103 | delete mount; 104 | } 105 | 106 | void lf_mount_copy (lfMount *dest, const lfMount *source) 107 | { 108 | *dest = *source; 109 | } 110 | 111 | cbool lf_mount_check (lfMount *mount) 112 | { 113 | return mount->Check (); 114 | } 115 | 116 | void lf_mount_add_compat (lfMount *mount, const char *val) 117 | { 118 | mount->AddCompat(val); 119 | } 120 | 121 | const char* const* lf_mount_get_compats (lfMount *mount) 122 | { 123 | return mount->GetCompats(); 124 | } 125 | -------------------------------------------------------------------------------- /docs/mounts.txt: -------------------------------------------------------------------------------- 1 | Canon: 2 | FL - Introduced in 1964 3 | FD - Another mount (incompatible with FL) feat. automatic aperture 4 | EF - Another incompatible mount, EF stands for electro-focus 5 | EF-S - A newer variant of EF with shorter flange depth, allowing 6 | for manufacturing of less expensive wide-angle lenses. Not useable 7 | on cameras with crop 1.0 and on EF-only cameras. 8 | 9 | Contax: 10 | N - ? 11 | Contax/Yashica - ? 12 | G - Rangefinder mount with autofocus 13 | 14 | Generic: 15 | M42 - First used in Zeiss Contax S (1949) and then adopted by many 16 | other manufacturers due to patent-less nature. 17 | M39/1 - Russian metric variant of Leica's M39 mount. 18 | T2 - Introduced by Tamron in 1957, with adaptors for virtually all other 19 | mounts (due to large flange distance). Used in astronomical 20 | devices and some mirror lenses. 21 | C - Intended for cinematographic lenses on very different viewframe sizes 22 | (often smaller that µFT), it can be adapted to most mirrorless systems. 23 | It has a very short flange distance, but due to the small radius of 24 | most C mount lenses, the adapter can be realised as a ring around the 25 | lens. In photography, most C mount lenses must be considered fun 26 | lenses. 27 | 28 | Leica: 29 | M - Classical Leica rangefinder mount 30 | R - SLR mount, discontinued since 2009 31 | S - Medium-format mount 32 | 33 | Hasselblad: 34 | H - Current medium format mount of this brand 35 | 36 | Minolta: 37 | MC - Older Minolta mount for manual lenses 38 | MD - Newer version of MC with aperture information to the camera 39 | AF - (1985) features autofocus, several generations. 40 | 41 | Nikon: 42 | F - Introduced in 1959 43 | F AI - (1977) - Added electrical interface for automatic aperture control. 44 | F AI-S - (1979) - Added a mean to tell camera current focal length. 45 | F AF - (1986) - Added screwdriver AF coupling, compatible with older mounts 46 | 47 | Olympus: 48 | 4/3 System - (2002), the new "digital" mount together with Kodak 49 | 50 | Pentax: 51 | K - the original mount as introduced in 1975 52 | KF - the world's first autofocus mount, 1981. Abandoned. 53 | KA - the K mount plus electrical contacts to detect the min/max lens 54 | aperture and also whether the 'A' aperture mode is enabled. 55 | KAF - the KA mount plus autofocus 56 | KAF2 - in addition to KAF features implements power zooming and 57 | adds MTF information to the lens data 58 | 59 | Samsung: 60 | NX - mirrorless APS-C mount introduced in 2010 61 | NX mini - mirrorless 1" mount introduced in 2014 62 | 63 | Voigtländer: 64 | DKL - the "Deckel" mount used in the Bessamatic 65 | 66 | Kiev: 67 | 88 - screw mount for medium format 68 | 69 | Tamron: 70 | Adaptall - created by Tamron in the 1970's with large flange distance and a 71 | pleathora of adapters. 72 | -------------------------------------------------------------------------------- /docs/example/example.c: -------------------------------------------------------------------------------- 1 | /* 2 | A simple example of library usage from plain C 3 | */ 4 | 5 | #include "lensfun.h" 6 | #include 7 | #include 8 | #include 9 | 10 | int main () 11 | { 12 | int i, j; 13 | const struct lfMount *const *mounts; 14 | const struct lfCamera *const *cameras; 15 | const struct lfLens *const *lenses; 16 | struct lfDatabase *ldb; 17 | lfError e; 18 | 19 | /* Initialize locale in order to get translated names */ 20 | setlocale (LC_ALL, ""); 21 | 22 | ldb = lf_db_new (); 23 | if (!ldb) 24 | { 25 | fprintf (stderr, "Failed to create database\n"); 26 | return -1; 27 | } 28 | 29 | g_print ("HomeDataDir: %s\n", ldb->HomeDataDir); 30 | 31 | lf_db_load (ldb); 32 | 33 | g_print ("< --------------- < Mounts > --------------- >\n"); 34 | mounts = lf_db_get_mounts (ldb); 35 | for (i = 0; mounts [i]; i++) 36 | { 37 | g_print ("Mount: %s\n", lf_mlstr_get (mounts [i]->Name)); 38 | if (mounts [i]->Compat) 39 | for (j = 0; mounts [i]->Compat [j]; j++) 40 | g_print ("\tCompat: %s\n", mounts [i]->Compat [j]); 41 | } 42 | 43 | g_print ("< --------------- < Cameras > --------------- >\n"); 44 | cameras = lf_db_get_cameras (ldb); 45 | for (i = 0; cameras [i]; i++) 46 | { 47 | g_print ("Camera: %s / %s %s%s%s\n", 48 | lf_mlstr_get (cameras [i]->Maker), 49 | lf_mlstr_get (cameras [i]->Model), 50 | cameras [i]->Variant ? "(" : "", 51 | cameras [i]->Variant ? lf_mlstr_get (cameras [i]->Variant) : "", 52 | cameras [i]->Variant ? ")" : ""); 53 | g_print ("\tMount: %s\n", lf_db_mount_name (ldb, cameras [i]->Mount)); 54 | g_print ("\tCrop factor: %g\n", cameras [i]->CropFactor); 55 | } 56 | 57 | g_print ("< --------------- < Lenses > --------------- >\n"); 58 | lenses = lf_db_get_lenses (ldb); 59 | for (i = 0; lenses [i]; i++) 60 | { 61 | g_print ("Lens: %s / %s\n", 62 | lf_mlstr_get (lenses [i]->Maker), 63 | lf_mlstr_get (lenses [i]->Model)); 64 | g_print ("\tCrop factor: %g\n", lenses [i]->CropFactor); 65 | g_print ("\tAspect ratio: %g\n", lenses [i]->AspectRatio); 66 | g_print ("\tFocal: %g-%g\n", lenses [i]->MinFocal, lenses [i]->MaxFocal); 67 | g_print ("\tAperture: %g-%g\n", lenses [i]->MinAperture, lenses [i]->MaxAperture); 68 | g_print ("\tCenter: %g,%g\n", lenses [i]->CenterX, lenses [i]->CenterY); 69 | if (lenses [i]->Mounts) 70 | for (j = 0; lenses [i]->Mounts [j]; j++) 71 | g_print ("\tMount: %s\n", lf_db_mount_name (ldb, lenses [i]->Mounts [j])); 72 | } 73 | 74 | g_print ("< ---< Saving database into one big file >--- >\n"); 75 | e = lf_db_save_file (ldb, "example-big.xml", mounts, cameras, lenses); 76 | if (e != LF_NO_ERROR) 77 | fprintf (stderr, "Failed writing to file, error code %d\n", e); 78 | 79 | lf_db_destroy (ldb); 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /tools/check_database/check_database.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """Checks sanity of the database. Pass the path to the database on the command 4 | line. This path defaults to ``../../data/db``, relatively to the directory of 5 | this script. 6 | 7 | If you want to add a check, just add a "check_..." function to this program. 8 | It must take a set of ElementTree roots. 9 | """ 10 | 11 | import glob, sys, os, inspect, subprocess 12 | from xml.etree import ElementTree 13 | 14 | ERROR_FOUND = False 15 | 16 | ########## 17 | # Helper functions 18 | 19 | def normalize_string(string): 20 | return " ".join(string.lower().split()) 21 | 22 | def name(element, tag_name): 23 | for subelement in element.findall(tag_name): 24 | if not subelement.attrib: 25 | return normalize_string(subelement.text) 26 | 27 | 28 | ########## 29 | # Database check_... functions 30 | 31 | def check_primary_keys_uniqueness(db_files): 32 | global ERROR_FOUND 33 | 34 | roots = set() 35 | for filepath in db_files: 36 | roots.add(ElementTree.parse(filepath).getroot()) 37 | 38 | lenses, mounts, cameras = set(), set(), set() 39 | for root in roots: 40 | for element in root.findall("lens"): 41 | lens = (name(element, "maker"), name(element, "model"), float(element.find("cropfactor").text)) 42 | if lens in lenses: 43 | print("ERROR: Double primary key for lens! {}".format(lens)) 44 | ERROR_FOUND = True 45 | else: 46 | lenses.add(lens) 47 | for element in root.findall("mount"): 48 | mount = name(element, "name") 49 | if mount in mounts: 50 | print("ERROR: Double primary key for mounts! {}".format(mount)) 51 | ERROR_FOUND = True 52 | else: 53 | mounts.add(mount) 54 | for element in root.findall("camera"): 55 | camera = (name(element, "maker"), name(element, "model"), name(element, "variant")) 56 | if camera in cameras: 57 | print("ERROR: Double primary key for cameras! {}".format(camera)) 58 | ERROR_FOUND = True 59 | else: 60 | cameras.add(camera) 61 | 62 | def check_xmllint(db_files): 63 | global ERROR_FOUND 64 | db_path = os.path.split(db_files[0])[0] 65 | for filepath in db_files: 66 | err = subprocess.call(["xmllint", 67 | "--valid", "--noout", 68 | "--schema", os.path.join(db_path,"lensfun-database.xsd"), 69 | filepath,]) 70 | 71 | if err is not 0: 72 | print("ERROR: xmllint check failed for " + filepath) 73 | ERROR_FOUND= True 74 | 75 | 76 | 77 | ########## 78 | # Main program 79 | 80 | try: 81 | rootdir = sys.argv[1] 82 | except IndexError: 83 | rootdir = os.path.join(os.path.dirname(__file__), "../../data/db") 84 | 85 | db_files = glob.glob(os.path.join(rootdir, "*.xml")) 86 | 87 | for check_function in [function for function in globals().copy().values() 88 | if inspect.isfunction(function) and function.__name__.startswith("check_")]: 89 | check_function(db_files) 90 | 91 | if ERROR_FOUND: 92 | sys.exit(1) 93 | else: 94 | sys.exit(0) 95 | -------------------------------------------------------------------------------- /tests/test_modifier_performance.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "xmmintrin.h" 7 | #include "time.h" 8 | 9 | #include "lensfun.h" 10 | #include "../libs/lensfun/lensfunprv.h" 11 | 12 | 13 | typedef struct 14 | { 15 | lfDatabase *db; 16 | size_t img_height; 17 | size_t img_width; 18 | } lfFixture; 19 | 20 | // setup a standard lens 21 | void mod_setup (lfFixture *lfFix, gconstpointer data) 22 | { 23 | 24 | lfFix->db = new lfDatabase (); 25 | lfFix->db->LoadDirectory("data/db"); 26 | 27 | lfFix->img_height = 4000; 28 | lfFix->img_width = 6000; 29 | } 30 | 31 | void mod_teardown (lfFixture *lfFix, gconstpointer data) 32 | { 33 | lfFix->db->Destroy(); 34 | } 35 | 36 | // very simple nearest neighbour interpolation to simulate some memory access 37 | void interp_row_nearest(unsigned char** img, unsigned int row, unsigned int width, unsigned int height, float* coords) 38 | { 39 | for (int c = 0; c=width) 47 | x = width - 1; 48 | if (y < 0) 49 | y = 0; 50 | if (y>=height) 51 | y = height - 1; 52 | 53 | img[row][3*c] = img[y][3*x]; 54 | img[row][3*c+1] = img[y][3*x+1]; 55 | img[row][3*c+2] = img[y][3*x+2]; 56 | } 57 | 58 | } 59 | 60 | void test_perf_dist_ptlens (lfFixture *lfFix, gconstpointer data) 61 | { 62 | // select a lens from database 63 | const lfLens** lenses = lfFix->db->FindLenses (NULL, NULL, "PENTAX-F 28-80mm"); 64 | g_assert_nonnull(lenses); 65 | g_assert_cmpstr(lenses[0]->Model, ==, "Pentax-F 28-80mm f/3.5-4.5"); 66 | 67 | lfModifier* mod = new lfModifier (lenses[0], 1.534f, lfFix->img_width, lfFix->img_height); 68 | 69 | mod->Initialize (lenses[0], LF_PF_F32, 30.89f, 2.8f, 1000.0f, 10.0f, LF_RECTILINEAR, 70 | LF_MODIFY_DISTORTION, false); 71 | 72 | 73 | unsigned char** img = (unsigned char**)_mm_malloc(lfFix->img_height*sizeof(unsigned char*), 32); 74 | for (int r = 0; r < lfFix->img_height; r++) 75 | img[r] = (unsigned char*)_mm_malloc(lfFix->img_width*sizeof(unsigned char)*3, 32); 76 | 77 | float *res = (float*)_mm_malloc(lfFix->img_width*sizeof(float)*2, 32); 78 | unsigned long start_time = clock(); 79 | for (int r = 0; r < lfFix->img_height; r++) 80 | { 81 | mod->ApplyGeometryDistortion (0, r, lfFix->img_width, 1, res); 82 | interp_row_nearest(img, r, lfFix->img_width, lfFix->img_height, res); 83 | } 84 | float run_time = ((float)(clock() - start_time)) / CLOCKS_PER_SEC; 85 | g_print("time elapsed : %.3fs, ",run_time); 86 | 87 | _mm_free(res); 88 | _mm_free(img); 89 | 90 | delete mod; 91 | lf_free (lenses); 92 | } 93 | 94 | int main (int argc, char **argv) 95 | { 96 | setlocale (LC_ALL, ""); 97 | setlocale(LC_NUMERIC, "C"); 98 | 99 | g_test_init (&argc, &argv, NULL); 100 | 101 | g_test_add ("/modifier/performance/dist/ptlens", lfFixture, NULL, 102 | mod_setup, test_perf_dist_ptlens, mod_teardown); 103 | 104 | return g_test_run(); 105 | } 106 | -------------------------------------------------------------------------------- /tools/perspective_control/test_image.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 38 | 40 | 41 | 43 | image/svg+xml 44 | 46 | 47 | 48 | 49 | 50 | 54 | 61 | 68 | 77 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /data/db/6x6.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Rollei 6x6 6 | Generic 7 | 8 | 9 | 10 | Mamiya 645 11 | Generic 12 | 13 | 14 | 15 | Mamiya 16 | Mamiya 645 17 | Mamiya 645 18 | 0.577 19 | 20 | 21 | 22 | Mamiya 23 | Mamiya ZD 24 | Mamiya 645 25 | 0.721 26 | 27 | 28 | 29 | Phase One 30 | P 25 31 | Mamiya 645 32 | 0.577 33 | 34 | 35 | 36 | Rolleiflex 37 | 2.8E 38 | Rollei 6x6 39 | 0.510 40 | 41 | 42 | 43 | Schneider 44 | Schneider 28mm Digitar f/2.8 45 | Mamiya 645 46 | 0.577 47 | 4:3 48 | 49 | 50 | 51 | 52 | 53 | 54 | Mamiya 55 | Mamiya 35mm f/3.5 56 | Mamiya 645 57 | 0.577 58 | 4:3 59 | 60 | 61 | 62 | 63 | 64 | 65 | Mamiya 66 | Mamiya 80mm f/2.8 67 | Mamiya 645 68 | 0.577 69 | 4:3 70 | 71 | 72 | 73 | 74 | 75 | 76 | Mamiya 77 | Mamiya 55-110mm f/4.5 78 | Mamiya 645 79 | 0.577 80 | 4:3 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | Schneider 94 | Schneider 80mm Xenotar f/2.8 95 | Rollei 6x6 96 | 0.510 97 | 1:1 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /apps/lensfun/__init__.py.in: -------------------------------------------------------------------------------- 1 | """The Lensfun Python package. It provides common functionality for Python 2 | scripts that want to find or read the Lensfun database. 3 | 4 | :var user_local_db_path: absolute path to the Lensfun DB of the current user. 5 | :var system_db_update_path: absolute path to the local but system-wide update 6 | of the Lensfun DB. 7 | 8 | :vartype user_local_db_path: str 9 | :vartype system_db_update_path: str 10 | """ 11 | 12 | import os 13 | 14 | 15 | user_local_db_path = os.path.join( 16 | os.environ.get("XDG_DATA_HOME", os.path.expanduser("~/.local/share")), "lensfun") 17 | system_db_path = os.path.join("${CMAKE_INSTALL_FULL_DATAROOTDIR}", "lensfun") 18 | system_db_update_path = os.path.join("/", "${CMAKE_INSTALL_LOCALSTATEDIR}", "lib", "lensfun-updates") 19 | 20 | 21 | def get_database_version(): 22 | """Returns the database version of the installed Lensfun. Note that if 23 | multiple versions of Lensfun are installed, the returned version number 24 | refers to the one that was installed together with the Python scripts. 25 | 26 | :return: 27 | the version number of Lensfun's database 28 | 29 | :rtype: int 30 | """ 31 | return ${LENSFUN_DB_VERSION} 32 | 33 | 34 | def get_core_database(): 35 | """Finds the upstream (core) database. The core database is the database 36 | installed with Lensfun, or downloaded by “lensfun-update-data”. 37 | 38 | :return: 39 | the timestamp of the local core database and its path; if no core 40 | database is found, it returns ``(0, None)`` 41 | 42 | :rtype: int, str 43 | """ 44 | 45 | def get_timestamp(path): 46 | try: 47 | return int(open(os.path.join(path, "timestamp.txt")).read()) 48 | except (FileNotFoundError, PermissionError, ValueError): 49 | return 0 50 | 51 | versioned_subdir = "version_{}".format(get_database_version()) 52 | db_path_candidates = {system_db_update_path, 53 | os.path.join(user_local_db_path, "updates"), 54 | system_db_path} 55 | newest_path = None 56 | newest_timestamp = 0 57 | for path in db_path_candidates: 58 | path = os.path.join(path, versioned_subdir) 59 | timestamp = get_timestamp(path) 60 | if timestamp > newest_timestamp: 61 | newest_timestamp = timestamp 62 | newest_path = path 63 | return newest_timestamp, newest_path 64 | 65 | 66 | def get_database_directories(): 67 | """Returns the directories containing Lensfun databases. The list returned 68 | should be iterated over to realise proper overriding of database entries. 69 | Thus, later entries take higher precedence over earlier entries. Note that 70 | if multiple versions of Lensfun are installed, the returned list refers to 71 | the one that was installed together with the Python scripts. Also note 72 | that Lensfun databases consist only of the files in a particular directory, 73 | and do not include automatically all files in sub-directories as well. 74 | 75 | All returned paths are guaranteed to exist, however, they may contain no 76 | database files or at least no ones readable to the current user. 77 | 78 | :return: 79 | list with paths to Lensfun databases 80 | 81 | :rtype: list of str 82 | """ 83 | versioned_subdir = "version_{}".format(get_database_version()) 84 | core_database_path = get_core_database()[1] 85 | paths = [core_database_path] if core_database_path else [] 86 | for path in (user_local_db_path, 87 | os.path.join(user_local_db_path, versioned_subdir)): 88 | if os.path.isdir(path): 89 | paths.append(path) 90 | return paths 91 | -------------------------------------------------------------------------------- /tools/calibration_webserver/owncloud.py: -------------------------------------------------------------------------------- 1 | """Interaction with the ownCloud synchronisation program ``owncloudcmd``. It 2 | works only on UNIX. 3 | """ 4 | 5 | import os, fcntl, subprocess, time, configparser 6 | 7 | 8 | config = configparser.ConfigParser() 9 | config.read(os.path.expanduser("~/calibration_webserver.ini")) 10 | 11 | 12 | class OwncloudLock: 13 | """Lock on the ownCloud synchronisation program as a context manager. It is 14 | adapted from very similar code from the JuliaBase project. You can use 15 | this class like this:: 16 | 17 | with OwncloudLock() as locked: 18 | if locked: 19 | do_work() 20 | else: 21 | print "I could not acquire the lock. I just exit." 22 | 23 | The lock file is /tmp/owncloudcmd.pid. 24 | """ 25 | 26 | def __init__(self): 27 | self.lockfile_path = os.path.join("/tmp/owncloudcmd.pid") 28 | self.locked = False 29 | 30 | def __enter__(self): 31 | try: 32 | self.lockfile = open(self.lockfile_path, "r+") 33 | fcntl.flock(self.lockfile.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) 34 | pid = int(self.lockfile.read().strip()) 35 | except IOError as e: 36 | if e.strerror == "No such file or directory": 37 | self.lockfile = open(self.lockfile_path, "w") 38 | fcntl.flock(self.lockfile.fileno(), fcntl.LOCK_EX) 39 | already_running = False 40 | elif e.strerror == "Resource temporarily unavailable": 41 | already_running = True 42 | else: 43 | raise 44 | except ValueError: 45 | # Ignore invalid lock 46 | already_running = False 47 | self.lockfile.seek(0) 48 | self.lockfile.truncate() 49 | else: 50 | try: 51 | os.kill(pid, 0) 52 | except OSError as error: 53 | if error.strerror == "No such process": 54 | # Ignore invalid lock 55 | already_running = False 56 | self.lockfile.seek(0) 57 | self.lockfile.truncate() 58 | else: 59 | raise 60 | else: 61 | # sister process is already active 62 | already_running = True 63 | if not already_running: 64 | self.lockfile.write(str(os.getpid())) 65 | self.lockfile.flush() 66 | self.locked = True 67 | return self.locked 68 | 69 | def __exit__(self, type_, value, tb): 70 | if self.locked: 71 | fcntl.flock(self.lockfile.fileno(), fcntl.LOCK_UN) 72 | self.lockfile.close() 73 | os.remove(self.lockfile_path) 74 | 75 | 76 | class LockError(Exception): 77 | """Raised if the ownCloud lock could not be acquired. 78 | """ 79 | pass 80 | 81 | 82 | def sync(): 83 | """Syncs the local ownCloud directory with the ownCloud server. It prevents 84 | two synchronisations being performed at the same time. 85 | 86 | :raises LockError: if the lock could not be acquired even after retrying 87 | every minute for 6 hours. 88 | """ 89 | cycles_left = 60 * 6 90 | while cycles_left: 91 | with OwncloudLock() as locked: 92 | if locked: 93 | subprocess.run(["owncloudcmd", "--non-interactive", "-h", "--user", config["ownCloud"]["login"], 94 | "--password", config["ownCloud"]["password"], config["ownCloud"]["local_root"], 95 | config["ownCloud"]["server_url"]], check=True) 96 | return 97 | cycles_left -= 1 98 | time.sleep(60) 99 | raise LockError 100 | -------------------------------------------------------------------------------- /apps/lenstool/auxfun.h: -------------------------------------------------------------------------------- 1 | #ifndef __LENSTOOL_AUXFUN_H__ 2 | #define __LENSTOOL_AUXFUN_H__ 3 | 4 | // atof() with sanity checks 5 | static float _atof (const char *s) 6 | { 7 | char *end = NULL; 8 | float r = strtof (s, &end); 9 | if (end && *end) 10 | { 11 | g_print ("ERROR: Invalid number `%s', parsed as %g\n", s, r); 12 | g_print ("%s", "Use your locale-specific number format (e.g. ',' or '.' etc)\n"); 13 | exit (-1); 14 | } 15 | return r; 16 | } 17 | 18 | static bool smartstreq (const char *str, const char *pattern) 19 | { 20 | const char *src = str; 21 | while (*src) 22 | { 23 | char cs = toupper (*src++); 24 | char cp = toupper (*pattern++); 25 | if (!cs) 26 | return (src != str); 27 | if (!cp) 28 | return false; 29 | if (cs != cp) 30 | return false; 31 | } 32 | return true; 33 | } 34 | 35 | static void PrintCamera (const lfCamera *camera, const lfDatabase *ldb) 36 | { 37 | g_print (" %s / %s %s%s%s\n", 38 | lf_mlstr_get (camera->Maker), 39 | lf_mlstr_get (camera->Model), 40 | camera->Variant ? "(" : "", 41 | camera->Variant ? lf_mlstr_get (camera->Variant) : "", 42 | camera->Variant ? ")" : ""); 43 | g_print (" |- Mount: %s\n", lf_db_mount_name (ldb, camera->Mount)); 44 | g_print (" |- Crop factor: %g\n", camera->CropFactor); 45 | } 46 | 47 | static void PrintLens (const lfLens *lens, const lfDatabase *ldb, bool verbose = false) 48 | { 49 | g_print (" %s / %s\n", 50 | lf_mlstr_get (lens->Maker), 51 | lf_mlstr_get (lens->Model)); 52 | 53 | if (lens->MinFocal != lens->MaxFocal) 54 | g_print (" |- Focal: %g-%gmm\n", lens->MinFocal, lens->MaxFocal); 55 | else 56 | g_print (" |- Focal: %gmm\n", lens->MinFocal); 57 | 58 | if (lens->MaxAperture > 0.f) 59 | g_print (" |- Aperture: f/%g - f/%g\n", lens->MinAperture, lens->MaxAperture); 60 | else 61 | g_print (" |- Aperture: f/%g\n", lens->MinAperture); 62 | 63 | g_print (" |- Center %g/%g\n", lens->CenterX, lens->CenterY); 64 | 65 | g_print ("%s", " |- Compatible mounts: "); 66 | const char* const* lm = lens->GetMountNames(); 67 | if (lm) 68 | for (int j = 0; lm[j]; j++) 69 | g_print ("%s, ", ldb->MountName(lm[j])); 70 | g_print ("%s", "\n"); 71 | 72 | g_print ("%s", " |- Calibrations: ["); 73 | 74 | int calibFlags = lens->AvailableModifications(-1.0f); 75 | 76 | if (calibFlags & LF_MODIFY_TCA) 77 | g_print ("%s", "tca, "); 78 | if (calibFlags & LF_MODIFY_VIGNETTING) 79 | g_print ("%s", "vign, "); 80 | if (calibFlags & LF_MODIFY_DISTORTION) 81 | g_print ("%s", "dist,"); 82 | g_print ("%s", "]\n"); 83 | 84 | if (verbose) 85 | { 86 | g_print ("%s", " |- Calibration data:\n"); 87 | const lfLensCalibrationSet* const* calibrations = lens->GetCalibrationSets(); 88 | if (calibrations != nullptr) 89 | { 90 | for (int j = 0; calibrations[j] != NULL; j++) 91 | { 92 | g_print (" |- Crop %g, Aspect ratio %g, [", 93 | calibrations[j]->Attributes.CropFactor, 94 | calibrations[j]->Attributes.AspectRatio); 95 | 96 | if (calibrations[j]->HasTCA()) 97 | g_print ("%s", "tca, "); 98 | if (calibrations[j]->HasVignetting()) 99 | g_print ("%s", "vign, "); 100 | if (calibrations[j]->HasDistortion()) 101 | g_print ("%s", "dist,"); 102 | g_print ("%s", "]\n"); 103 | } 104 | } 105 | } 106 | } 107 | 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /tests/test_modifier_coord_centering.cpp: -------------------------------------------------------------------------------- 1 | /* This checks for correct calculation of image center (optical axis). For 2 | * quite some time, Lensfun erroneously set the optical axis in image sensor 3 | * coordinates instead of lens coordinates. */ 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "lensfun.h" 13 | #include "../libs/lensfun/lensfunprv.h" 14 | 15 | 16 | typedef struct 17 | { 18 | void *coordBuff; 19 | size_t img_width, img_height; 20 | lfLens *lens; 21 | lfModifier *mod; 22 | } lfFixture; 23 | 24 | // setup a standard lens 25 | void mod_setup (lfFixture *lfFix, gconstpointer data) 26 | { 27 | lfFix->lens = new lfLens (); 28 | lfFix->lens->CenterX = 0.1; 29 | lfFix->lens->CenterY = 0.1; 30 | 31 | lfLensCalibAttributes cs = {1.0, 1.5}; 32 | lfLensCalibDistortion calib_data = { 33 | LF_DIST_MODEL_POLY3, 50.0f, 50.0f, false, {-0.1}, cs 34 | }; 35 | lfFix->lens->AddCalibDistortion (&calib_data); 36 | lfFix->lens->Type = LF_RECTILINEAR; 37 | 38 | lfFix->img_height = 1001; 39 | lfFix->img_width = 1501; 40 | 41 | lfFix->mod = new lfModifier (lfFix->lens, 50.0f, 10.0f, lfFix->img_width, lfFix->img_height, LF_PF_F32, true); 42 | 43 | lfFix->coordBuff = NULL; 44 | 45 | const size_t bufsize = 2 * lfFix->img_width * lfFix->img_height * sizeof (float); 46 | lfFix->coordBuff = g_malloc (bufsize); 47 | } 48 | 49 | void mod_teardown (lfFixture *lfFix, gconstpointer data) 50 | { 51 | g_free (lfFix->coordBuff); 52 | delete lfFix->mod; 53 | delete lfFix->lens; 54 | } 55 | 56 | void test_mod_coord_scaling_only (lfFixture *lfFix, gconstpointer data) 57 | { 58 | 59 | lfFix->mod->EnableScaling(2.0f); 60 | 61 | const float epsilon = 1e-3f; 62 | float expected_x[] = {-800.0f, -600.0f, -400.0f, -200.0f, 0.0f, 63 | 200.0f, 400.0f, 600.0f, 800.0f, 1000.0f}; 64 | float expected_y[] = {-550.0f, -350.0f, -150.0f, 50.0f, 250.0f, 65 | 450.0f, 650.0f, 850.0f, 1050.0f, 1250.0f}; 66 | std::vector coords (2); 67 | for (int i = 0; i < 10; i++) 68 | { 69 | g_assert_true (lfFix->mod->ApplyGeometryDistortion (100.0f * i, 100.0f * i, 1, 1, &coords [0])); 70 | g_assert_cmpfloat (fabs (coords [0] - expected_x [i]), <=, epsilon); 71 | g_assert_cmpfloat (fabs (coords [1] - expected_y [i]), <=, epsilon); 72 | } 73 | } 74 | 75 | void test_mod_coord_distortion (lfFixture *lfFix, gconstpointer data) 76 | { 77 | 78 | lfFix->mod->EnableDistortionCorrection(); 79 | 80 | const float epsilon = 1e-3f; 81 | float expected_x[] = {-2.2818394f, 98.536278f, 199.12755f, 299.52982f, 400.0f, 82 | 500.0f, 600.0f, 700.0f, 800.0f, 900.0f}; 83 | float expected_y[] = {-1.5687886f, 99.059074f, 199.49104f, 299.76492f, 400.0f, 84 | 500.0f, 600.0f, 700.0f, 800.0f, 900.0f}; 85 | std::vector coords (2); 86 | for (int i = 0; i < 10; i++) 87 | { 88 | g_assert_true (lfFix->mod->ApplyGeometryDistortion (100.0f * i, 100.0f * i, 1, 1, &coords [0])); 89 | g_assert_cmpfloat (fabs (coords [0] - expected_x [i]), <=, epsilon); 90 | g_assert_cmpfloat (fabs (coords [1] - expected_y [i]), <=, epsilon); 91 | } 92 | } 93 | 94 | 95 | int main (int argc, char **argv) 96 | { 97 | setlocale (LC_ALL, ""); 98 | 99 | g_test_init (&argc, &argv, NULL); 100 | 101 | g_test_add ("/modifier/coord/centering/scaling", lfFixture, NULL, 102 | mod_setup, test_mod_coord_scaling_only, mod_teardown); 103 | 104 | g_test_add ("/modifier/coord/centering/distortion", lfFixture, NULL, 105 | mod_setup, test_mod_coord_distortion, mod_teardown); 106 | 107 | return g_test_run(); 108 | } 109 | 110 | -------------------------------------------------------------------------------- /tests/test_lens.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "lensfun.h" 4 | 5 | void test_lens_guess_parameter() 6 | { 7 | lfLens* lens; 8 | 9 | lens = new lfLens(); 10 | lens->SetMaker("Sigma"); 11 | lens->SetModel("Sigma 100-300mm f/4 APO EX DG HSM"); 12 | lens->GuessParameters(); 13 | g_assert_cmpfloat(lens->MinFocal, ==, 100.0f); 14 | g_assert_cmpfloat(lens->MaxFocal, ==, 300.0f); 15 | g_assert_cmpfloat(lens->MinAperture, ==, 4.0f); 16 | delete lens; 17 | 18 | lens = new lfLens(); 19 | lens->SetMaker("Tamron"); 20 | lens->SetModel("Tamron SP AF 90mm f/2.8 Di Macro 1:1"); 21 | lens->GuessParameters(); 22 | g_assert_cmpfloat(lens->MinFocal, ==, 90.0f); 23 | g_assert_cmpfloat(lens->MaxFocal, ==, 90.0f); 24 | g_assert_cmpfloat(lens->MinAperture, ==, 2.8f); 25 | delete lens; 26 | 27 | lens = new lfLens(); 28 | lens->SetMaker("Sigma"); 29 | lens->SetModel("D-Xenon 1:4-5.6 50-200mm AL"); 30 | lens->GuessParameters(); 31 | g_assert_cmpfloat(lens->MinFocal, ==, 50.0f); 32 | g_assert_cmpfloat(lens->MaxFocal, ==, 200.0f); 33 | g_assert_cmpfloat(lens->MinAperture, ==, 4.0f); 34 | delete lens; 35 | 36 | lens = new lfLens(); 37 | lens->SetMaker("Nikon"); 38 | lens->SetModel("1 Nikkor AW 11-27.5mm f/3.5-5.6"); 39 | lens->GuessParameters(); 40 | g_assert_cmpfloat(lens->MinFocal, ==, 11.0f); 41 | g_assert_cmpfloat(lens->MaxFocal, ==, 27.5f); 42 | g_assert_cmpfloat(lens->MinAperture, ==, 3.5f); 43 | delete lens; 44 | 45 | 46 | lens = new lfLens(); 47 | lens->SetMaker("Fujifilm"); 48 | lens->SetModel("XF 35mm f/1.4 R"); 49 | lens->GuessParameters(); 50 | g_assert_cmpfloat(lens->MinFocal, ==, 35.0f); 51 | g_assert_cmpfloat(lens->MaxFocal, ==, 35.0f); 52 | g_assert_cmpfloat(lens->MinAperture, ==, 1.4f); 53 | delete lens; 54 | 55 | lens = new lfLens(); 56 | lens->SetMaker("KMZ"); 57 | lens->SetModel("MC MTO 11CA 10/1000"); 58 | lens->GuessParameters(); 59 | g_assert_cmpfloat(lens->MinFocal, ==, 1000.0f); 60 | g_assert_cmpfloat(lens->MaxFocal, ==, 1000.0f); 61 | g_assert_cmpfloat(lens->MinAperture, ==, 10.0f); 62 | delete lens; 63 | 64 | lens = new lfLens(); 65 | lens->SetMaker("Fotasy"); 66 | lens->SetModel("Fotasy M3517 35mm f/1.7"); 67 | lens->GuessParameters(); 68 | g_assert_cmpfloat(lens->MinFocal, ==, 35.0f); 69 | g_assert_cmpfloat(lens->MaxFocal, ==, 35.0f); 70 | g_assert_cmpfloat(lens->MinAperture, ==, 1.7f); 71 | delete lens; 72 | 73 | lens = new lfLens(); 74 | lens->SetMaker("Vivitar"); 75 | lens->SetModel("Vivitar Series One 70-210mm 1:3.5 SN 22..."); 76 | lens->GuessParameters(); 77 | g_assert_cmpfloat(lens->MinFocal, ==, 70.0f); 78 | g_assert_cmpfloat(lens->MaxFocal, ==, 210.0f); 79 | g_assert_cmpfloat(lens->MinAperture, ==, 3.5f); 80 | delete lens; 81 | 82 | // check if extenders are ignored 83 | lens = new lfLens(); 84 | lens->SetMaker("Canon"); 85 | lens->SetModel("Canon EF 300mm f/2.8L IS II USM + EF 1.4x ext. III"); 86 | lens->GuessParameters(); 87 | g_assert_cmpfloat(lens->MinFocal, ==, 0.0f); 88 | g_assert_cmpfloat(lens->MaxFocal, ==, 0.0f); 89 | g_assert_cmpfloat(lens->MinAperture, ==, 0.0f); 90 | delete lens; 91 | 92 | // ignore nonsense input 93 | lens = new lfLens(); 94 | lens->SetMaker("Pentax"); 95 | lens->SetModel("Foo 8912 DX F90 AL"); 96 | lens->GuessParameters(); 97 | g_assert_cmpfloat(lens->MinFocal, ==, 0.0f); 98 | g_assert_cmpfloat(lens->MaxFocal, ==, 0.0f); 99 | g_assert_cmpfloat(lens->MinAperture, ==, 0.0f); 100 | delete lens; 101 | 102 | } 103 | 104 | 105 | int main (int argc, char **argv) 106 | { 107 | 108 | setlocale (LC_ALL, ""); 109 | 110 | g_test_init(&argc, &argv, NULL); 111 | 112 | g_test_add_func("/lens/parameter guessing", test_lens_guess_parameter); 113 | 114 | return g_test_run(); 115 | } 116 | -------------------------------------------------------------------------------- /tests/test_modifier_coord_centering_old.cpp: -------------------------------------------------------------------------------- 1 | /* This checks for correct calculation of image center (optical axis). For 2 | * quite some time, Lensfun erroneously set the optical axis in image sensor 3 | * coordinates instead of lens coordinates. */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "lensfun.h" 12 | #include "../libs/lensfun/lensfunprv.h" 13 | 14 | 15 | typedef struct 16 | { 17 | void *coordBuff; 18 | size_t img_width, img_height; 19 | lfLens *lens; 20 | lfModifier *mod; 21 | } lfFixture; 22 | 23 | // setup a standard lens 24 | void mod_setup (lfFixture *lfFix, gconstpointer data) 25 | { 26 | lfFix->lens = new lfLens(); 27 | lfLensCalibDistortion calib_data = { 28 | LF_DIST_MODEL_POLY3, 50.0f, 50.0f, false, {-0.1} 29 | }; 30 | lfFix->lens->AddCalibDistortion (&calib_data); 31 | lfFix->lens->CropFactor = 1.0f; 32 | lfFix->lens->AspectRatio = 3.0f / 2.0f; 33 | lfFix->lens->CenterX = 0.1f; 34 | lfFix->lens->CenterY = 0.1f; 35 | lfFix->lens->Type = LF_RECTILINEAR; 36 | 37 | lfFix->img_height = 1001; 38 | lfFix->img_width = 1501; 39 | 40 | lfFix->mod = new lfModifier (lfFix->lens, 10.0f, lfFix->img_width, lfFix->img_height); 41 | 42 | lfFix->coordBuff = NULL; 43 | 44 | const size_t bufsize = 2 * lfFix->img_width * lfFix->img_height * sizeof (float); 45 | lfFix->coordBuff = g_malloc (bufsize); 46 | } 47 | 48 | void mod_teardown (lfFixture *lfFix, gconstpointer data) 49 | { 50 | g_free (lfFix->coordBuff); 51 | delete lfFix->mod; 52 | delete lfFix->lens; 53 | } 54 | 55 | void test_mod_coord_scaling_only (lfFixture *lfFix, gconstpointer data) 56 | { 57 | lfFix->mod->Initialize (lfFix->lens, LF_PF_F32, 50.89f, 2.8f, 1000.0f, 2.0f, LF_RECTILINEAR, 58 | LF_MODIFY_SCALE, true); 59 | 60 | const float epsilon = 1e-3f; 61 | float expected_x[] = {-800.0f, -600.0f, -400.0f, -200.0f, 0.0f, 62 | 200.0f, 400.0f, 600.0f, 800.0f, 1000.0f}; 63 | float expected_y[] = {-550.0f, -350.0f, -150.0f, 50.0f, 250.0f, 64 | 450.0f, 650.0f, 850.0f, 1050.0f, 1250.0f}; 65 | std::vector coords (2); 66 | for (int i = 0; i < 10; i++) 67 | { 68 | g_assert_true (lfFix->mod->ApplyGeometryDistortion (100.0f * i, 100.0f * i, 1, 1, &coords [0])); 69 | g_assert_cmpfloat (fabs (coords [0] - expected_x [i]), <=, epsilon); 70 | g_assert_cmpfloat (fabs (coords [1] - expected_y [i]), <=, epsilon); 71 | } 72 | } 73 | 74 | void test_mod_coord_distortion (lfFixture *lfFix, gconstpointer data) 75 | { 76 | lfFix->mod->Initialize (lfFix->lens, LF_PF_F32, 50.89f, 2.8f, 1000.0f, 2.0f, LF_RECTILINEAR, 77 | LF_MODIFY_DISTORTION, true); 78 | 79 | const float epsilon = 1e-3f; 80 | float expected_x[] = {-2.2818394f, 98.536278f, 199.12755f, 299.52982f, 400.0f, 81 | 500.0f, 600.0f, 700.0f, 800.0f, 900.0f}; 82 | float expected_y[] = {-1.5687886f, 99.059074f, 199.49104f, 299.76492f, 400.0f, 83 | 500.0f, 600.0f, 700.0f, 800.0f, 900.0f}; 84 | std::vector coords (2); 85 | for (int i = 0; i < 10; i++) 86 | { 87 | g_assert_true (lfFix->mod->ApplyGeometryDistortion (100.0f * i, 100.0f * i, 1, 1, &coords [0])); 88 | g_assert_cmpfloat (fabs (coords [0] - expected_x [i]), <=, epsilon); 89 | g_assert_cmpfloat (fabs (coords [1] - expected_y [i]), <=, epsilon); 90 | } 91 | } 92 | 93 | 94 | int main (int argc, char **argv) 95 | { 96 | setlocale (LC_ALL, ""); 97 | 98 | g_test_init (&argc, &argv, NULL); 99 | 100 | g_test_add ("/modifier/coord/centering/scaling", lfFixture, NULL, 101 | mod_setup, test_mod_coord_scaling_only, mod_teardown); 102 | 103 | g_test_add ("/modifier/coord/centering/distortion", lfFixture, NULL, 104 | mod_setup, test_mod_coord_distortion, mod_teardown); 105 | 106 | return g_test_run(); 107 | } 108 | -------------------------------------------------------------------------------- /docs/man/lensfun-convert-lcp.1.rst: -------------------------------------------------------------------------------- 1 | ===================== 2 | lensfun-convert-lcp 3 | ===================== 4 | 5 | ----------------------------------- 6 | convert LCP files to Lensfun files 7 | ----------------------------------- 8 | 9 | :Author: This manual page was written by Torsten Bronger 10 | :Date: 2015-05-11 11 | :Manual section: 1 12 | 13 | SYNOPSIS 14 | ============ 15 | 16 | | ``lensfun-convert-lcp`` [``--output`` `OUTPUT`] [``--db-path`` `DB_PATH`] 17 | | [``--prefer-lcp``] [path] 18 | 19 | DESCRIPTION 20 | =============== 21 | 22 | Lensfun is a library that corrects flaws in photographic images introduced by 23 | the lens. It also contains a comprehensive database of cameras and lenses 24 | together with their characteristics to be able to apply automatic corrections 25 | of images taken with these devices. Lensfun is used by darktable, digiKam, 26 | rawstudio, GimpLensfun, UFRaw, and others. 27 | 28 | ``lensfun-convert-lcp`` is a command-line program that converts LCP files into 29 | Lensfun's XML format. LCP files contain distortion, TCA, and vignetting 30 | correction data for lenses, just like Lensfun's XML files do. The LCP file 31 | format is defined by Adobe, and such files are created by e.g Adobe's “Lens 32 | Profile creator”. ``lensfun-convert-lcp`` reads all LCP files in a given 33 | directory (and in all of its subdirectories) and converts them to one single 34 | Lensfun XML file. It assumes that one LCP file contains exactly one lens. 35 | 36 | By default, it takes existing Lensfun data for each LCP lens from Lensfun's own 37 | DB, and uses the LCP data only for filling gaps. 38 | 39 | OPTIONS 40 | ========= 41 | 42 | ``--output`` `OUTPUT` 43 | The path of output file. This file is overwritten silently. It defaults 44 | to ``~/.local/share/lensfun/_lcps.xml``. 45 | 46 | ``--db-path`` `DB_PATH` 47 | The path to the lensfun database. If given, ``lensfun-convert-lcp`` looks 48 | only there (not even in subdirectories) for files with the extension 49 | “.xml”. If not given, the DB directory discovery works as explained under 50 | the section “FILES” below. XML files starting with an underscore are 51 | ignored. In particular, this prevents the output file from a previous run 52 | from being read (if the default file name was used, at least). 53 | 54 | ``--prefer-lcp`` 55 | If given, prefer LCP data over Lensfun data. Normally, LCP data is only 56 | used to fill gaps in Lensfun's data. This way, Lensfun's data is only used 57 | for camera and lens metadata, while Lensfun's actual correction data is 58 | overridden and supplemented by the LCP data. 59 | 60 | ``path`` 61 | The path to the root directory with the LCP files. It defaults to “.”. 62 | The LCP files are recognised by their content, not by their file extension. 63 | 64 | FILES 65 | ====== 66 | 67 | It writes by default into ``~/.local/share/lensfun/_lcps.xml``. Note that it 68 | will silently overwrite this file if it was already existing. The Lensfun 69 | database is by default searched in these directories (without subdirectories): 70 | ``/usr/share/lensfun``, ``/usr/share/local/lensfun``, 71 | ``/var/lib/lensfun-updates``, ``~/.local/share/lensfun/updates``, and 72 | ``~/.local/share/lensfun`` (with later directories overriding ealier ones). 73 | Note that this database discovery is slightly different from the Lensfun 74 | library's one. 75 | 76 | DIAGNOSTICS 77 | =============== 78 | 79 | ``lensfun-convert-lcp`` may print warnings to stdout. Its exit code is 80 | always 0. 81 | 82 | REPORTING BUGS 83 | ==================== 84 | 85 | Report bugs at . 86 | 87 | COPYRIGHT 88 | ============= 89 | 90 | Lensfun is Copyright © 2007 Andrew Zabolotny 91 | 92 | License of the code: GNU Lesser General Public License, version 3 93 | 94 | License of the database: Creative Commons Attribution-Share Alike 3.0 license 95 | 96 | SEE ALSO 97 | ============ 98 | 99 | lensfun-update-data(1), g-lensfun-update-data(1), lensfun-add-adapter(1) 100 | -------------------------------------------------------------------------------- /tests/test_database.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "lensfun.h" 4 | 5 | typedef struct { 6 | lfDatabase* db; 7 | } lfFixture; 8 | 9 | 10 | void db_setup(lfFixture *lfFix, gconstpointer data) 11 | { 12 | lfFix->db = new lfDatabase (); 13 | lfFix->db->Load("data/db"); 14 | } 15 | 16 | 17 | void db_teardown(lfFixture *lfFix, gconstpointer data) 18 | { 19 | delete lfFix->db; 20 | } 21 | 22 | 23 | // test different lens search strings 24 | void test_DB_lens_search(lfFixture* lfFix, gconstpointer data) 25 | { 26 | const lfLens **lenses = NULL; 27 | 28 | // search only by name 29 | lenses = lfFix->db->FindLenses (NULL, NULL, "pEntax 50-200 ED"); 30 | g_assert_nonnull(lenses); 31 | g_assert_cmpstr(lenses[0]->Model, ==, "smc Pentax-DA 50-200mm f/4-5.6 DA ED"); 32 | g_assert_true(lfLens(*lenses[0]).Check()); 33 | lf_free (lenses); 34 | 35 | lenses = lfFix->db->FindLenses (NULL, NULL, "smc Pentax-DA 50-200mm f/4-5.6 DA ED"); 36 | g_assert_nonnull(lenses); 37 | g_assert_cmpstr(lenses[0]->Model, ==, "smc Pentax-DA 50-200mm f/4-5.6 DA ED"); 38 | g_assert_true(lfLens(*lenses[0]).Check()); 39 | lf_free (lenses); 40 | 41 | lenses = lfFix->db->FindLenses (NULL, NULL, "PENTAX fa 28mm 2.8"); 42 | g_assert_nonnull(lenses); 43 | g_assert_cmpstr(lenses[0]->Model, ==, "smc Pentax-FA 28mm f/2.8 AL"); 44 | g_assert_true(lfLens(*lenses[0]).Check()); 45 | lf_free (lenses); 46 | 47 | // search lens for a certain camera considering mount compatibilities 48 | const lfCamera **cameras = NULL; 49 | cameras = lfFix->db->FindCamerasExt("Ricoh", "k-70"); 50 | g_assert_nonnull(cameras); 51 | 52 | lenses = lfFix->db->FindLenses (cameras[0], NULL, "Fotasy M3517 35mm"); 53 | g_assert_nonnull(lenses); 54 | g_assert_cmpstr(lenses[0]->Model, ==, "Fotasy M3517 35mm f/1.7"); 55 | g_assert_true(lfLens(*lenses[0]).Check()); 56 | lf_free (lenses); 57 | 58 | lf_free(cameras); 59 | } 60 | 61 | // test different camera search strings 62 | void test_DB_cam_search(lfFixture* lfFix, gconstpointer data) 63 | { 64 | const lfCamera **cameras = NULL; 65 | 66 | cameras = lfFix->db->FindCamerasExt("pentax", "K100D"); 67 | g_assert_nonnull(cameras); 68 | g_assert_cmpstr(cameras[0]->Model, ==, "Pentax K100D"); 69 | g_assert_true(lfCamera(*cameras[0]).Check()); 70 | lf_free (cameras); 71 | 72 | cameras = lfFix->db->FindCamerasExt(NULL, "K 100 D"); 73 | g_assert_nonnull(cameras); 74 | g_assert_cmpstr(cameras[0]->Model, ==, "Pentax K100D"); 75 | g_assert_true(lfCamera(*cameras[0]).Check()); 76 | lf_free (cameras); 77 | 78 | cameras = lfFix->db->FindCamerasExt(NULL, "PentAX K100 D"); 79 | g_assert_nonnull(cameras); 80 | g_assert_cmpstr(cameras[0]->Model, ==, "Pentax K100D"); 81 | g_assert_true(lfCamera(*cameras[0]).Check()); 82 | lf_free (cameras); 83 | 84 | } 85 | 86 | // copy some entries into a new database file 87 | void test_DB_save(lfFixture* lfFix, gconstpointer data) 88 | { 89 | 90 | lfDatabase* db2 = new lfDatabase (); 91 | 92 | const lfCamera **cameras = NULL; 93 | const lfLens **lenses = NULL; 94 | 95 | cameras = lfFix->db->FindCamerasExt("pentax", "K100D"); 96 | lenses = lfFix->db->FindLenses (NULL, NULL, "smc Pentax-DA 50-200mm f/4-5.6 DA ED"); 97 | 98 | lfLens* lens = new lfLens(*lenses[0]); 99 | lfCamera* camera = new lfCamera(*cameras[0]); 100 | 101 | db2->AddCamera(camera); 102 | db2->AddLens(lens); 103 | db2->Save("test_db.xml"); 104 | 105 | delete db2; 106 | 107 | lf_free (lenses); 108 | lf_free (cameras); 109 | 110 | } 111 | 112 | int main (int argc, char **argv) 113 | { 114 | 115 | setlocale (LC_ALL, ""); 116 | 117 | g_test_init(&argc, &argv, NULL); 118 | 119 | g_test_add("/database/camera search", lfFixture, NULL, db_setup, test_DB_cam_search, db_teardown); 120 | g_test_add("/database/lens search", lfFixture, NULL, db_setup, test_DB_lens_search, db_teardown); 121 | g_test_add("/database/save", lfFixture, NULL, db_setup, test_DB_save, db_teardown); 122 | 123 | return g_test_run(); 124 | } 125 | -------------------------------------------------------------------------------- /docs/man/lensfun-add-adapter.1.rst: -------------------------------------------------------------------------------- 1 | ====================== 2 | lensfun-add-adapter 3 | ====================== 4 | 5 | -------------------------------------------------------- 6 | add lens mount compatibilities to Lensfun's database 7 | -------------------------------------------------------- 8 | 9 | :Author: This manual page was written by Torsten Bronger 10 | :Date: 2013-12-23 11 | :Manual section: 1 12 | 13 | SYNOPSIS 14 | ============ 15 | 16 | | ``lensfun-add-adapter`` 17 | | ``lensfun-add-adapter`` [``--maker`` `MAKER`] [``--model`` `MODEL`] [``--mount`` `MOUNT`] 18 | | ``lensfun-add-adapter`` ``--remove-local-mount-config`` 19 | 20 | DESCRIPTION 21 | =============== 22 | 23 | Lensfun is a library that corrects flaws in photographic images introduced by 24 | the lens. It also contains a comprehensive database of cameras and lenses 25 | together with their characteristics to be able to apply automatic corrections 26 | of images taken with these devices. Lensfun is used by darktable, digiKam, 27 | rawstudio, GimpLensfun, UFRaw, and others. 28 | 29 | Lensfun contains information about lens mounts of cameras and available mounts 30 | for lens models. This way, the calling application can offer the user a list 31 | with lenses that fit on their camera in order to pick one. Otherwise, you 32 | would see *all* lenses every time. This can be pretty overwhelming. 33 | 34 | But if you bought an adapter for another mount system, you would want to see 35 | lenses of that mount system listed for your camera. So, you must tell Lensfun 36 | somehow that you own the adapter. You can do so by calling 37 | ``lensfun-add-adapter``. 38 | 39 | The easiest way to use it is to call it with no parameters. 40 | ``lensfun-add-adapter`` will then enter an interactive mode. First you have to 41 | enter your camera model. ``lensfun-add-adapter`` will use that to determine 42 | the destination mount. In particular, the extended lens lists will show up for 43 | every camera with that mount, not just the one you entered. Then, you have to 44 | select the mount of the lenses you can now put on your camera, using the 45 | adapter. That's it. 46 | 47 | With the options ``--maker``, ``--model``, and ``--mount``, you can avoid 48 | interactive mode by passing the necessary data explicitly. If you pass only 49 | maker/model or only mount, ``lensfun-add-adapter`` will enter interactive mode 50 | only for the missing data. 51 | 52 | You can also use ``lensfun-add-adapter`` to reset your adapter configuration. 53 | Call it with the ``--help`` parameter to see all functions. 54 | 55 | OPTIONS 56 | ========= 57 | 58 | ``--maker`` `MAKER` ``--model`` `MODEL` 59 | The exact maker and model of the camera the mount of which should be made 60 | compatible. You must provide these options only in combination rather than 61 | only one of them. 62 | 63 | ``--mount`` `MOUNT` 64 | The exact name of the mount of the lenses that should be made compatible. 65 | 66 | ``--remove-local-mount-config`` 67 | Resets the local mount configuration, i.e. the additional mount 68 | compatibilities that were created by this program. Effectively, it removes 69 | the file ``_mount.xml`` from the local Lensfun database of the current 70 | user. 71 | 72 | FILES 73 | ===== 74 | 75 | ``~/.local/share/lensfun/_mounts.xml`` 76 | File with all mount compatibilities that were added by this program. 77 | 78 | DIAGNOSTICS 79 | =============== 80 | 81 | Exit status: 82 | 83 | =========== ===================================== 84 | 0 successful 85 | 1 invalid command line arguments 86 | 2 invalid input in interactive mode 87 | =========== ===================================== 88 | 89 | 90 | REPORTING BUGS 91 | ==================== 92 | 93 | Report bugs at . 94 | 95 | COPYRIGHT 96 | ============= 97 | 98 | Lensfun is Copyright © 2007 Andrew Zabolotny 99 | 100 | License of the code: GNU Lesser General Public License, version 3 101 | 102 | License of the database: Creative Commons Attribution-Share Alike 3.0 license 103 | 104 | SEE ALSO 105 | ============ 106 | 107 | g-lensfun-update-data(1), lensfun-update-data(1), lensfun-convert-lcp(1) 108 | -------------------------------------------------------------------------------- /apps/lenstool/rgbpixel.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001 by Andrew Zabolotny 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Library General Public 6 | License as published by the Free Software Foundation; either 7 | version 2 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Library General Public License for more details. 13 | 14 | You should have received a copy of the GNU Library General Public 15 | License along with this library; if not, write to the Free 16 | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 | */ 18 | 19 | #ifndef __RGBPIXEL_H__ 20 | #define __RGBPIXEL_H__ 21 | 22 | #ifdef HAVE_ENDIAN_H 23 | # include 24 | #endif 25 | 26 | #ifndef __LITTLE_ENDIAN 27 | # define __LITTLE_ENDIAN 1234 28 | #endif 29 | #ifndef __BIG_ENDIAN 30 | # define __BIG_ENDIAN 4321 31 | #endif 32 | #if !defined __BYTE_ORDER 33 | # 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__ 34 | # define __BYTE_ORDER __BIG_ENDIAN 35 | # else 36 | # define __BYTE_ORDER __LITTLE_ENDIAN 37 | # endif 38 | #else 39 | # define __BYTE_ORDER __LITTLE_ENDIAN 40 | #endif 41 | 42 | // For optimized performance, we sometimes handle all R/G/B values simultaneously 43 | #if __BYTE_ORDER == __BIG_ENDIAN 44 | # define RGB_MASK 0xffffff00 45 | #else 46 | # define RGB_MASK 0x00ffffff 47 | #endif 48 | 49 | /** 50 | * An RGB pixel. Besides R,G,B color components this structure also 51 | * contains the Alpha channel component, which is used in images 52 | * (that potentially have an alpha channel). 53 | */ 54 | struct RGBpixel 55 | { 56 | /// The red, green, blue and alpha components 57 | unsigned char red, green, blue, alpha; 58 | /// Constructor (initialize to zero, alpha to 255) 59 | RGBpixel () /* : red(0), green(0), blue(0), alpha(255) {} */ 60 | { *(unsigned *)this = (unsigned)~RGB_MASK; } 61 | /// Copy constructor 62 | RGBpixel (const RGBpixel& p) 63 | /* : red (p.red), green (p.green), blue (p.blue), alpha (p.alpha) {} */ 64 | { *(unsigned *)this = *(unsigned *)&p; } 65 | /// Initialize the pixel with some R/G/B value 66 | RGBpixel (int r, int g, int b) : 67 | red (r), green (g), blue (b), alpha (255) {} 68 | /// Compare with an RGBpixel (including alpha value) 69 | bool operator == (const RGBpixel& p) const 70 | /* { return (p.red == red) && (p.green == green) && (p.blue == blue); } */ 71 | { return *(unsigned *)this == *(unsigned *)&p; } 72 | /// Check if the RGBpixel is not equal to another RGBpixel (including alpha) 73 | bool operator != (const RGBpixel& p) const 74 | { return !operator == (p); } 75 | /// Compare with another RGBpixel, but don't take alpha into account 76 | bool eq (const RGBpixel& p) const 77 | { return ((*(unsigned *)this) & RGB_MASK) == ((*(unsigned *)&p) & RGB_MASK); } 78 | /// Get the pixel intensity 79 | int Intensity () 80 | { return (red + green + blue) / 3; } 81 | /// Assign given red/green/blue values to this pixel 82 | void Set (const int r, const int g, const int b) 83 | { red = r; green = g; blue = b; alpha = 255; } 84 | /// Assign given red/green/blue/alpha values to this pixel 85 | void Set (const int r, const int g, const int b, const int a) 86 | { red = r; green = g; blue = b; alpha = a; } 87 | void Set (const RGBpixel& p) 88 | /* : red (p.red), green (p.green), blue (p.blue), alpha (p.alpha) {} */ 89 | { *(unsigned *)this = *(unsigned *)&p; } 90 | }; 91 | 92 | // We don't need RGB_MASK anymore 93 | #undef RGB_MASK 94 | 95 | /** 96 | * Eye sensivity to different color components, from NTSC grayscale equation. 97 | * The coefficients are multiplied by 100 and rounded towards nearest integer, 98 | * to facilitate integer math. The squared coefficients are also multiplied 99 | * by 100 and rounded to nearest integer (thus 173 == 1.73, 242 == 2.42 etc). 100 | */ 101 | /// Red component sensivity 102 | #define R_COEF 173 103 | /// Green component sensivity 104 | #define G_COEF 242 105 | /// Blue component sensivity 106 | #define B_COEF 107 107 | 108 | #endif // RGBPIXEL_H__ 109 | -------------------------------------------------------------------------------- /tools/database-ng/transform_db.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """Transforms a version-1 database into a version-2 database. Eventually, this 4 | will be used as a helper for the user to transform their local XML files to the 5 | new DB version format. Until then, only parts of it will run at a time, 6 | because we must do the transition of the core DB step by step. 7 | 8 | 1. Assign unique IDs to cameras, and lenses. All numbers < 1000 are reserved 9 | for private/local use. Anything which is not a positive integer (this 10 | includes 0) is an invalid ID. 11 | 12 | 2. is renamed to . 13 | 14 | 3. Move the element out of into the element 15 | as an attribute. 16 | 17 | 4. Introduce a element in which denotes the minimal 18 | crop factor this lens is specified for. Populate this field with the 19 | minimal calibration cropfactor found. 20 | 21 | 5. Move the element out of into the element 22 | as an attribute. 23 | 24 | 6. Move tags as attributes into . 25 | 26 | 7. Collect all elements of one lens model in one entry. 27 | 28 | 8. Add informative "camera" attribute to . 29 | 30 | Manual postprocessing necessary: 31 | 32 | 1. Some lenses may have a too big . (For example, FF lenses 33 | for which Lensfun only had got APS-C calibrations yet.) 34 | 35 | 2. Alias entries must be merged. 36 | 37 | 3. Merge multiple camera entries for multiple crop factors in one. 38 | """ 39 | 40 | import sys, glob, os, io 41 | from lxml import etree 42 | 43 | 44 | def bump_up_version(root): 45 | root.attrib["version"] = "2" 46 | 47 | 48 | def move_real_focal_length(root): 49 | for real_focal_length in root.xpath("//real-focal-length"): 50 | focal = real_focal_length.get("focal") 51 | real_focal = real_focal_length.get("real-focal") 52 | calibration = real_focal_length.getparent() 53 | distortion = calibration.xpath("distortion[@focal='{}']".format(focal))[0] 54 | distortion.set("real-focal", real_focal) 55 | calibration.remove(real_focal_length) 56 | 57 | 58 | camera_ids = {999} 59 | lens_ids = {999} 60 | 61 | def assign_ids(root): 62 | for child in root.xpath("camera"): 63 | next_id = max(camera_ids) + 1 64 | child.attrib["id"] = str(next_id) 65 | camera_ids.add(next_id) 66 | for child in root.xpath("lens"): 67 | next_id = max(lens_ids) + 1 68 | child.attrib["id"] = str(next_id) 69 | lens_ids.add(next_id) 70 | 71 | 72 | def rename_aperture_to_f_stop(root): 73 | for element in root.xpath("//aperture"): 74 | element.tag = "f-stop" 75 | 76 | 77 | def get_model(element): 78 | for model in element.iter("model"): 79 | if not(model.get("lang")): 80 | return model.text 81 | else: 82 | assert False, "No model found." 83 | 84 | 85 | def copy_cropfactor_and_move_aspect_ratio(root): 86 | # I don't delete here in order to be able to replace it with 87 | # later. 88 | for element in root.xpath("lens"): 89 | try: 90 | calibration = element.xpath("calibration")[0] 91 | except IndexError: 92 | continue 93 | calibration.set("crop-factor", element.xpath("cropfactor")[0].text) 94 | try: 95 | aspect_ratio = element.xpath("aspect-ratio")[0] 96 | except IndexError: 97 | pass 98 | else: 99 | calibration.set("aspect-ratio", aspect_ratio.text) 100 | aspect_ratio.getparent().remove(aspect_ratio) 101 | 102 | 103 | def min_cropfactor(root): 104 | cropfactors = {} 105 | for element in root.xpath("lens"): 106 | cropfactors.setdefault(get_model(element), set()).add(element.xpath("cropfactor")[0].text) 107 | for element in root.xpath("lens"): 108 | cropfactor_element = element.xpath("cropfactor")[0] 109 | cropfactor_element.tag = "min-crop-factor" 110 | cropfactor_element.text = str(min(cropfactors[get_model(element)])) 111 | 112 | 113 | for path in glob.glob(os.path.join(sys.argv[1], "*.xml")): 114 | tree = etree.parse(open(path)) 115 | root = tree.getroot() 116 | 117 | bump_up_version(root) 118 | assign_ids(root) 119 | rename_aperture_to_f_stop(root) 120 | copy_cropfactor_and_move_aspect_ratio(root) 121 | min_cropfactor(root) 122 | 123 | output = io.BytesIO() 124 | tree.write(output, encoding="utf-8") 125 | output = output.getvalue() + b"\n" 126 | open(os.path.join(sys.argv[2], os.path.basename(path)), "wb").write(output) 127 | -------------------------------------------------------------------------------- /tools/calibration_webserver/calibration/templates/calibration/upload.html: -------------------------------------------------------------------------------- 1 | {% extends "calibration/base.html" %} 2 | 3 | {% block content %} 4 |

Upload calibration pictures

5 | 6 |

So you want to use lens correction features of Darktable, Rawstudio, 7 | digiKam, Imagemagick etc, but your lens is not yet supported? No problem – 8 | just take some test shots and upload them here.

9 | 10 |

How to upload

11 | 12 |

First, check whether the data is already 13 | available in current Lensfun!

14 | 15 |

Then, read carefully the section “How should test 16 | shots look like?” below.

17 | 18 |

Please select a tarball (.tar.gz) or a ZIP file from your computer that 19 | contains the RAW pictures. A single upload may contain RAWs for many different 20 | lenses, but only one camera.

21 | 22 |

Important: By uploading files here, you thereby grant 23 | me, {{ admin_name }}, the 24 | right to permanently store them on my computer and use them for generating 25 | calibration data. This data is then published under the 26 | Creative Commons 27 | Attribution-Share Alike 3.0 license. I may make your images anonymously 28 | available to open source projects, e.g. to exiv2 in order to improve automatic 29 | lens model detection. I will never publish or give away your email 30 | address.

31 | 32 |
33 | 34 | {{ upload }} 35 |
36 |

37 |
38 | 39 |
40 | 41 |

What happens after the upload?

42 | 43 | You receive an email with the acknowledgement and a link to the GitHub issue 44 | that tracks your upload. After processing, I will send you an email with 45 | instruction for how to install them locally. At the same time, your data is 46 | included into the Lensfun project. Please give us time for this. You can 47 | accelerate this process 48 | by becoming 49 | a calibrator yourself. 50 | 51 | Good anti-distortion target 53 | 54 |

How should test shots look like?

55 | 56 |

If you calibrate a zoom lens, take pictures at at least five different focal 57 | lengths. Always include the extreme values.

58 | 59 |

Test shots need to be taken at a distance of at least 5 metres. The 60 | pictures must contain one straight line, running from one end of the picture to 61 | the other, very close to the long border of the picture. Ideally, it contains a 62 | second straight line 1/3 of the image height from the top.

63 | 64 |

The picture on the left is a good example. The numbered marks follow the 65 | two lines that I mentioned. I recommend that you use a modern building and 66 | take pictures of it. Don't take picures of brick walls or tiles. Tilting or 67 | rotating the camera is allowed. Make really sharp pictures. Switch off all 68 | corrections (some cameras do this even for RAWs).

69 | 70 |

I have compiled three further sample pictures, 71 | to eliminate all doubts.

72 | 73 | Good TCA correction target 75 | 76 |

TCA and vignetting

77 | 78 | 79 |

The more corrections are possible, the better. As for TCA (chromatic 80 | aberration), I can maybe use the same pictures that you uploaded for distortion 81 | above. Anyway, they need to contain sharp high-contrast edges over the whole 82 | image, see the photo on the right.

83 | 84 |

As for taking pictures for vignetting correction, 85 | see my lens 86 | calibration tutorial.

87 | 88 |

About EXIF data …

89 | 90 |

I need to know lens model, focal length, and aperture for each shot. 91 | Mostly, this is already included in the RAW. In case it isn’t, you will be 92 | pointed to a web page where you can add any missing data.

93 | 94 |

However, if the EXIF data in some files is plain wrong (for example, you 95 | used a fisheye converter), it is necessary that you rename such files. For 96 | example, you may rename to

97 | 98 |
    Canon_EF_24-70mm_f__2.8L_USM--35mm--2.8.CR2
99 | 100 |

In the lens name, a single underscore “_” represents a space “ ”, and double 101 | underscore “__” represents a slash “/”.

102 | 103 | {% endblock %} 104 | -------------------------------------------------------------------------------- /tests/test_modifier_coord_scale.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "lensfun.h" 14 | 15 | #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) 16 | #include 17 | #endif 18 | #ifdef __APPLE__ 19 | #include 20 | #endif 21 | 22 | #include "common_code.hpp" 23 | 24 | typedef struct 25 | { 26 | void *coordBuff; 27 | size_t img_width, img_height; 28 | lfModifier *mod; 29 | lfLens *lens; 30 | } lfFixture; 31 | 32 | typedef struct 33 | { 34 | bool reverse; 35 | float scale; 36 | size_t alignment; 37 | } lfTestParams; 38 | 39 | // setup a standard lens 40 | void mod_setup(lfFixture *lfFix, gconstpointer data) 41 | { 42 | lfTestParams *p = (lfTestParams *)data; 43 | 44 | lfFix->img_height = 300; 45 | lfFix->img_width = 300; 46 | 47 | lfFix->lens = new lfLens(); 48 | 49 | lfFix->mod = new lfModifier(lfFix->lens, 0.0f, 1.0f, lfFix->img_width, lfFix->img_height, LF_PF_F32, p->reverse); 50 | 51 | lfFix->mod->EnableScaling(p->scale); 52 | 53 | lfFix->coordBuff = NULL; 54 | 55 | const size_t bufsize = 2 * lfFix->img_width * lfFix->img_height * sizeof(float); 56 | if(p->alignment == 0) 57 | lfFix->coordBuff = g_malloc(bufsize); 58 | else 59 | lfFix->coordBuff = lf_alloc_align(p->alignment, bufsize); 60 | } 61 | 62 | void mod_teardown(lfFixture *lfFix, gconstpointer data) 63 | { 64 | lfTestParams *p = (lfTestParams *)data; 65 | 66 | if(p->alignment == 0) 67 | g_free(lfFix->coordBuff); 68 | else 69 | lf_free_align(lfFix->coordBuff); 70 | 71 | delete lfFix->mod; 72 | delete lfFix->lens; 73 | } 74 | 75 | void test_mod_coord_scale(lfFixture *lfFix, gconstpointer data) 76 | { 77 | for(size_t y = 0; y < lfFix->img_height; y++) 78 | { 79 | float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; 80 | 81 | g_assert_true( 82 | lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) 83 | ); 84 | } 85 | } 86 | 87 | #ifdef _OPENMP 88 | void test_mod_coord_scale_parallel(lfFixture *lfFix, gconstpointer data) 89 | { 90 | #pragma omp parallel for schedule(static) 91 | for(int y = 0; y < static_cast(lfFix->img_height); y++) 92 | { 93 | float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; 94 | 95 | g_assert_true( 96 | lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) 97 | ); 98 | } 99 | } 100 | #endif 101 | 102 | gchar *describe(lfTestParams *p, const char *prefix) 103 | { 104 | gchar alignment[32] = ""; 105 | g_snprintf(alignment, sizeof(alignment), "%lu-byte", p->alignment); 106 | 107 | return g_strdup_printf( 108 | "/%s/%s/%f/%s", 109 | prefix, 110 | p->reverse ? "unScale" : "Scale", 111 | p->scale, 112 | p->alignment == 0 ? "unaligned" : alignment 113 | ); 114 | } 115 | 116 | void add_set_item(lfTestParams *p) 117 | { 118 | gchar *desc = NULL; 119 | 120 | desc = describe(p, "modifier/coord/serialFor"); 121 | g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_scale, mod_teardown); 122 | g_free(desc); 123 | desc = NULL; 124 | 125 | #ifdef _OPENMP 126 | desc = describe(p, "modifier/coord/parallelFor"); 127 | g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_scale_parallel, mod_teardown); 128 | g_free(desc); 129 | desc = NULL; 130 | #endif 131 | } 132 | 133 | int main(int argc, char **argv) 134 | { 135 | setlocale(LC_ALL, ""); 136 | 137 | g_test_init(&argc, &argv, NULL); 138 | 139 | GSList *slist = NULL; 140 | 141 | std::vector reverse; 142 | reverse.push_back(false); 143 | reverse.push_back(true); 144 | 145 | for(std::vector::iterator it_reverse = reverse.begin(); it_reverse != reverse.end(); ++it_reverse) 146 | { 147 | std::vector scale; 148 | scale.push_back(0.75f); 149 | scale.push_back(1.25f); 150 | 151 | for(std::vector::iterator it_scale = scale.begin(); it_scale != scale.end(); ++it_scale) 152 | { 153 | std::vector align; 154 | align.push_back(0); 155 | align.push_back(4 * sizeof(float)); // SSE 156 | //align.push_back(8 * sizeof(float)); // AVX 157 | //align.push_back(16 * sizeof(float)); // AVX512 158 | 159 | for(std::vector::iterator it_align = align.begin(); it_align != align.end(); ++it_align) 160 | { 161 | lfTestParams *p = (lfTestParams *)g_malloc(sizeof(lfTestParams)); 162 | 163 | p->reverse = *it_reverse; 164 | p->scale = *it_scale; 165 | p->alignment = *it_align; 166 | 167 | add_set_item(p); 168 | 169 | slist = g_slist_append(slist, p); 170 | } 171 | } 172 | } 173 | 174 | const int res = g_test_run(); 175 | 176 | g_slist_free_full(slist, (GDestroyNotify)g_free); 177 | 178 | return res; 179 | } 180 | -------------------------------------------------------------------------------- /libs/getopt/getopt.h: -------------------------------------------------------------------------------- 1 | /* Declarations for getopt. 2 | Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. 3 | 4 | This program is free software; you can redistribute it and/or modify it 5 | under the terms of the GNU General Public License as published by the 6 | Free Software Foundation; either version 2, or (at your option) any 7 | later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | #ifndef _GETOPT_H 19 | #define _GETOPT_H 1 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | /* For communication from `getopt' to the caller. 26 | When `getopt' finds an option that takes an argument, 27 | the argument value is returned here. 28 | Also, when `ordering' is RETURN_IN_ORDER, 29 | each non-option ARGV-element is returned here. */ 30 | 31 | extern char *optarg; 32 | 33 | /* Index in ARGV of the next element to be scanned. 34 | This is used for communication to and from the caller 35 | and for communication between successive calls to `getopt'. 36 | 37 | On entry to `getopt', zero means this is the first call; initialize. 38 | 39 | When `getopt' returns EOF, this is the index of the first of the 40 | non-option elements that the caller should itself scan. 41 | 42 | Otherwise, `optind' communicates from one call to the next 43 | how much of ARGV has been scanned so far. */ 44 | 45 | extern int optind; 46 | 47 | /* Callers store zero here to inhibit the error message `getopt' prints 48 | for unrecognized options. */ 49 | 50 | extern int opterr; 51 | 52 | /* Set to an option character which was unrecognized. */ 53 | 54 | extern int optopt; 55 | 56 | /* Describe the long-named options requested by the application. 57 | The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector 58 | of `struct option' terminated by an element containing a name which is 59 | zero. 60 | 61 | The field `has_arg' is: 62 | no_argument (or 0) if the option does not take an argument, 63 | required_argument (or 1) if the option requires an argument, 64 | optional_argument (or 2) if the option takes an optional argument. 65 | 66 | If the field `flag' is not NULL, it points to a variable that is set 67 | to the value given in the field `val' when the option is found, but 68 | left unchanged if the option is not found. 69 | 70 | To have a long-named option do something other than set an `int' to 71 | a compiled-in constant, such as set a value from `optarg', set the 72 | option's `flag' field to zero and its `val' field to a nonzero 73 | value (the equivalent single-letter option character, if there is 74 | one). For long options that have a zero `flag' field, `getopt' 75 | returns the contents of the `val' field. */ 76 | 77 | struct option 78 | { 79 | #if __STDC__ || _MSC_VER || defined(XP_OS2_VACPP) 80 | const char *name; 81 | #else 82 | char *name; 83 | #endif 84 | /* has_arg can't be an enum because some compilers complain about 85 | type mismatches in all the code that assumes it is an int. */ 86 | int has_arg; 87 | int *flag; 88 | int val; 89 | }; 90 | 91 | /* Names for the values of the `has_arg' field of `struct option'. */ 92 | 93 | #define no_argument 0 94 | #define required_argument 1 95 | #define optional_argument 2 96 | 97 | #if __STDC__ || _MSC_VER || defined( XP_OS2_VACPP ) 98 | #if defined(__GNU_LIBRARY__) || defined( XP_OS2_VACPP ) || defined(_MSC_VER) 99 | /* Many other libraries have conflicting prototypes for getopt, with 100 | differences in the consts, in stdlib.h. To avoid compilation 101 | errors, only prototype getopt for the GNU C library. */ 102 | extern int getopt (int argc, char *const *argv, const char *shortopts); 103 | #else /* not __GNU_LIBRARY__ */ 104 | extern int getopt (); 105 | #endif /* not __GNU_LIBRARY__ */ 106 | extern int getopt_long (int argc, char *const *argv, const char *shortopts, 107 | const struct option *longopts, int *longind); 108 | extern int getopt_long_only (int argc, char *const *argv, 109 | const char *shortopts, 110 | const struct option *longopts, int *longind); 111 | 112 | /* Internal only. Users should not call this directly. */ 113 | extern int _getopt_internal (int argc, char *const *argv, 114 | const char *shortopts, 115 | const struct option *longopts, int *longind, 116 | int long_only); 117 | #else /* not __STDC__ */ 118 | extern int getopt (); 119 | extern int getopt_long (); 120 | extern int getopt_long_only (); 121 | 122 | extern int _getopt_internal (); 123 | #endif /* not __STDC__ */ 124 | 125 | #ifdef __cplusplus 126 | } 127 | #endif 128 | 129 | #endif /* _GETOPT_H */ 130 | -------------------------------------------------------------------------------- /tests/test_modifier.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #ifdef _MSC_VER 4 | #define _USE_MATH_DEFINES 5 | #endif 6 | #include 7 | #include "lensfun.h" 8 | 9 | typedef struct { 10 | size_t img_width, img_height; 11 | lfLens* lens; 12 | lfModifier* mod; 13 | } lfFixture; 14 | 15 | // setup a standard lens 16 | void mod_setup(lfFixture *lfFix, gconstpointer data) 17 | { 18 | lfFix->lens = new lfLens(); 19 | lfFix->lens->Type = LF_RECTILINEAR; 20 | 21 | lfLensCalibAttributes lensSetting = { 1.0, 1.0 }; 22 | lfLensCalibDistortion lensCalibDist = {LF_DIST_MODEL_POLY3, 12.0f, 10.8f, false, {0.1}, lensSetting}; 23 | lfFix->lens->AddCalibDistortion(&lensCalibDist); 24 | 25 | // width and height have to be odd, so we have a non fractional center position 26 | lfFix->img_height = 301; 27 | lfFix->img_width = 301; 28 | } 29 | 30 | 31 | void mod_teardown(lfFixture *lfFix, gconstpointer data) 32 | { 33 | delete lfFix->lens; 34 | } 35 | 36 | // test to verifiy that projection center is image center 37 | void test_mod_projection_center(lfFixture* lfFix, gconstpointer data) 38 | { 39 | float in[2] = {0, 0}; 40 | float res[2] = {0, 0}; 41 | 42 | // check mapping of center to center 43 | lfLensType geom_types [] = {LF_RECTILINEAR, LF_PANORAMIC, LF_EQUIRECTANGULAR , LF_FISHEYE, LF_FISHEYE_EQUISOLID, LF_FISHEYE_ORTHOGRAPHIC, LF_FISHEYE_THOBY, LF_UNKNOWN}; 44 | const char* geom_names [] = {"rectilinear", "panoramic", "equirect", "fisheye", "fisheye-equisolid", "fisheye-orthographic", "fisheye-thoby", NULL}; 45 | int j = 0; 46 | while (geom_types[j]!=LF_UNKNOWN) { 47 | 48 | lfFix->lens->Type = geom_types[j]; 49 | 50 | int i = 0; 51 | while (geom_types[i]!=LF_UNKNOWN) { 52 | 53 | if(g_test_verbose()) 54 | g_print(" ~ Conversion from %s -> %s \n", geom_names[j], geom_names[i]); 55 | 56 | lfFix->mod = new lfModifier (lfFix->lens, 12.0f, 1.0f, lfFix->img_width, lfFix->img_height, LF_PF_U8, false); 57 | 58 | lfFix->mod->EnableProjectionTransform(geom_types[i]); 59 | 60 | // check if center is not influenced 61 | in[0] = (lfFix->img_width-1)/2; 62 | in[1] = (lfFix->img_height-1)/2; 63 | if (lfFix->mod->ApplyGeometryDistortion(in[0],in[1],1,1,res)) { 64 | g_assert_cmpfloat(in[0],==,res[0]); 65 | g_assert_cmpfloat(in[1],==,res[1]); 66 | } 67 | 68 | delete lfFix->mod; 69 | i++; 70 | } 71 | j++; 72 | } 73 | } 74 | 75 | // check if output becomes NaN when processing geometry conversion 76 | void test_mod_projection_borders(lfFixture* lfFix, gconstpointer data) 77 | { 78 | float in[2] = {(float) lfFix->img_width, (float) lfFix->img_height}; 79 | float in2[2] = {(float) (lfFix->img_width-1)/2, (float) (lfFix->img_height-1)/2}; 80 | float res[2] = {0, 0}; 81 | 82 | 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}; 83 | const char* geom_names [] = {"rectilinear", "panoramic", "equirect", "fisheye-sterographic", "fisheye", "fisheye-equisolid", "fisheye-orthographic", "fisheye-thoby", NULL}; 84 | int j = 0; 85 | while (geom_types[j]!=LF_UNKNOWN) { 86 | 87 | lfFix->lens->Type = geom_types[j]; 88 | 89 | int i = 0; 90 | while (geom_types[i]!=LF_UNKNOWN) { 91 | 92 | if(g_test_verbose()) 93 | g_print(" ~ Conversion from %s -> %s \n", geom_names[j], geom_names[i]); 94 | 95 | lfFix->mod = new lfModifier (lfFix->lens, 12.0f, 1.0f, lfFix->img_width, lfFix->img_height, LF_PF_U8, false); 96 | 97 | lfFix->mod->EnableProjectionTransform(geom_types[i]); 98 | 99 | if (lfFix->mod->ApplyGeometryDistortion(0,0,1,1,res)) { 100 | g_assert_false(std::isnan(res[0])); 101 | g_assert_false(std::isnan(res[1])); 102 | } 103 | 104 | if (lfFix->mod->ApplyGeometryDistortion(in[0],in[1],1,1,res)) { 105 | g_assert_false(std::isnan(res[0])); 106 | g_assert_false(std::isnan(res[1])); 107 | } 108 | 109 | if (lfFix->mod->ApplyGeometryDistortion(in2[0],in2[1],1,1,res)) { 110 | g_assert_false(std::isnan(res[0])); 111 | g_assert_false(std::isnan(res[1])); 112 | } 113 | 114 | delete lfFix->mod; 115 | i++; 116 | } 117 | j++; 118 | } 119 | } 120 | 121 | 122 | int main (int argc, char **argv) 123 | { 124 | 125 | setlocale (LC_ALL, ""); 126 | 127 | g_test_init(&argc, &argv, NULL); 128 | 129 | g_test_add("/modifier/projection center", lfFixture, NULL, mod_setup, test_mod_projection_center, mod_teardown); 130 | g_test_add("/modifier/projection borders", lfFixture, NULL, mod_setup, test_mod_projection_borders, mod_teardown); 131 | 132 | return g_test_run(); 133 | } 134 | -------------------------------------------------------------------------------- /tests/test_modifier_coord_scale_old.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "lensfun.h" 14 | 15 | #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) 16 | #include 17 | #endif 18 | #ifdef __APPLE__ 19 | #include 20 | #endif 21 | 22 | #include "common_code.hpp" 23 | 24 | typedef struct 25 | { 26 | void *coordBuff; 27 | size_t img_width, img_height; 28 | lfLens *lens; 29 | lfModifier *mod; 30 | } lfFixture; 31 | 32 | typedef struct 33 | { 34 | bool reverse; 35 | float scale; 36 | size_t alignment; 37 | } lfTestParams; 38 | 39 | // setup a standard lens 40 | void mod_setup(lfFixture *lfFix, gconstpointer data) 41 | { 42 | lfTestParams *p = (lfTestParams *)data; 43 | 44 | lfFix->lens = new lfLens(); 45 | //lfFix->lens->CropFactor = 1.0f; 46 | lfFix->lens->Type = LF_RECTILINEAR; 47 | 48 | lfFix->img_height = 300; 49 | lfFix->img_width = 300; 50 | 51 | lfFix->mod = new lfModifier(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); 52 | 53 | lfFix->mod->Initialize( 54 | lfFix->lens, LF_PF_F32, 55 | 24.0f, 2.8f, 1000.0f, p->scale, LF_RECTILINEAR, 56 | LF_MODIFY_SCALE, p->reverse); 57 | 58 | lfFix->coordBuff = NULL; 59 | 60 | const size_t bufsize = 2 * lfFix->img_width * lfFix->img_height * sizeof(float); 61 | if(p->alignment == 0) 62 | lfFix->coordBuff = g_malloc(bufsize); 63 | else 64 | lfFix->coordBuff = lf_alloc_align(p->alignment, bufsize); 65 | } 66 | 67 | void mod_teardown(lfFixture *lfFix, gconstpointer data) 68 | { 69 | lfTestParams *p = (lfTestParams *)data; 70 | 71 | if(p->alignment == 0) 72 | g_free(lfFix->coordBuff); 73 | else 74 | lf_free_align(lfFix->coordBuff); 75 | 76 | delete lfFix->mod; 77 | delete lfFix->lens; 78 | } 79 | 80 | void test_mod_coord_scale(lfFixture *lfFix, gconstpointer data) 81 | { 82 | for(size_t y = 0; y < lfFix->img_height; y++) 83 | { 84 | float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; 85 | 86 | g_assert_true( 87 | lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) 88 | ); 89 | } 90 | } 91 | 92 | #ifdef _OPENMP 93 | void test_mod_coord_scale_parallel(lfFixture *lfFix, gconstpointer data) 94 | { 95 | #pragma omp parallel for schedule(static) 96 | for(int y = 0; y < static_cast(lfFix->img_height); y++) 97 | { 98 | float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; 99 | 100 | g_assert_true( 101 | lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) 102 | ); 103 | } 104 | } 105 | #endif 106 | 107 | gchar *describe(lfTestParams *p, const char *prefix) 108 | { 109 | gchar alignment[32] = ""; 110 | g_snprintf(alignment, sizeof(alignment), "%lu-byte", p->alignment); 111 | 112 | return g_strdup_printf( 113 | "/%s/%s/%f/%s", 114 | prefix, 115 | p->reverse ? "unScale" : "Scale", 116 | p->scale, 117 | p->alignment == 0 ? "unaligned" : alignment 118 | ); 119 | } 120 | 121 | void add_set_item(lfTestParams *p) 122 | { 123 | gchar *desc = NULL; 124 | 125 | desc = describe(p, "modifier/coord/serialFor"); 126 | g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_scale, mod_teardown); 127 | g_free(desc); 128 | desc = NULL; 129 | 130 | #ifdef _OPENMP 131 | desc = describe(p, "modifier/coord/parallelFor"); 132 | g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_scale_parallel, mod_teardown); 133 | g_free(desc); 134 | desc = NULL; 135 | #endif 136 | } 137 | 138 | int main(int argc, char **argv) 139 | { 140 | setlocale(LC_ALL, ""); 141 | 142 | g_test_init(&argc, &argv, NULL); 143 | 144 | GSList *slist = NULL; 145 | 146 | std::vector reverse; 147 | reverse.push_back(false); 148 | reverse.push_back(true); 149 | 150 | for(std::vector::iterator it_reverse = reverse.begin(); it_reverse != reverse.end(); ++it_reverse) 151 | { 152 | std::vector scale; 153 | scale.push_back(0.75f); 154 | scale.push_back(1.25f); 155 | 156 | for(std::vector::iterator it_scale = scale.begin(); it_scale != scale.end(); ++it_scale) 157 | { 158 | std::vector align; 159 | align.push_back(0); 160 | align.push_back(4 * sizeof(float)); // SSE 161 | //align.push_back(8 * sizeof(float)); // AVX 162 | //align.push_back(16 * sizeof(float)); // AVX512 163 | 164 | for(std::vector::iterator it_align = align.begin(); it_align != align.end(); ++it_align) 165 | { 166 | lfTestParams *p = (lfTestParams *)g_malloc(sizeof(lfTestParams)); 167 | 168 | p->reverse = *it_reverse; 169 | p->scale = *it_scale; 170 | p->alignment = *it_align; 171 | 172 | add_set_item(p); 173 | 174 | slist = g_slist_append(slist, p); 175 | } 176 | } 177 | } 178 | 179 | const int res = g_test_run(); 180 | 181 | g_slist_free_full(slist, (GDestroyNotify)g_free); 182 | 183 | return res; 184 | } 185 | -------------------------------------------------------------------------------- /tests/test_modifier_old.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #ifdef _MSC_VER 4 | #define _USE_MATH_DEFINES 5 | #endif 6 | #include 7 | #include "lensfun.h" 8 | 9 | typedef struct { 10 | size_t img_width, img_height; 11 | lfLens* lens; 12 | lfModifier* mod; 13 | } lfFixture; 14 | 15 | // setup a standard lens 16 | void mod_setup(lfFixture *lfFix, gconstpointer data) 17 | { 18 | lfFix->lens = new lfLens(); 19 | lfFix->lens->Type = LF_RECTILINEAR; 20 | lfFix->lens->CropFactor = 1.0; 21 | lfFix->lens->AspectRatio = 1.0; 22 | 23 | lfLensCalibDistortion lensCalibDist = {LF_DIST_MODEL_POLY3, 12.0f, 10.8f, false, {0.1}}; 24 | lfFix->lens->AddCalibDistortion(&lensCalibDist); 25 | 26 | // width and height have to be odd, so we have a non fractional center position 27 | lfFix->img_height = 301; 28 | lfFix->img_width = 301; 29 | } 30 | 31 | 32 | void mod_teardown(lfFixture *lfFix, gconstpointer data) 33 | { 34 | delete lfFix->lens; 35 | } 36 | 37 | // test to verifiy that projection center is image center 38 | void test_mod_projection_center(lfFixture* lfFix, gconstpointer data) 39 | { 40 | float in[2] = {0, 0}; 41 | float res[2] = {0, 0}; 42 | 43 | // check mapping of center to center 44 | lfLensType geom_types [] = {LF_RECTILINEAR, LF_PANORAMIC, LF_EQUIRECTANGULAR , LF_FISHEYE, LF_FISHEYE_EQUISOLID, LF_FISHEYE_ORTHOGRAPHIC, LF_FISHEYE_THOBY, LF_UNKNOWN}; 45 | const char* geom_names [] = {"rectilinear", "panoramic", "equirect", "fisheye", "fisheye-equisolid", "fisheye-orthographic", "fisheye-thoby", NULL}; 46 | int j = 0; 47 | while (geom_types[j]!=LF_UNKNOWN) { 48 | 49 | lfFix->lens->Type = geom_types[j]; 50 | 51 | int i = 0; 52 | while (geom_types[i]!=LF_UNKNOWN) { 53 | 54 | if(g_test_verbose()) 55 | g_print(" ~ Conversion from %s -> %s \n", geom_names[j], geom_names[i]); 56 | 57 | lfFix->mod = new lfModifier (lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); 58 | lfFix->mod->Initialize ( 59 | lfFix->lens, LF_PF_U8, 12.0f, 60 | 6.7f, 2.0f, 1.0f, geom_types[i], 61 | LF_MODIFY_GEOMETRY, false); 62 | 63 | // check if center is not influenced 64 | in[0] = (lfFix->img_width-1)/2; 65 | in[1] = (lfFix->img_height-1)/2; 66 | if (lfFix->mod->ApplyGeometryDistortion(in[0],in[1],1,1,res)) { 67 | g_assert_cmpfloat(in[0],==,res[0]); 68 | g_assert_cmpfloat(in[1],==,res[1]); 69 | } 70 | 71 | delete lfFix->mod; 72 | i++; 73 | } 74 | j++; 75 | } 76 | } 77 | 78 | // check if output becomes NaN when processing geometry conversion 79 | void test_mod_projection_borders(lfFixture* lfFix, gconstpointer data) 80 | { 81 | float in[2] = {(float) lfFix->img_width, (float) lfFix->img_height}; 82 | float in2[2] = {(float) (lfFix->img_width-1)/2, (float) (lfFix->img_height-1)/2}; 83 | float res[2] = {0, 0}; 84 | 85 | 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}; 86 | const char* geom_names [] = {"rectilinear", "panoramic", "equirect", "fisheye-sterographic", "fisheye", "fisheye-equisolid", "fisheye-orthographic", "fisheye-thoby", NULL}; 87 | int j = 0; 88 | while (geom_types[j]!=LF_UNKNOWN) { 89 | 90 | lfFix->lens->Type = geom_types[j]; 91 | 92 | int i = 0; 93 | while (geom_types[i]!=LF_UNKNOWN) { 94 | 95 | if(g_test_verbose()) 96 | g_print(" ~ Conversion from %s -> %s \n", geom_names[j], geom_names[i]); 97 | 98 | lfFix->mod = new lfModifier (lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); 99 | lfFix->mod->Initialize ( 100 | lfFix->lens, LF_PF_U8, 12.0f, 101 | 6.7f, 2.0f, 1.0f, geom_types[i], 102 | LF_MODIFY_GEOMETRY, false); 103 | 104 | if (lfFix->mod->ApplyGeometryDistortion(0,0,1,1,res)) { 105 | g_assert_false(std::isnan(res[0])); 106 | g_assert_false(std::isnan(res[1])); 107 | } 108 | 109 | if (lfFix->mod->ApplyGeometryDistortion(in[0],in[1],1,1,res)) { 110 | g_assert_false(std::isnan(res[0])); 111 | g_assert_false(std::isnan(res[1])); 112 | } 113 | 114 | if (lfFix->mod->ApplyGeometryDistortion(in2[0],in2[1],1,1,res)) { 115 | g_assert_false(std::isnan(res[0])); 116 | g_assert_false(std::isnan(res[1])); 117 | } 118 | 119 | delete lfFix->mod; 120 | i++; 121 | } 122 | j++; 123 | } 124 | } 125 | 126 | 127 | int main (int argc, char **argv) 128 | { 129 | 130 | setlocale (LC_ALL, ""); 131 | 132 | g_test_init(&argc, &argv, NULL); 133 | 134 | g_test_add("/modifier/projection center", lfFixture, NULL, mod_setup, test_mod_projection_center, mod_teardown); 135 | g_test_add("/modifier/projection borders", lfFixture, NULL, mod_setup, test_mod_projection_borders, mod_teardown); 136 | 137 | return g_test_run(); 138 | } 139 | -------------------------------------------------------------------------------- /data/db/compact-leica.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leica 6 | Digilux 2 7 | leicaDigilux2 8 | 3.933 9 | 10 | 11 | 12 | Leica 13 | D-LUX2 14 | Digilux 2 15 | panasonicLX1 16 | 4.45 17 | 18 | 19 | 20 | 21 | Leica 22 | D-LUX 4 23 | Digilux 4 24 | panasonicLX4 25 | 4.33 26 | 27 | 28 | 29 | 30 | Leica 31 | D-LUX 3 32 | Digilux 3 33 | panasonicLX3 34 | 4.33 35 | 36 | 37 | 38 | 39 | Leica Camera AG 40 | Leica Q (Typ 116) 41 | leicaQTyp116 42 | 1 43 | 44 | 45 | 46 | Leica Camera AG 47 | LEICA Q2 48 | LeicaQ2 49 | 1 50 | 51 | 52 | 53 | Leica 54 | Leica X Vario (Typ 107) 55 | leicaXVario107 56 | 1.53 57 | 58 | 59 | 60 | Leica 61 | Digilux 2 & compatibles (Standard) 62 | fixed lens 63 | festes Objektiv 64 | leicaDigilux2 65 | 3.933 66 | 4:3 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | Leica Camera AG 87 | Leica 88 | 28.0mm f/1.7 89 | leicaQTyp116 90 | 1 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | LEICA CAMERA AG 100 | SUMMILUX 1:1.7/28 ASPH. 101 | LeicaQ2 102 | 1 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | Leica 111 | Leica X Vario 18.0-46.0 mm f/3.5-6.4 112 | fixed lens 113 | festes Objektiv 114 | leicaXVario107 115 | 1.53 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /tools/calibration_webserver/settings.py: -------------------------------------------------------------------------------- 1 | # Django settings for calibration project. 2 | 3 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 4 | import os, configparser 5 | BASE_DIR = os.path.dirname(os.path.dirname(__file__)) 6 | 7 | DEBUG = False 8 | TEMPLATE_DEBUG = DEBUG 9 | 10 | config = configparser.ConfigParser() 11 | assert config.read(os.path.expanduser("~/calibration_webserver.ini")) 12 | 13 | ADMINS = ( 14 | (config["General"]["admin_name"], config["General"]["admin_email"]), 15 | ) 16 | 17 | EMAIL_HOST = config["SMTP"]["machine"] 18 | EMAIL_PORT = config["SMTP"]["port"] 19 | EMAIL_HOST_USER = config["SMTP"].get("login") 20 | EMAIL_HOST_PASSWORD = config["SMTP"].get("password") 21 | EMAIL_USE_TLS = config["SMTP"].get("TLS", "off").lower() in {"on", "true", "yes"} 22 | DEFAULT_FROM_EMAIL = config["General"]["admin_email"] 23 | 24 | #TEST_RUNNER = "django.test.runner.DiscoverRunner" 25 | 26 | # Hosts/domain names that are valid for this site; required if DEBUG is False 27 | # See https://docs.djangoproject.com/en//ref/settings/#allowed-hosts 28 | ALLOWED_HOSTS = ["wilson", "wilson.bronger.org", "0.0.0.0"] 29 | 30 | # Language code for this installation. All choices can be found here: 31 | # http://www.i18nguy.com/unicode/language-identifiers.html 32 | LANGUAGE_CODE = "en-us" 33 | 34 | # If you set this to False, Django will make some optimizations so as not 35 | # to load the internationalization machinery. 36 | USE_I18N = True 37 | 38 | # If you set this to False, Django will not format dates, numbers and 39 | # calendars according to the current locale. 40 | USE_L10N = True 41 | 42 | # Absolute filesystem path to the directory that will hold user-uploaded files. 43 | # Example: "/home/media/media.lawrence.com/media/" 44 | MEDIA_ROOT = "" 45 | 46 | FILE_UPLOAD_TEMP_DIR = config["General"]["upload_temp_path"] 47 | 48 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a 49 | # trailing slash. 50 | # Examples: "http://media.lawrence.com/media/", "http://example.com/media/" 51 | MEDIA_URL = "" 52 | 53 | # Absolute path to the directory static files should be collected to. 54 | # don't put anything in this directory yourself; store your static files 55 | # in apps" "static/" subdirectories and in STATICFILES_DIRS. 56 | # Example: "/home/media/media.lawrence.com/static/" 57 | STATIC_ROOT = os.path.expanduser("~/calibration") 58 | 59 | # URL prefix for static files. 60 | # Example: "http://media.lawrence.com/static/" 61 | STATIC_URL = "/calibration/static/" 62 | 63 | # Additional locations of static files 64 | STATICFILES_DIRS = ( 65 | # Put strings here, like "/home/html/static" or "C:/www/django/static". 66 | # Always use forward slashes, even on Windows. 67 | # don't forget to use absolute paths, not relative paths. 68 | ) 69 | 70 | # Make this unique, and don't share it with anybody. 71 | SECRET_KEY = "yyq3%@)4tg6@a86m8s=dopd)i+nu^-ma@p=lzk^su18h@*+hb3" 72 | 73 | MIDDLEWARE_CLASSES = ( 74 | "django.middleware.common.CommonMiddleware", 75 | "django.contrib.sessions.middleware.SessionMiddleware", 76 | "django.contrib.auth.middleware.AuthenticationMiddleware", 77 | "django.contrib.messages.middleware.MessageMiddleware", 78 | # Uncomment the next line for simple clickjacking protection: 79 | # "django.middleware.clickjacking.XFrameOptionsMiddleware", 80 | ) 81 | 82 | ROOT_URLCONF = "calibration.urls" 83 | 84 | # Python dotted path to the WSGI application used by Django's runserver. 85 | #WSGI_APPLICATION = "calibration.wsgi.application" 86 | 87 | TEMPLATES = [ 88 | { 89 | "BACKEND": "django.template.backends.django.DjangoTemplates", 90 | "APP_DIRS": True, 91 | "OPTIONS": { 92 | "context_processors": ["django.template.context_processors.debug", 93 | "django.template.context_processors.request", 94 | "django.contrib.auth.context_processors.auth", 95 | "django.contrib.messages.context_processors.messages", 96 | "calibration.context_processors.default"] 97 | } 98 | } 99 | ] 100 | 101 | INSTALLED_APPS = ( 102 | "django.contrib.auth", 103 | "django.contrib.contenttypes", 104 | "django.contrib.sessions", 105 | "django.contrib.sites", 106 | "django.contrib.messages", 107 | "django.contrib.staticfiles", 108 | "calibration" 109 | ) 110 | 111 | # A sample logging configuration. The only tangible logging 112 | # performed by this configuration is to send an email to 113 | # the site admins on every HTTP 500 error when DEBUG=False. 114 | # See http://docs.djangoproject.com/en/dev/topics/logging for 115 | # more details on how to customize your logging configuration. 116 | LOGGING = { 117 | "version": 1, 118 | "disable_existing_loggers": False, 119 | "filters": { 120 | "require_debug_false": { 121 | "()": "django.utils.log.RequireDebugFalse" 122 | } 123 | }, 124 | "handlers": { 125 | "mail_admins": { 126 | "level": "ERROR", 127 | "filters": ["require_debug_false"], 128 | "class": "django.utils.log.AdminEmailHandler" 129 | } 130 | }, 131 | "loggers": { 132 | "django.request": { 133 | "handlers": ["mail_admins"], 134 | "level": "ERROR", 135 | "propagate": True, 136 | }, 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /apps/lenstool/image.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001 by Andrew Zabolotny 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Library General Public 6 | License as published by the Free Software Foundation; either 7 | version 2 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Library General Public License for more details. 13 | 14 | You should have received a copy of the GNU Library General Public 15 | License along with this library; if not, write to the Free 16 | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 | */ 18 | 19 | #ifndef __IMAGE_H__ 20 | #define __IMAGE_H__ 21 | 22 | #include "rgbpixel.h" 23 | #include 24 | 25 | #if defined (_MSC_VER) && !defined(CONF_LENSFUN_STATIC) 26 | #if defined auxfun_EXPORTS 27 | #define AF_EXPORT __declspec(dllexport) 28 | #else 29 | #define AF_EXPORT __declspec(dllimport) 30 | #endif 31 | #else 32 | #define AF_EXPORT 33 | #endif 34 | 35 | /** 36 | * This class represents an image object. 37 | * It provides loading/saving from a PNG file functionality (through libPNG), 38 | * the rest was cut off ;-) 39 | */ 40 | class AF_EXPORT Image 41 | { 42 | FILE *file; 43 | int filesize; 44 | bool lanczos_func_in_use; 45 | static float *lanczos_func; 46 | static int lanczos_func_use; 47 | 48 | unsigned char (*fGetR) (Image *This, float x, float y); 49 | unsigned char (*fGetG) (Image *This, float x, float y); 50 | unsigned char (*fGetB) (Image *This, float x, float y); 51 | void (*fGet) (Image *This, RGBpixel &out, float x, float y); 52 | 53 | // --- Nearest interpolation --- // 54 | 55 | /// Get interpolated red value at given position 56 | static unsigned char GetR_n (Image *This, float x, float y); 57 | /// Get interpolated green value at given position 58 | static unsigned char GetG_n (Image *This, float x, float y); 59 | /// Get interpolated blue value at given position 60 | static unsigned char GetB_n (Image *This, float x, float y); 61 | /// Get interpolated pixel value at given position 62 | static void Get_n (Image *This, RGBpixel &out, float x, float y); 63 | 64 | // --- Linear interpolation --- // 65 | 66 | /// Get interpolated red value at given position 67 | static unsigned char GetR_b (Image *This, float x, float y); 68 | /// Get interpolated green value at given position 69 | static unsigned char GetG_b (Image *This, float x, float y); 70 | /// Get interpolated blue value at given position 71 | static unsigned char GetB_b (Image *This, float x, float y); 72 | /// Get interpolated pixel value at given position 73 | static void Get_b (Image *This, RGBpixel &out, float x, float y); 74 | 75 | // --- Lanczos interpolation --- // 76 | 77 | /// Get interpolated red value at given position 78 | static unsigned char GetR_l (Image *This, float x, float y); 79 | /// Get interpolated green value at given position 80 | static unsigned char GetG_l (Image *This, float x, float y); 81 | /// Get interpolated blue value at given position 82 | static unsigned char GetB_l (Image *This, float x, float y); 83 | /// Get interpolated pixel value at given position 84 | static void Get_l (Image *This, RGBpixel &out, float x, float y); 85 | 86 | public: 87 | /// The actual image data 88 | RGBpixel *image; 89 | /// Image size 90 | unsigned width, height; 91 | /// The transparent color 92 | RGBpixel transp; 93 | 94 | enum InterpolationMethod 95 | { 96 | /// Nearest interpolation (very fast, very low quality) 97 | I_NEAREST, 98 | /// Bi-linear interpolation (fast, low quality) 99 | I_BILINEAR, 100 | /// Lanczos interpolation (slow, high quality) 101 | I_LANCZOS 102 | }; 103 | 104 | /// Initialize the image object 105 | Image (); 106 | /// Destroy the image object 107 | ~Image (); 108 | /// Open the file and prepare to read from it 109 | bool Open (const char *fName); 110 | /// Close the file 111 | void Close (); 112 | /// Free the image 113 | void Free (); 114 | /// Load next image from file: this completely discards previously loaded one 115 | bool LoadPNG (); 116 | /// Save the image into a PNG file in given format 117 | bool SavePNG (const char *fName); 118 | /// Check if file is at EOF 119 | bool AtEOF () 120 | { return ftell (file) >= filesize; } 121 | /// Allocate a new image of given size 122 | void Resize (unsigned newwidth, unsigned newheight); 123 | 124 | /// Initialize interpolation method 125 | void InitInterpolation (InterpolationMethod method); 126 | 127 | /// Get interpolated red value at given position 128 | unsigned char GetR (float x, float y) 129 | { return fGetR (this, x, y); } 130 | /// Get interpolated green value at given position 131 | unsigned char GetG (float x, float y) 132 | { return fGetG (this, x, y); } 133 | /// Get interpolated blue value at given position 134 | unsigned char GetB (float x, float y) 135 | { return fGetB (this, x, y); } 136 | /// Get interpolated pixel value at given position 137 | void Get (RGBpixel &out, float x, float y) 138 | { fGet (this, out, x, y); } 139 | }; 140 | 141 | #endif // __IMAGE_H__ 142 | --------------------------------------------------------------------------------